[PATCH v2 0/3] rest: add rest.js to handle PATCH requests & respective responses

Raxel Gutierrez raxel at google.com
Wed Aug 18 07:31:39 AEST 2021


This series is a revision to the previous version of the patch series 
[1]. Following comments, the counter for the number of objects in the 
update message is fixed. Also, errors when fetching are now caught in 
rest.js and added to the list of error messages. This resolves the case
where a network failure doesn’t give feedback to the user of what 
happened to their action. 

Since v1, the following changes:
- Patch 1: 
  - fix bullets showing up for message and errors containers
  - move errors container to base.html
  - add background color to errors container to appear as a continuation
    of the messages element
- Patch 2: nothing, reviewed by dja
- Patch 3: fix update message counter and handle fetch request errors

[1] https://lists.ozlabs.org/pipermail/patchwork/2021-August/007093.html
[2] https://lists.ozlabs.org/pipermail/patchwork/2021-August/007100.html

Raxel Gutierrez (3):
  messages: clean up messages and errors containers
  static: add JS Cookie library to get csrftoken for client-side
    requests
  static: add rest.js to handle PATCH requests & respective responses

 htdocs/README.rst                             |   9 ++
 htdocs/css/style.css                          |  43 +++++--
 htdocs/js/js.cookie.min.js                    |   2 +
 htdocs/js/rest.js                             | 110 ++++++++++++++++++
 patchwork/templates/patchwork/list.html       |  10 --
 .../patchwork/user-link-confirm.html          |   5 +-
 patchwork/templates/patchwork/user-link.html  |   4 +-
 templates/base.html                           |  31 +++--
 8 files changed, 180 insertions(+), 34 deletions(-)
 create mode 100644 htdocs/js/js.cookie.min.js
 create mode 100644 htdocs/js/rest.js

