mirror of
https://git.proxmox.com/git/pmg-gui
synced 2025-08-04 06:35:02 +00:00
rewrite ruleinfo
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@proxmox.com>
This commit is contained in:
parent
d75b37b80b
commit
c3339ea165
614
js/RuleInfo.js
614
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 = '<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);
|
||||
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: [
|
||||
'<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,
|
||||
},
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user