[pve-devel] [PATCH manager 11/11] lxc/MPEdit: rework for advanced options

Dominik Csapak d.csapak at proxmox.com
Thu Apr 5 16:03:56 CEST 2018


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.csapak at 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




More information about the pve-devel mailing list