]> git.proxmox.com Git - pmg-gui.git/blob - js/QuarantineView.js
spam quarantine: batch actions into 2500-sized chunks
[pmg-gui.git] / js / QuarantineView.js
1 Ext.define('PMG.QuarantineNavigationTree', {
2 extend: 'Ext.list.Tree',
3 xtype: 'quarantinenavigationtree',
4
5 select: function(path) {
6 let me = this;
7 let item = me.getStore().findRecord('path', path, 0, false, true, true);
8 me.setSelection(item);
9 },
10
11 store: {
12 root: {
13 expanded: true,
14 children: [
15 {
16 text: gettext('Spam Quarantine'),
17 iconCls: 'fa fa-cubes',
18 path: 'pmgSpamQuarantine',
19 expanded: true,
20 children: [
21 {
22 text: gettext('Whitelist'),
23 iconCls: 'fa fa-file-o',
24 path: 'pmgUserWhitelist',
25 leaf: true,
26 },
27 {
28 text: gettext('Blacklist'),
29 iconCls: 'fa fa-file',
30 path: 'pmgUserBlacklist',
31 leaf: true,
32 },
33 ],
34 },
35 ],
36 },
37 },
38
39 animation: false,
40 expanderOnly: true,
41 expanderFirst: false,
42 ui: 'nav',
43 });
44
45 Ext.define('PMG.QuarantineView', {
46 extend: 'Ext.container.Container',
47 xtype: 'quarantineview',
48
49 title: 'Proxmox Mail Gateway Quarantine',
50
51 controller: {
52 xclass: 'Ext.app.ViewController',
53 routes: {
54 ':path:subpath': {
55 action: 'changePath',
56 before: 'beforeChangePath',
57 conditions: {
58 ':path': '(?:([%a-zA-Z0-9\\-\\_\\s,]+))',
59 ':subpath': '(?:(?::)([%a-zA-Z0-9\\-\\_\\s,]+))?',
60 },
61 },
62 },
63
64 beforeChangePath: function(path, subpath, action) {
65 let me = this;
66
67 if (!Ext.ClassManager.getByAlias('widget.'+ path)) {
68 console.warn('xtype "'+path+'" not found');
69 action.stop();
70 return;
71 }
72
73 let lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem();
74 if (lastpanel && lastpanel.xtype === path) {
75 // we have the right component already,
76 // we just need to select the correct tab
77 // default to the first
78 subpath = subpath || 0;
79 if (lastpanel.getActiveTab) {
80 // we assume lastpanel is a tabpanel
81 if (lastpanel.getActiveTab().getItemId() !== subpath) {
82 // set the active tab
83 lastpanel.setActiveTab(subpath);
84 }
85 // else we are already there
86 }
87 action.stop();
88 return;
89 }
90
91 action.resume();
92 },
93
94 changePath: function(path, subpath) {
95 let me = this;
96 let contentpanel = me.lookupReference('contentpanel');
97 let lastpanel = contentpanel.getLayout().getActiveItem();
98
99 let obj = contentpanel.add({ xtype: path, cselect: subpath });
100 let treelist = me.lookupReference('navtree');
101
102 treelist.suspendEvents();
103 treelist.select(path);
104 treelist.resumeEvents();
105
106 if (Ext.isFunction(obj.setActiveTab)) {
107 obj.setActiveTab(subpath || 0);
108 obj.addListener('tabchange', function(tabpanel, newc, oldc) {
109 let newpath = path;
110
111 // only add the subpath part for the
112 // non-default tabs
113 if (tabpanel.items.findIndex('id', newc.id) !== 0) {
114 newpath += ":" + newc.getItemId();
115 }
116
117 me.redirectTo(newpath);
118 });
119 }
120
121 contentpanel.setActiveItem(obj);
122
123 if (lastpanel) {
124 contentpanel.remove(lastpanel, { destroy: true });
125 }
126 },
127
128 logout: function() {
129 PMG.app.logout();
130 },
131
132 changeLanguage: function() {
133 Ext.create('Proxmox.window.LanguageEditWindow', {
134 cookieName: 'PMGLangCookie',
135 }).show();
136 },
137
138 navigate: function(treelist, item) {
139 this.redirectTo(item.get('path'));
140 },
141
142 execQuarantineAction: function(qa) {
143 PMG.Utils.doQuarantineAction(qa.action, qa.cselect);
144 },
145
146 control: {
147 '[reference=logoutButton]': {
148 click: 'logout',
149 },
150 '[reference=languageButton]': {
151 click: 'changeLanguage',
152 },
153 },
154
155 init: function(view) {
156 let me = this;
157
158 // load username
159 let username = Proxmox.UserName.replace(/@quarantine$/, '');
160 me.lookupReference('usernameinfo').setText(username);
161
162 // show login on requestexception
163 // fixme: what about other errors
164 Ext.Ajax.on('requestexception', function(conn, response, options) {
165 if (response.status === 401) { // auth failure
166 me.logout();
167 }
168 });
169
170 let qa = PMG.Utils.extractQuarantineAction();
171 let token;
172 if (qa) {
173 token = 'pmgSpamQuarantine';
174 if (qa.action === 'blacklist') { token = 'pmgUserBlacklist'; }
175 if (qa.action === 'whitelist') { token = 'pmgUserWhitelist'; }
176 if (qa.cselect) {
177 token += ':' + qa.cselect;
178 }
179 this.redirectTo(token, true);
180 if (qa.action) {
181 me.execQuarantineAction(qa);
182 }
183 } else {
184 // select treeitem and load page from url fragment
185
186 token = Ext.util.History.getToken() || 'pmgSpamQuarantine';
187 this.redirectTo(token, true);
188 }
189 },
190 },
191
192 plugins: 'viewport',
193
194 layout: {
195 type: 'border',
196 },
197
198 items: [
199 {
200 region: 'north',
201 xtype: 'container',
202 layout: {
203 type: 'hbox',
204 align: 'middle',
205 },
206 margin: '2 0 2 5',
207 height: 38,
208 items: [
209 {
210 xtype: 'proxmoxlogo',
211 },
212 {
213 padding: '0 0 0 5',
214 xtype: 'versioninfo',
215 },
216 {
217 flex: 1,
218 },
219 {
220 xtype: 'button',
221 reference: 'usernameinfo',
222 style: {
223 // proxmox dark grey p light grey as border
224 backgroundColor: '#464d4d',
225 borderColor: '#ABBABA',
226 },
227 margin: '0 5 0 0',
228 iconCls: 'fa fa-user',
229 menu: [
230 {
231 iconCls: 'fa fa-language',
232 text: gettext('Language'),
233 reference: 'languageButton',
234 },
235 '-',
236 {
237 reference: 'logoutButton',
238 iconCls: 'fa fa-sign-out',
239 text: gettext('Logout'),
240 },
241 ],
242 },
243 ],
244 },
245 {
246 xtype: 'quarantinenavigationtree',
247 reference: 'navtree',
248 minWidth: 177,
249 border: false,
250 region: 'west',
251 // we have to define it here until extjs 6.2
252 // because of a bug where a viewcontroller does not detect
253 // the selectionchange event of a treelist
254 listeners: {
255 selectionchange: 'navigate',
256 },
257 },
258 {
259 xtype: 'panel',
260 layout: {
261 type: 'card',
262 },
263 region: 'center',
264 border: false,
265 reference: 'contentpanel',
266 },
267 ],
268 });