]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
WEBUI/API: add multi-row (foreach) editor, fixes #3075
authorJaroslav Kysela <perex@perex.cz>
Thu, 8 Oct 2015 13:17:36 +0000 (15:17 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 8 Oct 2015 13:22:59 +0000 (15:22 +0200)
src/api/api_idnode.c
src/webui/static/app/idnode.js

index 54b7b9141e0daf82962ddca6564b305441cba9f2..0e8f88f55326417ff5b1ebe59a5fef58d43bbd97 100644 (file)
@@ -375,6 +375,7 @@ api_idnode_save
   htsmsg_field_t *f;
   const char *uuid;
   int count = 0;
+  const idnodes_rb_t *domain = NULL;
 
   if (!(f = htsmsg_field_find(args, "node")))
     return EINVAL;
@@ -384,23 +385,49 @@ api_idnode_save
 
   pthread_mutex_lock(&global_lock);
 
-  /* Single */
+  /* Single or Foreach */
   if (!msg->hm_islist) {
-    if (!(uuid = htsmsg_get_str(msg, "uuid")))
-      goto exit;
-    if (!(in = idnode_find(uuid, NULL, NULL)))
-      goto exit;
-    if (idnode_perm(in, perm, msg)) {
-      err = EPERM;
-      goto exit;
+
+    if (!(uuid = htsmsg_get_str(msg, "uuid"))) {
+
+      /* Foreach */
+      f = htsmsg_field_find(msg, "uuid");
+      if (!(conf = htsmsg_field_get_list(f)))
+        goto exit;
+      HTSMSG_FOREACH(f, conf) {
+        if (!(uuid = htsmsg_field_get_str(f)))
+          continue;
+        if (!(in = idnode_find(uuid, NULL, domain)))
+          continue;
+        domain = in->in_domain;
+        if (idnode_perm(in, perm, msg)) {
+          err = EPERM;
+          continue;
+        }
+        count++;
+        idnode_update(in, msg);
+        idnode_perm_unset(in);
+      }
+      if (count)
+        err = 0;
+
+    } else {
+
+      if (!(in = idnode_find(uuid, NULL, NULL)))
+        goto exit;
+      if (idnode_perm(in, perm, msg)) {
+        err = EPERM;
+        goto exit;
+      }
+      idnode_update(in, msg);
+      idnode_perm_unset(in);
+      err = 0;
+
     }
-    idnode_update(in, msg);
-    idnode_perm_unset(in);
-    err = 0;
 
   /* Multiple */
   } else {
-    const idnodes_rb_t *domain = NULL;
+
     HTSMSG_FOREACH(f, msg) {
       if (!(conf = htsmsg_field_get_map(f)))
         continue;
@@ -419,6 +446,7 @@ api_idnode_save
     }
     if (count)
       err = 0;
+
   }
 
   // TODO: return updated UUIDs?
index d44387cdc027eef6396afdf4ae6e97bc109d8e00..1799a50edb3331c8cce83fa46a0778c45ed7ad89 100644 (file)
@@ -764,13 +764,40 @@ tvheadend.idnode_editor_form = function(d, meta, panel, conf)
     var rf = [];
     var df = [];
     var groups = null;
+    var width = 0;
 
     /* Fields */
     for (var i = 0; i < d.length; i++) {
         var p = d[i];
+        if (conf.uuids && p.rdonly)
+            continue;
         var f = tvheadend.idnode_editor_field(p, conf);
         if (!f)
             continue;
+        if (conf.uuids) {
+            var label = f.fieldLabel;
+            f.fieldLabel = null;
+            var w = 15 + 10 + conf.labelWidth + 10 +
+                    (f.initialConfig.width ? f.initialConfig.width : 100) + 10;
+            if (w > width)
+                width = w;
+            f = new Ext.form.CompositeField({
+                items: [
+                    new Ext.ux.form.XCheckbox({
+                        width: 15,
+                        height: 12,
+                        name: '_x_' + f.name
+                    }),
+                    {
+                        xtype: 'displayfield',
+                        width: conf.labelWidth,
+                        height: 12,
+                        value: label
+                    },
+                    f
+                ]
+            });
+        }
         if (p.group && meta.groups) {
             if (!groups)
                 groups = {};
@@ -868,6 +895,20 @@ tvheadend.idnode_editor_form = function(d, meta, panel, conf)
             panel.add(newFieldSet({ title: _("Read-only Info"), items: rf, collapsed: 'true'}));
     }
     panel.doLayout();
+    if (width)
+        panel.fixedWidth = width + 50;
+    if (conf.uuids) {
+        panel.getForm().getFieldValues = function(dirtyOnly) {
+            o = {};
+            this.items.each(function(f) {
+                var cbox = f.items.itemAt(0);
+                var field = f.items.itemAt(2);
+                if (cbox.getValue())
+                    o[field.getName()] = field.getValue();
+            });
+            return o;
+        }
+    }
 };
 
 /*
@@ -885,7 +926,7 @@ tvheadend.idnode_editor = function(item, conf)
             iconCls: 'save',
             handler: function() {
                 var node = panel.getForm().getFieldValues();
-                node.uuid = item.uuid;
+                node.uuid = conf.uuids ? conf.uuids : item.uuid;
                 tvheadend.Ajax({
                     url: 'api/idnode/save',
                     params: {
@@ -916,7 +957,7 @@ tvheadend.idnode_editor = function(item, conf)
         border: conf.inTabPanel ? false : true,
         bodyStyle: 'padding: 5px',
         labelAlign: 'left',
-        labelWidth: conf.labelWidth || 200,
+        labelWidth: conf.uuids ? 1 : (conf.labelWidth || 200),
         autoWidth: conf.noautoWidth ? false : true,
         autoHeight: !conf.fixedHeight,
         width: conf.nowidth ? null : (conf.width || 600),
@@ -926,9 +967,12 @@ tvheadend.idnode_editor = function(item, conf)
         buttons: buttons
     });
 
-    tvheadend.idnode_editor_form(item.props || item.params, item.meta, panel,
-                                 { showpwd: conf.showpwd });
-
+    var c = {
+        showpwd: conf.showpwd,
+        uuids: conf.uuids,
+        labelWidth: conf.labelWidth || 200
+    };
+    tvheadend.idnode_editor_form(item.props || item.params, item.meta, panel, c);
     return panel;
 };
 
@@ -1192,7 +1236,7 @@ tvheadend.idnode_grid = function(panel, conf)
                 abuttons.down.setDisabled(count === 0);
             }
             if (abuttons.edit)
-                abuttons.edit.setDisabled(count !== 1);
+                abuttons.edit.setDisabled(count === 0);
             if (conf.selected)
                 conf.selected(s, abuttons);
         });
@@ -1347,9 +1391,9 @@ tvheadend.idnode_grid = function(panel, conf)
                 text: _('Edit'),
                 disabled: true,
                 handler: function() {
-                    var r = select.getSelected();
-                    if (r) {
-                        if (conf.edittree) {
+                    if (conf.edittree) {
+                        var r = select.getSelected();
+                        if (r) {
                             var p = tvheadend.idnode_tree({
                                 url: 'api/idnode/tree',
                                 params: {
@@ -1367,11 +1411,17 @@ tvheadend.idnode_grid = function(panel, conf)
                                 items: p
                             });
                             w.show();
-                        } else {
+                        }
+                    } else {
+                        var r = select.getSelections();
+                        if (r && r.length > 0) {
+                            var uuids = [];
+                            for (var i = 0; i < r.length; i++)
+                                uuids.push(r[i].id);
                             var params = {};
                             if (conf.edit && conf.edit.params)
-                              params = conf.edit.params;
-                            params['uuid'] = r.id;
+                                params = conf.edit.params;
+                            params['uuid'] = r[0].id;
                             params['meta'] = 1;
                             tvheadend.Ajax({
                                 url: 'api/idnode/load',
@@ -1380,16 +1430,26 @@ tvheadend.idnode_grid = function(panel, conf)
                                     d = json_decode(d);
                                     var w = null;
                                     var c = {win: w};
+                                    if (uuids.length > 1) {
+                                        var title = String.format(_('Edit {0} ({1} entries)'),
+                                                                  conf.titleS, uuids.length);
+                                        c.uuids = uuids;
+                                    } else {
+                                        var title = String.format(_('Edit {0}'), conf.titleS);
+                                    }
                                     var p = tvheadend.idnode_editor(d[0], c);
+                                    var width = p.fixedWidth;
                                     w = new Ext.Window({
-                                        title: String.format(_('Edit {0}'), conf.titleS),
+                                        title: title,
                                         iconCls: 'edit',
                                         layout: 'fit',
-                                        autoWidth: true,
+                                        autoWidth: width ? false : true,
                                         autoHeight: true,
                                         plain: true,
                                         items: p
                                     });
+                                    if (width)
+                                        w.setWidth(width);
                                     c.win = w;
                                     w.show();
                                 }