2021-02-02 13:00:38 +00:00
|
|
|
Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
|
|
|
|
extend: 'Proxmox.window.Edit',
|
2021-03-25 10:04:40 +00:00
|
|
|
alias: 'widget.pbsTapeRestoreWindow',
|
2021-02-02 13:00:38 +00:00
|
|
|
mixins: ['Proxmox.Mixin.CBind'],
|
|
|
|
|
2021-03-25 10:04:40 +00:00
|
|
|
width: 800,
|
2021-02-02 13:00:38 +00:00
|
|
|
title: gettext('Restore Media Set'),
|
|
|
|
url: '/api2/extjs/tape/restore',
|
|
|
|
method: 'POST',
|
|
|
|
showTaskViewer: true,
|
|
|
|
isCreate: true,
|
|
|
|
|
|
|
|
defaults: {
|
|
|
|
labelWidth: 120,
|
|
|
|
},
|
|
|
|
|
2021-03-25 10:04:40 +00:00
|
|
|
referenceHolder: true,
|
|
|
|
|
2021-02-02 13:00:38 +00:00
|
|
|
items: [
|
|
|
|
{
|
2021-03-25 10:04:40 +00:00
|
|
|
xtype: 'inputpanel',
|
|
|
|
|
|
|
|
onGetValues: function(values) {
|
|
|
|
let me = this;
|
|
|
|
let datastores = [];
|
2021-03-29 11:25:37 +00:00
|
|
|
if (values.store.toString() !== "") {
|
2021-03-25 10:04:40 +00:00
|
|
|
datastores.push(values.store);
|
|
|
|
delete values.store;
|
|
|
|
}
|
|
|
|
|
2021-03-29 11:25:37 +00:00
|
|
|
if (values.mapping.toString() !== "") {
|
2021-03-25 10:04:40 +00:00
|
|
|
datastores.push(values.mapping);
|
|
|
|
}
|
2021-03-29 11:25:36 +00:00
|
|
|
delete values.mapping;
|
2021-03-25 10:04:40 +00:00
|
|
|
|
|
|
|
values.store = datastores.join(',');
|
|
|
|
|
|
|
|
return values;
|
2021-02-02 13:00:38 +00:00
|
|
|
},
|
2021-03-25 10:04:40 +00:00
|
|
|
|
|
|
|
column1: [
|
|
|
|
{
|
|
|
|
xtype: 'displayfield',
|
|
|
|
fieldLabel: gettext('Media Set'),
|
|
|
|
cbind: {
|
|
|
|
value: '{mediaset}',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
xtype: 'displayfield',
|
|
|
|
fieldLabel: gettext('Media Set UUID'),
|
|
|
|
name: 'media-set',
|
|
|
|
submitValue: true,
|
|
|
|
cbind: {
|
|
|
|
value: '{uuid}',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
xtype: 'pbsDriveSelector',
|
|
|
|
fieldLabel: gettext('Drive'),
|
|
|
|
name: 'drive',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
|
|
|
|
column2: [
|
|
|
|
{
|
|
|
|
xtype: 'pbsUserSelector',
|
|
|
|
name: 'notify-user',
|
|
|
|
fieldLabel: gettext('Notify User'),
|
|
|
|
emptyText: gettext('Current User'),
|
|
|
|
value: null,
|
|
|
|
allowBlank: true,
|
|
|
|
skipEmptyText: true,
|
|
|
|
renderer: Ext.String.htmlEncode,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
xtype: 'pbsUserSelector',
|
|
|
|
name: 'owner',
|
|
|
|
fieldLabel: gettext('Owner'),
|
|
|
|
emptyText: gettext('Current User'),
|
|
|
|
value: null,
|
|
|
|
allowBlank: true,
|
|
|
|
skipEmptyText: true,
|
|
|
|
renderer: Ext.String.htmlEncode,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
xtype: 'pbsDataStoreSelector',
|
|
|
|
fieldLabel: gettext('Datastore'),
|
|
|
|
reference: 'defaultDatastore',
|
|
|
|
name: 'store',
|
|
|
|
listeners: {
|
|
|
|
change: function(field, value) {
|
|
|
|
let me = this;
|
|
|
|
let grid = me.up('window').lookup('mappingGrid');
|
|
|
|
grid.setNeedStores(!value);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
|
|
|
|
columnB: [
|
|
|
|
{
|
|
|
|
fieldLabel: gettext('Datastore Mapping'),
|
|
|
|
labelWidth: 200,
|
|
|
|
hidden: true,
|
|
|
|
reference: 'mappingLabel',
|
|
|
|
xtype: 'displayfield',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
xtype: 'pbsDataStoreMappingField',
|
|
|
|
reference: 'mappingGrid',
|
|
|
|
name: 'mapping',
|
|
|
|
defaultBindProperty: 'value',
|
|
|
|
hidden: true,
|
|
|
|
},
|
|
|
|
],
|
2021-02-02 13:00:38 +00:00
|
|
|
},
|
2021-03-25 10:04:40 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
setDataStores: function(datastores) {
|
|
|
|
let me = this;
|
|
|
|
|
|
|
|
let label = me.lookup('mappingLabel');
|
|
|
|
let grid = me.lookup('mappingGrid');
|
|
|
|
let defaultField = me.lookup('defaultDatastore');
|
|
|
|
|
|
|
|
if (!datastores || datastores.length <= 1) {
|
|
|
|
label.setVisible(false);
|
|
|
|
grid.setVisible(false);
|
|
|
|
defaultField.setFieldLabel(gettext('Datastore'));
|
|
|
|
defaultField.setAllowBlank(false);
|
|
|
|
defaultField.setEmptyText("");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
label.setVisible(true);
|
|
|
|
defaultField.setFieldLabel(gettext('Default Datastore'));
|
|
|
|
defaultField.setAllowBlank(true);
|
|
|
|
defaultField.setEmptyText(Proxmox.Utils.NoneText);
|
|
|
|
|
|
|
|
grid.setDataStores(datastores);
|
|
|
|
grid.setVisible(true);
|
|
|
|
},
|
|
|
|
|
|
|
|
initComponent: function() {
|
|
|
|
let me = this;
|
|
|
|
|
|
|
|
me.callParent();
|
|
|
|
if (me.datastores) {
|
|
|
|
me.setDataStores(me.datastores);
|
|
|
|
} else {
|
|
|
|
// use timeout so that the window is rendered already
|
|
|
|
// for correct masking
|
|
|
|
setTimeout(function() {
|
|
|
|
Proxmox.Utils.API2Request({
|
|
|
|
waitMsgTarget: me,
|
|
|
|
url: `/tape/media/content?media-set=${me.uuid}`,
|
|
|
|
success: function(response, opt) {
|
|
|
|
let datastores = {};
|
|
|
|
for (const content of response.result.data) {
|
|
|
|
datastores[content.store] = true;
|
|
|
|
}
|
|
|
|
me.setDataStores(Object.keys(datastores));
|
|
|
|
},
|
|
|
|
failure: function() {
|
|
|
|
// ignore failing api call, maybe catalog is missing
|
|
|
|
me.setDataStores();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}, 10);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
|
|
|
|
extend: 'Ext.grid.Panel',
|
|
|
|
alias: 'widget.pbsDataStoreMappingField',
|
|
|
|
mixins: ['Ext.form.field.Field'],
|
|
|
|
|
|
|
|
getValue: function() {
|
|
|
|
let me = this;
|
|
|
|
let datastores = [];
|
|
|
|
me.getStore().each((rec) => {
|
|
|
|
let source = rec.data.source;
|
|
|
|
let target = rec.data.target;
|
|
|
|
if (target && target !== "") {
|
|
|
|
datastores.push(`${source}=${target}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return datastores.join(',');
|
|
|
|
},
|
|
|
|
|
|
|
|
// this determines if we need at least one valid mapping
|
|
|
|
needStores: false,
|
|
|
|
|
|
|
|
setNeedStores: function(needStores) {
|
|
|
|
let me = this;
|
|
|
|
me.needStores = needStores;
|
|
|
|
me.checkChange();
|
|
|
|
me.validate();
|
|
|
|
},
|
|
|
|
|
|
|
|
setValue: function(value) {
|
|
|
|
let me = this;
|
|
|
|
me.setDataStores(value);
|
|
|
|
return me;
|
|
|
|
},
|
|
|
|
|
|
|
|
getErrors: function(value) {
|
|
|
|
let me = this;
|
|
|
|
let error = false;
|
|
|
|
|
|
|
|
if (me.needStores) {
|
|
|
|
error = true;
|
|
|
|
me.getStore().each((rec) => {
|
|
|
|
if (rec.data.target) {
|
|
|
|
error = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
me.addCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
|
|
|
|
let errorMsg = gettext("Need at least one mapping");
|
|
|
|
me.getActionEl().dom.setAttribute('data-errorqtip', errorMsg);
|
|
|
|
|
|
|
|
return [errorMsg];
|
|
|
|
}
|
|
|
|
me.removeCls(['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid']);
|
|
|
|
me.getActionEl().dom.setAttribute('data-errorqtip', "");
|
|
|
|
return [];
|
|
|
|
},
|
|
|
|
|
|
|
|
setDataStores: function(datastores) {
|
|
|
|
let me = this;
|
|
|
|
let store = me.getStore();
|
|
|
|
let data = [];
|
|
|
|
|
|
|
|
for (const datastore of datastores) {
|
|
|
|
data.push({
|
|
|
|
source: datastore,
|
|
|
|
target: '',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
store.setData(data);
|
|
|
|
},
|
|
|
|
|
|
|
|
viewConfig: {
|
|
|
|
markDirty: false,
|
|
|
|
},
|
|
|
|
|
|
|
|
store: { data: [] },
|
|
|
|
|
|
|
|
columns: [
|
2021-02-02 13:00:38 +00:00
|
|
|
{
|
2021-03-25 10:04:40 +00:00
|
|
|
text: gettext('Source Datastore'),
|
|
|
|
dataIndex: 'source',
|
|
|
|
flex: 1,
|
2021-03-05 08:45:32 +00:00
|
|
|
},
|
2021-03-12 10:28:41 +00:00
|
|
|
{
|
2021-03-25 10:04:40 +00:00
|
|
|
text: gettext('Target Datastore'),
|
|
|
|
xtype: 'widgetcolumn',
|
|
|
|
dataIndex: 'target',
|
|
|
|
flex: 1,
|
|
|
|
widget: {
|
|
|
|
xtype: 'pbsDataStoreSelector',
|
|
|
|
allowBlank: true,
|
|
|
|
emptyText: Proxmox.Utils.NoneText,
|
|
|
|
listeners: {
|
|
|
|
change: function(selector, value) {
|
|
|
|
let me = this;
|
|
|
|
let rec = me.getWidgetRecord();
|
|
|
|
if (!rec) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
rec.set('target', value);
|
|
|
|
me.up('grid').checkChange();
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-03-12 10:28:41 +00:00
|
|
|
},
|
2021-02-02 13:00:38 +00:00
|
|
|
],
|
|
|
|
});
|