]> git.proxmox.com Git - pmg-gui.git/blame_incremental - js/ObjectGroup.js
spam detector: custom rules: consitent add/edit/remove button & modernization
[pmg-gui.git] / js / ObjectGroup.js
... / ...
CommitLineData
1Ext.define('PMG.ObjectGroup', {
2 extend: 'Ext.grid.GridPanel',
3 alias: 'widget.pmgObjectGroup',
4
5 baseurl: undefined,
6
7 otype_list: [],
8
9 hideGroupInfo: false,
10 showDirection: false, // only important for SMTP Whitelist
11
12 ogdata: undefined,
13 objectClass: undefined,
14
15 emptyText: gettext('Please select an object.'),
16
17 setBaseUrl: function(baseurl) {
18 let me = this;
19
20 me.baseurl = baseurl;
21
22 if (me.baseurl === undefined) {
23 me.store.proxy.setUrl(undefined);
24 me.store.setData([]);
25 me.setButtonState(me.store, [], false);
26 } else {
27 let url = '/api2/json' + me.baseurl + '/objects';
28 me.store.proxy.setUrl(url);
29 me.store.load();
30 }
31 },
32
33 setObjectInfo: function(ogdata) {
34 let me = this;
35
36 let mode = ogdata?.invert ? 'not' : '';
37 mode += ogdata?.and ? 'all' : 'any';
38
39 me.ogdata = ogdata;
40
41 if (me.ogdata === undefined) {
42 me.down('#oginfo').update(me.emptyText);
43 me.down('#separator').setHidden(true);
44 me.down('#modeBox').setHidden(true);
45 me.down('#whatWarning').setHidden(true);
46 } else {
47 let html = '<b style="font-weight: bold;">' + Ext.String.htmlEncode(me.ogdata.name) + '</b>';
48 html += "<br><br>";
49 html += Ext.String.htmlEncode(Ext.String.trim(me.ogdata.info));
50
51 me.down('#oginfo').update(html);
52 me.down('#ogdata').setHidden(false);
53 me.down('#separator').setHidden(false);
54 let modeSelector = me.down('#modeSelector');
55 modeSelector.suspendEvents();
56 me.down('#modeSelector').setValue(mode);
57 modeSelector.resumeEvents();
58 me.down('#modeBox').setHidden(false);
59 me.down('#whatWarning').setHidden(me.objectClass !== 'what' || mode === 'any');
60 }
61 },
62
63 setButtonState: function(store, records, success) {
64 let me = this;
65 if (!success || !me.baseurl) {
66 me.down('#addMenuButton').setDisabled(true);
67 return;
68 }
69 me.down('#addMenuButton').setDisabled(false);
70 },
71
72 initComponent: function() {
73 let me = this;
74
75 me.store = new Ext.data.Store({
76 model: 'pmg-object-list',
77 proxy: {
78 type: 'proxmox',
79 },
80 sorters: [
81 {
82 property: 'receivertest',
83 },
84 {
85 property: 'otype',
86 direction: 'ASC',
87 },
88 ],
89 });
90
91 me.columns = [{
92 header: gettext('Type'),
93 dataIndex: 'otype',
94 renderer: PMG.Utils.format_otype,
95 width: 200,
96 }];
97
98 if (me.showDirection) {
99 me.columns.push({
100 header: gettext('Direction'),
101 dataIndex: 'receivertest',
102 renderer: function(value) {
103 return value ? PMG.Utils.receiverText : PMG.Utils.senderText;
104 },
105 });
106 }
107
108 me.columns.push({
109 header: gettext('Value'),
110 dataIndex: 'descr',
111 renderer: Ext.String.htmlEncode,
112 flex: 1,
113 });
114
115 let reload = function() {
116 me.store.load();
117 };
118
119 me.selModel = Ext.create('Ext.selection.RowModel', {});
120
121 let remove_btn = Ext.createWidget('proxmoxStdRemoveButton', {
122 selModel: me.selModel,
123 getUrl: function(rec) {
124 return me.baseurl + '/objects/' + rec.data.id;
125 },
126 callback: reload,
127 getRecordName: function(rec) {
128 return PMG.Utils.format_otype(rec.data.otype) +
129 ': ' + rec.data.descr;
130 },
131 waitMsgTarget: me,
132 });
133
134 let full_subject = function(subject, receivertest) {
135 if (me.showDirection) {
136 let direction = receivertest
137 ? PMG.Utils.receiverText : PMG.Utils.senderText;
138
139 return subject + ' (' + direction + ')';
140 } else {
141 return subject;
142 }
143 };
144
145 let run_editor = function() {
146 let rec = me.selModel.getSelection()[0];
147 if (!rec) {
148 return;
149 }
150
151 let editor = PMG.Utils.object_editors[rec.data.otype];
152 if (!editor || editor.uneditable) {
153 return;
154 }
155
156 let config = Ext.apply({ method: 'PUT' }, editor);
157 config.subject = full_subject(editor.subject, rec.data.receivertest);
158 config.url = me.baseurl + '/' + editor.subdir + '/' + rec.data.id;
159
160 let win = Ext.createWidget(config);
161
162 win.load();
163 win.on('destroy', reload);
164 win.show();
165 };
166
167 let menu_items = [];
168
169 Ext.Array.each(me.otype_list, function(otype) {
170 let editor = PMG.Utils.object_editors[otype];
171
172 let config = Ext.apply({ method: 'POST' }, editor);
173 config.subject = full_subject(editor.subject, editor.receivertest);
174
175 menu_items.push({
176 text: config.subject,
177 iconCls: config.iconCls || 'fa fa-question-circle',
178 handler: function() {
179 if (me.baseurl === undefined) {
180 return;
181 }
182 config.url = me.baseurl + '/' + editor.subdir;
183 let win = Ext.create(config);
184 win.on('destroy', reload);
185 win.show();
186 },
187 });
188 });
189
190 me.dockedItems = [];
191
192 me.dockedItems.push({
193 xtype: 'toolbar',
194 dock: 'top',
195 items: [
196 {
197 text: gettext('Add'),
198 disabled: true,
199 itemId: 'addMenuButton',
200 menu: {
201 items: menu_items,
202 },
203 },
204 '-',
205 {
206 xtype: 'proxmoxButton',
207 text: gettext('Edit'),
208 disabled: true,
209 selModel: me.selModel,
210 enableFn: function(rec) {
211 let editor = PMG.Utils.object_editors[rec.data.otype];
212 return editor && !editor.uneditable;
213 },
214 handler: run_editor,
215 },
216 remove_btn,
217 '->',
218 {
219 xtype: 'pmgFilterField',
220 filteredFields: [
221 {
222 name: 'otype',
223 renderer: (otype) => PMG.Utils.object_editors[otype].subject,
224 },
225 'descr',
226 ],
227 },
228 ],
229 });
230
231 me.dockedItems.push({
232 dock: 'top',
233 border: 1,
234 layout: {
235 type: 'hbox',
236 align: 'stretch',
237 },
238 hidden: !!me.hideGroupInfo,
239 itemId: 'ogdata',
240 xtype: 'toolbar',
241 items: [
242 {
243 xtype: 'container',
244 itemId: 'modeBox',
245 hidden: true,
246 width: 220,
247 padding: 10,
248 layout: {
249 type: 'vbox',
250 align: 'stretch',
251 },
252 items: [
253 {
254 xtype: 'box',
255 html: `<b style="font-weight: bold;">${gettext("Match if")}</b>`,
256 },
257 {
258 xtype: 'pmgMatchModeSelector',
259 itemId: 'modeSelector',
260 padding: '10 0 0 0',
261 listeners: {
262 change: function(_field, value) {
263 let invert = value.startsWith('not') ? 1 : 0;
264 let and = value.endsWith('all') ? 1 : 0;
265
266 Proxmox.Utils.API2Request({
267 url: `${me.baseurl}/config`,
268 method: 'PUT',
269 params: {
270 and,
271 invert,
272 },
273 success: () => {
274 me.fireEvent('modeUpdate', me, !!and, !!invert);
275 me.down('#whatWarning')
276 .setHidden(me.objectClass !== 'what' || value === 'any');
277 },
278 });
279 },
280 },
281 },
282 ],
283 },
284 {
285 xtype: 'tbseparator',
286 itemId: 'separator',
287 hidden: true,
288 },
289 {
290 xtype: 'component',
291 flex: 1,
292 itemId: 'oginfo',
293 style: { 'white-space': 'pre' },
294 padding: 10,
295 html: me.emptyText,
296 listeners: {
297 dblclick: {
298 fn: function(e, t) {
299 if (me.ogdata === undefined) { return; }
300 me.fireEvent('dblclickOGInfo', me, e, t, me.ogdata);
301 },
302 element: 'el',
303 scope: this,
304 },
305 },
306 },
307 ],
308 });
309
310 me.dockedItems.push({
311 dock: 'top',
312 border: 1,
313 hidden: true,
314 itemId: 'whatWarning',
315 bodyPadding: 5,
316 items: {
317 xtype: 'displayfield',
318 margin: 0,
319 value: gettext("Caution: 'What Objects' match each mail part separately, so be careful with any option besides 'Any matches'."),
320 userCls: 'pmx-hint',
321 },
322 });
323
324 Proxmox.Utils.monStoreErrors(me, me.store, true);
325
326 Ext.apply(me, {
327 run_editor: run_editor,
328 listeners: {
329 itemdblclick: run_editor,
330 activate: reload,
331 },
332 });
333
334 me.callParent();
335
336 me.mon(me.store, 'load', me.setButtonState, me);
337
338 if (me.baseurl) {
339 me.setBaseUrl(me.baseurl); // configure store, load()
340 }
341 },
342});