this is a complete rework of the inputpanel (long overdue) it uses a viewModel and viewcontroller to avoid the multiple is zfs/root/bind checks and concentrate them in one place
also some features get optimized (e.g. the noreplication checkbox) adds a setNodename to the DiskStorageSelector so that we can bind the nodename there Signed-off-by: Dominik Csapak <d.csa...@proxmox.com> --- www/manager6/form/DiskStorageSelector.js | 9 + www/manager6/lxc/MPEdit.js | 441 +++++++++++++++---------------- 2 files changed, 227 insertions(+), 223 deletions(-) diff --git a/www/manager6/form/DiskStorageSelector.js b/www/manager6/form/DiskStorageSelector.js index 0fdb5c5c..d5aaa0f8 100644 --- a/www/manager6/form/DiskStorageSelector.js +++ b/www/manager6/form/DiskStorageSelector.js @@ -76,6 +76,15 @@ Ext.define('PVE.form.DiskStorageSelector', { hdsizesel.setVisible(!select && !me.hideSize); }, + setNodename: function(nodename) { + var me = this; + var hdstorage = me.getComponent('hdstorage'); + var hdfilesel = me.getComponent('hdimage'); + + hdstorage.setNodename(nodename); + hdfilesel.setNodename(nodename); + }, + initComponent: function() { var me = this; diff --git a/www/manager6/lxc/MPEdit.js b/www/manager6/lxc/MPEdit.js index 079b8ddc..37f725ea 100644 --- a/www/manager6/lxc/MPEdit.js +++ b/www/manager6/lxc/MPEdit.js @@ -1,6 +1,11 @@ +/*jslint confusion: true*/ +/* hidden: boolean and string + * bind: function and object + * disabled: boolean and string + */ Ext.define('PVE.lxc.MountPointInputPanel', { extend: 'Proxmox.panel.InputPanel', - alias: 'widget.pveLxcMountPointInputPanel', + xtype: 'pveLxcMountPointInputPanel', insideWizard: false, @@ -13,284 +18,274 @@ Ext.define('PVE.lxc.MountPointInputPanel', { vmconfig: {}, // used to select unused disks setUnprivileged: function(unprivileged) { - this.unprivileged = unprivileged; - this.quota.setDisabled(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; + values.file = me.down('field[name=file]').getValue(); if (me.unused) { - me.mpdata.file = me.vmconfig[values.unusedId]; confid = values.mpsel; } 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; + values.file = values.hdstorage + ':' + values.disksize; } - if (values.noreplicate) { - me.mpdata.replicate = '0'; - } - delete me.mpdata.noreplicate; + // delete unnecessary fields + delete values.mpsel; + delete values.hdstorage; + delete values.disksize; + delete values.diskformat; var res = {}; - res[confid] = PVE.Parser.printLxcMountPoint(me.mpdata); + res[confid] = PVE.Parser.printLxcMountPoint(values); 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.acl.setDisabled(true); - me.acl.setValue('Default'); - me.down('#hdstorage').setDisabled(true); - if (me.confid !== 'rootfs') { - me.backup.setDisabled(true); - } - } - - if (mp.replicate) { // check box reverses the config option - mp.noreplicate = !PVE.Parser.parseBoolean(mp.replicate, 1); - delete mp.replicate; - } - + var vm = this.getViewModel(); + vm.set('mptype', mp.type); me.setValues(mp); }, setVMConfig: function(vmconfig) { var me = this; - + var vm = me.getViewModel(); me.vmconfig = vmconfig; - - 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; - } + vm.set('unpriv', vmconfig.unprivileged); + vm.notify(); + + PVE.Utils.forEachMP(function(bus, i) { + var name = "mp" + i.toString(); + if (!Ext.isDefined(vmconfig[name])) { + me.down('field[name=mpsel]').setValue(name); + 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); - } + }); }, setNodename: function(nodename) { var me = this; - me.down('#hdstorage').setNodename(nodename); - me.down('#hdimage').setStorage(undefined, nodename); + var vm = me.getViewModel(); + vm.set('node', nodename); + vm.notify(); + me.down('#diskstorage').setNodename(nodename); }, - initComponent : function() { - var me = this; - - var isroot = me.confid === 'rootfs'; - - me.mpdata = {}; + controller: { + xclass: 'Ext.app.ViewController', - 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('Proxmox.form.KVComboBox', { - name: 'mpsel', - fieldLabel: gettext('Mount Point'), - matchFieldWidth: false, - allowBlank: false, - comboItems: names, - validator: function(value) { - if (!me.rendered) { + control: { + 'field[name=mpsel]': { + change: function(field, value) { + field.validate(); + } + }, + '#hdstorage': { + change: function(field, newValue) { + var me = this; + if (!newValue) { return; } - if (Ext.isDefined(me.vmconfig[value])) { - return "Mount point is already in use."; - } - /*jslint confusion: true*/ - /* returns a string above */ - return true; - }, - listeners: { - change: function(field, value) { - field.validate(); + + var rec = field.store.getById(newValue); + if (!rec) { + return; } + + var vm = me.getViewModel(); + vm.set('type', rec.data.type); + vm.notify(); } - }); - me.column1.push(me.mpsel); + } + }, + + init: function(view) { + var me = this; + var vm = this.getViewModel(); + 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); + vm.notify(); } + }, - 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: 'proxmoxKVComboBox', + name: 'mpsel', + fieldLabel: gettext('Mount Point'), + matchFieldWidth: false, + hidden: true, + allowBlank: false, + bind: { + hidden: '{hasMP}', + disabled: '{hasMP}' + }, + comboItems: (function(){ + var mps = []; + PVE.Utils.forEachMP(function(bus,i) { + var name = 'mp' + i.toString(); + mps.push([name,name]); + }); + return mps; + }()), + validator: function(value) { + var me = this.up('inputpanel'); + if (!me.rendered) { + return; + } + if (Ext.isDefined(me.vmconfig[value])) { + return "Mount point is already in use."; + } + /*jslint confusion: true*/ + /* returns a string above */ + 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('Proxmox.form.KVComboBox', { - name: 'unusedId', - fieldLabel: gettext('Disk image'), - matchFieldWidth: false, - listConfig: { - width: 350 - }, - 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' - }); + 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, + fieldLabel: gettext('Path'), + bind: { + hidden: '{isRoot}', + disabled: '{isRoot}' + } + }, + { + xtype: 'proxmoxcheckbox', + name: 'backup', + fieldLabel: gettext('Backup'), + bind: { + hidden: '{isRoot}', + disabled: '{isBindOrRoot}' + } + } + ], - me.acl = Ext.createWidget('proxmoxKVComboBox', { - name: 'acl', - fieldLabel: 'ACLs', - comboItems: [['Default', 'Default'], ['1', 'On'], ['0', 'Off']], - value: 'Default', - allowBlank: true - }); - - me.quota = Ext.createWidget('proxmoxcheckbox', { + advancedColumn1: [ + { + xtype: 'proxmoxcheckbox', name: 'quota', defaultValue: 0, - disabled: me.unprivileged, + bind: { + disabled: '{!quota}' + }, fieldLabel: gettext('Enable quota'), listeners: { disable: function() { this.reset(); } } - }); - - me.column2 = [ - me.acl, - me.quota - ]; - - if (!isroot) { - me.column2.splice(1, 0, { - xtype: 'proxmoxcheckbox', - name: 'ro', - defaultValue: 0, - fieldLabel: gettext('Read-only'), - hidden: me.insideWizard - }); - - me.backup = Ext.createWidget('proxmoxcheckbox',{ - xtype: 'proxmoxcheckbox', - name: 'backup', - fieldLabel: gettext('Backup') - }); - if (me.mpdata.type !== 'bind') { - me.column2.push(me.backup); - } - me.column2.push({ - xtype: 'proxmoxcheckbox', - 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') - }); + }, + { + xtype: 'proxmoxcheckbox', + name: 'ro', + defaultValue: 0, + bind: { + hidden: '{isRoot}', + disabled: '{isRoot}' + }, + fieldLabel: gettext('Read-only') } + ], - 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); - } else { - me.quota.setDisabled(me.unprivileged); - } - }); + advancedColumn2: [ + { + xtype: 'proxmoxKVComboBox', + name: 'acl', + fieldLabel: 'ACLs', + 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', { -- 2.11.0 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel