]>
Commit | Line | Data |
---|---|---|
7ece65a0 DC |
1 | Ext.define('pbs-datastore-list', { |
2 | extend: 'Ext.data.Model', | |
adf5dcba | 3 | fields: ['name', 'comment', 'maintenance'], |
7ece65a0 DC |
4 | proxy: { |
5 | type: 'proxmox', | |
6 | url: "/api2/json/admin/datastore", | |
7 | }, | |
8 | idProperty: 'store', | |
9 | }); | |
10 | ||
2e268e31 DC |
11 | Ext.define('pbs-tape-drive-list', { |
12 | extend: 'Ext.data.Model', | |
13 | fields: ['name', 'changer'], | |
14 | proxy: { | |
15 | type: 'proxmox', | |
16 | url: "/api2/json/tape/drive", | |
17 | }, | |
18 | idProperty: 'name', | |
19 | }); | |
20 | ||
b0ee976f DM |
21 | Ext.define('PBS.store.NavigationStore', { |
22 | extend: 'Ext.data.TreeStore', | |
23 | ||
24 | storeId: 'NavigationStore', | |
25 | ||
26 | root: { | |
27 | expanded: true, | |
28 | children: [ | |
84b9eced TL |
29 | { |
30 | text: gettext('Dashboard'), | |
31 | iconCls: 'fa fa-tachometer', | |
32 | path: 'pbsDashboard', | |
264c1958 | 33 | leaf: true, |
84b9eced | 34 | }, |
f3b02a9b SS |
35 | { |
36 | text: gettext('Notes'), | |
37 | iconCls: 'fa fa-sticky-note-o', | |
38 | path: 'pbsNodeNotes', | |
39 | leaf: true, | |
40 | }, | |
b0ee976f DM |
41 | { |
42 | text: gettext('Configuration'), | |
43 | iconCls: 'fa fa-gears', | |
44 | path: 'pbsSystemConfiguration', | |
45 | expanded: true, | |
46 | children: [ | |
88acc861 | 47 | { |
2f1a46f7 TL |
48 | text: gettext('Access Control'), |
49 | iconCls: 'fa fa-key', | |
50 | path: 'pbsAccessControlPanel', | |
264c1958 | 51 | leaf: true, |
0542cfdf | 52 | }, |
9e2a4653 DC |
53 | { |
54 | text: gettext('Remotes'), | |
55 | iconCls: 'fa fa-server', | |
56 | path: 'pbsRemoteView', | |
57 | leaf: true, | |
58 | }, | |
ac4e399a DC |
59 | { |
60 | text: gettext('Traffic Control'), | |
f251367c | 61 | iconCls: 'fa fa-signal fa-rotate-90', |
ac4e399a DC |
62 | path: 'pbsTrafficControlView', |
63 | leaf: true, | |
64 | }, | |
4b5d9b6e WB |
65 | { |
66 | text: gettext('Certificates'), | |
67 | iconCls: 'fa fa-certificate', | |
68 | path: 'pbsCertificateConfiguration', | |
69 | leaf: true, | |
70 | }, | |
b0ee976f DM |
71 | { |
72 | text: gettext('Subscription'), | |
73 | iconCls: 'fa fa-support', | |
74 | path: 'pbsSubscription', | |
264c1958 TL |
75 | leaf: true, |
76 | }, | |
77 | ], | |
b0ee976f DM |
78 | }, |
79 | { | |
80 | text: gettext('Administration'), | |
81 | iconCls: 'fa fa-wrench', | |
82 | path: 'pbsServerAdministration', | |
7f17f744 DC |
83 | expanded: true, |
84 | leaf: false, | |
85 | children: [ | |
8e12e86f DC |
86 | { |
87 | text: gettext('Shell'), | |
88 | iconCls: 'fa fa-terminal', | |
89 | path: 'pbsXtermJsConsole', | |
90 | leaf: true, | |
91 | }, | |
7f17f744 | 92 | { |
ee0ab12d | 93 | text: gettext('Storage / Disks'), |
7f17f744 | 94 | iconCls: 'fa fa-hdd-o', |
ee0ab12d TL |
95 | path: 'pbsStorageAndDiskPanel', |
96 | leaf: true, | |
264c1958 TL |
97 | }, |
98 | ], | |
98bb3b90 | 99 | }, |
a21f9852 TL |
100 | { |
101 | text: "Tape Backup", | |
102 | iconCls: 'pbs-icon-tape', | |
103 | id: 'tape_management', | |
104 | path: 'pbsTapeManagement', | |
105 | expanded: true, | |
106 | children: [], | |
107 | }, | |
98bb3b90 | 108 | { |
58f950c5 | 109 | text: gettext('Datastore'), |
98bb3b90 | 110 | iconCls: 'fa fa-archive', |
7ece65a0 | 111 | id: 'datastores', |
ed1329ec | 112 | path: 'pbsDataStores', |
98bb3b90 | 113 | expanded: true, |
7ece65a0 | 114 | expandable: false, |
264c1958 | 115 | leaf: false, |
7ece65a0 DC |
116 | children: [ |
117 | { | |
118 | text: gettext('Add Datastore'), | |
119 | iconCls: 'fa fa-plus-circle', | |
120 | leaf: true, | |
121 | id: 'addbutton', | |
bc42bb3c | 122 | virtualEntry: true, |
7ece65a0 DC |
123 | }, |
124 | ], | |
98bb3b90 | 125 | }, |
264c1958 TL |
126 | ], |
127 | }, | |
b0ee976f DM |
128 | }); |
129 | ||
130 | Ext.define('PBS.view.main.NavigationTree', { | |
131 | extend: 'Ext.list.Tree', | |
132 | xtype: 'navigationtree', | |
133 | ||
ca23a97f DM |
134 | controller: { |
135 | xclass: 'Ext.app.ViewController', | |
136 | ||
137 | init: function(view) { | |
ca23a97f DM |
138 | view.rstore = Ext.create('Proxmox.data.UpdateStore', { |
139 | autoStart: true, | |
140 | interval: 15 * 1000, | |
141 | storeid: 'pbs-datastore-list', | |
264c1958 | 142 | model: 'pbs-datastore-list', |
ca23a97f DM |
143 | }); |
144 | ||
145 | view.rstore.on('load', this.onLoad, this); | |
146 | view.on('destroy', view.rstore.stopUpdate); | |
2e268e31 | 147 | |
fa29d7eb TL |
148 | if (view.tapeStore === undefined) { |
149 | view.tapeStore = Ext.create('Proxmox.data.UpdateStore', { | |
a21f9852 TL |
150 | autoStart: true, |
151 | interval: 60 * 1000, | |
152 | storeid: 'pbs-tape-drive-list', | |
153 | model: 'pbs-tape-drive-list', | |
154 | }); | |
fa29d7eb TL |
155 | view.tapeStore.on('load', this.onTapeDriveLoad, this); |
156 | view.on('destroy', view.tapeStore.stopUpdate); | |
2e268e31 | 157 | } |
ca23a97f DM |
158 | }, |
159 | ||
2e268e31 | 160 | onTapeDriveLoad: function(store, records, success) { |
98bb3b90 | 161 | if (!success) return; |
ca23a97f | 162 | |
2e268e31 | 163 | let view = this.getView(); |
ca23a97f DM |
164 | let root = view.getStore().getRoot(); |
165 | ||
2e268e31 | 166 | records.sort((a, b) => a.data.name.localeCompare(b.data.name)); |
2e268e31 | 167 | |
94b7f56e TL |
168 | let list = root.findChild('id', 'tape_management', false); |
169 | let existingChildren = {}; | |
2e268e31 DC |
170 | for (const drive of records) { |
171 | let path, text, iconCls; | |
172 | if (drive.data.changer !== undefined) { | |
173 | text = drive.data.changer; | |
174 | path = `Changer-${text}`; | |
9a8bf2ca | 175 | iconCls = 'fa fa-exchange'; |
2e268e31 DC |
176 | } else { |
177 | text = drive.data.name; | |
178 | path = `Drive-${text}`; | |
9a8bf2ca | 179 | iconCls = 'pbs-icon-tape-drive'; |
2e268e31 | 180 | } |
94b7f56e | 181 | existingChildren[path] = { |
2e268e31 DC |
182 | text, |
183 | path, | |
184 | iconCls, | |
185 | leaf: true, | |
186 | }; | |
187 | } | |
188 | ||
94b7f56e | 189 | let paths = Object.keys(existingChildren).sort(); |
2e268e31 DC |
190 | |
191 | let oldIdx = 0; | |
192 | for (let newIdx = 0; newIdx < paths.length; newIdx++) { | |
193 | let newPath = paths[newIdx]; | |
194 | // find index to insert | |
195 | while (oldIdx < list.childNodes.length && newPath > list.getChildAt(oldIdx).data.path) { | |
196 | oldIdx++; | |
197 | } | |
198 | ||
199 | if (oldIdx >= list.childNodes.length || list.getChildAt(oldIdx).data.path !== newPath) { | |
94b7f56e | 200 | list.insertChild(oldIdx, existingChildren[newPath]); |
ff50c07e DM |
201 | } |
202 | } | |
203 | ||
94b7f56e | 204 | let toRemove = []; |
2e268e31 | 205 | list.eachChild((child) => { |
94b7f56e TL |
206 | if (!existingChildren[child.data.path]) { |
207 | toRemove.push(child); | |
2e268e31 DC |
208 | } |
209 | }); | |
94b7f56e | 210 | toRemove.forEach((child) => list.removeChild(child, true)); |
2e268e31 DC |
211 | |
212 | if (view.pathToSelect !== undefined) { | |
213 | let path = view.pathToSelect; | |
214 | delete view.pathToSelect; | |
215 | view.select(path, true); | |
216 | } | |
217 | }, | |
218 | ||
219 | onLoad: function(store, records, success) { | |
94b7f56e TL |
220 | if (!success) { |
221 | return; | |
222 | } | |
223 | let view = this.getView(); | |
2e268e31 DC |
224 | let root = view.getStore().getRoot(); |
225 | ||
7ece65a0 | 226 | records.sort((a, b) => a.id.localeCompare(b.id)); |
8277f4ac | 227 | |
94b7f56e TL |
228 | let list = root.findChild('id', 'datastores', false); |
229 | let getChildTextAt = i => list.getChildAt(i).data.text; | |
230 | let existingChildren = {}; | |
231 | for (let i = 0, j = 0, length = records.length; i < length; i++) { | |
264c1958 | 232 | let name = records[i].id; |
94b7f56e | 233 | existingChildren[name] = true; |
7ece65a0 | 234 | |
94b7f56e | 235 | while (name.localeCompare(getChildTextAt(j)) > 0 && (j+1) < list.childNodes.length) { |
7ece65a0 DC |
236 | j++; |
237 | } | |
238 | ||
adf5dcba HL |
239 | let iconCls = 'fa fa-database'; |
240 | const maintenance = records[i].data.maintenance; | |
241 | if (maintenance) { | |
242 | iconCls = 'fa fa-database pmx-tree-icon-custom maintenance'; | |
243 | } | |
244 | ||
245 | const child = { | |
246 | text: name, | |
247 | path: `DataStore-${name}`, | |
248 | iconCls, | |
249 | leaf: true, | |
250 | }; | |
94b7f56e | 251 | if (getChildTextAt(j).localeCompare(name) !== 0) { |
adf5dcba HL |
252 | list.insertChild(j, child); |
253 | } else { | |
254 | list.replaceChild(child, list.getChildAt(j)); | |
ca23a97f DM |
255 | } |
256 | } | |
257 | ||
94b7f56e TL |
258 | // remove entries which are not existing anymore |
259 | let toRemove = []; | |
260 | list.eachChild(child => { | |
bc42bb3c | 261 | if (!existingChildren[child.data.text] && !child.data.virtualEntry) { |
94b7f56e | 262 | toRemove.push(child); |
ca23a97f DM |
263 | } |
264 | }); | |
94b7f56e | 265 | toRemove.forEach(child => list.removeChild(child, true)); |
2565fdd0 DC |
266 | |
267 | if (view.pathToSelect !== undefined) { | |
268 | let path = view.pathToSelect; | |
269 | delete view.pathToSelect; | |
270 | view.select(path, true); | |
271 | } | |
7ece65a0 DC |
272 | }, |
273 | }, | |
274 | ||
275 | listeners: { | |
276 | itemclick: function(tl, info) { | |
7ece65a0 DC |
277 | if (info.node.data.id === 'addbutton') { |
278 | let me = this; | |
279 | Ext.create('PBS.DataStoreEdit', { | |
280 | listeners: { | |
f05085ab | 281 | destroy: () => me.rstore.reload(), |
7ece65a0 DC |
282 | }, |
283 | }).show(); | |
284 | return false; | |
285 | } | |
286 | return true; | |
264c1958 | 287 | }, |
ca23a97f DM |
288 | }, |
289 | ||
dcf155da DC |
290 | reloadTapeStore: function() { |
291 | let me = this; | |
fa29d7eb | 292 | me.tapeStore.load(); |
dcf155da DC |
293 | }, |
294 | ||
2565fdd0 | 295 | select: function(path, silent) { |
b0ee976f | 296 | var me = this; |
fa29d7eb | 297 | if (me.rstore.isLoaded() && me.tapeStore.isLoaded()) { |
2565fdd0 DC |
298 | if (silent) { |
299 | me.suspendEvents(false); | |
300 | } | |
301 | var item = me.getStore().findRecord('path', path, 0, false, true, true); | |
302 | me.setSelection(item); | |
303 | if (silent) { | |
304 | me.resumeEvents(true); | |
305 | } | |
306 | } else { | |
307 | me.pathToSelect = path; | |
308 | } | |
b0ee976f DM |
309 | }, |
310 | ||
311 | animation: false, | |
312 | expanderOnly: true, | |
313 | expanderFirst: false, | |
314 | store: 'NavigationStore', | |
264c1958 | 315 | ui: 'nav', |
b0ee976f | 316 | }); |