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