From: Jaroslav Kysela Date: Thu, 8 Oct 2015 13:17:36 +0000 (+0200) Subject: WEBUI/API: add multi-row (foreach) editor, fixes #3075 X-Git-Tag: v4.2.1~1964 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=15bd98215c97649f39e58746875bca1dec5a1794;p=thirdparty%2Ftvheadend.git WEBUI/API: add multi-row (foreach) editor, fixes #3075 --- diff --git a/src/api/api_idnode.c b/src/api/api_idnode.c index 54b7b9141..0e8f88f55 100644 --- a/src/api/api_idnode.c +++ b/src/api/api_idnode.c @@ -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? diff --git a/src/webui/static/app/idnode.js b/src/webui/static/app/idnode.js index d44387cdc..1799a50ed 100644 --- a/src/webui/static/app/idnode.js +++ b/src/webui/static/app/idnode.js @@ -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(); }