]> git.proxmox.com Git - pmg-gui.git/blame - js/MailTracker.js
mail-proxy-relaying: format function arguments
[pmg-gui.git] / js / MailTracker.js
CommitLineData
cf248533
DM
1Ext.define('pmg-mail-tracker', {
2 extend: 'Ext.data.Model',
3 fields: [
c87d46fb 4 'id', 'from', 'to', 'dstatus', 'rstatus', 'qid', 'msgid', 'client',
cf248533 5 { type: 'number', name: 'size' },
c87d46fb 6 { type: 'date', dateFormat: 'timestamp', name: 'time' },
cf248533
DM
7 ],
8 proxy: {
c87d46fb 9 type: 'proxmox',
cf248533 10 },
9bde3d85
DM
11 // do not use field 'id', because "id/to" is the unique Id
12 // this way we display an entry for each receiver
c87d46fb 13 idProperty: 'none',
cf248533
DM
14});
15
16
17Ext.define('PMG.MailTrackerFilter', {
18 extend: 'Ext.container.Container',
19 xtype: 'pmgMailTrackerFilter',
20
21 layout: {
c87d46fb 22 type: 'hbox',
cf248533
DM
23 },
24
25 controller: {
26
27 xclass: 'Ext.app.ViewController',
28
29 onFilterChange: function() {
28eb60c0 30 let view = this.getView();
cf248533
DM
31 view.fireEvent('filterChanged');
32 },
33
34 onSpecialKey: function(field, e) {
28eb60c0 35 if (e.getKey() === e.ENTER) {
cf248533
DM
36 this.onFilterChange();
37 }
c87d46fb 38 },
cf248533
DM
39 },
40
41 getFilterParams: function() {
28eb60c0
TL
42 let me = this;
43 let param = {};
cf248533 44
28eb60c0 45 let names = ['from', 'target', 'xfilter', 'starttime', 'endtime', 'ndr', 'greylist'];
cf248533 46 Ext.Array.each(names, function(name) {
28eb60c0 47 let value = me.lookupReference(name).getSubmitValue();
cf248533
DM
48 if (value) { param[name] = value; }
49 });
50
e8e332fe
DC
51 // there must always be a start and endtime, otherwise the field was invalid
52 if (!param.starttime || !param.endtime) {
53 return undefined;
54 }
cf248533
DM
55 return param;
56 },
57
58 items: [
59 {
60 width: 400,
61 border: false,
62 padding: 10,
63 layout: {
64 type: 'vbox',
c87d46fb 65 align: 'stretch',
cf248533
DM
66 },
67 items: [
68 {
69 fieldLabel: gettext('Sender'),
70 xtype: 'textfield',
71 listeners: { specialkey: 'onSpecialKey' },
c87d46fb 72 reference: 'from',
cf248533
DM
73 },
74 {
75 fieldLabel: gettext('Receiver'),
76 xtype: 'textfield',
77 listeners: { specialkey: 'onSpecialKey' },
c87d46fb 78 reference: 'target',
cf248533
DM
79 },
80 {
81 fieldLabel: gettext('Filter'),
82 xtype: 'textfield',
83 listeners: { specialkey: 'onSpecialKey' },
c87d46fb
TL
84 reference: 'xfilter',
85 },
86 ],
cf248533
DM
87 },
88 {
cf248533
DM
89 border: false,
90 padding: 10,
91 layout: {
92 type: 'vbox',
c87d46fb 93 align: 'stretch',
cf248533
DM
94 },
95 items: [
96 {
97 fieldLabel: gettext('Start'),
98 reference: 'starttime',
2e330d44
DC
99 listeners: {
100 change: {
101 fn: 'onFilterChange',
102 buffer: 500,
103 },
104 },
cf248533 105 value: (function() {
28eb60c0 106 let now = new Date();
cf248533 107 return new Date(now.getTime() - 3600000);
be95ef5d 108 }()),
c87d46fb 109 xtype: 'promxoxDateTimeField',
cf248533
DM
110 },
111 {
112 fieldLabel: gettext('End'),
113 reference: 'endtime',
2e330d44
DC
114 listeners: {
115 change: {
116 fn: 'onFilterChange',
117 buffer: 500,
118 },
119 },
00ac25c1 120 value: (function() {
28eb60c0
TL
121 let now = new Date();
122 let tomorrow = new Date();
00ac25c1
DM
123 tomorrow.setDate(now.getDate()+1);
124 tomorrow.setHours(0);
125 tomorrow.setMinutes(0);
126 tomorrow.setSeconds(0);
127 return tomorrow;
128 }()),
c87d46fb 129 xtype: 'promxoxDateTimeField',
cf248533
DM
130 },
131 {
de0ebd99 132 layout: {
c87d46fb 133 type: 'hbox',
de0ebd99 134 },
cf248533
DM
135 border: false,
136 items: [
137 {
d545f59e 138 boxLabel: gettext('Include Empty Senders'),
cf248533
DM
139 xtype: 'proxmoxcheckbox',
140 listeners: { change: 'onFilterChange' },
141 reference: 'ndr',
c87d46fb 142 name: 'ndrs',
cf248533
DM
143 },
144 {
145 boxLabel: gettext('Include Greylist'),
146 xtype: 'proxmoxcheckbox',
147 listeners: { change: 'onFilterChange' },
148 margin: { left: 20 },
149 reference: 'greylist',
c87d46fb
TL
150 name: 'greylist',
151 },
152 ],
153 },
154 ],
155 },
156 ],
cf248533
DM
157});
158
159Ext.define('PMG.MaiLogWindow', {
160 extend: 'Ext.window.Window',
161 xtype: 'pmgMaiLogWindow',
162
163 title: gettext('Syslog'),
164
165 logid: undefined,
166 starttime: undefined,
167 endtime: undefined,
168
169 width: 1024,
170 height: 400,
171 scrollable: true,
172
de0ebd99 173 layout: {
c87d46fb 174 type: 'auto',
de0ebd99 175 },
cf248533
DM
176 modal: true,
177 bodyPadding: 5,
178
179 load: function() {
28eb60c0 180 let me = this;
cf248533
DM
181
182 Proxmox.Utils.API2Request({
183 method: 'GET',
184 params: { starttime: me.starttime, endtime: me.endtime },
185 url: '/nodes/' + Proxmox.NodeName + '/tracker/' + me.logid,
186 waitMsgTarget: me,
187 failure: function(response, opts) {
188 me.update(gettext('Error') + " " + response.htmlStatus);
189 },
190 success: function(response, opts) {
28eb60c0 191 let data = response.result.data;
cf248533 192
28eb60c0 193 let logs = "<pre style='margin: 0;'>";
cf248533
DM
194 Ext.Array.each(data.logs, function(line) {
195 logs += Ext.htmlEncode(line) + "\n";
196 });
197 logs += "</pre>";
198 me.update(logs);
c87d46fb 199 },
cf248533
DM
200 });
201 },
202
c87d46fb 203 initComponent: function() {
28eb60c0 204 let me = this;
cf248533
DM
205
206 if (!me.logid) {
207 throw "no logid specified";
208 }
209
210 if (!me.starttime) {
211 throw "no starttime specified";
212 }
213 if (!me.endtime) {
214 throw "no endtime specified";
215 }
216
217 me.callParent();
218
219 me.setHtml('Loading...');
220 me.load();
c87d46fb 221 },
cf248533
DM
222});
223
224Ext.define('PMG.MailTracker', {
225 extend: 'Ext.grid.GridPanel',
226 xtype: 'pmgMailTracker',
227
228 title: gettext('Tracking Center'),
229
230 border: false,
231
23959bb0 232 emptyText: gettext("Please enter your search parameters and press 'Search'."),
0960034c
DC
233 disableSelection: true,
234
cf248533 235 viewConfig: {
0960034c
DC
236 deferEmptyText: false,
237 enableTextSelection: true,
dd502c64 238 getRowClass: function(record, index) {
28eb60c0 239 let status = record.data.rstatus || record.data.dstatus;
dd502c64 240 return PMG.Utils.mail_status_map[status];
c87d46fb 241 },
cf248533
DM
242 },
243
0960034c
DC
244 plugins: [
245 {
246 ptype: 'rowexpander',
b5314633 247 expandOnDblClick: false,
c87d46fb
TL
248 rowBodyTpl: '<p class="logs">{logs}</p>',
249 },
0960034c
DC
250 ],
251
cf248533
DM
252 store: {
253 autoDestroy: true,
3d309d74
DC
254 model: 'pmg-mail-tracker',
255 sorters: 'time',
cf248533
DM
256 },
257
258 controller: {
259
260 xclass: 'Ext.app.ViewController',
261
262 onSearch: function() {
28eb60c0 263 let view = this.getView();
23959bb0 264 view.setEmptyText(gettext('No data in database'));
28eb60c0
TL
265 let filter = this.lookupReference('filter');
266 let status = this.lookupReference('status');
267 let params = filter.getFilterParams();
e8e332fe
DC
268 if (params === undefined) {
269 return; // something went wrong with the filters bail out
270 }
cf248533
DM
271 status.update(''); // clear status before load
272 view.store.proxy.setExtraParams(params);
273 view.store.proxy.setUrl('/api2/json/nodes/' + Proxmox.NodeName + '/tracker');
274 view.store.load(function(records, operation, success) {
28eb60c0 275 let response = operation.getResponse();
cf248533
DM
276 if (success) {
277 // fixme: howto avoid duplicate Ext.decode ?
28eb60c0 278 let result = Ext.decode(response.responseText);
cf248533
DM
279 if (result.changes) {
280 status.update(result.changes);
281 }
282 }
283 });
284 },
285
0960034c 286 showDetails: function(rowNode, record) {
28eb60c0 287 let view = this.getView();
cf248533 288
28eb60c0 289 let params = view.store.proxy.getExtraParams();
cf248533 290
0960034c
DC
291 Proxmox.Utils.API2Request({
292 method: 'GET',
293 params: { starttime: params.starttime, endtime: params.endtime },
294 url: '/nodes/' + Proxmox.NodeName + '/tracker/' + record.data.id,
295 waitMsgTarget: view,
296 failure: function(response, opts) {
c87d46fb 297 record.set('logs', gettext('Error') + " " + response.htmlStatus);
0960034c
DC
298 },
299 success: function(response, opts) {
28eb60c0
TL
300 let data = response.result.data;
301 let logs = "";
0960034c
DC
302
303 Ext.Array.each(data.logs, function(line) {
304 logs += Ext.htmlEncode(line) + "<br>";
305 });
306
307 record.set('logs', logs);
c87d46fb 308 },
cf248533 309 });
0960034c
DC
310 },
311
b5314633
DC
312 // only expand row on dblclick, but do not collapse
313 expand: function(view, record, row, rowIdx, e) {
314 // inspired by RowExpander.js
315 let rowNode = view.getNode(rowIdx);
316 let normalRow = Ext.fly(rowNode);
317
318 let collapsedCls = view.rowBodyFeature.rowCollapsedCls;
319
320 if (normalRow.hasCls(collapsedCls)) {
321 view.rowBodyFeature.rowExpander.toggleRow(rowIdx, record);
322 }
323 },
324
0960034c
DC
325 control: {
326 'gridview': {
b5314633
DC
327 expandbody: 'showDetails',
328 itemdblclick: 'expand',
c87d46fb
TL
329 },
330 },
cf248533
DM
331 },
332
23959bb0
DC
333 // extjs has no method to dynamically change the emptytext on
334 // grids, so we have to do it this way
335 setEmptyText: function(emptyText) {
336 let me = this;
337 let tableview = me.getView();
338 tableview.emptyText = `<div class="x-grid-empty">${emptyText || ""}</div>`;
339 },
340
cf248533
DM
341 dockedItems: [
342 {
343 xtype: 'pmgMailTrackerFilter',
344 reference: 'filter',
c87d46fb 345 listeners: { filterChanged: 'onSearch' },
cf248533 346 border: false,
c87d46fb 347 dock: 'top',
cf248533
DM
348 },
349 {
350 xtype: 'toolbar',
351 items: [
352 { text: 'Search', handler: 'onSearch' },
c87d46fb
TL
353 { xtype: 'component', html: '', reference: 'status' },
354 ],
355 },
cf248533
DM
356 ],
357
358 columns: [
359 {
360 xtype: 'datecolumn',
361 header: gettext('Time'),
362 width: 120,
363 dataIndex: 'time',
c87d46fb 364 format: 'M d H:i:s',
cf248533
DM
365 },
366 {
367 header: gettext('From'),
368 flex: 1,
07d37f59 369 dataIndex: 'from',
c87d46fb 370 renderer: Ext.htmlEncode,
cf248533
DM
371 },
372 {
373 header: gettext('To'),
374 flex: 1,
07d37f59 375 dataIndex: 'to',
c87d46fb 376 renderer: Ext.htmlEncode,
cf248533
DM
377 },
378 {
379 header: gettext('Status'),
380 width: 150,
381 renderer: function(v, metaData, rec) {
28eb60c0
TL
382 let returntext = 'unknown';
383 let icon = 'question-circle';
384 let rstatus = rec.data.rstatus;
cf248533 385 if (v !== undefined && v !== '') {
28eb60c0 386 let vtext = PMG.Utils.mail_status_map[v] || v;
dd502c64 387 icon = v;
d42f76fc
DM
388 if (v === 'Q' || v === 'B') {
389 returntext = vtext;
c87d46fb 390 } else if (rstatus !== undefined && rstatus !== '') {
28eb60c0 391 let rtext = PMG.Utils.mail_status_map[rstatus] || rstatus;
dd502c64
DC
392 returntext = vtext + '/' + rtext;
393 icon = rstatus;
394 } else if (rec.data.qid !== undefined) {
395 returntext = 'queued/' + vtext;
396 } else {
397 returntext = vtext;
cf248533 398 }
cf248533 399 }
dd502c64
DC
400
401 return PMG.Utils.format_status_icon(icon) + returntext;
cf248533 402 },
c87d46fb 403 dataIndex: 'dstatus',
cf248533
DM
404 },
405 {
406 header: gettext('Size'),
407 hidden: true,
c87d46fb 408 dataIndex: 'size',
cf248533
DM
409 },
410 {
411 header: 'MSGID',
412 width: 300,
413 hidden: true,
07d37f59 414 dataIndex: 'msgid',
c87d46fb 415 renderer: Ext.htmlEncode,
cf248533
DM
416 },
417 {
418 header: gettext('Client'),
419 width: 200,
420 hidden: true,
07d37f59 421 dataIndex: 'client',
c87d46fb
TL
422 renderer: Ext.htmlEncode,
423 },
cf248533
DM
424 ],
425
cf248533 426 initComponent: function() {
28eb60c0 427 let me = this;
cf248533
DM
428
429 me.callParent();
430
431 Proxmox.Utils.monStoreErrors(me.getView(), me.store);
c87d46fb 432 },
cf248533 433});