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