[pve-devel] [PATCH 16/18] rewrite ruleinfo
Dominik Csapak
d.csapak at proxmox.com
Tue Apr 4 13:48:56 CEST 2017
complete rewrite of the ruleinfo sidebar
* uses mvvm system
* show tabpanel with all unused objects, each category in a tab
* group the used objects by type
* allow for drag/drop or the actionbuttons for adding/removing
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
js/RuleInfo.js | 608 +++++++++++++++++++++++++++++++++++----------------------
1 file changed, 379 insertions(+), 229 deletions(-)
diff --git a/js/RuleInfo.js b/js/RuleInfo.js
index 8d3b388..6989fe0 100644
--- a/js/RuleInfo.js
+++ b/js/RuleInfo.js
@@ -1,120 +1,73 @@
Ext.define('PMG.RuleInfo', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pmgRuleInfo',
-
- baseurl: undefined,
-
- ruledata: undefined,
-
- emptyText: gettext('Please select a rule.'),
-
- setBaseUrl: function(baseurl) {
- var me = this;
-
- me.baseurl = baseurl;
-
- me.reload();
- },
-
- reload: function() {
- var me = this;
-
- if (!me.baseurl) {
- me.setRuleInfo(undefined);
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: me.baseurl + "/config",
- method: 'GET',
- waitMsgTarget: me,
- success: function(response, opts) {
- me.setRuleInfo(response.result.data);
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ extend: 'Ext.panel.Panel',
+ xtype: 'pmgRuleInfo',
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ setBaseUrl: function(baseurl) {
+ var me = this;
+ me.getViewModel().set('baseurl', baseurl);
+ me.reload();
+ },
+
+ reload: function() {
+ var me = this;
+ var viewmodel = me.getViewModel();
+ var baseurl = viewmodel.get('baseurl');
+
+ if (!baseurl) {
+ me.setRuleInfo(undefined);
+ return;
}
- });
- },
- setRuleInfo: function(ruledata) {
- var me = this;
-
- me.ruledata = ruledata;
-
- me.down('#addFromButton').setDisabled(me.ruledata === undefined);
- me.down('#addToButton').setDisabled(me.ruledata === undefined);
- me.down('#addWhenButton').setDisabled(me.ruledata === undefined);
- me.down('#addWhatButton').setDisabled(me.ruledata === undefined);
- me.down('#addActionButton').setDisabled(me.ruledata === undefined);
-
- if (me.ruledata === undefined) {
-
- me.store.setData([]);
- me.down('#ruleinfo').update(me.emtpyText);
- me.down('#ruledata').setHidden(true);
-
- } else {
-
- var html = '<b>' + Ext.String.htmlEncode(me.ruledata.name) + '</b>';
- html += '<br><br>';
- html += 'Priority: ' + me.ruledata.priority + '<br>';
- html += 'Direction: ' + PMG.Utils.format_rule_direction(me.ruledata.direction) + '<br>';
- html += 'Active: ' + Proxmox.Utils.format_boolean(me.ruledata.active) + '<br>';
-
- var data = [];
- Ext.Array.each(['from', 'to', 'when', 'what', 'action'], function(oc) {
- var list = ruledata[oc];
- if (list === undefined) { return; }
- Ext.Array.each(list, function(og) {
- data.push({ oclass: oc, name: og.name, id: og.id });
- });
+ Proxmox.Utils.API2Request({
+ url: baseurl + "/config",
+ method: 'GET',
+ success: function(response, opts) {
+ me.setRuleInfo(response.result.data);
+ },
+ failure: function (response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ }
});
-
- me.store.setData(data);
-
- me.down('#ruleinfo').update(html);
- me.down('#ruledata').setHidden(false);
- }
- },
-
- initComponent : function() {
- var me = this;
-
- me.store = new Ext.data.Store({
- fields: [ 'oclass', 'name' ]
- });
-
- me.columns = [
- {
- header: gettext('Type'),
- dataIndex: 'oclass',
- },
- {
- header: gettext('name'),
- dataIndex: 'name',
- flex: 1
- }
- ];
-
- me.selModel = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.createWidget('proxmoxStdRemoveButton', {
- selModel: me.selModel,
- getUrl: function(rec) {
- return me.baseurl + '/' + rec.data.oclass + '/'+ rec.data.id;
- },
- callback: function() { me.reload(); },
- getRecordName: function(rec) { return rec.data.name; },
- waitMsgTarget: me
- });
-
- var add_object_group = function(url, ogroupId) {
+ },
+
+ removeObjectGroup: function(rec) {
+ var me = this;
+ Ext.Msg.confirm(
+ gettext('Confirm'),
+ Ext.String.format(
+ gettext('Are you sure you want to remove entry {0}'),
+ "'" + rec.data.name + "'"),
+ function(button) {
+ if (button === 'yes') {
+ Proxmox.Utils.API2Request({
+ url: me.getViewModel().get('baseurl') + '/' + rec.data.oclass + '/'+ rec.data.typeid,
+ method: 'DELETE',
+ waitMsgTarget: me.getView(),
+ callback: function() {
+ me.reload();
+ },
+ failure: function (response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ }
+ });
+ }
+ }
+ );
+ },
+
+ addObjectGroup: function(type, record) {
+ var me = this;
+ var baseurl = me.getViewModel().get('baseurl');
+ var url = baseurl + '/' + type;
+ var id = (type === 'action')?record.data.ogroup:record.data.id;
Proxmox.Utils.API2Request({
url: url,
- params: { ogroup: ogroupId },
+ params: { ogroup: id },
method: 'POST',
- waitMsgTarget: me,
+ waitMsgTarget: me.getView(),
callback: function() {
me.reload();
},
@@ -122,140 +75,337 @@ Ext.define('PMG.RuleInfo', {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
}
});
- };
+ },
- me.dockedItems = [];
+ setRuleInfo: function(ruledata) {
+ var me = this;
- me.dockedItems.push({
- xtype: 'toolbar',
- dock: 'top',
- items: [
- {
- text: gettext('From'),
- disabled: true,
- itemId: 'addFromButton',
- handler: function() {
- var win = Ext.create('PMG.ObjectGroupSelector', {
- rulegroup: 'from',
- listeners: {
- selectObjectGroup: function(view, rec) {
- win.destroy();
- add_object_group(me.baseurl + '/from', rec.data.id);
- }
- }
- });
- win.show();
+ var viewmodel = me.getViewModel();
+
+ if (ruledata === undefined) {
+
+ viewmodel.set('selectedRule', null);
+ viewmodel.get('objects').setData([]);
+
+ } else {
+
+ ruledata.name = Ext.String.htmlEncode(ruledata.name);
+ viewmodel.set('selectedRule', ruledata);
+
+ var data = [];
+ Ext.Array.each(['from', 'to', 'when', 'what', 'action'], function(oc) {
+
+ var store = viewmodel.get(oc + 'objects');
+ if (ruledata[oc] === undefined || store === undefined) { return; }
+
+ // we build a filter for the objects,
+ // which are already added to the rule,
+ // so what we only show the ones,
+ // which are still available
+
+ var ids = Ext.Array.pluck(ruledata[oc], 'id');
+ // for the actions, we have a different id field
+ var idField = (oc === 'action')?'ogroup':'id';
+ store.clearFilter();
+ store.addFilter({
+ filterFn:function(record){
+ // FIXME
+ // actions have the ogroup as a string
+ // -> parseInt
+ return (ids.indexOf(parseInt(record.data[idField])) === -1);
+ }
+ });
+ store.load();
+ Ext.Array.each(ruledata[oc], function(og) {
+ data.push({ oclass: oc, name: og.name, typeid: og.id });
+ });
+ });
+
+ viewmodel.get('objects').setData(data);
+ }
+ },
+
+ removeIconClick: function(gridView, rowindex, colindex, button, event, record) {
+ var me = this;
+ me.removeObjectGroup(record);
+ },
+
+ removeDrop: function(gridView, data, overModel) {
+ var me = this;
+ var record = data.records[0]; // only one
+ me.removeObjectGroup(record);
+ return true;
+ },
+
+ addIconClick: function(gridView, rowindex, colindex, button, event, record) {
+ var me = this;
+ me.addObjectGroup(gridView.panel.type, record);
+ return true;
+ },
+
+ addDrop: function(gridView, data, overModel) {
+ var me = this;
+ var record = data.records[0]; // only one
+ me.addObjectGroup(data.view.panel.type, record);
+ return true;
+ },
+
+ control: {
+ 'grid[reference=usedobjects]': {
+ drop: 'addDrop'
+ },
+ 'tabpanel[reference=availobjects] > grid': {
+ drop: 'removeDrop'
+ }
+ },
+ },
+
+ viewModel: {
+ data: {
+ baseurl: undefined,
+ },
+
+ stores: {
+ objects: {
+ fields: ['oclass', 'name', 'typeid'],
+ groupField: 'oclass',
+ sorters: 'name'
+ },
+
+ actionobjects: {
+ model: 'pmg-action-list',
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/config/ruledb/action/objects",
+ },
+ sorters: 'name'
+ },
+ fromobjects: {
+ model: 'pmg-object-group',
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/config/ruledb/who",
+ },
+ sorters: 'name'
+ },
+ toobjects: {
+ model: 'pmg-object-group',
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/config/ruledb/who",
+ },
+ sorters: 'name'
+ },
+ whatobjects: {
+ model: 'pmg-object-group',
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/config/ruledb/what",
+ },
+ sorters: 'name'
+ },
+ whenobjects: {
+ model: 'pmg-object-group',
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/config/ruledb/when",
+ },
+ sorters: 'name'
+ },
+ }
+ },
+
+
+ defaults: {
+ padding: '5 10 5 10',
+ },
+
+ bodyPadding: '5 0 5 0',
+
+ layout: {
+ type: 'vbox',
+ align: 'stretch'
+ },
+
+ scrollable: true,
+
+ items: [
+ {
+ xtype: 'panel',
+ bodyPadding: 10,
+ data: {
+ name: false,
+ },
+ bind: {
+ data: {
+ name: '{selectedRule.name}',
+ priority: '{selectedRule.priority}',
+ active: '{selectedRule.active}',
+ direction: '{selectedRule.direction}',
+ selected: '{selectedRule}'
+ }
+ },
+ tpl: [
+ '<tpl if="selected">',
+ '<b>{name}</b><br><br>',
+ 'Priority: {priority}<br>',
+ 'Direction: {[PMG.Utils.format_rule_direction(values.direction)]}<br>',
+ 'Active: {[Proxmox.Utils.format_boolean(values.active)]}<br>',
+ '<tpl else>',
+ gettext('Please select a rule.'),
+ '</tpl>'
+ ],
+ },
+ {
+ xtype: 'grid',
+ reference: 'usedobjects',
+ hidden: true,
+ emptyText: gettext('No Objects'),
+ features: [{
+ id: 'group',
+ ftype: 'grouping',
+ enableGroupingMenu: false,
+ collapsible: false,
+ groupHeaderTpl: [
+ '{[PMG.Utils.format_oclass(values.name)]}'
+ ]
+ }],
+
+ title: gettext('Used Objects'),
+
+ viewConfig: {
+ plugins: {
+ ptype: 'gridviewdragdrop',
+ copy: true,
+ dragGroup: 'usedobjects',
+ dropGroup: 'unusedobjects',
+
+ // do not show default grid dragdrop behaviour
+ dropZone: {
+ indicatorHtml: '',
+ indicatorCls: '',
+ handleNodeDrop: Ext.emptyFn
}
+ }
+ },
+
+ columns: [
+ {
+ header: gettext('Type'),
+ dataIndex: 'oclass',
+ hidden: true,
},
{
- text: gettext('To'),
- disabled: true,
- itemId: 'addToButton',
- handler: function() {
- var win = Ext.create('PMG.ObjectGroupSelector', {
- rulegroup: 'to',
- listeners: {
- selectObjectGroup: function(view, rec) {
- win.destroy();
- add_object_group(me.baseurl + '/to', rec.data.id);
- }
- }
- });
- win.show();
- }
+ header: gettext('Name'),
+ dataIndex: 'name',
+ flex: 1
},
{
- text: gettext('When'),
- disabled: true,
- itemId: 'addWhenButton',
- handler: function() {
- var win = Ext.create('PMG.ObjectGroupSelector', {
- rulegroup: 'when',
- listeners: {
- selectObjectGroup: function(view, rec) {
- win.destroy();
- add_object_group(me.baseurl + '/when', rec.data.id);
- }
- }
- });
- win.show();
+ header: gettext('Actions'),
+ xtype: 'actioncolumn',
+ width: 65,
+ items: [
+ {
+ iconCls: 'x-fa fa-fw fa-minus-circle',
+ tooltip: gettext('Remove'),
+ handler: 'removeIconClick'
+ }
+ ]
+ }
+ ],
+
+ bind: {
+ store: '{objects}',
+ hidden: '{!selectedRule}'
+ },
+ },
+ {
+ xtype: 'tabpanel',
+ title: gettext('Available Objects'),
+ reference: 'availobjects',
+ hidden: true,
+ bind: {
+ hidden: '{!selectedRule}'
+ },
+ defaults: {
+ xtype: 'grid',
+ emptyText: gettext('No Objects'),
+ viewConfig: {
+ plugins: {
+ ptype: 'gridviewdragdrop',
+ dragGroup: 'unusedobjects',
+ dropGroup: 'usedobjects',
+
+ // do not show default grid dragdrop behaviour
+ dropZone: {
+ indicatorHtml: '',
+ indicatorCls: '',
+ handleNodeDrop: Ext.emptyFn
+ }
}
},
- {
- text: gettext('What'),
- disabled: true,
- itemId: 'addWhatButton',
- handler: function() {
- var win = Ext.create('PMG.ObjectGroupSelector', {
- rulegroup: 'what',
- listeners: {
- selectObjectGroup: function(view, rec) {
- win.destroy();
- add_object_group(me.baseurl + '/what', rec.data.id);
- }
+ columns: [
+ {
+ header: gettext('Name'),
+ dataIndex: 'name',
+ flex: 1
+ },
+ {
+ header: gettext('Actions'),
+ width: 65,
+ xtype: 'actioncolumn',
+ items: [
+ {
+ iconCls: 'x-fa fa-fw fa-plus-circle',
+ tooltip: gettext('Add'),
+ handler: 'addIconClick'
}
- });
- win.show();
+ ]
}
+ ],
+ },
+ items: [
+ {
+ title: gettext('Action'),
+ bind: {
+ store: '{actionobjects}'
+ },
+ type: 'action',
+ iconCls: 'fa fa-flag',
},
{
- text: gettext('Action'),
- disabled: true,
- itemId: 'addActionButton',
- handler: function() {
- var win = Ext.create('PMG.ObjectGroupSelector', {
- rulegroup: 'action',
- listeners: {
- selectObjectGroup: function(view, rec) {
- win.destroy();
- add_object_group(me.baseurl + '/action', rec.data.ogroup);
- }
- }
- });
- win.show();
- }
+ title: gettext('From'),
+ iconCls: 'fa fa-user-circle',
+ type: 'from',
+ bind: {
+ store: '{fromobjects}'
+ },
},
- remove_btn
- ]
- });
-
- me.dockedItems.push({
- dock: 'top',
- border: 1,
- layout: 'anchor',
- itemId: 'ruledata',
- items: [
{
- xtype: 'component',
- anchor: '100%',
- itemId: 'ruleinfo',
- style: { 'white-space': 'pre' },
- padding: 10,
- html: me.emptyText,
- listeners: {
- dblclick: {
- fn: function(e, t) {
- if (me.ruledata === undefined) { return; }
- me.fireEvent('dblclickRuleInfo', me, e, t, me.ruledata);
- },
- element: 'el',
- scope: this,
- }
- }
- }
+ title: gettext('To'),
+ iconCls: 'fa fa-user-circle',
+ type: 'to',
+ bind: {
+ store: '{toobjects}'
+ },
+ },
+ {
+ title: gettext('What'),
+ iconCls: 'fa fa-cube',
+ type: 'what',
+ bind: {
+ store: '{whatobjects}'
+ },
+ },
+ {
+ title: gettext('When'),
+ iconCls: 'fa fa-clock-o',
+ type: 'when',
+ bind: {
+ store: '{whenobjects}'
+ },
+ },
]
- });
-
- Ext.apply(me, {
- listeners: {
- activate: function() { me.reload() }
- }
- });
-
- me.callParent();
-
- if (me.baseurl) {
- me.reload();
}
- }
+ ]
});
--
2.11.0
More information about the pve-devel
mailing list