]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/lxc/MPEdit.js
ui: utils: refactor mps to mp
[pve-manager.git] / www / manager6 / lxc / MPEdit.js
index 54eca7b41fe3f814ec4140c17997b2e282d339d6..609447efb84348379411312c035fcbec16bb57ae 100644 (file)
 Ext.define('PVE.lxc.MountPointInputPanel', {
-    extend: 'PVE.panel.InputPanel',
-    alias: 'widget.pveLxcMountPointInputPanel',
-
-    insideWizard: false,
+    extend: 'Proxmox.panel.InputPanel',
+    xtype: 'pveLxcMountPointInputPanel',
 
     onlineHelp: 'pct_container_storage',
 
-    unused: false, // add unused disk imaged
+    insideWizard: false,
 
+    unused: false, // add unused disk imaged
     unprivileged: false,
 
     vmconfig: {}, // used to select unused disks
 
+    setUnprivileged: function(unprivileged) {
+       var me = this;
+       var vm = me.getViewModel();
+       me.unprivileged = unprivileged;
+       vm.set('unpriv', unprivileged);
+    },
+
     onGetValues: function(values) {
        var me = this;
 
-       var confid = me.confid || values.mpsel;
+       var confid = me.confid || "mp"+values.mpid;
+       me.mp.file = me.down('field[name=file]').getValue();
 
        if (me.unused) {
-           me.mpdata.file = me.vmconfig[values.unusedId];
-           confid = values.mpsel;
+           confid = "mp"+values.mpid;
        } else if (me.isCreate) {
-           me.mpdata.file = values.hdstorage + ':' + values.disksize;
-       }
-
-       if (confid !== 'rootfs') {
-           me.mpdata.mp = values.mp;
-       }
-
-       if (values.ro) {
-           me.mpdata.ro = 1;
-       } else {
-           delete me.mpdata.ro;
-       }
-
-       if (values.quota) {
-           me.mpdata.quota = 1;
-       } else {
-           delete me.mpdata.quota;
-       }
-
-       if (values.acl === 'Default') {
-           delete me.mpdata.acl;
-       } else {
-           me.mpdata.acl = values.acl;
-       }
-
-       if (values.backup) {
-           me.mpdata.backup = 1;
-       } else {
-           delete me.mpdata.backup;
-       }
-
-       if (values.noreplicate) {
-           me.mpdata.replicate = '0';
+           me.mp.file = values.hdstorage + ':' + values.disksize;
        }
-       delete me.mpdata.noreplicate;
 
-       var res = {};
-       res[confid] = PVE.Parser.printLxcMountPoint(me.mpdata);
+       // delete unnecessary fields
+       delete values.mpid;
+       delete values.hdstorage;
+       delete values.disksize;
+       delete values.diskformat;
+
+       let setMPOpt = (k, src, v) => PVE.Utils.propertyStringSet(me.mp, src, k, v);
+
+       setMPOpt('mp', values.mp);
+       let mountOpts = (values.mountoptions || []).join(';');
+       setMPOpt('mountoptions', values.mountoptions, mountOpts);
+       setMPOpt('mp', values.mp);
+       setMPOpt('backup', values.backup);
+       setMPOpt('quota', values.quota);
+       setMPOpt('ro', values.ro);
+       setMPOpt('acl', values.acl);
+       setMPOpt('replicate', values.replicate);
+
+       let res = {};
+       res[confid] = PVE.Parser.printLxcMountPoint(me.mp);
        return res;
     },
 
     setMountPoint: function(mp) {
-       var me = this;
-
-       // the fields name is 'hdstorage',
-       // but the api expects/has 'storage'
-       mp.hdstorage = mp.storage;
-       delete mp.hdstorage;
-
-       me.mpdata = mp;
-       if (!Ext.isDefined(me.mpdata.acl)) {
-           me.mpdata.acl = 'Default';
-       }
-
-       if (mp.type === 'bind') {
-           me.quota.setDisabled(true);
-           me.quota.setValue(false);
-           me.acl.setDisabled(true);
-           me.acl.setValue('Default');
-           me.down('#hdstorage').setDisabled(true);
-           if (me.confid !== 'rootfs') {
-               me.backup.setDisabled(true);
-           }
+       let me = this;
+       let vm = me.getViewModel();
+       vm.set('mptype', mp.type);
+       if (mp.mountoptions) {
+           mp.mountoptions = mp.mountoptions.split(';');
        }
-
-       if (mp.replicate) { // check box reverses the config option
-           mp.noreplicate = !PVE.Parser.parseBoolean(mp.replicate, 1);
-           delete mp.replicate;
-       }
-
+       me.mp = mp;
+       me.filterMountOptions();
        me.setValues(mp);
     },
 
-    setVMConfig: function(vmconfig) {
-       var me = this;
+    filterMountOptions: function() {
+       let me = this;
+       if (me.confid === 'rootfs') {
+           let field = me.down('field[name=mountoptions]');
+           let exclude = ['nodev', 'noexec'];
+           let filtered = field.comboItems.filter(v => !exclude.includes(v[0]));
+           field.setComboItems(filtered);
+       }
+    },
 
+    updateVMConfig: function(vmconfig) {
+       let me = this;
+       let vm = me.getViewModel();
        me.vmconfig = vmconfig;
+       vm.set('unpriv', vmconfig.unprivileged);
+       me.down('field[name=mpid]').validate();
+    },
 
-       if (me.mpsel) {
-           var i;
-           for (i = 0; i != 8; ++i) {
-               var name = "mp" + i.toString();
-               if (!Ext.isDefined(vmconfig[name])) {
-                   me.mpsel.setValue(name);
-                   break;
-               }
+    setVMConfig: function(vmconfig) {
+       let me = this;
+
+       me.updateVMConfig(vmconfig);
+       PVE.Utils.forEachMP((bus, i) => {
+           let name = "mp" + i.toString();
+           if (!Ext.isDefined(vmconfig[name])) {
+               me.down('field[name=mpid]').setValue(i);
+               return false;
            }
-       }
-
-       if (me.unusedDisks) {
-           var disklist = [];
-           Ext.Object.each(vmconfig, function(key, value) {
-               if (key.match(/^unused\d+$/)) {
-                   disklist.push([key, value]);
-               }
-           });
-           me.unusedDisks.store.loadData(disklist);
-           me.unusedDisks.setValue(me.confid);
-       }
+           return undefined;
+       });
     },
 
     setNodename: function(nodename) {
-       var me = this;
-       me.down('#hdstorage').setNodename(nodename);
-       me.down('#hdimage').setStorage(undefined, nodename);
+       let me = this;
+       let vm = me.getViewModel();
+       vm.set('node', nodename);
+       me.down('#diskstorage').setNodename(nodename);
     },
 
-    initComponent : function() {
-       var me = this;
-
-       var isroot = me.confid === 'rootfs';
+    controller: {
+       xclass: 'Ext.app.ViewController',
 
-       me.mpdata = {};
-
-       me.column1 = [];
-
-       if (!me.confid || me.unused) {
-           var names = [];
-           var i;
-           for (i = 0; i != 8; ++i) {
-               var name = 'mp' + i.toString();
-               names.push([name, name]);
-           }
-           me.mpsel = Ext.create('PVE.form.KVComboBox', {
-               name: 'mpsel',
-               fieldLabel: gettext('Mount Point'),
-               matchFieldWidth: false,
-               allowBlank: false,
-               comboItems: names,
-               validator: function(value) {
-                   if (!me.rendered) {
+       control: {
+           'field[name=mpid]': {
+               change: function(field, value) {
+                   let me = this;
+                   let view = this.getView();
+                   if (view.confid !== 'rootfs') {
+                       view.fireEvent('diskidchange', view, `mp${value}`);
+                   }
+                   field.validate();
+               },
+           },
+           '#hdstorage': {
+               change: function(field, newValue) {
+                   let me = this;
+                   if (!newValue) {
                        return;
                    }
-                   if (Ext.isDefined(me.vmconfig[value])) {
-                       return "Mount point is already in use.";
+
+                   let rec = field.store.getById(newValue);
+                   if (!rec) {
+                       return;
                    }
-                   /*jslint confusion: true*/
-                   /* returns a string above */
-                   return true;
+                   me.getViewModel().set('type', rec.data.type);
                },
-               listeners: {
-                   change: function(field, value) {
-                       field.validate();
-                   }
+           },
+       },
+       init: function(view) {
+           let me = this;
+           let vm = this.getViewModel();
+           view.mp = {};
+           vm.set('confid', view.confid);
+           vm.set('unused', view.unused);
+           vm.set('node', view.nodename);
+           vm.set('unpriv', view.unprivileged);
+           vm.set('hideStorSelector', view.unused || !view.isCreate);
+
+           if (view.isCreate) { // can be array if created from unused disk
+               vm.set('isIncludedInBackup', true);
+               if (view.insideWizard) {
+                   view.filterMountOptions();
                }
-           });
-           me.column1.push(me.mpsel);
-       }
+           }
+           if (view.selectFree) {
+               view.setVMConfig(view.vmconfig);
+           }
+       },
+    },
 
-       me.column1.push({
+    viewModel: {
+       data: {
+           unpriv: false,
+           unused: false,
+           showStorageSelector: false,
+           mptype: '',
+           type: '',
+           confid: '',
+           node: '',
+       },
+
+       formulas: {
+           quota: function(get) {
+               return !(get('type') === 'zfs' ||
+                        get('type') === 'zfspool' ||
+                        get('unpriv') ||
+                        get('isBind'));
+           },
+           hasMP: function(get) {
+               return !!get('confid') && !get('unused');
+           },
+           isRoot: function(get) {
+               return get('confid') === 'rootfs';
+           },
+           isBind: function(get) {
+               return get('mptype') === 'bind';
+           },
+           isBindOrRoot: function(get) {
+               return get('isBind') || get('isRoot');
+           },
+       },
+    },
+
+    column1: [
+       {
+           xtype: 'proxmoxintegerfield',
+           name: 'mpid',
+           fieldLabel: gettext('Mount Point ID'),
+           minValue: 0,
+           maxValue: PVE.Utils.mp_counts.mp - 1,
+           hidden: true,
+           allowBlank: false,
+           disabled: true,
+           bind: {
+               hidden: '{hasMP}',
+               disabled: '{hasMP}',
+           },
+           validator: function(value) {
+               let view = this.up('inputpanel');
+               if (!view.rendered) {
+                   return undefined;
+               }
+               if (Ext.isDefined(view.vmconfig["mp"+value])) {
+                   return "Mount point is already in use.";
+               }
+               return true;
+           },
+       },
+       {
            xtype: 'pveDiskStorageSelector',
-           nodename: me.nodename,
+           itemId: 'diskstorage',
            storageContent: 'rootdir',
+           hidden: true,
            autoSelect: true,
+           selectformat: false,
            defaultSize: 8,
-           hidden: me.unused || !me.isCreate
-       });
-
-       if (me.unused) {
-           me.unusedDisks = Ext.create('PVE.form.KVComboBox', {
-               name: 'unusedId',
-               fieldLabel: gettext('Disk image'),
-               matchFieldWidth: false,
-               listConfig: {
-                   width: 350
+           bind: {
+               hidden: '{hideStorSelector}',
+               disabled: '{hideStorSelector}',
+               nodename: '{node}',
+           },
+       },
+       {
+           xtype: 'textfield',
+           disabled: true,
+           submitValue: false,
+           fieldLabel: gettext('Disk image'),
+           name: 'file',
+           bind: {
+               hidden: '{!hideStorSelector}',
+           },
+       },
+    ],
+
+    column2: [
+       {
+           xtype: 'textfield',
+           name: 'mp',
+           value: '',
+           emptyText: gettext('/some/path'),
+           allowBlank: false,
+           disabled: true,
+           fieldLabel: gettext('Path'),
+           bind: {
+               hidden: '{isRoot}',
+               disabled: '{isRoot}',
+           },
+       },
+       {
+           xtype: 'proxmoxcheckbox',
+           name: 'backup',
+           fieldLabel: gettext('Backup'),
+           autoEl: {
+               tag: 'div',
+               'data-qtip': gettext('Include volume in backup job'),
+           },
+           bind: {
+               hidden: '{isRoot}',
+               disabled: '{isBindOrRoot}',
+               value: '{isIncludedInBackup}',
+           },
+       },
+    ],
+
+    advancedColumn1: [
+       {
+           xtype: 'proxmoxcheckbox',
+           name: 'quota',
+           defaultValue: 0,
+           bind: {
+               disabled: '{!quota}',
+           },
+           fieldLabel: gettext('Enable quota'),
+           listeners: {
+               disable: function() {
+                   this.reset();
                },
-               data: [],
-               allowBlank: false,
-               listeners: {
-                   change: function(f, value) {
-                       // make sure our buttons are enabled/disabled when switching
-                       // between images on different storages:
-                       var disk = me.vmconfig[value];
-                       var storage = disk.split(':')[0];
-                       me.down('#hdstorage').setValue(storage);
-                   }
-               }
-           });
-           me.column1.push(me.unusedDisks);
-       } else if (!me.isCreate) {
-           me.column1.push({
-               xtype: 'textfield',
-               disabled: true,
-               submitValue: false,
-               fieldLabel: gettext('Disk image'),
-               name: 'file'
-           });
-       }
-
-       me.acl = Ext.createWidget('pveKVComboBox', {
+           },
+       },
+       {
+           xtype: 'proxmoxcheckbox',
+           name: 'ro',
+           defaultValue: 0,
+           bind: {
+               hidden: '{isRoot}',
+               disabled: '{isRoot}',
+           },
+           fieldLabel: gettext('Read-only'),
+       },
+       {
+           xtype: 'proxmoxKVComboBox',
+           name: 'mountoptions',
+           fieldLabel: gettext('Mount options'),
+           deleteEmpty: false,
+           comboItems: [
+               ['lazytime', 'lazytime'],
+               ['noatime', 'noatime'],
+               ['nodev', 'nodev'],
+               ['noexec', 'noexec'],
+               ['nosuid', 'nosuid'],
+           ],
+           multiSelect: true,
+           value: [],
+           allowBlank: true,
+       },
+    ],
+
+    advancedColumn2: [
+       {
+           xtype: 'proxmoxKVComboBox',
            name: 'acl',
            fieldLabel: 'ACLs',
-           comboItems: [['Default', 'Default'], ['1', 'On'], ['0', 'Off']],
-           value: 'Default',
-           allowBlank: true
-       });
-
-       me.quota = Ext.createWidget('pvecheckbox', {
-           name: 'quota',
-           defaultValue: 0,
-           disabled: me.unprivileged,
-           fieldLabel: gettext('Enable quota')
-       });
-
-       me.column2 = [
-           me.acl,
-           me.quota
-       ];
-
-       if (!isroot) {
-           me.column2.splice(1, 0, {
-               xtype: 'pvecheckbox',
-               name: 'ro',
-               defaultValue: 0,
-               fieldLabel: gettext('Read-only'),
-               hidden: me.insideWizard
-           });
-
-           me.backup = Ext.createWidget('pvecheckbox',{
-               xtype: 'pvecheckbox',
-               name: 'backup',
-               fieldLabel: gettext('Backup')
-           });
-           if (me.mpdata.type !== 'bind') {
-               me.column2.push(me.backup);
-           }
-           me.column2.push({
-               xtype: 'pvecheckbox',
-               name: 'noreplicate',
-               fieldLabel: gettext('Skip replication')
-           });
-           me.column2.push({
-               xtype: 'textfield',
-               name: 'mp',
-               value: '',
-               emptyText:  gettext('/some/path'),
-               allowBlank: false,
-               hidden: isroot,
-               fieldLabel: gettext('Path')
-           });
-       }
-
-       me.callParent();
-
-       if (me.unused || me.isCreate) {
-           me.mon(me.down('#hdstorage'), 'change', function(field, newValue) {
-               if (!newValue) {
-                   return;
-               }
-               var rec = field.store.getById(newValue);
-               if (!rec) {
-                   return;
-               }
-               if (rec.data.type === 'zfs' || rec.data.type === 'zfspool') {
-                   me.quota.setDisabled(true);
-                   me.quota.setValue(false);
-               } else {
-                   me.quota.setDisabled(me.unprivileged);
-               }
-           });
-       }
-    }
+           deleteEmpty: false,
+           comboItems: [
+               ['__default__', Proxmox.Utils.defaultText],
+               ['1', Proxmox.Utils.enabledText],
+               ['0', Proxmox.Utils.disabledText],
+           ],
+           value: '__default__',
+           bind: {
+               disabled: '{isBind}',
+           },
+           allowBlank: true,
+       },
+       {
+           xtype: 'proxmoxcheckbox',
+           inputValue: '0', // reverses the logic
+           name: 'replicate',
+           fieldLabel: gettext('Skip replication'),
+       },
+    ],
 });
 
 Ext.define('PVE.lxc.MountPointEdit', {
-    extend: 'PVE.window.Edit',
+    extend: 'Proxmox.window.Edit',
 
     unprivileged: false,
 
-    initComponent : function() {
-       var me = this;
+    initComponent: function() {
+       let me = this;
 
-       var nodename = me.pveSelNode.data.node;
+       let nodename = me.pveSelNode.data.node;
        if (!nodename) {
            throw "no node name specified";
        }
 
-       var unused = me.confid && me.confid.match(/^unused\d+$/);
+       let unused = me.confid && me.confid.match(/^unused\d+$/);
 
        me.isCreate = me.confid ? unused : true;
 
-       var ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
+       let ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
            confid: me.confid,
            nodename: nodename,
            unused: unused,
            unprivileged: me.unprivileged,
-           isCreate: me.isCreate
+           isCreate: me.isCreate,
        });
 
-       var subject;
+       let subject;
        if (unused) {
            subject = gettext('Unused Disk');
        } else if (me.isCreate) {
@@ -321,7 +374,8 @@ Ext.define('PVE.lxc.MountPointEdit', {
 
        Ext.apply(me, {
            subject: subject,
-           items: ipanel
+           defaultFocus: me.confid !== 'rootfs' ? 'textfield[name=mp]' : 'tool',
+           items: ipanel,
        });
 
        me.callParent();
@@ -329,23 +383,19 @@ Ext.define('PVE.lxc.MountPointEdit', {
        me.load({
            success: function(response, options) {
                ipanel.setVMConfig(response.result.data);
-               if (me.confid) {
-                   /*jslint confusion: true*/
-                   /*data is defined as array above*/
-                   var value = response.result.data[me.confid];
-                   /*jslint confusion: false*/
-                   var mp = PVE.Parser.parseLxcMountPoint(value);
 
+               if (me.confid) {
+                   let value = response.result.data[me.confid];
+                   let mp = PVE.Parser.parseLxcMountPoint(value);
                    if (!mp) {
                        Ext.Msg.alert(gettext('Error'), 'Unable to parse mount point options');
                        me.close();
                        return;
                    }
-
                    ipanel.setMountPoint(mp);
                    me.isValid(); // trigger validation
                }
-           }
+           },
        });
-    }
+    },
 });