]> git.proxmox.com Git - proxmox-backup.git/blob - www/MainView.js
ui: align version and user-menu spacing with pve/pmg
[proxmox-backup.git] / www / MainView.js
1 Ext.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',
13 conditions : {
14 ':path' : '(?:([%a-zA-Z0-9\\-\\_\\s,\.]+))',
15 ':subpath' : '(?:(?::)([%a-zA-Z0-9\\-\\_\\s,]+))?'
16 }
17 }
18 },
19
20 beforeChangePath: function(path, subpath, action) {
21 var me = this;
22
23 let xtype = path;
24 let datastore;
25 let isDataStore = PBS.Utils.isDataStorePath(path);
26 if (isDataStore) {
27 xtype = 'pbsDataStorePanel';
28 datastore = PBS.Utils.getDataStoreFromPath(path);
29 }
30
31 if (!Ext.ClassManager.getByAlias(`widget.${xtype}`)) {
32 console.warn(`xtype ${xtype} not found`);
33 action.stop();
34 return;
35 }
36
37 var lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem();
38 if (lastpanel && lastpanel.xtype === xtype) {
39 if (isDataStore) {
40 if (datastore === lastpanel.datastore) {
41 action.stop();
42 return;
43 }
44 } else {
45 // we have the right component already,
46 // we just need to select the correct tab
47 // default to the first
48 subpath = subpath || 0;
49 if (lastpanel.getActiveTab) {
50 // we assume lastpanel is a tabpanel
51 if (lastpanel.getActiveTab().getItemId() !== subpath) {
52 // set the active tab
53 lastpanel.setActiveTab(subpath);
54 }
55 // else we are already there
56 }
57 action.stop();
58 return;
59 }
60 }
61
62 action.resume();
63 },
64
65 changePath: function(path, subpath) {
66 var me = this;
67 var contentpanel = me.lookupReference('contentpanel');
68 var lastpanel = contentpanel.getLayout().getActiveItem();
69
70 var obj;
71 if (PBS.Utils.isDataStorePath(path)) {
72 let datastore = PBS.Utils.getDataStoreFromPath(path);
73 obj = contentpanel.add({
74 xtype: 'pbsDataStorePanel',
75 nodename: 'localhost',
76 datastore,
77 });
78 } else {
79 obj = contentpanel.add({
80 xtype: path,
81 nodename: 'localhost',
82 border: false
83 });
84 }
85
86 var treelist = me.lookupReference('navtree');
87
88 treelist.suspendEvents();
89 if (subpath === undefined) {
90 treelist.select(path);
91 } else {
92 treelist.select(path + ':' + subpath);
93 }
94 treelist.resumeEvents();
95
96 if (Ext.isFunction(obj.setActiveTab)) {
97 obj.setActiveTab(subpath || 0);
98 obj.addListener('tabchange', function(tabpanel, newc, oldc) {
99 var newpath = path;
100
101 // only add the subpath part for the
102 // non-default tabs
103 if (tabpanel.items.findIndex('id', newc.id) !== 0) {
104 newpath += ":" + newc.getItemId();
105 }
106
107 me.redirectTo(newpath);
108 });
109 }
110
111 contentpanel.setActiveItem(obj);
112
113 if (lastpanel) {
114 contentpanel.remove(lastpanel, { destroy: true });
115 }
116
117 },
118
119 logout: function() {
120 PBS.app.logout();
121 },
122
123 navigate: function(treelist, item) {
124 this.redirectTo(item.get('path'));
125 },
126
127 control: {
128 '[reference=logoutButton]': {
129 click: 'logout'
130 }
131 },
132
133 init: function(view) {
134 var me = this;
135
136 PBS.data.RunningTasksStore.startUpdate();
137 me.lookupReference('usernameinfo').setText(Proxmox.UserName);
138
139 // show login on requestexception
140 // fixme: what about other errors
141 Ext.Ajax.on('requestexception', function(conn, response, options) {
142 if (response.status == 401) { // auth failure
143 me.logout();
144 }
145 });
146
147 // get ticket periodically
148 Ext.TaskManager.start({
149 run: function() {
150 var ticket = Proxmox.Utils.authOK();
151 if (!ticket || !Proxmox.UserName) {
152 return;
153 }
154
155 Ext.Ajax.request({
156 params: {
157 username: Proxmox.UserName,
158 password: ticket
159 },
160 url: '/api2/json/access/ticket',
161 method: 'POST',
162 failure: function() {
163 me.logout();
164 },
165 success: function(response, opts) {
166 var obj = Ext.decode(response.responseText);
167 PBS.Utils.updateLoginData(obj.data);
168 }
169 });
170 },
171 interval: 15*60*1000
172 });
173
174
175 // select treeitem and load page from url fragment, if set
176 let token = Ext.util.History.getToken() || 'pbsDashboard';
177 this.redirectTo(token, true);
178 }
179 },
180
181 plugins: 'viewport',
182
183 layout: { type: 'border' },
184
185 items: [
186 {
187 region: 'north',
188 xtype: 'container',
189 layout: {
190 type: 'hbox',
191 align: 'middle'
192 },
193 margin: '2 0 2 5',
194 height: 38,
195 items: [
196 {
197 xtype: 'proxmoxlogo',
198 prefix: '',
199 },
200 {
201 padding: '0 0 0 5',
202 xtype: 'versioninfo',
203 },
204 {
205 padding: 5,
206 html: '<a href="https://bugzilla.proxmox.com" target="_blank">BETA</a>',
207 baseCls: 'x-plain',
208 },
209 {
210 flex: 1,
211 baseCls: 'x-plain',
212 },
213 {
214 xtype: 'button',
215 baseCls: 'x-btn',
216 cls: 'x-btn-default-toolbar-small proxmox-inline-button',
217 iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
218 text: gettext('Documentation'),
219 href: '/docs/index.html',
220 margin: '0 5 0 0',
221 },
222 {
223 xtype: 'pbsTaskButton',
224 margin: '0 5 0 0',
225 },
226 {
227 xtype: 'button',
228 reference: 'usernameinfo',
229 style: {
230 // proxmox dark grey p light grey as border
231 backgroundColor: '#464d4d',
232 borderColor: '#ABBABA'
233 },
234 margin: '0 5 0 0',
235 iconCls: 'fa fa-user',
236 menu: [
237 {
238 reference: 'logoutButton',
239 iconCls: 'fa fa-sign-out',
240 text: gettext('Logout'),
241 },
242 ],
243 },
244 ]
245 },
246 {
247 xtype: 'panel',
248 scrollable: 'y',
249 border: false,
250 region: 'west',
251 layout: {
252 type: 'vbox',
253 align: 'stretch'
254 },
255 items: [{
256 xtype: 'navigationtree',
257 minWidth: 180,
258 reference: 'navtree',
259 // we have to define it here until extjs 6.2
260 // because of a bug where a viewcontroller does not detect
261 // the selectionchange event of a treelist
262 listeners: {
263 selectionchange: 'navigate'
264 }
265 }, {
266 xtype: 'box',
267 cls: 'x-treelist-nav',
268 flex: 1
269 }]
270 },
271 {
272 xtype: 'panel',
273 layout: { type: 'card' },
274 region: 'center',
275 border: false,
276 reference: 'contentpanel'
277 }
278 ]
279 });