ui: tape/Restore: allow simple namespace mapping
add a default namespace selector (of the current default store) and a namespace selector per target datastore (for media-sets with multiple datastores). to achieve that we have to change the way we handle the mapping field a bit: * don't use it as field directly (otherwise the value gets stringified), but use the 'getValue' method in 'onGetValues'. * set the defaultStore there, not only that we have one (with this we can now easily show it as emptytext for each store) * add a reference to the widgets to the record so that we can access them in the respective change handler (also clean those references up, else we have a cyclic reference between record <-> widget) in onGetValues, if we have multiple datastores, the mapping grid does all the work for us, otherwise, we have to create the ns mapping ourselves there. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
f6b09e83cb
commit
b70a12e723
|
@ -66,6 +66,9 @@ Ext.define('PBS.form.NamespaceSelector', {
|
||||||
}
|
}
|
||||||
me.store.load();
|
me.store.load();
|
||||||
me.validate();
|
me.validate();
|
||||||
|
} else {
|
||||||
|
me.datastore = undefined;
|
||||||
|
me.setDisabled(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
|
||||||
singleSelectorLabel: get =>
|
singleSelectorLabel: get =>
|
||||||
get('singleDatastore') ? gettext('Target Datastore') : gettext('Default Datastore'),
|
get('singleDatastore') ? gettext('Target Datastore') : gettext('Default Datastore'),
|
||||||
singleSelectorEmptyText: get => get('singleDatastore') ? '' : Proxmox.Utils.NoneText,
|
singleSelectorEmptyText: get => get('singleDatastore') ? '' : Proxmox.Utils.NoneText,
|
||||||
|
singleSelectorLabelNs: get =>
|
||||||
|
get('singleDatastore') ? gettext('Target Namespace') : gettext('Default Namespace'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -371,16 +373,29 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
|
||||||
xtype: 'inputpanel',
|
xtype: 'inputpanel',
|
||||||
onGetValues: function(values) {
|
onGetValues: function(values) {
|
||||||
let me = this;
|
let me = this;
|
||||||
|
let controller = me.up('window').getController();
|
||||||
let datastores = [];
|
let datastores = [];
|
||||||
if (values.store.toString() !== "") {
|
if (values.store.toString() !== "") {
|
||||||
datastores.push(values.store);
|
datastores.push(values.store);
|
||||||
delete values.store;
|
delete values.store;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.mapping.toString() !== "") {
|
let defaultNs = values.defaultNs;
|
||||||
datastores.push(values.mapping);
|
delete values.defaultNs;
|
||||||
|
|
||||||
|
let [ds_map, ns_map] = me.down('pbsDataStoreMappingField').getValue();
|
||||||
|
if (ds_map !== '') {
|
||||||
|
datastores.push(ds_map);
|
||||||
}
|
}
|
||||||
delete values.mapping;
|
if (ns_map.length > 0) {
|
||||||
|
values.namespaces = ns_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultNs && ns_map.length === 0 && controller.datastores.length === 1) {
|
||||||
|
// we only have one datastore and a default ns
|
||||||
|
values.namespaces = [`store=${controller.datastores[0]},target=${defaultNs}`];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
values.store = datastores.join(',');
|
values.store = datastores.join(',');
|
||||||
|
|
||||||
|
@ -427,7 +442,22 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
|
||||||
},
|
},
|
||||||
listeners: {
|
listeners: {
|
||||||
change: function(field, value) {
|
change: function(field, value) {
|
||||||
this.up('window').lookup('mappingGrid').setNeedStores(!value);
|
this.up('window').lookup('mappingGrid').setDefaultStore(value);
|
||||||
|
this.up('window').lookup('defaultNs').setDatastore(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xtype: 'pbsNamespaceSelector',
|
||||||
|
name: 'defaultNs',
|
||||||
|
reference: 'defaultNs',
|
||||||
|
labelWidth: 120,
|
||||||
|
bind: {
|
||||||
|
fieldLabel: '{singleSelectorLabelNs}',
|
||||||
|
},
|
||||||
|
listeners: {
|
||||||
|
change: function(field, value) {
|
||||||
|
this.up('window').lookup('mappingGrid').setDefaultNs(value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -444,9 +474,9 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype: 'pbsDataStoreMappingField',
|
xtype: 'pbsDataStoreMappingField',
|
||||||
name: 'mapping',
|
isFormField: false,
|
||||||
reference: 'mappingGrid',
|
reference: 'mappingGrid',
|
||||||
height: 260,
|
height: 240,
|
||||||
defaultBindProperty: 'value',
|
defaultBindProperty: 'value',
|
||||||
bind: {
|
bind: {
|
||||||
hidden: '{singleDatastore}',
|
hidden: '{singleDatastore}',
|
||||||
|
@ -473,28 +503,54 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
getValue: function() {
|
getValue: function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
let datastores = [];
|
let datastores = [];
|
||||||
|
let namespaces = [];
|
||||||
|
let defaultStore = me.getViewModel().get('defaultStore');
|
||||||
|
let defaultNs = me.getViewModel().get('defaultNs');
|
||||||
me.getStore().each(rec => {
|
me.getStore().each(rec => {
|
||||||
let { source, target } = rec.data;
|
let { source, target, targetns } = rec.data;
|
||||||
if (target && target !== "") {
|
if (target && target !== "") {
|
||||||
datastores.push(`${source}=${target}`);
|
datastores.push(`${source}=${target}`);
|
||||||
}
|
}
|
||||||
|
if (target || defaultStore) {
|
||||||
|
let ns = targetns || defaultNs;
|
||||||
|
if (ns) {
|
||||||
|
namespaces.push(`store=${source},target=${ns}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return datastores.join(',');
|
return [datastores.join(','), namespaces];
|
||||||
},
|
},
|
||||||
|
|
||||||
viewModel: {
|
viewModel: {
|
||||||
data: {
|
data: {
|
||||||
needStores: false, // this determines if we need at least one valid mapping
|
defaultStore: '',
|
||||||
|
defaultNs: false,
|
||||||
},
|
},
|
||||||
formulas: {
|
formulas: {
|
||||||
emptyMeans: get => get('needStores') ? Proxmox.Utils.NoneText : Proxmox.Utils.defaultText,
|
emptyStore: get => get('defaultStore') || Proxmox.Utils.NoneText,
|
||||||
|
emptyNs: get => get('defaultNs') || gettext('Root'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setNeedStores: function(needStores) {
|
setDefaultStore: function(store) {
|
||||||
let me = this;
|
let me = this;
|
||||||
me.getViewModel().set('needStores', needStores);
|
me.getViewModel().set('defaultStore', store);
|
||||||
|
me.getStore().each((rec) => {
|
||||||
|
if (!rec.dswidget) {
|
||||||
|
return; // not yet attached
|
||||||
|
}
|
||||||
|
if (!rec.dswidget.getValue()) {
|
||||||
|
rec.nswidget.setDatastore(store);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
me.checkChange();
|
||||||
|
me.validate();
|
||||||
|
},
|
||||||
|
|
||||||
|
setDefaultNs: function(defaultNs) {
|
||||||
|
let me = this;
|
||||||
|
me.getViewModel().set('defaultNs', defaultNs);
|
||||||
me.checkChange();
|
me.checkChange();
|
||||||
me.validate();
|
me.validate();
|
||||||
},
|
},
|
||||||
|
@ -509,7 +565,7 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
let me = this;
|
let me = this;
|
||||||
let error = false;
|
let error = false;
|
||||||
|
|
||||||
if (me.getViewModel().get('needStores')) {
|
if (me.getViewModel().get('defaultStore') !== '') {
|
||||||
error = true;
|
error = true;
|
||||||
me.getStore().each(rec => {
|
me.getStore().each(rec => {
|
||||||
if (rec.data.target) {
|
if (rec.data.target) {
|
||||||
|
@ -543,6 +599,7 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
data.push({
|
data.push({
|
||||||
source: datastore,
|
source: datastore,
|
||||||
target: '',
|
target: '',
|
||||||
|
targetNs: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,6 +612,16 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
|
|
||||||
store: { data: [] },
|
store: { data: [] },
|
||||||
|
|
||||||
|
listeners: {
|
||||||
|
beforedestroy: function() {
|
||||||
|
// break cyclic reference
|
||||||
|
this.getStore()?.each((rec) => {
|
||||||
|
delete rec.nswidget;
|
||||||
|
delete rec.dswidget;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
text: gettext('Source Datastore'),
|
text: gettext('Source Datastore'),
|
||||||
|
@ -564,6 +631,10 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
{
|
{
|
||||||
text: gettext('Target Datastore'),
|
text: gettext('Target Datastore'),
|
||||||
xtype: 'widgetcolumn',
|
xtype: 'widgetcolumn',
|
||||||
|
onWidgetAttach: function(col, widget, rec) {
|
||||||
|
// so that we can access it from the store
|
||||||
|
rec.dswidget = widget;
|
||||||
|
},
|
||||||
dataIndex: 'target',
|
dataIndex: 'target',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
widget: {
|
widget: {
|
||||||
|
@ -571,7 +642,7 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
isFormField: false,
|
isFormField: false,
|
||||||
allowBlank: true,
|
allowBlank: true,
|
||||||
bind: {
|
bind: {
|
||||||
emptyText: '{emptyMeans}',
|
emptyText: '{emptyStore}',
|
||||||
},
|
},
|
||||||
listeners: {
|
listeners: {
|
||||||
change: function(selector, value) {
|
change: function(selector, value) {
|
||||||
|
@ -581,6 +652,36 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rec.set('target', value);
|
rec.set('target', value);
|
||||||
|
rec.nswidget.setDatastore(value);
|
||||||
|
me.up('grid').checkChange();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: gettext('Target Namespace'),
|
||||||
|
xtype: 'widgetcolumn',
|
||||||
|
onWidgetAttach: function(col, widget, rec) {
|
||||||
|
// so that we can access it from the store
|
||||||
|
rec.nswidget = widget;
|
||||||
|
},
|
||||||
|
dataIndex: 'targetns',
|
||||||
|
flex: 1,
|
||||||
|
widget: {
|
||||||
|
xtype: 'pbsNamespaceSelector',
|
||||||
|
isFormField: false,
|
||||||
|
allowBlank: true,
|
||||||
|
bind: {
|
||||||
|
emptyText: '{emptyNs}',
|
||||||
|
},
|
||||||
|
listeners: {
|
||||||
|
change: function(selector, value) {
|
||||||
|
let me = this;
|
||||||
|
let rec = me.getWidgetRecord();
|
||||||
|
if (!rec) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rec.set('targetns', value);
|
||||||
me.up('grid').checkChange();
|
me.up('grid').checkChange();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue