]> git.proxmox.com Git - proxmox-backup.git/blame - www/MainView.js
ui: system config: fix leading whitespace in translation
[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
TL
186
187
188 // select treeitem and load page from url fragment, if set
189 let token = Ext.util.History.getToken() || 'pbsDashboard';
67466ce5 190 this.redirectTo(token, { force: true });
8acd4d9a 191 },
5c7a1b15
DM
192 },
193
194 plugins: 'viewport',
195
196 layout: { type: 'border' },
197
198 items: [
199 {
200 region: 'north',
201 xtype: 'container',
202 layout: {
203 type: 'hbox',
8acd4d9a 204 align: 'middle',
5c7a1b15 205 },
86443141 206 margin: '2 0 2 5',
5c7a1b15
DM
207 height: 38,
208 items: [
209 {
1d8ef0dc
DC
210 xtype: 'proxmoxlogo',
211 prefix: '',
5c7a1b15
DM
212 },
213 {
86443141
TL
214 padding: '0 0 0 5',
215 xtype: 'versioninfo',
5c7a1b15
DM
216 },
217 {
bd260569
DC
218 flex: 1,
219 baseCls: 'x-plain',
5c7a1b15 220 },
9c01e73c
TL
221 {
222 xtype: 'button',
223 baseCls: 'x-btn',
224 cls: 'x-btn-default-toolbar-small proxmox-inline-button',
225 iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
226 text: gettext('Documentation'),
227 href: '/docs/index.html',
228 margin: '0 5 0 0',
229 },
a3970d6c
DC
230 {
231 xtype: 'pbsTaskButton',
232 margin: '0 5 0 0',
233 },
5c7a1b15 234 {
5c7a1b15 235 xtype: 'button',
f6e964b9
TL
236 reference: 'usernameinfo',
237 style: {
238 // proxmox dark grey p light grey as border
239 backgroundColor: '#464d4d',
8acd4d9a 240 borderColor: '#ABBABA',
f6e964b9
TL
241 },
242 margin: '0 5 0 0',
243 iconCls: 'fa fa-user',
244 menu: [
85eedfb7
DC
245 {
246 iconCls: 'fa fa-gear',
247 text: gettext('My Settings'),
248 handler: () => Ext.create('PBS.window.Settings').show(),
249 },
a443dd5c
SS
250 {
251 iconCls: 'fa fa-paint-brush',
18c2110b 252 text: gettext('Color Theme'),
a443dd5c
SS
253 handler: () => Ext.create('Proxmox.window.ThemeEditWindow', {
254 cookieName: 'PBSThemeCookie',
255 autoShow: true,
256 }),
257 },
f6e964b9 258 {
f8a682a8
TL
259 iconCls: 'fa fa-language',
260 text: gettext('Language'),
261 reference: 'languageButton',
262 handler: () => Ext.create('Proxmox.window.LanguageEditWindow', {
263 cookieName: 'PBSLangCookie',
264 autoShow: true,
265 }),
266 },
267 '-',
268 {
f6e964b9
TL
269 iconCls: 'fa fa-sign-out',
270 text: gettext('Logout'),
f8a682a8 271 reference: 'logoutButton',
f6e964b9
TL
272 },
273 ],
274 },
8acd4d9a 275 ],
5c7a1b15
DM
276 },
277 {
ecf5f468 278 xtype: 'container',
5c7a1b15
DM
279 scrollable: 'y',
280 border: false,
281 region: 'west',
282 layout: {
283 type: 'vbox',
8acd4d9a 284 align: 'stretch',
5c7a1b15 285 },
b0ee976f
DM
286 items: [{
287 xtype: 'navigationtree',
288 minWidth: 180,
c793da1e 289 ui: 'pve-nav',
b0ee976f
DM
290 reference: 'navtree',
291 // we have to define it here until extjs 6.2
292 // because of a bug where a viewcontroller does not detect
293 // the selectionchange event of a treelist
294 listeners: {
8acd4d9a
TL
295 selectionchange: 'navigate',
296 },
b0ee976f
DM
297 }, {
298 xtype: 'box',
c793da1e 299 cls: 'x-treelist-pve-nav',
8acd4d9a
TL
300 flex: 1,
301 }],
5c7a1b15
DM
302 },
303 {
ecf5f468 304 xtype: 'container',
5c7a1b15
DM
305 layout: { type: 'card' },
306 region: 'center',
307 border: false,
8acd4d9a
TL
308 reference: 'contentpanel',
309 },
310 ],
5c7a1b15 311});