Range-diff against v1:
1:  31a065c6 ! 1:  9087ddbe messages: clean up messages and errors containers
    @@ Commit message
         concept, customize the text color of each existing message level. Also,
         this addition resolves a TODO by stephenfin in the previous code.
     
    -    Modularize the errors container with a new partial template errors.html
    -    that makes it easier to reuse errors in various pages. These changes
    -    make the code more readable and ready for change.
    +    Move the errors container after the messages container in the DOM in the
    +    base.html template so that every template can share the same errors
    +    container. Also, add a background color to the errors container so that
    +    both containers blend in as a uniform block. Add bullet points to each
    +    error item in the list of errors.
     
         Change both the messages and errors containers to always exist in
         the DOM. With this, the addition of update and error messages is simpler
    @@ Commit message
     
         [1] https://docs.djangoproject.com/en/3.2/ref/contrib/messages/#message-tags
     
    -    Signed-off-by: Raxel Gutierrez <raxel at google.com>
    -
      ## htdocs/css/style.css ##
     @@
     +:root {
    @@ htdocs/css/style.css: dl dt {
     -#messages {
     +.messages {
          background: #e0e0f0;
    -     margin: 0.5em 1em 0.0em 0.5em;
    +-    margin: 0.5em 1em 0.0em 0.5em;
    ++    margin: 0.5em 1em 0.0em 1em;
          padding: 0.3em;
    - }
    - 
    --#messages .message {
    --    color: green;
    ++    list-style-type: none;
    ++}
    ++
     +.messages:empty {
     +    display: none;
     +}
    @@ htdocs/css/style.css: dl dt {
     +
     +.messages .warning {
     +    color: var(--warning-color);
    -+}
    -+
    + }
    + 
    +-#messages .message {
    +-    color: green;
     +.messages .error {
     +    color: var(--danger-color);
      }
    @@ htdocs/css/style.css: table.loginform {
      
      /* form errors */
     -.errorlist {
    -+.error-list {
    +-    color: red;
    +-    list-style-type: none;
    +-    padding-left: 0.2em;
    +-    margin: 0em;
    ++#errors {
    ++    background: #e0e0f0;
    ++    margin: 0em 1em 0.5em 1em;
    ++    padding: 0.3em;
    + }
    +-.error {
    ++
    ++#errors:empty {
    ++    display: none;
    ++}
    ++
    ++.error-list, .errorlist {
          color: red;
    -     list-style-type: none;
    -     padding-left: 0.2em;
    + }
    + 
     
      ## patchwork/templates/patchwork/list.html ##
     @@
    @@ patchwork/templates/patchwork/list.html
     -{% endfor %}
     -</ul>
     -{% endif %}
    -+{% include "patchwork/partials/errors.html" %}
    - 
    +-
      {% include "patchwork/partials/patch-list.html" %}
      
    + {% endblock %}
     
    - ## patchwork/templates/patchwork/partials/errors.html (new) ##
    -@@
    -+<div id="errors">
    -+    {% if errors %}
    -+        <p>The following error{{ errors|length|pluralize:" was,s were" }} encountered while updating patches:</p>
    -+        <ul class="error-list">
    -+        {% for error in errors %}
    -+            <li>{{ error }}</li>
    -+        {% endfor %}
    -+        </ul>
    -+    {% endif %}
    -+</div>
    -
    - ## patchwork/templates/patchwork/submission.html ##
    + ## patchwork/templates/patchwork/user-link-confirm.html ##
     @@
      
      {% block body %}
      
    -+{% include "patchwork/partials/errors.html" %}
    -+
    - <div>
    -   {% include "patchwork/partials/download-buttons.html" %}
    -   <h1>{{ submission.name }}</h1>
    +-{% if errors %}
    +-<p>{{ errors }}</p>
    +-{% else %}
    ++{% if not errors %}
    +  <p>You have successfully linked the email address {{ person.email }} to
    +   your Patchwork account</p>
    +-
    + {% endif %}
    + <p>Back to <a href="{% url 'user-profile' %}">your
    +  profile</a>.</p>
     
      ## patchwork/templates/patchwork/user-link.html ##
    -@@ patchwork/templates/patchwork/user-link.html: you.</p>
    +@@
    + on the link provided in the email to confirm that this address belongs to
    + you.</p>
    + {% else %}
    ++   <p>There was an error submitting your link request:</p>
    +    {% if form.errors %}
    +-   <p>There was an error submitting your link request.</p>
          {{ form.non_field_errors }}
         {% endif %}
         {% if error %}
    @@ templates/base.html
     -  {# converted to django.contrib.messages #}
     -   <div class="message">{{ message }}</div>
     -  {% endfor %}
    --  </div>
    --{% endif %}
     +  <!--
     +    spaceless tag is used to remove automatically added whitespace so that the container
     +    is truly considered empty by the `:empty` pseudo-class that is used for styling
    @@ templates/base.html
     +    {% endfor %}
     +  {% endif %}
     +  </ul>
    ++  <div id="errors">
    ++    {% if errors %}
    ++        <p>The following error{{ errors|length|pluralize:" was,s were" }} encountered:</p>
    ++        <ul class="error-list">
    ++        {% for error in errors %}
    ++            <li>{{ error }}</li>
    ++        {% endfor %}
    ++        </ul>
    ++    {% endif %}
    +   </div>
    +-{% endif %}
     +  {% endspaceless %}
        <div id="main-content" class="container-fluid">
      {% block body %}
2:  3cf3a280 ! 2:  c92b0dcd static: add JS Cookie library to get csrftoken for client-side requests
    @@ Commit message
         [1] https://docs.djangoproject.com/en/3.2/ref/csrf/#ajax
         [2] https://github.com/js-cookie/js-cookie/releases
     
    -    Signed-off-by: Raxel Gutierrez <raxel at google.com>
    -    Reviewed-by: Daniel Axtens <dja at axtens.net>
    -
      ## htdocs/README.rst ##
     @@ htdocs/README.rst: js
        :GitHub: jQuery plug-in to drag and drop rows in HTML tables
    @@ htdocs/README.rst: js
      ## htdocs/js/js.cookie.min.js (new) ##
     @@
     +/*! js-cookie v3.0.0 | MIT */
    -+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,r=e.Cookies=t();r.noConflict=function(){return e.Cookies=n,r}}())}(this,(function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)e[r]=n[r]}return e}var t={read:function(e){return e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}};return function n(r,o){function i(t,n,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape),n=r.write(n,t);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.coo
    ++!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,r=e.Cookies=t();r.noConflict=function(){return e.Cookies=n,r}}())}(this,(function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)e[r]=n[r]}return e}var t={read:function(e){return e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}};return function n(r,o){function i(t,n,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape),n=r.write(n,t);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n+c}}return Object.create({set:i,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var n=document.cookie?document.cookie.split("; "):[],o={},i=0;i<n.length;i++){var c=n[i].split("="),u=c.slice(1).join("=");'"'===u[0]&&(u=u.slice(1,-1));try{var f=t.read(c[0]);if(o[f]=r.read(u,f),e===f)break}catch(e){}}return e?o[e]:o}},remove:function(t,n){i(t,"",e({},n,{expires:-1}))},withAttributes:function(t){return n(this.converter,e({},this.attributes,t))},withConverter:function(t){return n(e({},this.converter,t),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(r)}})}(t,{path:"/"})}));
     
      ## templates/base.html ##
     @@
3:  18aaa0a5 ! 3:  66bd1270 static: add rest.js to handle PATCH requests & respective responses
    @@ Commit message
         update messages and vice versa. Consecutive successful update messages
         add to a counter of updated objects. Consecutive error messages stack up.
     
    -    Signed-off-by: Raxel Gutierrez <raxel at google.com>
    -
      ## htdocs/js/rest.js (new) ##
     @@
     +/**
    @@ htdocs/js/rest.js (new)
     +            }
     +            handleUpdateMessages(message, success);
     +            return response.ok
    ++        }).catch(error => {
    ++            handleErrorMessages(error);
     +        });
     +}
     +
    @@ htdocs/js/rest.js (new)
     +
     +    // Increment counter of consecutive success update messages
     +    if (messages.firstChild != null) {
    -+        const newMessageCount = parseInt(messages.firstChild.textContent.slice(0,1)) + 1
    ++        const currentMessageCount = messages.firstChild.textContent.match('^([0-9]+)')[0];
    ++        const newMessageCount = parseInt(currentMessageCount) + 1;
     +        messageContent = newMessageCount + messageContent.slice(1);
     +    }
     +
-- 
2.33.0.rc1.237.g0d66db33f3-goog



More information about the Patchwork mailing list