]> git.proxmox.com Git - pmg-gui.git/blame - js/RuleInfo.js
rules: use tree panel instead of grouping feature of the grid
[pmg-gui.git] / js / RuleInfo.js
CommitLineData
ad834b6f 1Ext.define('PMG.RuleInfo', {
c3339ea1
DC
2 extend: 'Ext.panel.Panel',
3 xtype: 'pmgRuleInfo',
ad834b6f 4
c3339ea1
DC
5 controller: {
6 xclass: 'Ext.app.ViewController',
ad834b6f 7
c3339ea1
DC
8 setBaseUrl: function(baseurl) {
9 var me = this;
10 me.getViewModel().set('baseurl', baseurl);
11 me.reload();
12 },
ad834b6f 13
c3339ea1
DC
14 reload: function() {
15 var me = this;
16 var viewmodel = me.getViewModel();
17 var baseurl = viewmodel.get('baseurl');
ad834b6f 18
c3339ea1
DC
19 if (!baseurl) {
20 me.setRuleInfo(undefined);
21 return;
22 }
ad834b6f 23
c3339ea1
DC
24 Proxmox.Utils.API2Request({
25 url: baseurl + "/config",
26 method: 'GET',
27 success: function(response, opts) {
28 me.setRuleInfo(response.result.data);
29 },
c87d46fb 30 failure: function(response, opts) {
c3339ea1 31 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
c87d46fb 32 },
c3339ea1
DC
33 });
34 },
ad834b6f 35
c3339ea1
DC
36 removeObjectGroup: function(rec) {
37 var me = this;
38 Ext.Msg.confirm(
39 gettext('Confirm'),
40 Ext.String.format(
41 gettext('Are you sure you want to remove entry {0}'),
42 "'" + rec.data.name + "'"),
43 function(button) {
44 if (button === 'yes') {
45 Proxmox.Utils.API2Request({
46 url: me.getViewModel().get('baseurl') + '/' + rec.data.oclass + '/'+ rec.data.typeid,
47 method: 'DELETE',
48 waitMsgTarget: me.getView(),
49 callback: function() {
50 me.reload();
51 },
c87d46fb 52 failure: function(response, opts) {
c3339ea1 53 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
c87d46fb 54 },
c3339ea1
DC
55 });
56 }
c87d46fb 57 },
c3339ea1
DC
58 );
59 },
ad834b6f 60
c3339ea1
DC
61 addObjectGroup: function(type, record) {
62 var me = this;
63 var baseurl = me.getViewModel().get('baseurl');
64 var url = baseurl + '/' + type;
c87d46fb 65 var id = type === 'action'?record.data.ogroup:record.data.id;
c3339ea1
DC
66 Proxmox.Utils.API2Request({
67 url: url,
68 params: { ogroup: id },
69 method: 'POST',
70 waitMsgTarget: me.getView(),
71 callback: function() {
72 me.reload();
73 },
c87d46fb 74 failure: function(response, opts) {
c3339ea1 75 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
c87d46fb 76 },
c3339ea1
DC
77 });
78 },
ad834b6f 79
c3339ea1
DC
80 setRuleInfo: function(ruledata) {
81 var me = this;
ad834b6f 82
c3339ea1 83 var viewmodel = me.getViewModel();
ad834b6f 84
c3339ea1 85 if (ruledata === undefined) {
c3339ea1
DC
86 viewmodel.set('selectedRule', null);
87 viewmodel.get('objects').setData([]);
c3339ea1 88 } else {
c3339ea1 89 viewmodel.set('selectedRule', ruledata);
ad834b6f 90
60875e2d
DC
91 let data = {
92 leaf: false,
93 expanded: true,
94 children: [],
95 };
c3339ea1 96 Ext.Array.each(['from', 'to', 'when', 'what', 'action'], function(oc) {
c3339ea1
DC
97 var store = viewmodel.get(oc + 'objects');
98 if (ruledata[oc] === undefined || store === undefined) { return; }
ad834b6f 99
c3339ea1
DC
100 // we build a filter for the objects,
101 // which are already added to the rule,
102 // so what we only show the ones,
103 // which are still available
ad834b6f 104
c3339ea1
DC
105 var ids = Ext.Array.pluck(ruledata[oc], 'id');
106 // for the actions, we have a different id field
c87d46fb 107 var idField = oc === 'action'?'ogroup':'id';
c3339ea1
DC
108 store.clearFilter();
109 store.addFilter({
c87d46fb 110 filterFn: function(record) {
c3339ea1
DC
111 // FIXME
112 // actions have the ogroup as a string
113 // -> parseInt
c87d46fb
TL
114 return ids.indexOf(parseInt(record.data[idField], 10)) === -1;
115 },
c3339ea1
DC
116 });
117 store.load();
60875e2d
DC
118
119 let group = {
120 name: oc,
121 oclass: oc,
122 type: true,
123 leaf: false,
124 expanded: true,
125 expandable: false,
126 children: [],
127 };
c3339ea1 128 Ext.Array.each(ruledata[oc], function(og) {
60875e2d 129 group.children.push({ oclass: oc, name: og.name, typeid: og.id, leaf: true });
c3339ea1 130 });
ad834b6f 131
60875e2d
DC
132 if (group.children.length) {
133 data.children.push(group);
134 }
135 });
136 viewmodel.get('objects').setRoot(data);
c3339ea1
DC
137 }
138 },
ad834b6f 139
c3339ea1
DC
140 removeIconClick: function(gridView, rowindex, colindex, button, event, record) {
141 var me = this;
142 me.removeObjectGroup(record);
143 },
144
145 removeDrop: function(gridView, data, overModel) {
146 var me = this;
147 var record = data.records[0]; // only one
148 me.removeObjectGroup(record);
149 return true;
150 },
ad834b6f 151
c3339ea1
DC
152 addIconClick: function(gridView, rowindex, colindex, button, event, record) {
153 var me = this;
154 me.addObjectGroup(gridView.panel.type, record);
155 return true;
156 },
ad834b6f 157
c3339ea1
DC
158 addDrop: function(gridView, data, overModel) {
159 var me = this;
160 var record = data.records[0]; // only one
161 me.addObjectGroup(data.view.panel.type, record);
162 return true;
163 },
ad834b6f 164
c3339ea1 165 control: {
60875e2d 166 'treepanel[reference=usedobjects]': {
c87d46fb 167 drop: 'addDrop',
ad834b6f 168 },
c3339ea1 169 'tabpanel[reference=availobjects] > grid': {
c87d46fb
TL
170 drop: 'removeDrop',
171 },
172 },
c3339ea1 173 },
ad834b6f 174
c3339ea1
DC
175 viewModel: {
176 data: {
c87d46fb 177 baseurl: '',
c3339ea1 178 },
ad834b6f 179
c3339ea1
DC
180 stores: {
181 objects: {
60875e2d 182 type: 'tree',
c3339ea1
DC
183 fields: ['oclass', 'name', 'typeid'],
184 groupField: 'oclass',
c87d46fb 185 sorters: 'name',
ad834b6f 186 },
ad834b6f 187
c3339ea1
DC
188 actionobjects: {
189 model: 'pmg-action-list',
190 proxy: {
191 type: 'proxmox',
c87d46fb 192 url: "/api2/json/config/ruledb/action/objects",
f71626c2 193 },
c87d46fb 194 sorters: 'name',
c3339ea1
DC
195 },
196 fromobjects: {
197 model: 'pmg-object-group',
198 proxy: {
199 type: 'proxmox',
c87d46fb 200 url: "/api2/json/config/ruledb/who",
c3339ea1 201 },
c87d46fb 202 sorters: 'name',
c3339ea1
DC
203 },
204 toobjects: {
205 model: 'pmg-object-group',
206 proxy: {
207 type: 'proxmox',
c87d46fb 208 url: "/api2/json/config/ruledb/who",
c3339ea1 209 },
c87d46fb 210 sorters: 'name',
c3339ea1
DC
211 },
212 whatobjects: {
213 model: 'pmg-object-group',
214 proxy: {
215 type: 'proxmox',
c87d46fb 216 url: "/api2/json/config/ruledb/what",
c3339ea1 217 },
c87d46fb 218 sorters: 'name',
c3339ea1
DC
219 },
220 whenobjects: {
221 model: 'pmg-object-group',
222 proxy: {
223 type: 'proxmox',
c87d46fb 224 url: "/api2/json/config/ruledb/when",
c3339ea1 225 },
c87d46fb
TL
226 sorters: 'name',
227 },
228 },
c3339ea1
DC
229 },
230
231
232 defaults: {
c87d46fb 233 padding: '5 10 5 10',
c3339ea1
DC
234 },
235
236 bodyPadding: '5 0 5 0',
237
238 layout: {
239 type: 'vbox',
c87d46fb 240 align: 'stretch',
c3339ea1
DC
241 },
242
243 scrollable: true,
244
245 items: [
246 {
247 xtype: 'panel',
ea07c9aa 248 bodyPadding: '10 10 10 10',
c3339ea1 249 data: {
c87d46fb 250 name: '',
c3339ea1
DC
251 },
252 bind: {
253 data: {
df2a647a 254 name: '{selectedRule.name:htmlEncode}',
c3339ea1
DC
255 priority: '{selectedRule.priority}',
256 active: '{selectedRule.active}',
257 direction: '{selectedRule.direction}',
c87d46fb
TL
258 selected: '{selectedRule}',
259 },
c3339ea1
DC
260 },
261 tpl: [
262 '<tpl if="selected">',
263 '<b>{name}</b><br><br>',
64fb657f
DC
264 gettext('Priority') + ': {priority}<br>',
265 gettext('Direction') + ': {[PMG.Utils.format_rule_direction(values.direction)]}<br>',
266 gettext('Active') + ': {[Proxmox.Utils.format_boolean(values.active)]}<br>',
c3339ea1
DC
267 '<tpl else>',
268 gettext('Please select a rule.'),
c87d46fb
TL
269 '</tpl>',
270 ],
c3339ea1
DC
271 },
272 {
60875e2d 273 xtype: 'treepanel',
c3339ea1
DC
274 reference: 'usedobjects',
275 hidden: true,
276 emptyText: gettext('No Objects'),
f71626c2 277
c3339ea1 278 title: gettext('Used Objects'),
60875e2d
DC
279 rootVisible: false,
280 useArrows: true,
281 rowLines: true,
282 userCls: 'pmx-rule-tree',
ad834b6f 283
c3339ea1 284 viewConfig: {
60875e2d 285 getRowClass: record => record.data.type ? 'pmx-type-row' : '',
c3339ea1
DC
286 plugins: {
287 ptype: 'gridviewdragdrop',
288 copy: true,
289 dragGroup: 'usedobjects',
290 dropGroup: 'unusedobjects',
291
292 // do not show default grid dragdrop behaviour
293 dropZone: {
294 indicatorHtml: '',
295 indicatorCls: '',
c87d46fb
TL
296 handleNodeDrop: Ext.emptyFn,
297 },
298 },
c3339ea1
DC
299 },
300
301 columns: [
f71626c2 302 {
c3339ea1
DC
303 header: gettext('Name'),
304 dataIndex: 'name',
60875e2d
DC
305 xtype: 'treecolumn',
306 renderer: PMG.Utils.format_oclass,
307 sorter: function(a, b) {
308 if (a.data.type && b.data.type) {
309 return a.data.oclass.localeCompare(b.data.oclass);
310 }
311 return a.data.text.localeCompare(b.data.text);
312 },
c87d46fb 313 flex: 1,
f71626c2
DM
314 },
315 {
1f639768 316 text: '',
c3339ea1 317 xtype: 'actioncolumn',
1f639768
DC
318 align: 'center',
319 width: 40,
c3339ea1
DC
320 items: [
321 {
c3339ea1 322 tooltip: gettext('Remove'),
60875e2d
DC
323 isActionDisabled: (v, rI, cI, i, rec) => rec.data.type,
324 getClass: (v, mD, { data }) => data.type ? 'pmx-hidden' : 'fa fa-fw fa-minus-circle',
c87d46fb
TL
325 handler: 'removeIconClick',
326 },
327 ],
328 },
c3339ea1
DC
329 ],
330
331 bind: {
332 store: '{objects}',
c87d46fb
TL
333 hidden: '{!selectedRule}',
334 },
c3339ea1
DC
335 },
336 {
337 xtype: 'tabpanel',
338 title: gettext('Available Objects'),
339 reference: 'availobjects',
340 hidden: true,
341 bind: {
c87d46fb 342 hidden: '{!selectedRule}',
c3339ea1
DC
343 },
344 defaults: {
345 xtype: 'grid',
346 emptyText: gettext('No Objects'),
347 viewConfig: {
348 plugins: {
349 ptype: 'gridviewdragdrop',
350 dragGroup: 'unusedobjects',
351 dropGroup: 'usedobjects',
352
353 // do not show default grid dragdrop behaviour
354 dropZone: {
355 indicatorHtml: '',
356 indicatorCls: '',
c87d46fb
TL
357 handleNodeDrop: Ext.emptyFn,
358 },
359 },
f71626c2 360 },
c3339ea1
DC
361 columns: [
362 {
363 header: gettext('Name'),
364 dataIndex: 'name',
c87d46fb 365 flex: 1,
c3339ea1
DC
366 },
367 {
1f639768 368 text: '',
c3339ea1 369 xtype: 'actioncolumn',
1f639768
DC
370 align: 'center',
371 width: 40,
c3339ea1
DC
372 items: [
373 {
2b97521b 374 iconCls: 'fa fa-fw fa-plus-circle',
c3339ea1 375 tooltip: gettext('Add'),
c87d46fb
TL
376 handler: 'addIconClick',
377 },
378 ],
379 },
380 ],
c3339ea1
DC
381 },
382 items: [
383 {
384 title: gettext('Action'),
385 bind: {
c87d46fb 386 store: '{actionobjects}',
c3339ea1
DC
387 },
388 type: 'action',
c87d46fb 389 iconCls: 'fa fa-flag',
ad834b6f 390 },
39700611 391 {
c3339ea1
DC
392 title: gettext('From'),
393 iconCls: 'fa fa-user-circle',
394 type: 'from',
395 bind: {
c87d46fb
TL
396 store: '{fromobjects}',
397 },
39700611 398 },
ad834b6f 399 {
c3339ea1
DC
400 title: gettext('To'),
401 iconCls: 'fa fa-user-circle',
402 type: 'to',
403 bind: {
c87d46fb
TL
404 store: '{toobjects}',
405 },
c3339ea1
DC
406 },
407 {
408 title: gettext('What'),
409 iconCls: 'fa fa-cube',
410 type: 'what',
411 bind: {
c87d46fb
TL
412 store: '{whatobjects}',
413 },
c3339ea1
DC
414 },
415 {
416 title: gettext('When'),
417 iconCls: 'fa fa-clock-o',
418 type: 'when',
419 bind: {
c87d46fb
TL
420 store: '{whenobjects}',
421 },
422 },
423 ],
424 },
425 ],
ad834b6f 426});