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