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', + extend: 'Ext.panel.Panel', + xtype: 'pmgRuleInfo', - baseurl: undefined, + controller: { + xclass: 'Ext.app.ViewController', - ruledata: undefined, + setBaseUrl: function(baseurl) { + var me = this; + me.getViewModel().set('baseurl', baseurl); + me.reload(); + }, - emptyText: gettext('Please select a rule.'), + reload: function() { + var me = this; + var viewmodel = me.getViewModel(); + var baseurl = viewmodel.get('baseurl'); - 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); + 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 = '' + Ext.String.htmlEncode(me.ruledata.name) + ''; - html += '

'; - html += 'Priority: ' + me.ruledata.priority + '
'; - html += 'Direction: ' + PMG.Utils.format_rule_direction(me.ruledata.direction) + '
'; - html += 'Active: ' + Proxmox.Utils.format_boolean(me.ruledata.active) + '
'; - - 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); + 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); + } + }); + } + } + ); + }, - 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) { + 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(); - } - }, - { - 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(); - } - }, - { - 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(); - } - }, - { - 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); - } - } - }); - win.show(); - } - }, - { - 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(); - } - }, - remove_btn - ] - }); + var viewmodel = me.getViewModel(); - 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, + 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: [ + '', + '{name}

', + 'Priority: {priority}
', + 'Direction: {[PMG.Utils.format_rule_direction(values.direction)]}
', + 'Active: {[Proxmox.Utils.format_boolean(values.active)]}
', + '', + gettext('Please select a rule.'), + '' + ], + }, + { + 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, + }, + { + header: gettext('Name'), + dataIndex: 'name', + flex: 1 + }, + { + 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 + } + } + }, + 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' + } + ] + } + ], + }, + items: [ + { + title: gettext('Action'), + bind: { + store: '{actionobjects}' + }, + type: 'action', + iconCls: 'fa fa-flag', + }, + { + title: gettext('From'), + iconCls: 'fa fa-user-circle', + type: 'from', + bind: { + store: '{fromobjects}' + }, + }, + { + 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(); } - } + ] });