alias: 'widget.pbsTapeRestoreWindow',
mixins: ['Proxmox.Mixin.CBind'],
+ title: gettext('Restore Media-Set'),
+
width: 800,
height: 500,
- title: gettext('Restore Media Set'),
+
url: '/api2/extjs/tape/restore',
method: 'POST',
- showTaskViewer: true,
- isCreate: true,
+
+ resizable: false,
+ modal: true,
+
+ mediaset: undefined,
+ prefilter: undefined,
+ uuid: undefined,
cbindData: function(config) {
let me = this;
layout: 'fit',
bodyPadding: 0,
+ viewModel: {
+ data: {
+ uuid: "",
+ singleDatastore: true,
+ },
+ formulas: {
+ singleSelectorLabel: get =>
+ get('singleDatastore') ? gettext('Target Datastore') : gettext('Default Datastore'),
+ singleSelectorEmptyText: get => get('singleDatastore') ? '' : Proxmox.Utils.NoneText,
+ },
+ },
+
controller: {
xclass: 'Ext.app.ViewController',
return panel.query('[isFormField]').every(field => field.isValid());
},
+ changeMediaSet: function(field, value) {
+ let me = this;
+ let vm = me.getViewModel();
+ vm.set('uuid', value);
+ me.updateSnapshots();
+ },
+
checkValidity: function() {
let me = this;
+
let tabpanel = me.lookup('tabpanel');
+ if (!tabpanel) {
+ return; // can get triggered early, when the tabpanel is not yet available
+ }
let items = tabpanel.items;
let indexOfActiveTab = items.indexOf(tabpanel.getActiveTab());
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
success: function(response, options) {
- // stay around so we can trigger our close events
- // when background action is completed
+ // keep around so we can trigger our close events when background action completes
view.hide();
Ext.create('Proxmox.window.TaskViewer', {
autoShow: true,
upid: response.result.data,
listeners: {
- destroy: function() {
- view.close();
- },
+ destroy: () => view.close(),
},
});
},
});
},
- updateDatastores: function() {
+ updateDatastores: function(grid, values) {
let me = this;
- let grid = me.lookup('snapshotGrid');
- let values = grid.getValue();
if (values === 'all') {
values = [];
}
let datastores = {};
- values.forEach((snapshot) => {
- const [datastore] = snapshot.split(':');
- datastores[datastore] = true;
+ values.forEach((snapshotOrDatastore) => {
+ let datastore = snapshotOrDatastore;
+ if (snapshotOrDatastore.indexOf(':') !== -1) {
+ let snapshot = snapshotOrDatastore;
+ let match = snapshot.split(':');
+ datastore = match[0];
+ } datastores[datastore] = true;
});
me.setDataStores(Object.keys(datastores));
datastores = me.datastores;
}
- let label = me.lookup('mappingLabel');
+ const singleDatastore = !datastores || datastores.length <= 1;
+ me.getViewModel().set('singleDatastore', singleDatastore);
+
let grid = me.lookup('mappingGrid');
- let defaultField = me.lookup('defaultDatastore');
-
- if (!datastores || datastores.length <= 1) {
- label.setVisible(false);
- grid.setVisible(false);
- defaultField.setFieldLabel(gettext('Target Datastore'));
- defaultField.setAllowBlank(false);
- defaultField.setEmptyText("");
- return;
+ if (!singleDatastore && grid) {
+ grid.setDataStores(datastores);
}
-
- label.setVisible(true);
- defaultField.setFieldLabel(gettext('Default Datastore'));
- defaultField.setAllowBlank(true);
- defaultField.setEmptyText(Proxmox.Utils.NoneText);
-
- grid.setDataStores(datastores);
- grid.setVisible(true);
},
updateSnapshots: function() {
let me = this;
let view = me.getView();
let grid = me.lookup('snapshotGrid');
+ let vm = me.getViewModel();
+ let uuid = vm.get('uuid');
Proxmox.Utils.API2Request({
waitMsgTarget: view,
- url: `/tape/media/content?media-set=${view.uuid}`,
+ url: `/tape/media/content?media-set=${uuid}`,
success: function(response, opt) {
let datastores = {};
for (const content of response.result.data) {
me.setDataStores(Object.keys(datastores), true);
if (response.result.data.length > 0) {
grid.setDisabled(false);
- grid.setVisible(true);
- grid.getStore().setData(response.result.data);
+ grid.setData(response.result.data);
grid.getSelectionModel().selectAll();
// we've shown a big list, center the window again
view.center();
});
},
+ init: function(view) {
+ let me = this;
+ let vm = me.getViewModel();
+
+ vm.set('uuid', view.uuid);
+ },
+
control: {
'[isFormField]': {
change: 'checkValidity',
onGetValues: function(values) {
let me = this;
- if (values.snapshots === 'all') {
- delete values.snapshots;
- } else if (Ext.isString(values.snapshots) && values.snapshots) {
+ if (values !== "all" &&
+ Ext.isString(values.snapshots) &&
+ values.snapshots &&
+ values.snapshots.indexOf(':') !== -1
+ ) {
values.snapshots = values.snapshots.split(',');
+ } else {
+ delete values.snapshots;
}
return values;
},
column1: [
+ {
+ xtype: 'pbsMediaSetSelector',
+ fieldLabel: gettext('Media-Set'),
+ width: 350,
+ submitValue: false,
+ emptyText: gettext('Select Media-Set to restore'),
+ bind: {
+ value: '{uuid}',
+ },
+ cbind: {
+ hidden: '{uuid}',
+ disabled: '{uuid}',
+ },
+ listeners: {
+ change: 'changeMediaSet',
+ },
+ },
{
xtype: 'displayfield',
- fieldLabel: gettext('Media Set'),
+ fieldLabel: gettext('Media-Set'),
cbind: {
value: '{mediaset}',
+ hidden: '{!uuid}',
+ disabled: '{!uuid}',
},
},
],
column2: [
{
xtype: 'displayfield',
- fieldLabel: gettext('Media Set UUID'),
+ fieldLabel: gettext('Media-Set UUID'),
name: 'media-set',
submitValue: true,
- cbind: {
+ bind: {
value: '{uuid}',
+ hidden: '{!uuid}',
+ disabled: '{!uuid}',
},
},
],
name: 'snapshots',
height: 322,
disabled: true, // will be shown/enabled on successful load
- hidden: true,
listeners: {
change: 'updateDatastores',
},
},
{
xtype: 'pbsDataStoreSelector',
- fieldLabel: gettext('Target Datastore'),
- labelWidth: 120,
- reference: 'defaultDatastore',
name: 'store',
+ labelWidth: 120,
+ bind: {
+ fieldLabel: '{singleSelectorLabel}',
+ emptyText: '{singleSelectorEmptyText}',
+ allowBlank: '{!singleDatastore}',
+ },
listeners: {
change: function(field, value) {
this.up('window').lookup('mappingGrid').setNeedStores(!value);
columnB: [
{
xtype: 'displayfield',
- reference: 'mappingLabel',
fieldLabel: gettext('Datastore Mapping'),
labelWidth: 200,
- hidden: true,
+ bind: {
+ hidden: '{singleDatastore}',
+ },
},
{
xtype: 'pbsDataStoreMappingField',
reference: 'mappingGrid',
height: 260,
defaultBindProperty: 'value',
- hidden: true,
+ bind: {
+ hidden: '{singleDatastore}',
+ },
},
],
},
flex: 1,
widget: {
xtype: 'pbsDataStoreSelector',
+ isFormField: false,
allowBlank: true,
bind: {
emptyText: '{emptyMeans}',
let me = this;
let snapshots = [];
+ let storeCounts = {};
+
me.getSelection().forEach((rec) => {
let id = rec.get('id');
let store = rec.data.store;
// only add if not filtered
if (me.store.findExact('id', id) !== -1) {
snapshots.push(`${store}:${snap}`);
+ if (storeCounts[store] === undefined) {
+ storeCounts[store] = 0;
+ }
+ storeCounts[store]++;
}
});
return "all";
}
+ let wholeStores = [];
+ let wholeStoresSelected = true;
+ for (const [store, count] of Object.entries(storeCounts)) {
+ if (me.storeCounts[store] === count) {
+ wholeStores.push(store);
+ } else {
+ wholeStoresSelected = false;
+ break;
+ }
+ }
+
+ if (wholeStoresSelected) {
+ return wholeStores;
+ }
+
return snapshots;
},
return [];
},
+ setData: function(records) {
+ let me = this;
+ let storeCounts = {};
+ records.forEach((rec) => {
+ let store = rec.store;
+ if (storeCounts[store] === undefined) {
+ storeCounts[store] = 0;
+ }
+ storeCounts[store]++;
+ });
+ me.storeCounts = storeCounts;
+ me.getStore().setData(records);
+ },
+
scrollable: true,
plugins: 'gridfilters',
let me = this;
me.callParent();
if (me.prefilter !== undefined) {
- me.store.filters.add(
- {
- id: 'x-gridfilter-store',
- property: 'store',
- operator: 'in',
- value: [me.prefilter.store],
- },
- {
- id: 'x-gridfilter-snapshot',
- property: 'snapshot',
- value: me.prefilter.snapshot,
- },
- );
+ if (me.prefilter.store !== undefined) {
+ me.store.filters.add(
+ {
+ id: 'x-gridfilter-store',
+ property: 'store',
+ operator: 'in',
+ value: [me.prefilter.store],
+ },
+ );
+ }
+
+ if (me.prefilter.snapshot !== undefined) {
+ me.store.filters.add(
+ {
+ id: 'x-gridfilter-snapshot',
+ property: 'snapshot',
+ value: me.prefilter.snapshot,
+ },
+ );
+ }
}
me.mon(me.store, 'filterchange', () => me.checkChange());
},
});
+
+Ext.define('PBS.TapeManagement.MediaSetSelector', {
+ extend: 'Proxmox.form.ComboGrid',
+ alias: 'widget.pbsMediaSetSelector',
+
+ allowBlank: false,
+ displayField: 'media-set-name',
+ valueField: 'media-set-uuid',
+ autoSelect: false,
+
+ store: {
+ proxy: {
+ type: 'proxmox',
+ url: '/api2/json/tape/media/media-sets',
+ },
+ autoLoad: true,
+ idProperty: 'media-set-uuid',
+ sorters: ['pool', 'media-set-ctime'],
+ },
+
+ listConfig: {
+ width: 600,
+ columns: [
+ {
+ text: gettext('Pool'),
+ dataIndex: 'pool',
+ flex: 1,
+ },
+ {
+ text: gettext('Name'),
+ dataIndex: 'media-set-name',
+ width: 180,
+ },
+ {
+ text: gettext('Media-Set UUID'),
+ dataIndex: 'media-set-uuid',
+ width: 280,
+ },
+ ],
+ },
+});