]> git.proxmox.com Git - pmg-gui.git/blame - js/controller/QuarantineController.js
disclaimer edit: add 'add-separator' checkbox
[pmg-gui.git] / js / controller / QuarantineController.js
CommitLineData
e66c888b
SI
1Ext.define('PMG.controller.QuarantineController', {
2 extend: 'Ext.app.ViewController',
e66c888b
SI
3 alias: 'controller.quarantine',
4
5 updatePreview: function(raw, rec) {
6 let preview = this.lookupReference('preview');
7
8 if (!rec || !rec.data || !rec.data.id) {
9 preview.update('');
10 preview.setDisabled(true);
11 return;
12 }
13
14 let url = `/api2/htmlmail/quarantine/content?id=${rec.data.id}`;
15 if (raw) {
16 url += '&raw=1';
17 }
18 preview.setDisabled(false);
19 this.lookupReference('raw').setDisabled(false);
20 this.lookupReference('download').setDisabled(false);
21 preview.update("<iframe frameborder=0 width=100% height=100% sandbox='allow-same-origin' src='" + url +"'></iframe>");
22 },
23
24 multiSelect: function(selection) {
25 let me = this;
26 me.lookupReference('raw').setDisabled(true);
27 me.lookupReference('download').setDisabled(true);
28 me.lookupReference('mailinfo').setVisible(false);
38229fc8 29 me.lookup('attachmentlist')?.setVisible(false);
e66c888b
SI
30
31 let preview = me.lookupReference('preview');
32 preview.setDisabled(false);
33 preview.update(`<h3 style="padding-left:5px;">${gettext('Multiple E-Mails selected')} (${selection.length})</h3>`);
34 },
35
9bcb553c
SS
36 toggleTheme: function(button) {
37 let preview = this.lookup('preview');
38 this.themed = !this.themed;
39
40 if (this.themed) {
41 preview.addCls("pmg-mail-preview-themed");
42 } else {
43 preview.removeCls("pmg-mail-preview-themed");
44 }
45 },
46
47 hideThemeToggle: function(argument) {
48 let me = this;
e950ec72 49 let themeButton = me.lookup('themeCheck');
9bcb553c
SS
50 themeButton.disable();
51 themeButton.hide();
e950ec72 52 me.lookup('themeCheckSep').hide();
9bcb553c
SS
53 me.themed = true;
54 me.toggleTheme();
55 },
56
57 showThemeToggle: function(argument) {
58 let me = this;
e950ec72 59 let themeButton = me.lookup('themeCheck');
9bcb553c
SS
60 me.themed = false;
61 me.toggleTheme();
e950ec72 62 themeButton.setValue(true);
9bcb553c
SS
63 themeButton.enable();
64 themeButton.show();
e950ec72 65 me.lookup('themeCheckSep').show();
9bcb553c
SS
66 },
67
e66c888b
SI
68 toggleRaw: function(button) {
69 let me = this;
70 let list = me.lookupReference('list');
71 let rec = list.selModel.getSelection()[0];
72 me.lookupReference('mailinfo').setVisible(me.raw);
73 me.raw = !me.raw;
74 me.updatePreview(me.raw, rec);
75 },
76
77 btnHandler: function(button, e) {
78 let me = this;
79 let action = button.reference;
80 let list = me.lookupReference('list');
81 let selected = list.getSelection();
82 me.doAction(action, selected);
83 },
84
85 doAction: function(action, selected) {
86 if (!selected.length) {
87 return;
88 }
89
90 let list = this.lookupReference('list');
91
92 if (selected.length > 1) {
93 let idlist = selected.map(item => item.data.id);
94 Ext.Msg.confirm(
95 gettext('Confirm'),
96 Ext.String.format(
97 gettext("Action '{0}' for '{1}' items"),
98 action, selected.length,
99 ),
100 async function(button) {
101 if (button !== 'yes') {
102 return;
103 }
104
105 list.mask(gettext('Processing...'), 'x-mask-loading');
106
107 const sliceSize = 2500, maxInFlight = 2;
108 let batches = [], batchCount = Math.ceil(selected.length / sliceSize);
109 for (let i = 0; i * sliceSize < selected.length; i++) {
110 let sliceStart = i * sliceSize;
111 let sliceEnd = Math.min(sliceStart + sliceSize, selected.length);
112 batches.push(
113 PMG.Async.doQAction(
114 action,
115 idlist.slice(sliceStart, sliceEnd),
116 i + 1,
117 batchCount,
118 ),
119 );
120 if (batches.length >= maxInFlight) {
121 await Promise.allSettled(batches); // eslint-disable-line no-await-in-loop
122 batches = [];
123 }
124 }
125 await Promise.allSettled(batches); // await possible remaining ones
126 list.unmask();
127 // below can be slow, we could remove directly from the in-memory store, but
128 // with lots of elements and some failures we could be quite out of sync?
129 list.getController().load();
130 },
131 );
132 return;
133 }
134
135 PMG.Utils.doQuarantineAction(action, selected[0].data.id, function() {
136 let listController = list.getController();
137 listController.allowPositionSave = false;
138 // success -> remove directly to avoid slow store reload for a single-element action
139 list.getStore().remove(selected[0]);
140 listController.restoreSavedSelection();
141 listController.allowPositionSave = true;
142 });
143 },
144
145 onSelectMail: function() {
146 let me = this;
147 let list = this.lookupReference('list');
148 let selection = list.selModel.getSelection();
149 if (selection.length > 1) {
150 me.multiSelect(selection);
151 return;
152 }
153
154 let rec = selection[0] || {};
c7a67975
DC
155 me.lookup('spaminfo')?.setID(rec);
156 me.lookup('attachmentlist')?.setID(rec);
38229fc8 157 me.lookup('attachmentlist')?.setVisible(!!rec.data);
e66c888b
SI
158
159 me.getViewModel().set('mailid', rec.data ? rec.data.id : '');
160 me.updatePreview(me.raw || false, rec);
161 me.lookupReference('mailinfo').setVisible(!!rec.data && !me.raw);
162 me.lookupReference('mailinfo').update(rec.data);
163 },
164
165 openContextMenu: function(table, record, tr, index, event) {
166 event.stopEvent();
167 let me = this;
168 let list = me.lookup('list');
169 Ext.create('PMG.menu.QuarantineContextMenu', {
170 callback: action => me.doAction(action, list.getSelection()),
171 }).showAt(event.getXY());
172 },
173
174 keyPress: function(table, record, item, index, event) {
175 let me = this;
176 let list = me.lookup('list');
177 let key = event.getKey();
178 let action = '';
179 switch (key) {
180 case event.DELETE:
181 case 127:
182 action = 'delete';
183 break;
184 case Ext.event.Event.D:
185 case Ext.event.Event.D + 32:
186 action = 'deliver';
187 break;
188 }
189
190 if (action !== '') {
191 me.doAction(action, list.getSelection());
192 }
193 },
194
9bcb553c
SS
195 beforeRender: function() {
196 let me = this;
197 let currentTheme = Ext.util.Cookies.get("PMGThemeCookie");
198
aa557e80 199 if (currentTheme === "__default__" || currentTheme === null) {
9bcb553c
SS
200 me.mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
201
202 me.themeListener = (e) => {
203 if (e.matches) {
204 me.showThemeToggle();
205 } else {
206 me.hideThemeToggle();
207 }
208 };
209
210 me.themeListener(me.mediaQueryList);
211 me.mediaQueryList.addEventListener("change", me.themeListener);
aa557e80 212 } else if (currentTheme === "crisp") {
9bcb553c
SS
213 me.hideThemeToggle();
214 } else {
215 me.showThemeToggle();
216 }
217 },
218
219 destroy: function() {
220 let me = this;
221
222 me.mediaQueryList?.removeEventListener("change", me.themeListener);
223
224 me.callParent();
225 },
226
e66c888b
SI
227 control: {
228 'button[reference=raw]': {
229 click: 'toggleRaw',
230 },
e950ec72
SS
231 'proxmoxcheckbox[reference=themeCheck]': {
232 change: 'toggleTheme',
9bcb553c 233 },
e66c888b
SI
234 'pmgQuarantineList': {
235 selectionChange: 'onSelectMail',
236 itemkeypress: 'keyPress',
237 rowcontextmenu: 'openContextMenu',
238 },
239 },
240});