]> git.proxmox.com Git - proxmox-backup.git/blame - www/MainView.js
cargo config: add `debug=true`
[proxmox-backup.git] / www / MainView.js
CommitLineData
5c7a1b15
DM
1Ext.define('PBS.MainView', {
2 extend: 'Ext.container.Container',
3 xtype: 'mainview',
4
5 title: 'Proxmox Backup Server',
6
7 controller: {
8 xclass: 'Ext.app.ViewController',
9 routes: {
10 ':path:subpath': {
11 action: 'changePath',
12 before: 'beforeChangePath',
8acd4d9a
TL
13 conditions: {
14 ':path': '(?:([%a-zA-Z0-9\\-\\_\\s,.]+))',
15 ':subpath': '(?:(?::)([%a-zA-Z0-9\\-\\_\\s,]+))?',
16 },
17 },
5c7a1b15 18 },
2e75b6d8 19
3e182fd8 20 parseRouterPath: function(path) {
c0ac2074 21 let xtype = path;
3e182fd8
DC
22 let config = {};
23 if (PBS.Utils.isDataStorePath(path)) {
24 config.datastore = PBS.Utils.getDataStoreFromPath(path);
c0ac2074 25 xtype = 'pbsDataStorePanel';
3e182fd8
DC
26 } else if (path.indexOf('Changer-') === 0) {
27 config.changer = path.slice('Changer-'.length);
28 xtype = 'pbsChangerStatus';
29 } else if (path.indexOf('Drive-') === 0) {
30 config.drive = path.slice('Drive-'.length);
31 xtype = 'pbsDriveStatus';
c0ac2074
DC
32 }
33
3e182fd8
DC
34 return [xtype, config];
35 },
36
90066d22 37 beforeChangePath: function(path, subpathOrAction, action) {
3e182fd8
DC
38 var me = this;
39
90066d22
DC
40 let subpath = subpathOrAction;
41 if (!action) {
42 action = subpathOrAction;
43 subpath = undefined;
44 }
45
3e182fd8
DC
46 let [xtype, config] = me.parseRouterPath(path);
47
c0ac2074
DC
48 if (!Ext.ClassManager.getByAlias(`widget.${xtype}`)) {
49 console.warn(`xtype ${xtype} not found`);
b0ee976f
DM
50 action.stop();
51 return;
52 }
53
54 var lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem();
c0ac2074 55 if (lastpanel && lastpanel.xtype === xtype) {
3e182fd8
DC
56 for (const [prop, value] of Object.entries(config)) {
57 if (lastpanel[prop] !== value) {
58 action.resume();
ca23a97f
DM
59 return;
60 }
3e182fd8
DC
61 }
62 // we have the right component already,
63 // we just need to select the correct tab
64 // default to the first
65 subpath = subpath || 0;
66 if (lastpanel.getActiveTab) {
67 // we assume lastpanel is a tabpanel
68 if (lastpanel.getActiveTab().getItemId() !== subpath) {
69 // set the active tab
70 lastpanel.setActiveTab(subpath);
b0ee976f 71 }
3e182fd8 72 // else we are already there
b0ee976f 73 }
3e182fd8
DC
74 action.stop();
75 return;
b0ee976f
DM
76 }
77
5c7a1b15
DM
78 action.resume();
79 },
2e75b6d8 80
ca23a97f 81 changePath: function(path, subpath) {
5c7a1b15
DM
82 var me = this;
83 var contentpanel = me.lookupReference('contentpanel');
84 var lastpanel = contentpanel.getLayout().getActiveItem();
85
2565fdd0
DC
86 let tabChangeListener = function(tp, newc, oldc) {
87 let newpath = path;
b0ee976f 88
2565fdd0
DC
89 // only add the subpath part for the
90 // non-default tabs
91 if (tp.items.findIndex('id', newc.id) !== 0) {
92 newpath += `:${newc.getItemId()}`;
93 }
b0ee976f 94
2565fdd0
DC
95 me.redirectTo(newpath);
96 };
b0ee976f 97
3e182fd8 98 let [xtype, config] = me.parseRouterPath(path);
2565fdd0 99 var obj;
2565fdd0 100 if (PBS.Utils.isDataStorePath(path)) {
3e182fd8 101 if (lastpanel && lastpanel.xtype === xtype && !subpath) {
2565fdd0
DC
102 let activeTab = lastpanel.getActiveTab();
103 let newpath = path;
104 if (lastpanel.items.indexOf(activeTab) !== 0) {
105 subpath = activeTab.getItemId();
106 newpath += `:${subpath}`;
b0ee976f 107 }
b0ee976f 108 me.redirectTo(newpath);
2565fdd0 109 }
b0ee976f 110 }
3e182fd8 111 obj = contentpanel.add(Ext.apply(config, {
2565fdd0 112 xtype,
2565fdd0
DC
113 nodename: 'localhost',
114 border: false,
115 activeTab: subpath || 0,
116 listeners: {
117 tabchange: tabChangeListener,
118 },
3e182fd8 119 }));
2565fdd0
DC
120
121 var treelist = me.lookupReference('navtree');
122
123 treelist.select(path, true);
b0ee976f
DM
124
125 contentpanel.setActiveItem(obj);
126
127 if (lastpanel) {
128 contentpanel.remove(lastpanel, { destroy: true });
129 }
b0ee976f
DM
130 },
131
34f956bc
DM
132 logout: function() {
133 PBS.app.logout();
134 },
135
b0ee976f
DM
136 navigate: function(treelist, item) {
137 this.redirectTo(item.get('path'));
5c7a1b15
DM
138 },
139
34f956bc 140 control: {
f6e964b9 141 '[reference=logoutButton]': {
8acd4d9a
TL
142 click: 'logout',
143 },
34f956bc
DM
144 },
145
5c7a1b15
DM
146 init: function(view) {
147 var me = this;
5c7a1b15 148
cc83c136 149 PBS.data.RunningTasksStore.startUpdate();
f6e964b9 150 me.lookupReference('usernameinfo').setText(Proxmox.UserName);
a602faeb 151
8af272fd
TL
152 // show login on requestexception
153 // fixme: what about other errors
154 Ext.Ajax.on('requestexception', function(conn, response, options) {
8acd4d9a 155 if (response.status === 401 || response.status === '401') { // auth failure
8af272fd
TL
156 me.logout();
157 }
158 });
159
a602faeb
TL
160 // get ticket periodically
161 Ext.TaskManager.start({
162 run: function() {
163 var ticket = Proxmox.Utils.authOK();
164 if (!ticket || !Proxmox.UserName) {
165 return;
166 }
167
168 Ext.Ajax.request({
169 params: {
170 username: Proxmox.UserName,
8acd4d9a 171 password: ticket,
a602faeb
TL
172 },
173 url: '/api2/json/access/ticket',
174 method: 'POST',
175 failure: function() {
176 me.logout();
177 },
178 success: function(response, opts) {
179 var obj = Ext.decode(response.responseText);
323515c2 180 PBS.Utils.updateLoginData(obj.data);
8acd4d9a 181 },
a602faeb
TL
182 });
183 },
8acd4d9a 184 interval: 15*60*1000,
a602faeb 185 });
9710e5d0 186
a662274e
DC
187 Proxmox.Utils.API2Request({
188 url: `/api2/extjs/nodes/localhost/status`,
189 success: function({ result }) {
190 if (result?.data?.info?.fingerprint) {
191 Proxmox.Fingerprint = result.data.info.fingerprint;
192 }
193 },
194 failure: function() {
195 // silently ignore errors
196 },
197 });
9710e5d0
TL
198
199 // select treeitem and load page from url fragment, if set
200 let token = Ext.util.History.getToken() || 'pbsDashboard';
67466ce5 201 this.redirectTo(token, { force: true });
8acd4d9a 202 },
5c7a1b15
DM
203 },
204
205 plugins: 'viewport',
206
207 layout: { type: 'border' },
208
209 items: [
210 {
211 region: 'north',
212 xtype: 'container',
213 layout: {
214 type: 'hbox',
8acd4d9a 215 align: 'middle',
5c7a1b15 216 },
86443141 217 margin: '2 0 2 5',
5c7a1b15
DM
218 height: 38,
219 items: [
220 {
1d8ef0dc
DC
221 xtype: 'proxmoxlogo',
222 prefix: '',
5c7a1b15
DM
223 },
224 {
86443141
TL
225 padding: '0 0 0 5',
226 xtype: 'versioninfo',
5c7a1b15
DM
227 },
228 {
bd260569
DC
229 flex: 1,
230 baseCls: 'x-plain',
5c7a1b15 231 },
9c01e73c
TL
232 {
233 xtype: 'button',
234 baseCls: 'x-btn',
235 cls: 'x-btn-default-toolbar-small proxmox-inline-button',
236 iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
237 text: gettext('Documentation'),
238 href: '/docs/index.html',
239 margin: '0 5 0 0',
240 },
a3970d6c
DC
241 {
242 xtype: 'pbsTaskButton',
243 margin: '0 5 0 0',
244 },
5c7a1b15 245 {
5c7a1b15 246 xtype: 'button',
f6e964b9
TL
247 reference: 'usernameinfo',
248 style: {
249 // proxmox dark grey p light grey as border
250 backgroundColor: '#464d4d',
8acd4d9a 251 borderColor: '#ABBABA',
f6e964b9
TL
252 },
253 margin: '0 5 0 0',
254 iconCls: 'fa fa-user',
255 menu: [
85eedfb7
DC
256 {
257 iconCls: 'fa fa-gear',
258 text: gettext('My Settings'),
259 handler: () => Ext.create('PBS.window.Settings').show(),
260 },
a443dd5c
SS
261 {
262 iconCls: 'fa fa-paint-brush',
18c2110b 263 text: gettext('Color Theme'),
a443dd5c
SS
264 handler: () => Ext.create('Proxmox.window.ThemeEditWindow', {
265 cookieName: 'PBSThemeCookie',
266 autoShow: true,
267 }),
268 },
f6e964b9 269 {
f8a682a8
TL
270 iconCls: 'fa fa-language',
271 text: gettext('Language'),
272 reference: 'languageButton',
273 handler: () => Ext.create('Proxmox.window.LanguageEditWindow', {
274 cookieName: 'PBSLangCookie',
275 autoShow: true,
276 }),
277 },
278 '-',
279 {
f6e964b9
TL
280 iconCls: 'fa fa-sign-out',
281 text: gettext('Logout'),
f8a682a8 282 reference: 'logoutButton',
f6e964b9
TL
283 },
284 ],
285 },
8acd4d9a 286 ],
5c7a1b15
DM
287 },
288 {
ecf5f468 289 xtype: 'container',
5c7a1b15
DM
290 scrollable: 'y',
291 border: false,
292 region: 'west',
293 layout: {
294 type: 'vbox',
8acd4d9a 295 align: 'stretch',
5c7a1b15 296 },
b0ee976f
DM
297 items: [{
298 xtype: 'navigationtree',
299 minWidth: 180,
c793da1e 300 ui: 'pve-nav',
b0ee976f
DM
301 reference: 'navtree',
302 // we have to define it here until extjs 6.2
303 // because of a bug where a viewcontroller does not detect
304 // the selectionchange event of a treelist
305 listeners: {
8acd4d9a
TL
306 selectionchange: 'navigate',
307 },
b0ee976f
DM
308 }, {
309 xtype: 'box',
c793da1e 310 cls: 'x-treelist-pve-nav',
8acd4d9a
TL
311 flex: 1,
312 }],
5c7a1b15
DM
313 },
314 {
ecf5f468 315 xtype: 'container',
5c7a1b15
DM
316 layout: { type: 'card' },
317 region: 'center',
318 border: false,
8acd4d9a
TL
319 reference: 'contentpanel',
320 },
321 ],
5c7a1b15 322});