[Patchew-devel] [PATCH 09/17] mods: place a single Save button at the end of the forms

Paolo Bonzini pbonzini at redhat.com
Thu May 2 11:17:56 UTC 2019


Because the save button now acts on the whole config, we cannot anymore
rely on finding the property prefix from the save button's parents.
Instead, each property control has a data-property-path attribute and
building the configuration dictionary is as simple as looking all of
them up.  Likewise, each map item has a data-property-prefix attribute
which simplifies deletion and is also used to build the data-property-path
when a new map item is added.
---
 mod.py                            | 25 +++++++------------------
 static/js/config-editor.js        | 30 ++++++++++++++++++------------
 www/templates/project-detail.html |  7 +++++++
 3 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/mod.py b/mod.py
index 4cf2e9f..1b7910c 100644
--- a/mod.py
+++ b/mod.py
@@ -67,15 +67,9 @@ class PatchewModule(object):
         members = [self._build_one(request, project,
                                    prefix + "." + x.name,
                                    config.get(x.name), x) for x in scm.members]
-        show_save_button = False
-        for m in scm.members:
-            if type(m) == StringSchema:
-                show_save_button = True
-                break
         return self._render_template(request, project, TMPL_ARRAY,
                                      schema=scm,
                                      members=members,
-                                     show_save_button=show_save_button,
                                      prefix=prefix)
 
     def _build_string_scm(self, request, project, prefix, config, scm):
@@ -206,6 +200,7 @@ TMPL_STRING = """
         <input
     {% endif %}
     type="text" class="form-control project-property"
+    data-property-path="{{ prefix }}"
     id="{{ module.name }}-input-{{ schema.name }}" {% if schema.required %}required{%endif%}
     name="{{ name }}" placeholder="{{ schema.desc }}"
     {% if schema.multiline %}
@@ -220,6 +215,7 @@ TMPL_INTEGER = """
 <div class="form-group">
     <label for="{{ module.name }}-input-{{ schema.name }}">{{ schema.title }}</label>
     <input type="number" class="form-control project-property"
+    data-property-path="{{ prefix }}"
     id="{{ module.name }}-input-{{ schema.name }}" {% if schema.required %}required{%endif%}
     name="{{ name }}" placeholder="{{ schema.desc }}"
     {% if schema.multiline %}
@@ -234,6 +230,7 @@ TMPL_BOOLEAN = """
 <div class="checkbox">
 <label>
   <input class="project-property" type="checkbox" name="{{ name }}"
+    data-property-path="{{ prefix }}"
   {% if value == None %}
     {% if schema.default %}
       checked
@@ -260,6 +257,7 @@ TMPL_ENUM = """
     <label for="{{ module.name }}-input-{{ schema.name }}">{{ schema.title }}</label>
     <select class="form-control project-property"
     id="{{ module.name }}-input-{{ schema.name }}"
+    data-property-path="{{ prefix }}"
     onchange="enum_change(this)"
     {% if schema.required %}required{%endif%}
     name="{{ name }}">
@@ -288,25 +286,16 @@ TMPL_ENUM = """
 """
 
 TMPL_ARRAY = """
-<input type="hidden" name="property-prefix" class="property-prefix" value="{{ prefix }}">
 {% for schema in members %}
     {{ schema }}
 {% endfor %}
-{% if show_save_button %}
-    <div class="form-group">
-        <button type="button" class="btn btn-info" onclick="properties_save(this)">
-             Save
-         </button>
-    </div>
-{% endif %}
 """
 
 TMPL_MAP_ITEM = """
-<div class="item panel panel-default">
-    <div class="panel-heading panel-toggler" onclick="patchew_toggler_onclick(this)">
+<div class="item panel panel-default" data-property-prefix="{{ prefix }}{% if item.name %}.{{ item.name }}{% endif %}">
+    <div class="item-heading panel-heading panel-toggler" onclick="patchew_toggler_onclick(this)">
         {{ item_schema.title }}
         <strong class="item-name">{{ item.name }}</strong>
-        <input type="hidden" value="{{ prefix }}{{ item.name }}." class="prefix" />
     </div>
     <div class="panel-body panel-collapse collapse">
         {{ item.html }}
@@ -321,7 +310,7 @@ TMPL_MAP_ITEM = """
 """
 
 TMPL_MAP = """
