[PATCH 3/3] static: add rest.js to handle PATCH requests & respective responses
Daniel Axtens
dja at axtens.net
Tue Aug 17 12:31:09 AEST 2021
Raxel Gutierrez <raxel at 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 <raxel at 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 at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/patchwork
More information about the Patchwork
mailing list