* [pbs-devel] [PATCH proxmox-backup 2/5] ui: MainView: adapt router to add changer/drive entries
2021-03-01 11:22 [pbs-devel] [PATCH proxmox-backup 1/5] ui: tape: add DriveStatus panel Dominik Csapak
@ 2021-03-01 11:22 ` Dominik Csapak
2021-03-01 11:22 ` [pbs-devel] [PATCH proxmox-backup 3/5] ui: NavigationTree: add entries for changers/drives Dominik Csapak
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2021-03-01 11:22 UTC (permalink / raw)
To: pbs-devel
by generalizing the isDataStorePath logic to a 'parseRouterPath'.
We still have to keep the isDataStore logic for tabpanel handling,
If we add tabs to changer-/drivestatus panels, we have to adapt
that too.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/MainView.js | 70 +++++++++++++++++++++++++++----------------------
1 file changed, 38 insertions(+), 32 deletions(-)
diff --git a/www/MainView.js b/www/MainView.js
index 6ed86b77..e6257f35 100644
--- a/www/MainView.js
+++ b/www/MainView.js
@@ -17,17 +17,28 @@ Ext.define('PBS.MainView', {
},
},
- beforeChangePath: function(path, subpath, action) {
- var me = this;
-
+ parseRouterPath: function(path) {
let xtype = path;
- let datastore;
- let isDataStore = PBS.Utils.isDataStorePath(path);
- if (isDataStore) {
+ let config = {};
+ if (PBS.Utils.isDataStorePath(path)) {
+ config.datastore = PBS.Utils.getDataStoreFromPath(path);
xtype = 'pbsDataStorePanel';
- datastore = PBS.Utils.getDataStoreFromPath(path);
+ } else if (path.indexOf('Changer-') === 0) {
+ config.changer = path.slice('Changer-'.length);
+ xtype = 'pbsChangerStatus';
+ } else if (path.indexOf('Drive-') === 0) {
+ config.drive = path.slice('Drive-'.length);
+ xtype = 'pbsDriveStatus';
}
+ return [xtype, config];
+ },
+
+ beforeChangePath: function(path, subpath, action) {
+ var me = this;
+
+ let [xtype, config] = me.parseRouterPath(path);
+
if (!Ext.ClassManager.getByAlias(`widget.${xtype}`)) {
console.warn(`xtype ${xtype} not found`);
action.stop();
@@ -36,27 +47,26 @@ Ext.define('PBS.MainView', {
var lastpanel = me.lookupReference('contentpanel').getLayout().getActiveItem();
if (lastpanel && lastpanel.xtype === xtype) {
- if (isDataStore) {
- if (datastore === lastpanel.datastore) {
- action.stop();
+ for (const [prop, value] of Object.entries(config)) {
+ if (lastpanel[prop] !== value) {
+ action.resume();
return;
}
- } else {
- // we have the right component already,
- // we just need to select the correct tab
- // default to the first
- subpath = subpath || 0;
- if (lastpanel.getActiveTab) {
- // we assume lastpanel is a tabpanel
- if (lastpanel.getActiveTab().getItemId() !== subpath) {
- // set the active tab
- lastpanel.setActiveTab(subpath);
- }
- // else we are already there
+ }
+ // we have the right component already,
+ // we just need to select the correct tab
+ // default to the first
+ subpath = subpath || 0;
+ if (lastpanel.getActiveTab) {
+ // we assume lastpanel is a tabpanel
+ if (lastpanel.getActiveTab().getItemId() !== subpath) {
+ // set the active tab
+ lastpanel.setActiveTab(subpath);
}
- action.stop();
- return;
+ // else we are already there
}
+ action.stop();
+ return;
}
action.resume();
@@ -79,12 +89,10 @@ Ext.define('PBS.MainView', {
me.redirectTo(newpath);
};
- let xtype = path;
+ let [xtype, config] = me.parseRouterPath(path);
var obj;
- let datastore;
if (PBS.Utils.isDataStorePath(path)) {
- datastore = PBS.Utils.getDataStoreFromPath(path);
- if (lastpanel && lastpanel.xtype === 'pbsDataStorePanel' && !subpath) {
+ if (lastpanel && lastpanel.xtype === xtype && !subpath) {
let activeTab = lastpanel.getActiveTab();
let newpath = path;
if (lastpanel.items.indexOf(activeTab) !== 0) {
@@ -93,18 +101,16 @@ Ext.define('PBS.MainView', {
}
me.redirectTo(newpath);
}
- xtype = 'pbsDataStorePanel';
}
- obj = contentpanel.add({
+ obj = contentpanel.add(Ext.apply(config, {
xtype,
- datastore,
nodename: 'localhost',
border: false,
activeTab: subpath || 0,
listeners: {
tabchange: tabChangeListener,
},
- });
+ }));
var treelist = me.lookupReference('navtree');
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 3/5] ui: NavigationTree: add entries for changers/drives
2021-03-01 11:22 [pbs-devel] [PATCH proxmox-backup 1/5] ui: tape: add DriveStatus panel Dominik Csapak
2021-03-01 11:22 ` [pbs-devel] [PATCH proxmox-backup 2/5] ui: MainView: adapt router to add changer/drive entries Dominik Csapak
@ 2021-03-01 11:22 ` Dominik Csapak
2021-03-01 11:22 ` [pbs-devel] [PATCH proxmox-backup 4/5] ui: tape: ChangerStatus: remove changerselector combobox Dominik Csapak
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2021-03-01 11:22 UTC (permalink / raw)
To: pbs-devel
and only check TapeManagement once in the init function
we now have 2 updatestores that update individually
(one for datastores, one for drives/changers)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
www/NavigationTree.js | 103 ++++++++++++++++++++++++++++++++++++------
1 file changed, 89 insertions(+), 14 deletions(-)
diff --git a/www/NavigationTree.js b/www/NavigationTree.js
index e37447ce..8f9b366c 100644
--- a/www/NavigationTree.js
+++ b/www/NavigationTree.js
@@ -8,6 +8,16 @@ Ext.define('pbs-datastore-list', {
idProperty: 'store',
});
+Ext.define('pbs-tape-drive-list', {
+ extend: 'Ext.data.Model',
+ fields: ['name', 'changer'],
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/tape/drive",
+ },
+ idProperty: 'name',
+});
+
Ext.define('PBS.store.NavigationStore', {
extend: 'Ext.data.TreeStore',
@@ -101,34 +111,99 @@ Ext.define('PBS.view.main.NavigationTree', {
view.rstore = Ext.create('Proxmox.data.UpdateStore', {
autoStart: true,
interval: 15 * 1000,
- storeId: 'pbs-datastore-list',
storeid: 'pbs-datastore-list',
model: 'pbs-datastore-list',
});
view.rstore.on('load', this.onLoad, this);
view.on('destroy', view.rstore.stopUpdate);
+
+ if (PBS.TapeManagement !== undefined) {
+ view.tapestore = Ext.create('Proxmox.data.UpdateStore', {
+ autoStart: true,
+ interval: 2 * 1000,
+ storeid: 'pbs-tape-drive-list',
+ model: 'pbs-tape-drive-list',
+ });
+
+ let root = view.getStore().getRoot();
+ root.insertChild(3, {
+ text: "Tape Backup",
+ iconCls: 'pbs-icon-tape',
+ id: 'tape_management',
+ path: 'pbsTapeManagement',
+ expanded: true,
+ children: [],
+ });
+
+ view.tapestore.on('load', this.onTapeDriveLoad, this);
+ view.on('destroy', view.tapestore.stopUpdate);
+ }
},
- onLoad: function(store, records, success) {
+ onTapeDriveLoad: function(store, records, success) {
if (!success) return;
- var view = this.getView();
+ let view = this.getView();
let root = view.getStore().getRoot();
- if (PBS.TapeManagement !== undefined) {
- if (!root.findChild('id', 'tape_management', false)) {
- root.insertChild(3, {
- text: "Tape Backup",
- iconCls: 'pbs-icon-tape',
- id: 'tape_management',
- path: 'pbsTapeManagement',
- expanded: true,
- children: [],
- });
+ records.sort((a, b) => a.data.name.localeCompare(b.data.name));
+ let list = root.findChild('id', 'tape_management', false);
+ let newSet = {};
+
+ for (const drive of records) {
+ let path, text, iconCls;
+ if (drive.data.changer !== undefined) {
+ text = drive.data.changer;
+ path = `Changer-${text}`;
+ iconCls = 'fa fa-circle';
+ } else {
+ text = drive.data.name;
+ path = `Drive-${text}`;
+ iconCls = 'fa fa-square';
+ }
+ newSet[path] = {
+ text,
+ path,
+ iconCls,
+ leaf: true,
+ };
+ }
+
+ let paths = Object.keys(newSet).sort();
+
+ let oldIdx = 0;
+ for (let newIdx = 0; newIdx < paths.length; newIdx++) {
+ let newPath = paths[newIdx];
+ // find index to insert
+ while (oldIdx < list.childNodes.length && newPath > list.getChildAt(oldIdx).data.path) {
+ oldIdx++;
+ }
+
+ if (oldIdx >= list.childNodes.length || list.getChildAt(oldIdx).data.path !== newPath) {
+ list.insertChild(oldIdx, newSet[newPath]);
}
}
+ list.eachChild((child) => {
+ if (!newSet[child.data.path]) {
+ list.removeChild(child, true);
+ }
+ });
+
+ if (view.pathToSelect !== undefined) {
+ let path = view.pathToSelect;
+ delete view.pathToSelect;
+ view.select(path, true);
+ }
+ },
+
+ onLoad: function(store, records, success) {
+ if (!success) return;
+ var view = this.getView();
+
+ let root = view.getStore().getRoot();
+
records.sort((a, b) => a.id.localeCompare(b.id));
var list = root.findChild('id', 'datastores', false);
@@ -191,7 +266,7 @@ Ext.define('PBS.view.main.NavigationTree', {
select: function(path, silent) {
var me = this;
- if (me.rstore.isLoaded()) {
+ if (me.rstore.isLoaded() && (!PBS.TapeManagement || me.tapestore.isLoaded())) {
if (silent) {
me.suspendEvents(false);
}
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 4/5] ui: tape: ChangerStatus: remove changerselector combobox
2021-03-01 11:22 [pbs-devel] [PATCH proxmox-backup 1/5] ui: tape: add DriveStatus panel Dominik Csapak
2021-03-01 11:22 ` [pbs-devel] [PATCH proxmox-backup 2/5] ui: MainView: adapt router to add changer/drive entries Dominik Csapak
2021-03-01 11:22 ` [pbs-devel] [PATCH proxmox-backup 3/5] ui: NavigationTree: add entries for changers/drives Dominik Csapak
@ 2021-03-01 11:22 ` Dominik Csapak
2021-03-01 11:22 ` [pbs-devel] [PATCH proxmox-backup 5/5] ui: tape/ChangerStatus: handle vanishing view during reload Dominik Csapak
2021-03-01 11:39 ` [pbs-devel] applied: [PATCH proxmox-backup 1/5] ui: tape: add DriveStatus panel Dietmar Maurer
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2021-03-01 11:22 UTC (permalink / raw)
To: pbs-devel
because we now select it directly in the left-hand tree
so we have to adapt the changer to the one set by the router
and not by the drop down field
and remove it from the TapeManagement tabpanel
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
NOTE: this patch and the last 2 are very interdependent, but i wanted
to split them as it is easier to review that way. If wanted, they could
be squashed into a single commit
www/tape/ChangerStatus.js | 80 +++++++++++++-------------------------
www/tape/TapeManagement.js | 5 ---
2 files changed, 26 insertions(+), 59 deletions(-)
diff --git a/www/tape/ChangerStatus.js b/www/tape/ChangerStatus.js
index 1a7bcf6a..dab34038 100644
--- a/www/tape/ChangerStatus.js
+++ b/www/tape/ChangerStatus.js
@@ -15,34 +15,14 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
extend: 'Ext.panel.Panel',
alias: 'widget.pbsChangerStatus',
- viewModel: {
- data: {
- changer: '',
- },
-
- formulas: {
- changerSelected: (get) => get('changer') !== '',
- },
- },
-
controller: {
xclass: 'Ext.app.ViewController',
- changerChange: function(field, value) {
+ importTape: function(v, rI, cI, button, el, record) {
let me = this;
let view = me.getView();
- let vm = me.getViewModel();
- vm.set('changer', value);
- if (view.rendered) {
- me.reload();
- }
- },
-
- importTape: function(view, rI, cI, button, el, record) {
- let me = this;
- let vm = me.getViewModel();
let from = record.data['entry-id'];
- let changer = encodeURIComponent(vm.get('changer'));
+ let changer = encodeURIComponent(view.changer);
Ext.create('Proxmox.window.Edit', {
title: gettext('Import'),
isCreate: true,
@@ -71,11 +51,11 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
}).show();
},
- slotTransfer: function(view, rI, cI, button, el, record) {
+ slotTransfer: function(v, rI, cI, button, el, record) {
let me = this;
- let vm = me.getViewModel();
+ let view = me.getView();
let from = record.data['entry-id'];
- let changer = encodeURIComponent(vm.get('changer'));
+ let changer = encodeURIComponent(view.changer);
Ext.create('Proxmox.window.Edit', {
title: gettext('Transfer'),
isCreate: true,
@@ -104,12 +84,12 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
}).show();
},
- erase: function(view, rI, cI, button, el, record) {
+ erase: function(v, rI, cI, button, el, record) {
let me = this;
- let vm = me.getViewModel();
+ let view = me.getView();
let label = record.data['label-text'];
- let changer = vm.get('changer');
+ let changer = encodeURIComponent(view.changer);
Ext.create('PBS.TapeManagement.EraseWindow', {
label,
changer,
@@ -121,12 +101,12 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
}).show();
},
- load: function(view, rI, cI, button, el, record) {
+ load: function(v, rI, cI, button, el, record) {
let me = this;
- let vm = me.getViewModel();
+ let view = me.getView();
let label = record.data['label-text'];
- let changer = vm.get('changer');
+ let changer = encodeURIComponent(view.changer);
Ext.create('Proxmox.window.Edit', {
isCreate: true,
@@ -163,7 +143,7 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
});
},
- unload: async function(view, rI, cI, button, el, record) {
+ unload: async function(v, rI, cI, button, el, record) {
let me = this;
let drive = record.data.name;
try {
@@ -231,8 +211,8 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
barcodeLabel: function() {
let me = this;
- let vm = me.getViewModel();
- let changer = vm.get('changer');
+ let view = me.getView();
+ let changer = view.changer;
if (changer === '') {
return;
}
@@ -268,8 +248,8 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
inventory: function() {
let me = this;
- let vm = me.getViewModel();
- let changer = vm.get('changer');
+ let view = me.getView();
+ let changer = view.changer;
if (changer === '') {
return;
}
@@ -326,8 +306,7 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
reload_full: async function(use_cache) {
let me = this;
let view = me.getView();
- let vm = me.getViewModel();
- let changer = vm.get('changer');
+ let changer = view.changer;
if (changer === '') {
return;
}
@@ -483,6 +462,15 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
},
},
},
+
+ init: function(view) {
+ let me = this;
+ if (!view.changer) {
+ throw "no changer given";
+ }
+
+ view.title = `${gettext("Changer")}: ${view.changer}`;
+ },
},
listeners: {
@@ -490,16 +478,6 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
},
tbar: [
- {
- fieldLabel: gettext('Changer'),
- xtype: 'pbsChangerSelector',
- reference: 'changerselector',
- autoSelect: true,
- listeners: {
- change: 'changerChange',
- },
- },
- '-',
{
text: gettext('Reload'),
xtype: 'proxmoxButton',
@@ -512,18 +490,12 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
xtype: 'proxmoxButton',
handler: 'barcodeLabel',
iconCls: 'fa fa-barcode',
- bind: {
- disabled: '{!changerSelected}',
- },
},
{
text: gettext('Inventory'),
xtype: 'proxmoxButton',
handler: 'inventory',
iconCls: 'fa fa-book',
- bind: {
- disabled: '{!changerSelected}',
- },
},
],
diff --git a/www/tape/TapeManagement.js b/www/tape/TapeManagement.js
index 265b2b77..bac37d9c 100644
--- a/www/tape/TapeManagement.js
+++ b/www/tape/TapeManagement.js
@@ -21,11 +21,6 @@ Ext.define('PBS.TapeManagement', {
itemId: 'inventory',
xtype: 'pbsTapeInventory',
},
- {
- title: gettext('Library'),
- itemId: 'library',
- xtype: 'pbsChangerStatus',
- },
{
title: gettext('Changers'),
itemId: 'changers',
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread