]> git.proxmox.com Git - proxmox-backup.git/blobdiff - www/tape/window/TapeRestore.js
ui: tapeRestore: make window non-resizable
[proxmox-backup.git] / www / tape / window / TapeRestore.js
index 85ebcb1bfab065b3475f6f575fb87940d2513a40..d4bf43bbccb12e6139db1bf1aa4c7120638d3402 100644 (file)
@@ -3,13 +3,20 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
     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;
@@ -22,6 +29,18 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
     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',
 
@@ -29,16 +48,26 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
            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 checkValidity = true;
-
            let indexOfActiveTab = items.indexOf(tabpanel.getActiveTab());
            let indexOfLastValidTab = 0;
 
+           let checkValidity = true;
            items.each((panel) => {
                if (checkValidity) {
                    panel.setDisabled(false);
@@ -132,34 +161,33 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
                    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));
@@ -168,44 +196,32 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
        setDataStores: function(datastores, initial) {
            let me = this;
 
-           // save all datastores on the first setting, and
-           // restore them if we selected all
+           // save all datastores on the first setting, and restore them if we selected all
            if (initial) {
                me.datastores = datastores;
            } else if (datastores.length === 0) {
                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) {
@@ -214,8 +230,7 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
                    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();
@@ -228,6 +243,13 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
            });
        },
 
+       init: function(view) {
+           let me = this;
+           let vm = me.getViewModel();
+
+           vm.set('uuid', view.uuid);
+       },
+
        control: {
            '[isFormField]': {
                change: 'checkValidity',
@@ -272,21 +294,44 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
                    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}',
                            },
                        },
                    ],
@@ -294,11 +339,13 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
                    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}',
                            },
                        },
                    ],
@@ -309,9 +356,7 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
                            reference: 'snapshotGrid',
                            name: 'snapshots',
                            height: 322,
-                           // will be shown/enabled on successful load
-                           disabled: true,
-                           hidden: true,
+                           disabled: true, // will be shown/enabled on successful load
                            listeners: {
                                change: 'updateDatastores',
                            },
@@ -367,21 +412,22 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
                    column2: [
                        {
                            xtype: 'pbsDriveSelector',
+                           name: 'drive',
                            fieldLabel: gettext('Drive'),
                            labelWidth: 120,
-                           name: 'drive',
                        },
                        {
                            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) {
-                                   let me = this;
-                                   let grid = me.up('window').lookup('mappingGrid');
-                                   grid.setNeedStores(!value);
+                                   this.up('window').lookup('mappingGrid').setNeedStores(!value);
                                },
                            },
                        },
@@ -389,19 +435,22 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', {
 
                    columnB: [
                        {
+                           xtype: 'displayfield',
                            fieldLabel: gettext('Datastore Mapping'),
                            labelWidth: 200,
-                           hidden: true,
-                           reference: 'mappingLabel',
-                           xtype: 'displayfield',
+                           bind: {
+                               hidden: '{singleDatastore}',
+                           },
                        },
                        {
                            xtype: 'pbsDataStoreMappingField',
-                           reference: 'mappingGrid',
                            name: 'mapping',
+                           reference: 'mappingGrid',
                            height: 260,
                            defaultBindProperty: 'value',
-                           hidden: true,
+                           bind: {
+                               hidden: '{singleDatastore}',
+                           },
                        },
                    ],
                },
@@ -424,9 +473,8 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
     getValue: function() {
        let me = this;
        let datastores = [];
-       me.getStore().each((rec) => {
-           let source = rec.data.source;
-           let target = rec.data.target;
+       me.getStore().each(rec => {
+           let { source, target } = rec.data;
            if (target && target !== "") {
                datastores.push(`${source}=${target}`);
            }
@@ -463,7 +511,7 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
 
        if (me.getViewModel().get('needStores')) {
            error = true;
-           me.getStore().each((rec) => {
+           me.getStore().each(rec => {
                if (rec.data.target) {
                    error = false;
                }
@@ -489,9 +537,8 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
 
     setDataStores: function(datastores) {
        let me = this;
-       let store = me.getStore();
-       let data = [];
 
+       let data = [];
        for (const datastore of datastores) {
            data.push({
                source: datastore,
@@ -499,7 +546,7 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
            });
        }
 
-       store.setData(data);
+       me.getStore().setData(data);
     },
 
     viewConfig: {
@@ -521,6 +568,7 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', {
            flex: 1,
            widget: {
                xtype: 'pbsDataStoreSelector',
+               isFormField: false,
                allowBlank: true,
                bind: {
                    emptyText: '{emptyMeans}',
@@ -550,6 +598,8 @@ Ext.define('PBS.TapeManagement.SnapshotGrid', {
        let me = this;
        let snapshots = [];
 
+       let storeCounts = {};
+
        me.getSelection().forEach((rec) => {
            let id = rec.get('id');
            let store = rec.data.store;
@@ -557,6 +607,10 @@ Ext.define('PBS.TapeManagement.SnapshotGrid', {
            // 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]++;
            }
        });
 
@@ -567,6 +621,21 @@ Ext.define('PBS.TapeManagement.SnapshotGrid', {
            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;
     },
 
@@ -596,6 +665,20 @@ Ext.define('PBS.TapeManagement.SnapshotGrid', {
        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',
 
@@ -646,21 +729,69 @@ Ext.define('PBS.TapeManagement.SnapshotGrid', {
        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,
+           },
+       ],
+    },
+});