Raxel Gutierrez <ra...@google.com> writes: > Add `rest.js` file to have a utilities JavaScript module that can be > reused by any Patchwork JS files that make requests to the REST API. In > particular, this patch provides the following function: > > - `updateProperty`: make PATCH requests that partially update the > fields of an object given it's REST API endpoint specified by the > caller. Also, the caller can specify the field(s) to modify and the > associated content for update messages in the case of both failed > successful requests that render to the current webpage. The caller > receives whether the request was successful or not. > > The `rest.js` module can be further expanded to support and provide > functions that allow for other requests (e.g. GET, POST, PUT) to the > REST API. > > Also, add functions that handle update & error messages for these PATCH > requests that match the Django messages framework format and form error > styling. These functions are internal to the module and aren't exposed > outside of the `rest.js` file. > > Error and accompanying failed update messages are replaced by successful > update messages and vice versa. Consecutive successful update messages > add to a counter of updated objects. Consecutive error messages stack up.
I think most of my comments from the fuller series still apply, in particular: - the counter goes 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2. I think just have a global variable to store the number of items successfully updated? - you need to handle the case where `fetch()` fails. (e.g. network issues) [error display (when I cherry picked the rest of the fuller series on top of this smaller series - and I may have resolved a conflict wrong) is still a bit quirky but I don't think that's the fault of this patch.] It is genuinely quite exciting to be calling the API from the front-end, feels like patchwork is finally entering the 2010s! :P Kind regards, Daniel > > Signed-off-by: Raxel Gutierrez <ra...@google.com> > --- > htdocs/js/rest.js | 107 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 107 insertions(+) > create mode 100644 htdocs/js/rest.js > > diff --git a/htdocs/js/rest.js b/htdocs/js/rest.js > new file mode 100644 > index 00000000..f8e0a981 > --- /dev/null > +++ b/htdocs/js/rest.js > @@ -0,0 +1,107 @@ > +/** > + * Sends PATCH requests to update objects' properties using the REST API. > + * @param {string} url Path to the REST API endpoint. > + * @param {{field: string, value: string}} data > + * field: Name of the property field to update. > + * value: Value to update the property field to. > + * @param {{none: string, some: string}} updateMessage > + * none: Message when object update failed due to errors. > + * some: Message when object update successful. > + */ > +async function updateProperty(url, data, updateMessage) { > + const request = new Request(url, { > + method: 'PATCH', > + mode: "same-origin", > + headers: { > + "X-CSRFToken": Cookies.get("csrftoken"), > + "Content-Type": "application/json", > + }, > + body: JSON.stringify(data), > + }); > + > + return await fetch(request) > + .then(response => { > + let message = updateMessage.some; > + let success = true; > + if (!response.ok) { > + response.text().then(text => { > + const responseObject = JSON.parse(text); > + // Add error messages from response to page > + for (const [key,value] of > Object.entries(responseObject)) { > + if (Array.isArray(value)) { > + for (const error of value) { > + handleErrorMessages(key + ": " + error); > + } > + } else { > + handleErrorMessages(key + ": " + value); > + } > + } > + }); > + // Update message to be unsuccessful > + message = updateMessage.none; > + success = false; > + } > + handleUpdateMessages(message, success); > + return response.ok > + }); > +} > + > +/** > + * Populates update messages for API REST requests. > + * @param {string} messageContent Text for update message. > + */ > +function handleUpdateMessages(messageContent, success) { > + // Replace error and failure update messages with success update message > + const errorContainer = document.getElementById("errors"); > + let messages = document.getElementsByClassName("messages")[0]; > + if (success && errorContainer.firstChild != null) { > + messages.replaceChildren(); > + errorContainer.replaceChildren(); > + } else if (!success) { > + messages.replaceChildren(); > + } > + > + // Increment counter of consecutive success update messages > + if (messages.firstChild != null) { > + const newMessageCount = > parseInt(messages.firstChild.textContent.slice(0,1)) + 1 > + messageContent = newMessageCount + messageContent.slice(1); > + } > + > + // Create new message element and add to list > + const message = document.createElement("li"); > + message.setAttribute("class", "message"); > + if (success) { > + message.classList.add("class", "success"); > + } else { > + message.classList.add("class", "error"); > + } > + message.textContent = messageContent; > + messages.replaceChildren(...[message]); > +} > + > +/** > + * Populates error messages for API REST requests. > + * @param {string} errorMessage Text for error message. > + */ > +function handleErrorMessages(errorMessage) { > + let errorContainer = document.getElementById("errors"); > + let errorHeader = document.getElementById("errors-header"); > + let errorList = document.getElementsByClassName("error-list")[0]; > + > + // Create errors list and error header if container contents removed > + if (errorList == null) { > + errorHeader = document.createElement("p"); > + errorList = document.createElement("ul"); > + errorHeader.setAttribute("id", "errors-header") > + errorHeader.textContent = "The following errors were encountered > while making updates:"; > + errorList.setAttribute("class", "error-list"); > + errorContainer.appendChild(errorHeader); > + errorContainer.appendChild(errorList); > + } > + > + const error = document.createElement("li"); > + error.textContent = errorMessage; > + errorList.appendChild(error); > +} > + > +export { updateProperty }; > -- > 2.33.0.rc1.237.g0d66db33f3-goog > > _______________________________________________ > Patchwork mailing list > Patchwork@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/patchwork _______________________________________________ Patchwork mailing list Patchwork@lists.ozlabs.org https://lists.ozlabs.org/listinfo/patchwork