]> git.proxmox.com Git - pmg-gui.git/blob - js/Utils.js
utils: align notification toast to bottom-right again
[pmg-gui.git] / js / Utils.js
1 Ext.ns('PMG');
2
3 console.log("Starting PMG Manager");
4
5
6 Ext.define('PMG.Utils', {
7 singleton: true,
8
9 // this singleton contains miscellaneous utilities
10
11 // use in panels with object spread (...) operator, for example:
12 // ...PMG.Utils.onlineHelpTool('sysadmin_certificate_management'),
13 onlineHelpTool: function(blockid) {
14 let info = Proxmox.Utils.get_help_info(blockid);
15 if (info === undefined) {
16 info = Proxmox.Utils.get_help_info('pmg_documentation_index');
17 if (info === undefined) {
18 throw "get_help_info failed"; // should not happen
19 }
20 }
21
22 let docsURI = window.location.origin + info.link;
23 let title = info.title || gettext('Help');
24 if (info.subtitle) {
25 title += ' - ' + info.subtitle;
26 }
27 return {
28 tools: [
29 {
30 type: 'help',
31 tooltip: title,
32 handler: () => window.open(docsURI),
33 },
34 ],
35 };
36 },
37
38 senderText: gettext('Sender'),
39 receiverText: gettext('Receiver'),
40 scoreText: gettext('Score'),
41
42 user_role_text: {
43 root: gettext('Superuser'),
44 admin: gettext('Administrator'),
45 helpdesk: gettext('Help Desk'),
46 qmanager: gettext('Quarantine Manager'),
47 audit: gettext('Auditor'),
48 },
49
50 format_user_role: function(role) {
51 return PMG.Utils.user_role_text[role] || role;
52 },
53
54 oclass_text: {
55 who: gettext('Who Objects'),
56 what: gettext('What Objects'),
57 when: gettext('When Objects'),
58 action: gettext('Action Objects'),
59 from: gettext('From'),
60 to: gettext('To'),
61 },
62
63 oclass_icon: {
64 who: '<span class="fa fa-fw fa-user-circle"></span> ',
65 what: '<span class="fa fa-fw fa-cube"></span> ',
66 when: '<span class="fa fa-fw fa-clock-o"></span> ',
67 action: '<span class="fa fa-fw fa-flag"></span> ',
68 from: '<span class="fa fa-fw fa-user-circle"></span> ',
69 to: '<span class="fa fa-fw fa-user-circle"></span> ',
70 },
71
72 mail_status_map: {
73 2: 'delivered',
74 4: 'deferred',
75 5: 'bounced',
76 N: 'rejected',
77 G: 'greylisted',
78 A: 'accepted',
79 B: 'blocked',
80 Q: 'quarantine',
81 },
82
83 icon_status_map_class: {
84 2: 'check-circle',
85 4: 'clock-o',
86 5: 'mail-reply',
87 N: 'times-circle',
88 G: 'list',
89 A: 'check',
90 B: 'ban',
91 Q: 'cube',
92 },
93
94 icon_status_map_color: {
95 2: 'green',
96 5: 'gray',
97 A: 'green',
98 B: 'red',
99 },
100
101 format_status_icon: function(status) {
102 var icon = PMG.Utils.icon_status_map_class[status] || 'question-circle';
103 var color = PMG.Utils.icon_status_map_color[status] || '';
104 return '<i class="fa fa-' + icon + ' ' + color + '"></i> ';
105 },
106
107 format_oclass: function(oclass) {
108 var icon = PMG.Utils.oclass_icon[oclass] || '';
109 var text = PMG.Utils.oclass_text[oclass] || oclass;
110 return icon + text;
111 },
112
113 rule_direction_text: {
114 0: gettext('In'),
115 1: gettext('Out'),
116 2: gettext('In & Out'),
117 },
118
119 rule_direction_icon: {
120 0: '<span class="fa fa-fw fa-long-arrow-left"></span> ',
121 1: '<span class="fa fa-fw fa-long-arrow-right"></span> ',
122 2: '<span class="fa fa-fw fa-exchange"></span> ',
123 },
124
125 format_rule_direction: function(dir) {
126 var icon = PMG.Utils.rule_direction_icon[dir] || '';
127 var text = PMG.Utils.rule_direction_text[dir] || dir;
128 return icon + text;
129 },
130
131 format_otype: function(otype) {
132 var editor = PMG.Utils.object_editors[otype];
133 var iconCls = 'fa fa-question-circle';
134 if (editor) {
135 var icon = '<span class="fa-fw ' + (editor.iconCls || iconCls) + '"></span> ';
136 return icon + editor.subject;
137 }
138
139 return '<span class="fa-fw ' + iconCls + '"></span> unknown';
140 },
141
142 format_ldap_protocol: function(p) {
143 if (p === undefined) { return 'LDAP'; }
144 if (p === 'ldap') { return 'LDAP'; }
145 if (p === 'ldaps') { return 'LDAPS'; }
146 if (p === 'ldap+starttls') { return 'LDAP+STARTTLS'; }
147 return 'unknown';
148 },
149
150 convert_field_to_per_min: function(value, record) {
151 return value/(record.data.timespan/60);
152 },
153
154 object_editors: {
155 1000: {
156 onlineHelp: 'pmg_mailfilter_regex',
157 iconCls: 'fa fa-filter',
158 xtype: 'proxmoxWindowEdit',
159 subdir: 'regex',
160 subject: gettext("Regular Expression"),
161 width: 400,
162 items: [
163 {
164 xtype: 'textfield',
165 name: 'regex',
166 labelWidth: 150,
167 reference: 'regex',
168 fieldLabel: gettext("Regular Expression"),
169 },
170 {
171 labelWidth: 150,
172 fieldLabel: gettext('Test String'),
173 xtype: 'pmgRegexTester',
174 wholeMatch: true,
175 regexFieldReference: 'regex',
176 },
177 ],
178 },
179 1005: {
180 onlineHelp: 'pmgconfig_ldap',
181 iconCls: 'fa fa-users',
182 xtype: 'pmgLDAPGroupEditor',
183 subdir: 'ldap',
184 subject: gettext("LDAP Group"),
185 },
186 1006: {
187 onlineHelp: 'pmgconfig_ldap',
188 iconCls: 'fa fa-user',
189 xtype: 'pmgLDAPUserEditor',
190 subdir: 'ldapuser',
191 subject: gettext("LDAP User"),
192 },
193 1009: {
194 onlineHelp: 'pmg_mailfilter_regex',
195 iconCls: 'fa fa-filter',
196 xtype: 'proxmoxWindowEdit',
197 subdir: 'receiver_regex',
198 subject: gettext("Regular Expression"),
199 receivertest: true,
200 width: 400,
201 items: [
202 {
203 xtype: 'textfield',
204 name: 'regex',
205 labelWidth: 150,
206 fieldLabel: gettext("Regular Expression"),
207 },
208 ],
209 },
210 1001: {
211 onlineHelp: 'pmg_mailfilter_who',
212 iconCls: 'fa fa-envelope-o',
213 xtype: 'proxmoxWindowEdit',
214 subdir: 'email',
215 subject: gettext("E-Mail"),
216 width: 400,
217 items: [
218 {
219 xtype: 'textfield',
220 name: 'email',
221 fieldLabel: gettext("E-Mail"),
222 },
223 ],
224 },
225 1007: {
226 onlineHelp: 'pmg_mailfilter_who',
227 iconCls: 'fa fa-envelope-o',
228 xtype: 'proxmoxWindowEdit',
229 subdir: 'receiver',
230 subject: gettext("E-Mail"),
231 receivertest: true,
232 width: 400,
233 items: [
234 {
235 xtype: 'textfield',
236 name: 'email',
237 fieldLabel: gettext("E-Mail"),
238 },
239 ],
240 },
241 1002: {
242 onlineHelp: 'pmg_mailfilter_who',
243 iconCls: 'fa fa-globe',
244 xtype: 'proxmoxWindowEdit',
245 subdir: 'domain',
246 subject: gettext("Domain"),
247 width: 400,
248 items: [
249 {
250 xtype: 'textfield',
251 name: 'domain',
252 fieldLabel: gettext("Domain"),
253 },
254 ],
255 },
256 1008: {
257 onlineHelp: 'pmg_mailfilter_who',
258 iconCls: 'fa fa-globe',
259 xtype: 'proxmoxWindowEdit',
260 subdir: 'receiver_domain',
261 subject: gettext("Domain"),
262 receivertest: true,
263 width: 400,
264 items: [
265 {
266 xtype: 'textfield',
267 name: 'domain',
268 fieldLabel: gettext("Domain"),
269 },
270 ],
271 },
272 1003: {
273 onlineHelp: 'pmg_mailfilter_who',
274 iconCls: 'fa fa-globe',
275 xtype: 'proxmoxWindowEdit',
276 subdir: 'ip',
277 subject: gettext("IP Address"),
278 width: 400,
279 items: [
280 {
281 xtype: 'textfield',
282 name: 'ip',
283 fieldLabel: gettext("IP Address"),
284 },
285 ],
286 },
287 1004: {
288 onlineHelp: 'pmg_mailfilter_who',
289 iconCls: 'fa fa-globe',
290 xtype: 'proxmoxWindowEdit',
291 subdir: 'network',
292 subject: gettext("IP Network"),
293 width: 400,
294 items: [
295 {
296 xtype: 'textfield',
297 name: 'cidr',
298 fieldLabel: gettext("IP Network"),
299 },
300 ],
301 },
302 2000: {
303 onlineHelp: 'pmg_mailfilter_when',
304 iconCls: 'fa fa-clock-o',
305 xtype: 'proxmoxWindowEdit',
306 subdir: 'timeframe',
307 subject: gettext("TimeFrame"),
308 items: [
309 {
310 xtype: 'timefield',
311 name: 'start',
312 format: 'H:i',
313 fieldLabel: gettext("Start Time"),
314 },
315 {
316 xtype: 'timefield',
317 name: 'end',
318 format: 'H:i',
319 fieldLabel: gettext("End Time"),
320 },
321 ],
322 },
323 3000: {
324 onlineHelp: 'pmg_mailfilter_what',
325 iconCls: 'fa fa-bullhorn',
326 xtype: 'proxmoxWindowEdit',
327 subdir: 'spamfilter',
328 subject: gettext('Spam Filter'),
329 items: [
330 {
331 xtype: 'proxmoxintegerfield',
332 name: 'spamlevel',
333 allowBlank: false,
334 minValue: 0,
335 fieldLabel: gettext('Level'),
336 },
337 ],
338 },
339 3001: {
340 onlineHelp: 'pmg_mailfilter_what',
341 iconCls: 'fa fa-bug',
342 xtype: 'proxmoxWindowEdit',
343 subdir: 'virusfilter',
344 subject: gettext('Virus Filter'),
345 uneditable: true,
346 // there are no parameters to give, so we simply submit it
347 listeners: {
348 show: function(win) {
349 win.submit();
350 },
351 },
352 },
353 3002: {
354 onlineHelp: 'pmg_mailfilter_regex',
355 iconCls: 'fa fa-code',
356 xtype: 'proxmoxWindowEdit',
357 subdir: 'matchfield',
358 subject: gettext('Match Field'),
359 width: 400,
360 items: [
361 {
362 xtype: 'textfield',
363 name: 'field',
364 labelWidth: 150,
365 allowBlank: false,
366 fieldLabel: gettext('Field'),
367 },
368 {
369 xtype: 'textfield',
370 reference: 'value',
371 name: 'value',
372 labelWidth: 150,
373 allowBlank: false,
374 fieldLabel: gettext('Value'),
375 },
376 {
377 labelWidth: 150,
378 fieldLabel: gettext('Test String'),
379 xtype: 'pmgRegexTester',
380 regexFieldReference: 'value',
381 },
382 ],
383 },
384 3003: {
385 onlineHelp: 'pmg_mailfilter_what',
386 iconCls: 'fa fa-file-image-o',
387 xtype: 'proxmoxWindowEdit',
388 subdir: 'contenttype',
389 width: 400,
390 subject: gettext('Content Type Filter'),
391 items: [
392 {
393 xtype: 'combobox',
394 displayField: 'text',
395 labelWidth: 150,
396 valueField: 'mimetype',
397 name: 'contenttype',
398 editable: true,
399 queryMode: 'local',
400 store: {
401 autoLoad: true,
402 proxy: {
403 type: 'proxmox',
404 url: '/api2/json/config/mimetypes',
405 },
406 },
407 fieldLabel: gettext('Content Type'),
408 anyMatch: true,
409 matchFieldWidth: false,
410 listeners: {
411 change: function(cb, value) {
412 var me = this;
413 me.up().down('displayfield').setValue(value);
414 },
415 },
416 },
417 {
418 xtype: 'displayfield',
419 fieldLabel: gettext('Value'),
420 labelWidth: 150,
421 allowBlank: false,
422 reset: Ext.emptyFn,
423 },
424 ],
425 },
426 3004: {
427 onlineHelp: 'pmg_mailfilter_regex',
428 iconCls: 'fa fa-file-o',
429 xtype: 'proxmoxWindowEdit',
430 subdir: 'filenamefilter',
431 width: 400,
432 subject: gettext('Match Filename'),
433 items: [
434 {
435 xtype: 'textfield',
436 name: 'filename',
437 reference: 'filename',
438 fieldLabel: gettext('Filename'),
439 labelWidth: 150,
440 allowBlank: false,
441 },
442 {
443 labelWidth: 150,
444 fieldLabel: gettext('Test String'),
445 wholeMatch: true,
446 xtype: 'pmgRegexTester',
447 regexFieldReference: 'filename',
448 },
449 ],
450 },
451 3005: {
452 onlineHelp: 'pmg_mailfilter_what',
453 iconCls: 'fa fa-file-archive-o',
454 xtype: 'proxmoxWindowEdit',
455 subdir: 'archivefilter',
456 width: 400,
457 subject: gettext('Archive Filter'),
458 items: [
459 {
460 xtype: 'combobox',
461 displayField: 'text',
462 labelWidth: 150,
463 valueField: 'mimetype',
464 name: 'contenttype',
465 editable: true,
466 queryMode: 'local',
467 store: {
468 autoLoad: true,
469 proxy: {
470 type: 'proxmox',
471 url: '/api2/json/config/mimetypes',
472 },
473 },
474 fieldLabel: gettext('Content Type'),
475 anyMatch: true,
476 matchFieldWidth: false,
477 listeners: {
478 change: function(cb, value) {
479 var me = this;
480 me.up().down('displayfield').setValue(value);
481 },
482 },
483 },
484 {
485 xtype: 'displayfield',
486 fieldLabel: gettext('Value'),
487 labelWidth: 150,
488 allowBlank: false,
489 reset: Ext.emptyFn,
490 },
491 ],
492 },
493 3006: {
494 onlineHelp: 'pmg_mailfilter_regex',
495 iconCls: 'fa fa-file-archive-o',
496 xtype: 'proxmoxWindowEdit',
497 subdir: 'archivefilenamefilter',
498 width: 400,
499 subject: gettext('Match Archive Filename'),
500 items: [
501 {
502 xtype: 'textfield',
503 name: 'filename',
504 reference: 'filename',
505 fieldLabel: gettext('Filename'),
506 labelWidth: 150,
507 allowBlank: false,
508 },
509 {
510 labelWidth: 150,
511 fieldLabel: gettext('Test String'),
512 wholeMatch: true,
513 xtype: 'pmgRegexTester',
514 regexFieldReference: 'filename',
515 },
516 ],
517 },
518 4002: {
519 onlineHelp: 'pmg_mailfilter_action',
520 xtype: 'proxmoxWindowEdit',
521 subdir: 'notification',
522 subject: gettext('Notification'),
523 width: 400,
524 items: [
525 {
526 xtype: 'textfield',
527 name: 'name',
528 allowBlank: false,
529 fieldLabel: gettext('Name'),
530 },
531 {
532 xtype: 'textareafield',
533 name: 'info',
534 fieldLabel: gettext("Comment"),
535 },
536 {
537 xtype: 'textfield',
538 name: 'to',
539 allowBlank: false,
540 value: '__ADMIN__',
541 fieldLabel: gettext('Receiver'),
542 },
543 {
544 xtype: 'textfield',
545 name: 'subject',
546 allowBlank: false,
547 value: 'Notification: __SUBJECT__',
548 fieldLabel: gettext('Subject'),
549 },
550 {
551 xtype: 'textarea',
552 name: 'body',
553 allowBlank: false,
554 grow: true,
555 growMax: 250,
556 value:
557 "Proxmox Notifcation:\n\n" +
558 "Sender: __SENDER__\n" +
559 "Receiver: __RECEIVERS__\n" +
560 "Targets: __TARGETS__\n\n" +
561 "Subject: __SUBJECT__\n\n" +
562 "Matching Rule: __RULE__\n\n" +
563 "__RULE_INFO__\n\n" +
564 "__VIRUS_INFO__\n" +
565 "__SPAM_INFO__\n",
566 fieldLabel: gettext('Body'),
567 },
568 {
569 xtype: 'proxmoxcheckbox',
570 name: 'attach',
571 fieldLabel: gettext("Attach orig. Mail"),
572 },
573 ],
574 },
575 4003: {
576 onlineHelp: 'pmg_mailfilter_action',
577 xtype: 'proxmoxWindowEdit',
578 subdir: 'field',
579 subject: gettext('Header Attribute'),
580 width: 400,
581 items: [
582 {
583 xtype: 'textfield',
584 name: 'name',
585 allowBlank: false,
586 fieldLabel: gettext('Name'),
587 },
588 {
589 xtype: 'textareafield',
590 name: 'info',
591 fieldLabel: gettext("Comment"),
592 },
593 {
594 xtype: 'textfield',
595 name: 'field',
596 allowBlank: false,
597 fieldLabel: gettext('Field'),
598 },
599 {
600 xtype: 'textfield',
601 reference: 'value',
602 name: 'value',
603 allowBlank: false,
604 fieldLabel: gettext('Value'),
605 },
606 ],
607 },
608 4005: {
609 onlineHelp: 'pmg_mailfilter_action',
610 xtype: 'proxmoxWindowEdit',
611 subdir: 'bcc',
612 subject: gettext('BCC'),
613 width: 400,
614 items: [
615 {
616 xtype: 'textfield',
617 name: 'name',
618 allowBlank: false,
619 fieldLabel: gettext('Name'),
620 },
621 {
622 xtype: 'textareafield',
623 name: 'info',
624 fieldLabel: gettext("Comment"),
625 },
626 {
627 xtype: 'textfield',
628 name: 'target',
629 allowBlank: false,
630 fieldLabel: gettext("Target"),
631 },
632 {
633 xtype: 'proxmoxcheckbox',
634 checked: true,
635 name: 'original',
636 fieldLabel: gettext("send orig. Mail"),
637 },
638 ],
639
640 },
641 4007: {
642 onlineHelp: 'pmg_mailfilter_action',
643 xtype: 'proxmoxWindowEdit',
644 subdir: 'removeattachments',
645 subject: gettext('Remove Attachments'),
646 width: 500,
647 fieldDefaults: {
648 labelWidth: 150,
649 },
650 items: [
651 {
652 xtype: 'textfield',
653 name: 'name',
654 allowBlank: false,
655 fieldLabel: gettext('Name'),
656 },
657 {
658 xtype: 'textareafield',
659 name: 'info',
660 fieldLabel: gettext("Comment"),
661 },
662 {
663 xtype: 'textareafield',
664 name: 'text',
665 grow: true,
666 growMax: 250,
667 fieldLabel: gettext("Text Replacement"),
668 },
669 {
670 xtype: 'proxmoxcheckbox',
671 checked: true,
672 name: 'all',
673 fieldLabel: gettext("Remove all attachments"),
674 },
675 {
676 xtype: 'proxmoxcheckbox',
677 checked: false,
678 name: 'quarantine',
679 fieldLabel: gettext("Copy orignal mail to Attachment Quarantine"),
680 },
681 ],
682 },
683 4009: {
684 onlineHelp: 'pmg_mailfilter_action',
685 xtype: 'proxmoxWindowEdit',
686 subdir: 'disclaimer',
687 subject: gettext('Disclaimer'),
688 width: 400,
689 items: [
690 {
691 xtype: 'textfield',
692 name: 'name',
693 allowBlank: false,
694 fieldLabel: gettext('Name'),
695 },
696 {
697 xtype: 'textareafield',
698 name: 'info',
699 fieldLabel: gettext("Comment"),
700 },
701 {
702 xtype: 'textareafield',
703 name: 'disclaimer',
704 grow: true,
705 growMax: 250,
706 fieldLabel: gettext("Disclaimer"),
707 },
708 ],
709 },
710 },
711
712 updateLoginData: function(data) {
713 Proxmox.CSRFPreventionToken = data.CSRFPreventionToken;
714 Proxmox.UserName = data.username;
715 Ext.util.Cookies.set('PMGAuthCookie', data.ticket, null, '/', null, true);
716 },
717
718 quarantineActionExtracted: false,
719
720 extractQuarantineAction: function() {
721 if (PMG.Utils.quarantineActionExtracted) {
722 return null;
723 }
724
725 PMG.Utils.quarantineActionExtracted = true;
726
727 let qs = Ext.Object.fromQueryString(location.search);
728
729 let cselect = qs.cselect;
730 let action = qs.action;
731 let dateString = qs.date;
732
733 if (dateString) {
734 let date = new Date(dateString).getTime()/1000;
735
736 // set from date for QuarantineList
737 PMG.QuarantineList.from = date;
738 }
739
740 delete qs.cselect;
741 delete qs.action;
742 delete qs.ticket;
743 delete qs.date;
744
745 var newsearch = Ext.Object.toQueryString(qs);
746
747 var newurl = location.protocol + "//" + location.host + location.pathname;
748 if (newsearch) { newurl += '?' + newsearch; }
749 newurl += location.hash;
750
751 if (window.history) {
752 window.history.pushState({ path: newurl }, '', newurl);
753 }
754
755 if (action || cselect) {
756 return {
757 action: action,
758 cselect: cselect,
759 };
760 }
761 return null;
762 },
763
764 doQuarantineAction: function(action, id, callback) {
765 Proxmox.Utils.API2Request({
766 url: '/quarantine/content/',
767 params: {
768 action: action,
769 id: id,
770 },
771 method: 'POST',
772 failure: function(response, opts) {
773 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
774 },
775 success: function(response, opts) {
776 let count = id.split(';').length;
777 let fmt = count > 1
778 ? gettext("Action '{0}' for '{1}' items successful")
779 : gettext("Action '{0}' successful")
780 ;
781 let message = Ext.String.format(fmt, action, count);
782 let title = Ext.String.format("{0} successful", Ext.String.capitalize(action));
783
784 Ext.toast({
785 html: message,
786 title: title,
787 minWidth: 200,
788 hideDuration: 250,
789 slideBackDuration: 250,
790 slideBackAnimation: 'easeOut',
791 iconCls: 'fa fa-check',
792 shadow: true,
793 align: 'br',
794 });
795
796 if (Ext.isFunction(callback)) {
797 callback();
798 }
799 },
800 });
801 },
802
803 render_filetype: function(value) {
804 let iconCls = 'fa-file-o';
805 let text = Proxmox.Utils.unknownText;
806
807 if (!value) {
808 return `<i class='fa ${iconCls}'></i> ${text}`;
809 }
810
811 text = value.toString().toLowerCase();
812 const type = text.split('/')[0];
813
814 switch (type) {
815 case 'audio':
816 case 'image':
817 case 'video':
818 case 'text':
819 iconCls = `fa-file-${type}-o`;
820 break;
821 case 'application': {
822 const subtypes = ['excel', 'pdf', 'word', 'powerpoint'];
823 let found = subtypes.find(st => text.includes(st));
824 if (found !== undefined) {
825 iconCls = `fa-file-${found}-o`;
826 }
827 } break;
828 default:
829 break;
830 }
831
832 return `<i class='fa ${iconCls}'></i> ${text}`;
833 },
834
835 sender_renderer: function(value, metaData, rec) {
836 var subject = Ext.htmlEncode(value);
837 var from = Ext.htmlEncode(rec.data.from);
838 var sender = Ext.htmlEncode(rec.data.sender);
839 if (sender) {
840 from = Ext.String.format(gettext("{0} on behalf of {1}"),
841 sender, from);
842 }
843 return '<small>' + from + '</small><br>' + subject;
844 },
845
846 constructor: function() {
847 var me = this;
848
849 // do whatever you want here
850 Proxmox.Utils.override_task_descriptions({
851 applycustomscores: ['', gettext('Apply custom SpamAssassin scores')],
852 avupdate: ['', gettext('ClamAV update')],
853 backup: ['', gettext('Backup')],
854 clustercreate: ['', gettext('Create Cluster')],
855 clusterjoin: ['', gettext('Join Cluster')],
856 restore: ['', gettext('Restore')],
857 saupdate: ['', gettext('SpamAssassin update')],
858 });
859 },
860 });
861
862 Ext.define('PMG.Async', {
863 singleton: true,
864
865 // Returns a Promise which executes a quarantine action when awaited.
866 // Shows a Toast message box once completed, if batchNumber and batchTotal
867 // are set, they will be included into the title of that toast.
868 doQAction: function(action, ids, batchNumber, batchTotal) {
869 if (!Ext.isArray(ids)) {
870 ids = [ids];
871 }
872 return Proxmox.Async.api2({
873 url: '/quarantine/content/',
874 params: {
875 action: action,
876 id: ids.join(';'),
877 },
878 method: 'POST',
879 }).then(
880 response => {
881 let count = ids.length;
882 let fmt = count > 1
883 ? gettext("Action '{0}' for '{1}' items successful")
884 : gettext("Action '{0}' successful")
885 ;
886 let message = Ext.String.format(fmt, action, count);
887 let titleFmt = batchNumber !== undefined && batchTotal > 1
888 ? gettext("{0} ({1}/{2}) successful")
889 : gettext("{0} successful")
890 ;
891 let title = Ext.String.format(
892 titleFmt,
893 Ext.String.capitalize(action),
894 batchNumber,
895 batchTotal,
896 );
897
898 Ext.toast({
899 html: message,
900 title: title,
901 minWidth: 200,
902 hideDuration: 250,
903 slideBackDuration: 250,
904 slideBackAnimation: 'easeOut',
905 iconCls: 'fa fa-check',
906 shadow: true,
907 align: 'br',
908 });
909 },
910 response => Proxmox.Utils.alertResponseFailure(response),
911 );
912 },
913 });