-<div id="{{ schema.name }}-container">
+<div>
     <script class="item-template" type="text/x-custom-template">
     """ + TMPL_MAP_ITEM + """
     </script>
diff --git a/static/js/config-editor.js b/static/js/config-editor.js
index 56d0781..f15211f 100644
--- a/static/js/config-editor.js
+++ b/static/js/config-editor.js
@@ -17,9 +17,9 @@ function save_done(btn, succeeded, error) {
 }
 
 function collect_properties(btn, check_required) {
-    prefix = $(btn).parent().parent().find(".property-prefix").val();
     properties = {};
     $(btn).parent().parent().find(".project-property").each(function () {
+        path = $(this).data('property-path');
         if (check_required && this.required && !this.value) {
             alert($(this).parent().find("label").html() + " is required!");
             $(this).focus();
@@ -43,7 +43,7 @@ function collect_properties(btn, check_required) {
         } else {
             val = this.value;
         }
-        properties[prefix + this.name] = val;
+        properties[path] = val;
     });
     return properties;
 }
@@ -80,6 +80,7 @@ function map_add_item(btn) {
     if (!name || name == 'null') {
         return;
     }
+    container = $(btn).parent().parent();
     if (name in collect_items(btn)) {
         alert(test_name + " already exists.");
         return;
@@ -88,17 +89,23 @@ function map_add_item(btn) {
         alert("Invalid name, no dot is allowed.");
         return;
     }
-    container = $(btn).parent().parent();
     tmpl = container.find(".item-template").html();
-    nt = $(tmpl)
-    nt.find(".item-name").html(name);
-    old = nt.find(".property-prefix").val();
-    nt.find(".property-prefix").val(old + name + ".");
-    container.find(".items").append(nt);
+    nt = $(tmpl);
+    nt.find(".item-name").text(name);
+    prefix = nt.data('property-prefix') + '.' + name;
+    nt.data('property-prefix', prefix);
+    nt.find(".project-property").each(function() {
+        old = $(this).data('property-path');
+        $(this).data('property-path', prefix + old);
+    });
+    nt.find(".panel-collapse").collapse("show");
+    container.find("> .items").append(nt);
 }
+
 function map_delete_item(btn) {
-    name = $(btn).parent().parent().parent().find(".item-name").html();
-    prefix = $(btn).parent().parent().parent().find(".prefix").val();
+    item = $(btn).parent().parent().parent();
+    name = item.find(".item-name").text();
+    prefix = item.data('property-prefix') + ".";
     if (!window.confirm("Really delete '" + name +"'?")) {
         return;
     }
@@ -109,8 +116,7 @@ function map_delete_item(btn) {
                    { project: current_project(),
                      prefix: prefix })
         .done(function (data) {
-            container = $(btn).parent().parent().parent();
-            container.remove();
+            item.remove();
         })
         .fail(function (data, text, error) {
             $(btn).removeClass("disabled");
diff --git a/www/templates/project-detail.html b/www/templates/project-detail.html
index adf90a3..5895314 100644
--- a/www/templates/project-detail.html
+++ b/www/templates/project-detail.html
@@ -78,6 +78,13 @@
         </div>
     </div>
     {% endfor %}
+    {% if request.user.is_authenticated %}
+        <div class="form-group">
+            <button type="button" class="btn btn-info" onclick="properties_save(this)">
+                 Save
+             </button>
+        </div>
+    {% endif %}
 </div>
 
 <script type="text/javascript">
-- 
2.21.0





More information about the Patchew-devel mailing list