]> git.proxmox.com Git - pmg-gui.git/blame - js/QuarantineList.js
Revert "fix tracking center with newer proxmox-widget-toolkit"
[pmg-gui.git] / js / QuarantineList.js
CommitLineData
75fcb6fd
DC
1Ext.define('PMG.QuarantineList', {
2 extend: 'Ext.grid.GridPanel',
3 xtype: 'pmgQuarantineList',
4
5 emptyText: gettext('No E-Mail address selected'),
6 viewConfig: {
c87d46fb 7 deferEmptyText: false,
75fcb6fd
DC
8 },
9
10 config: {
c03e51ed 11 quarantineType: 'spam',
c87d46fb 12 notFoundText: gettext('No data in database'),
75fcb6fd
DC
13 },
14
c70a57fb
DC
15 statics: {
16 from: 0,
c87d46fb 17 to: 0,
c70a57fb 18 },
75fcb6fd 19
9133f72f
DC
20 allowPositionSave: false,
21
75fcb6fd
DC
22 controller: {
23 xclass: 'Ext.app.ViewController',
24
25 init: function(view) {
28eb60c0 26 let me = this;
c03e51ed 27 let emailCombobox = me.lookupReference('email');
99bba12c 28 if (PMG.view === 'quarantineview') {
c03e51ed 29 view.autoLoadAll = false;
75fcb6fd 30 me.setEmptyText();
c03e51ed
DC
31 } else {
32 emailCombobox.setVisible(true);
33 emailCombobox.setDisabled(false);
34 emailCombobox.getStore().on('load', me.injectAllOption, me);
35 }
36
37
38 if (view.quarantineType) {
39 emailCombobox.getStore().getProxy().setExtraParams({
40 'quarantine-type': view.quarantineType,
41 });
75fcb6fd 42 }
75fcb6fd 43
28eb60c0
TL
44 let from;
45 if (PMG.QuarantineList.from !== 0) {
c70a57fb
DC
46 from = new Date(PMG.QuarantineList.from * 1000);
47 } else {
28eb60c0 48 from = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
c70a57fb
DC
49 }
50
28eb60c0
TL
51 let to;
52 if (PMG.QuarantineList.to !== 0) {
c70a57fb
DC
53 to = new Date(PMG.QuarantineList.to * 1000);
54 } else {
55 to = new Date();
56 }
57
75fcb6fd 58 // we to this to trigger the change event of those fields
c70a57fb
DC
59 me.lookupReference('from').setValue(from);
60 me.lookupReference('to').setValue(to);
75fcb6fd 61
2f8fe1a3 62 Proxmox.Utils.monStoreErrors(view.getView(), view.getStore());
207471c0
DC
63 me.load(function() {
64 if (view.cselect) {
65 view.setSelection(view.getStore().getById(view.cselect));
66 }
67 });
75fcb6fd 68 },
d19c2794 69 // ExtJS cannot dynamically change the emptyText on grids, so implement ourself
75fcb6fd 70 setEmptyText: function(emptyText) {
28eb60c0
TL
71 let me = this;
72 let view = me.getView();
73 let tableview = view.getView();
d19c2794 74 tableview.emptyText = `<div class="x-grid-empty">${emptyText || view.notFoundText}</div>`;
75fcb6fd
DC
75 },
76
207471c0 77 load: function(callback) {
28eb60c0 78 let me = this;
9133f72f 79 me.allowPositionSave = false;
28eb60c0
TL
80 let view = me.getView();
81 let store = view.getStore();
c03e51ed 82 if (view.quarantineType === 'spam' && PMG.view !== 'quarantineview') {
75fcb6fd 83 if (!me.lookupReference('email').getSelection()) {
d19c2794 84 return; // if the combobox has no selection we do not reload
75fcb6fd 85 }
ff0ee46d 86 me.setEmptyText();
75fcb6fd 87 }
0bd9ee22
TL
88 // deselect all first, else ExtJS does some funky O(n^3) comparissions as it tries
89 // to keep the selection, but we do not care for that on a new load anyway
90 view.getSelectionModel().deselectAll();
91
9b4247fb
TL
92 store.load(() => {
93 me.restoreSavedSelection();
5fb0f71e
DC
94 if (Ext.isFunction(callback)) {
95 callback();
96 }
9133f72f 97 me.allowPositionSave = true;
5fb0f71e 98 });
75fcb6fd
DC
99 },
100
9b4247fb
TL
101 restoreSavedSelection: function() {
102 let me = this;
103 let view = me.getView();
104 if (me.savedPosition !== undefined) {
105 let store = view.getStore();
106 if (store.getCount() - 1 < me.savedPosition) {
107 me.savedPosition = store.getCount() - 1;
108 }
109 view.setSelection(store.getAt(me.savedPosition));
110 } else {
111 view.setSelection();
112 }
113 },
114
75fcb6fd 115 setFrom: function(from) {
28eb60c0
TL
116 let view = this.getView();
117 let params = view.getStore().getProxy().getExtraParams();
75fcb6fd 118 params.starttime = from;
c70a57fb 119 PMG.QuarantineList.from = from;
28eb60c0 120 view.getStore().getProxy().setExtraParams(params);
75fcb6fd
DC
121 },
122
123 setTo: function(to) {
28eb60c0
TL
124 let end_of_to = to + 24*60*60; // we want the end of the day
125 let view = this.getView();
126 let params = view.getStore().getProxy().getExtraParams();
c70a57fb
DC
127 params.endtime = end_of_to;
128 PMG.QuarantineList.to = to; // we save the start of the day here
28eb60c0 129 view.getStore().getProxy().setExtraParams(params);
75fcb6fd
DC
130 },
131
132 setUser: function(user) {
28eb60c0
TL
133 let view = this.getView();
134 let params = view.getStore().getProxy().getExtraParams();
c03e51ed 135 if (!user) {
0bd9ee22
TL
136 delete params.pmail;
137 } else {
138 params.pmail = user;
139 }
28eb60c0
TL
140 view.getStore().getProxy().setExtraParams(params);
141 view.user = user;
75fcb6fd
DC
142 },
143
144 changeTime: function(field, value) {
28eb60c0 145 let me = this;
75fcb6fd 146
9133f72f
DC
147 me.allowPositionSave = false;
148 me.savedPosition = undefined;
149
75fcb6fd
DC
150 if (!value) {
151 return;
152 }
153
28eb60c0
TL
154 let val = value.getTime() / 1000;
155 let combobox = me.lookupReference('email');
156 let params = combobox.getStore().getProxy().getExtraParams();
75fcb6fd 157
28eb60c0
TL
158 let to = me.lookupReference('to');
159 let from = me.lookupReference('from');
75fcb6fd
DC
160
161 if (field.name === 'from') {
162 me.setFrom(val);
163 params.starttime = val;
164 to.setMinValue(value);
75fcb6fd 165 } else if (field.name === 'to') {
c70a57fb 166 me.setTo(val);
75fcb6fd
DC
167 params.endtime = val + 24*60*60;
168 from.setMaxValue(value);
169 } else {
170 return;
171 }
172
75fcb6fd 173 combobox.getStore().getProxy().setExtraParams(params);
61a8a658 174 combobox.getStore().load();
75fcb6fd
DC
175
176 me.load();
177 },
178
179 resetEmail: function() {
28eb60c0 180 let me = this;
c03e51ed 181 me.setUser(undefined);
75fcb6fd
DC
182 },
183
184 changeEmail: function(tb, value) {
28eb60c0 185 let me = this;
9133f72f
DC
186 me.savedPosition = undefined;
187 me.allowPositionSave = false;
0bd9ee22
TL
188 if (value === 'all') {
189 me.setUser(null);
190 } else {
191 me.setUser(value);
192 }
5b920c35 193 tb.triggers.clear.setVisible(value?.length > 0 && value !== 'all');
75fcb6fd
DC
194 me.load();
195 },
196
5fb0f71e 197 savePosition: function(grid, selected, eopts) {
9133f72f
DC
198 let me = this;
199 if (!me.allowPositionSave) {
200 return;
201 }
0e26e20a 202 if (selected.length <= 0) {
9133f72f 203 me.savedPosition = undefined;
5fb0f71e
DC
204 return;
205 }
206
28eb60c0
TL
207 let view = me.getView();
208 let id = view.getStore().indexOf(selected[0]);
5fb0f71e
DC
209
210 me.savedPosition = id;
211 },
212
42de6d46 213 doFilter: function(searchValue, store, sm) {
d3e6c6a1
TL
214 const selected = sm.getSelection();
215 const selectedRecordId = selected.length === 1 ? selected[0].id : null;
216 let clearSelectedMail = true;
217 let toDeselect = [];
218 store.filterBy(function(record) {
219 let match = false;
220
42de6d46 221 Ext.each(['subject', 'from'], property => {
d3e6c6a1
TL
222 if (record.data[property] === null) {
223 return;
224 }
225
226 let v = record.data[property].toString();
227 if (v !== undefined) {
228 v = v.toLowerCase();
229 if (v.includes(searchValue)) {
230 match = true;
231 if (record.id === selectedRecordId) {
232 clearSelectedMail = false;
233 }
234 }
235 }
236 });
237 if (!match && sm.isSelected(record)) {
238 toDeselect.push(record);
239 }
240 return match;
241 });
242 if (toDeselect.length > 0) {
0bd9ee22
TL
243 sm.deselect(toDeselect, true);
244 sm.maybeFireSelectionChange(true);
d3e6c6a1 245 }
42de6d46
TL
246 return selectedRecordId !== null && clearSelectedMail;
247 },
248
249 updateFilter: async function(field) {
250 let me = this;
251 let view = me.getView();
252 let store = view.getStore();
253 let sm = view.getSelectionModel();
254
255 let searchValue = field.getValue().toLowerCase();
256
257 // supress store event if not empty, let filterBy below trigger it to avoid glitches
258 store.clearFilter(searchValue.length > 0);
259 field.triggers.clear.setVisible(searchValue.length > 0);
260
261 if (searchValue.length === 0) {
262 me.setEmptyText();
263 return;
264 }
265 me.setEmptyText(gettext('No match found'));
266
267 let clearSelection = me.doFilter(searchValue, store, sm);
268
269 if (clearSelection) {
d3e6c6a1
TL
270 view.setSelection();
271 }
272 },
5fb0f71e 273
c03e51ed
DC
274 injectAllOption: function(store, records, successfull) {
275 let me = this;
276 let view = me.getView();
277 if (successfull && records.length > 1) {
278 store.insert(0, { mail: 'all' });
279 }
280 let emailCombobox = me.lookup('email');
281 if (!emailCombobox.getSelection() && view.quarantineType !== 'spam') {
282 emailCombobox.setSelection(store.getAt(0));
283 }
284 },
285
75fcb6fd 286 control: {
c87d46fb 287 '#': {
5fb0f71e 288 beforedestroy: 'resetEmail',
c87d46fb 289 selectionchange: 'savePosition',
75fcb6fd
DC
290 },
291 'combobox[reference=email]': {
61a8a658 292 change: 'changeEmail',
75fcb6fd
DC
293 },
294 datefield: {
295 change: {
c87d46fb
TL
296 fn: 'changeTime',
297 },
298 },
75fcb6fd 299
c87d46fb 300 },
75fcb6fd
DC
301 },
302
303 features: [
304 {
305 ftype: 'grouping',
c87d46fb
TL
306 groupHeaderTpl: '{columnName}: {name} ({children.length})',
307 },
75fcb6fd
DC
308 ],
309
310 tbar: {
311 layout: {
312 type: 'vbox',
c87d46fb 313 align: 'stretch',
75fcb6fd
DC
314 },
315 defaults: {
c87d46fb 316 margin: 2,
75fcb6fd
DC
317 },
318 items: [
319 {
83a42bac
TL
320 xtype: 'datefield',
321 name: 'from',
76d5a738 322 fieldLabel: gettext('Since'),
75fcb6fd 323 reference: 'from',
75fcb6fd 324 format: 'Y-m-d',
75fcb6fd
DC
325 },
326 {
83a42bac
TL
327 xtype: 'datefield',
328 name: 'to',
76d5a738 329 fieldLabel: gettext('Until'),
75fcb6fd 330 reference: 'to',
75fcb6fd 331 format: 'Y-m-d',
75fcb6fd
DC
332 },
333 {
334 xtype: 'combobox',
335 hidden: true,
c03e51ed 336 disabled: true,
75fcb6fd
DC
337 displayField: 'mail',
338 valueField: 'mail',
94153e9a 339 listConfig: {
ea785e3f 340 emptyText: `<div class="x-grid-empty">${gettext('No data in database')}</div>`,
94153e9a 341 },
75fcb6fd
DC
342 store: {
343 proxy: {
344 type: 'proxmox',
c87d46fb 345 url: '/api2/json/quarantine/spamusers',
96fba078
DC
346 },
347 fields: [
348 {
349 name: 'mail',
c87d46fb
TL
350 renderer: Ext.htmlEncode,
351 },
352 ],
75fcb6fd 353 },
61a8a658
DC
354 queryMode: 'local',
355 editable: true,
356 typeAhead: true,
357 forceSelection: true,
358 autoSelect: true,
359 anyMatch: true,
360 selectOnFocus: true,
75fcb6fd 361 reference: 'email',
c87d46fb 362 fieldLabel: 'E-Mail',
cd0b3ffc
TL
363 triggers: {
364 clear: {
365 cls: 'pmx-clear-trigger',
366 weight: -1,
367 hidden: true,
368 handler: function() {
369 this.triggers.clear.setVisible(false);
370 // 'all' is unfiltered here, so empty/originalValue makes no sense
371 this.setValue('all');
372 },
373 },
374 },
c87d46fb 375 },
d3e6c6a1
TL
376 {
377 xtype: 'textfield',
378 name: 'filter',
379 fieldLabel: gettext('Search'),
380 emptyText: gettext('Subject, Sender'),
381 enableKeyEvents: true,
382 triggers: {
383 clear: {
384 cls: 'pmx-clear-trigger',
385 weight: -1,
386 hidden: true,
387 handler: function() {
388 let me = this;
389 me.setValue('');
390 // setValue does not results in a keyup event, so trigger manually
391 me.up('grid').getController().updateFilter(me);
392 },
393 },
394 },
395 listeners: {
396 buffer: 500,
397 keyup: 'updateFilter',
398 },
399 },
c87d46fb
TL
400 ],
401 },
75fcb6fd 402});