]>
Commit | Line | Data |
---|---|---|
0277bfeb DM |
1 | Ext.define('PMG.QuarantineNavigationTree', { |
2 | extend: 'Ext.list.Tree', | |
3 | xtype: 'quarantinenavigationtree', | |
4 | ||
5 | select: function(path) { | |
28eb60c0 TL |
6 | let me = this; |
7 | let item = me.getStore().findRecord('path', path, 0, false, true, true); | |
0277bfeb DM |
8 | me.setSelection(item); |
9 | }, | |
10 | ||
11 | store: { | |
0277bfeb DM |
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'), | |
3cac8c4e | 23 | iconCls: 'fa fa-file-o', |
0277bfeb | 24 | path: 'pmgUserWhitelist', |
c87d46fb | 25 | leaf: true, |
0277bfeb DM |
26 | }, |
27 | { | |
28 | text: gettext('Blacklist'), | |
3cac8c4e | 29 | iconCls: 'fa fa-file', |
0277bfeb | 30 | path: 'pmgUserBlacklist', |
c87d46fb TL |
31 | leaf: true, |
32 | }, | |
33 | ], | |
34 | }, | |
35 | ], | |
36 | }, | |
0277bfeb DM |
37 | }, |
38 | ||
39 | animation: false, | |
40 | expanderOnly: true, | |
41 | expanderFirst: false, | |
13f8df5c | 42 | ui: 'pve-nav', |
0277bfeb DM |
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', | |
c87d46fb TL |
57 | conditions: { |
58 | ':path': '(?:([%a-zA-Z0-9\\-\\_\\s,]+))', | |
59 | ':subpath': '(?:(?::)([%a-zA-Z0-9\\-\\_\\s,]+))?', | |
60 | }, | |
61 | }, | |
0277bfeb DM |
62 | }, |
63 | ||
e810c530 | 64 | beforeChangePath: function(path, subpathOrAction, action) { |
28eb60c0 | 65 | let me = this; |
0277bfeb | 66 | |
e810c530 TL |
67 | let subpath = subpathOrAction; |
68 | if (!action) { | |
69 | action = subpathOrAction; | |
70 | subpath = undefined; | |
71 | } | |
72 | ||
0277bfeb DM |
73 | if (!Ext.ClassManager.getByAlias('widget.'+ path)) { |
74 | console.warn('xtype "'+path+'" not found'); | |
75 | action.stop(); | |
76 | return; | |
77 | } | |
78 | ||
28eb60c0 | 79 | let lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem(); |
0277bfeb DM |
80 | if (lastpanel && lastpanel.xtype === path) { |
81 | // we have the right component already, | |
82 | // we just need to select the correct tab | |
83 | // default to the first | |
84 | subpath = subpath || 0; | |
85 | if (lastpanel.getActiveTab) { | |
86 | // we assume lastpanel is a tabpanel | |
5a768cc5 | 87 | if (lastpanel.getActiveTab().getItemId() !== subpath) { |
0277bfeb DM |
88 | // set the active tab |
89 | lastpanel.setActiveTab(subpath); | |
90 | } | |
5a768cc5 | 91 | // else we are already there |
0277bfeb DM |
92 | } |
93 | action.stop(); | |
94 | return; | |
95 | } | |
96 | ||
97 | action.resume(); | |
98 | }, | |
99 | ||
c87d46fb | 100 | changePath: function(path, subpath) { |
28eb60c0 TL |
101 | let me = this; |
102 | let contentpanel = me.lookupReference('contentpanel'); | |
103 | let lastpanel = contentpanel.getLayout().getActiveItem(); | |
0277bfeb | 104 | |
28eb60c0 TL |
105 | let obj = contentpanel.add({ xtype: path, cselect: subpath }); |
106 | let treelist = me.lookupReference('navtree'); | |
0277bfeb DM |
107 | |
108 | treelist.suspendEvents(); | |
109 | treelist.select(path); | |
110 | treelist.resumeEvents(); | |
111 | ||
112 | if (Ext.isFunction(obj.setActiveTab)) { | |
113 | obj.setActiveTab(subpath || 0); | |
114 | obj.addListener('tabchange', function(tabpanel, newc, oldc) { | |
28eb60c0 | 115 | let newpath = path; |
0277bfeb DM |
116 | |
117 | // only add the subpath part for the | |
118 | // non-default tabs | |
119 | if (tabpanel.items.findIndex('id', newc.id) !== 0) { | |
120 | newpath += ":" + newc.getItemId(); | |
121 | } | |
122 | ||
123 | me.redirectTo(newpath); | |
124 | }); | |
125 | } | |
126 | ||
127 | contentpanel.setActiveItem(obj); | |
128 | ||
129 | if (lastpanel) { | |
130 | contentpanel.remove(lastpanel, { destroy: true }); | |
131 | } | |
132 | }, | |
133 | ||
134 | logout: function() { | |
99bba12c | 135 | PMG.app.logout(); |
0277bfeb DM |
136 | }, |
137 | ||
590a3b9f | 138 | changeLanguage: function() { |
903548bc | 139 | Ext.create('Proxmox.window.LanguageEditWindow', { |
c87d46fb | 140 | cookieName: 'PMGLangCookie', |
590a3b9f DC |
141 | }).show(); |
142 | }, | |
143 | ||
4685066c SS |
144 | changeTheme: () => Ext.create('Proxmox.window.ThemeEditWindow', { |
145 | cookieName: 'PMGThemeCookie', | |
146 | autoShow: true, | |
147 | }), | |
0277bfeb DM |
148 | navigate: function(treelist, item) { |
149 | this.redirectTo(item.get('path')); | |
150 | }, | |
151 | ||
258d48b5 | 152 | execQuarantineAction: function(qa) { |
2fa0b505 | 153 | PMG.Utils.doQuarantineAction(qa.action, qa.cselect); |
258d48b5 DM |
154 | }, |
155 | ||
99bba12c | 156 | control: { |
590a3b9f | 157 | '[reference=logoutButton]': { |
c87d46fb | 158 | click: 'logout', |
590a3b9f DC |
159 | }, |
160 | '[reference=languageButton]': { | |
161 | click: 'changeLanguage', | |
162 | }, | |
4685066c SS |
163 | '[reference=themeButton]': { |
164 | click: 'changeTheme', | |
165 | }, | |
99bba12c DC |
166 | }, |
167 | ||
0277bfeb | 168 | init: function(view) { |
28eb60c0 | 169 | let me = this; |
0277bfeb DM |
170 | |
171 | // load username | |
28eb60c0 | 172 | let username = Proxmox.UserName.replace(/@quarantine$/, ''); |
590a3b9f | 173 | me.lookupReference('usernameinfo').setText(username); |
0277bfeb DM |
174 | |
175 | // show login on requestexception | |
176 | // fixme: what about other errors | |
177 | Ext.Ajax.on('requestexception', function(conn, response, options) { | |
28eb60c0 | 178 | if (response.status === 401) { // auth failure |
0277bfeb DM |
179 | me.logout(); |
180 | } | |
181 | }); | |
182 | ||
28eb60c0 TL |
183 | let qa = PMG.Utils.extractQuarantineAction(); |
184 | let token; | |
258d48b5 | 185 | if (qa) { |
cac4542e | 186 | token = 'pmgSpamQuarantine'; |
258d48b5 DM |
187 | if (qa.action === 'blacklist') { token = 'pmgUserBlacklist'; } |
188 | if (qa.action === 'whitelist') { token = 'pmgUserWhitelist'; } | |
207471c0 DC |
189 | if (qa.cselect) { |
190 | token += ':' + qa.cselect; | |
191 | } | |
258d48b5 | 192 | this.redirectTo(token, true); |
207471c0 DC |
193 | if (qa.action) { |
194 | me.execQuarantineAction(qa); | |
195 | } | |
258d48b5 DM |
196 | } else { |
197 | // select treeitem and load page from url fragment | |
c87d46fb | 198 | |
cac4542e | 199 | token = Ext.util.History.getToken() || 'pmgSpamQuarantine'; |
258d48b5 DM |
200 | this.redirectTo(token, true); |
201 | } | |
c87d46fb | 202 | }, |
0277bfeb DM |
203 | }, |
204 | ||
205 | plugins: 'viewport', | |
206 | ||
de0ebd99 | 207 | layout: { |
c87d46fb | 208 | type: 'border', |
de0ebd99 | 209 | }, |
0277bfeb DM |
210 | |
211 | items: [ | |
212 | { | |
213 | region: 'north', | |
214 | xtype: 'container', | |
215 | layout: { | |
216 | type: 'hbox', | |
c87d46fb | 217 | align: 'middle', |
0277bfeb | 218 | }, |
11f43687 | 219 | margin: '2 0 2 5', |
c45e23e4 | 220 | height: 38, |
0277bfeb DM |
221 | items: [ |
222 | { | |
c87d46fb | 223 | xtype: 'proxmoxlogo', |
0277bfeb DM |
224 | }, |
225 | { | |
11f43687 | 226 | padding: '0 0 0 5', |
c87d46fb | 227 | xtype: 'versioninfo', |
0277bfeb DM |
228 | }, |
229 | { | |
c87d46fb | 230 | flex: 1, |
0277bfeb DM |
231 | }, |
232 | { | |
590a3b9f | 233 | xtype: 'button', |
0277bfeb | 234 | reference: 'usernameinfo', |
590a3b9f DC |
235 | style: { |
236 | // proxmox dark grey p light grey as border | |
237 | backgroundColor: '#464d4d', | |
c87d46fb | 238 | borderColor: '#ABBABA', |
590a3b9f DC |
239 | }, |
240 | margin: '0 5 0 0', | |
241 | iconCls: 'fa fa-user', | |
242 | menu: [ | |
4685066c SS |
243 | { |
244 | reference: 'themeButton', | |
245 | iconCls: 'fa fa-paint-brush', | |
246 | text: gettext('Theme'), | |
247 | }, | |
590a3b9f DC |
248 | { |
249 | iconCls: 'fa fa-language', | |
250 | text: gettext('Language'), | |
251 | reference: 'languageButton', | |
252 | }, | |
253 | '-', | |
254 | { | |
255 | reference: 'logoutButton', | |
256 | iconCls: 'fa fa-sign-out', | |
c87d46fb | 257 | text: gettext('Logout'), |
590a3b9f DC |
258 | }, |
259 | ], | |
99bba12c | 260 | }, |
c87d46fb | 261 | ], |
0277bfeb DM |
262 | }, |
263 | { | |
3d233789 TL |
264 | xtype: 'panel', |
265 | scrollable: 'y', | |
0277bfeb DM |
266 | border: false, |
267 | region: 'west', | |
3d233789 TL |
268 | layout: { |
269 | type: 'vbox', | |
270 | align: 'stretch', | |
c87d46fb | 271 | }, |
3d233789 TL |
272 | items: [ |
273 | { | |
274 | xtype: 'quarantinenavigationtree', | |
275 | reference: 'navtree', | |
276 | minWidth: 180, | |
277 | // we have to define it here until extjs 6.2 because of a bug where a | |
278 | // viewcontroller does not detect the selectionchange event of a treelist | |
279 | listeners: { | |
280 | selectionchange: 'navigate', | |
281 | }, | |
282 | }, | |
283 | { | |
284 | xtype: 'box', | |
285 | cls: 'x-treelist-pve-nav', | |
286 | flex: 1, | |
287 | }, | |
288 | ], | |
0277bfeb DM |
289 | }, |
290 | { | |
291 | xtype: 'panel', | |
de0ebd99 | 292 | layout: { |
c87d46fb | 293 | type: 'card', |
de0ebd99 | 294 | }, |
0277bfeb DM |
295 | region: 'center', |
296 | border: false, | |
c87d46fb TL |
297 | reference: 'contentpanel', |
298 | }, | |
299 | ], | |
0277bfeb | 300 | }); |