[pve-devel] [PATCH manager 3/3] ui: ceph pool edit: rework with controller and formulas

Dominik Csapak d.csapak at proxmox.com
Wed Mar 8 13:15:00 CET 2023


some (minor) comments inline

On 1/13/23 16:09, Aaron Lauterer wrote:
> instead of relying purely on listeners that then manually change other
> components, we can use binds, formulas and a basic controller.
> 
> This makes it quite a bit easier to let multiple components react to
> changes.
> 
> A cbind is used for the size component to set the initial start value.
> Other options, like using setValue in the controller init, will trigger
> the change listener and therefore can affect the min size without any
> user interaction.
> 
> Signed-off-by: Aaron Lauterer <a.lauterer at proxmox.com>
> ---
>   www/manager6/ceph/Pool.js | 87 ++++++++++++++++++++++++++++-----------
>   1 file changed, 63 insertions(+), 24 deletions(-)
> 
> diff --git a/www/manager6/ceph/Pool.js b/www/manager6/ceph/Pool.js
> index 86f83ffb..a38c5b3f 100644
> --- a/www/manager6/ceph/Pool.js
> +++ b/www/manager6/ceph/Pool.js
> @@ -7,6 +7,49 @@ Ext.define('PVE.CephPoolInputPanel', {
>       onlineHelp: 'pve_ceph_pools',
>   
>       subject: 'Ceph Pool',
> +
> +    viewModel: {

typically we have the viewmodel between the controller
and the layout, but no big issue
(though we're probably not 100% consistent on that)

> +	data: {
> +	    minSize: null,
> +	    size: null,
> +	},
> +	formulas: {
> +	    minSizeLabel: (get) => {
> +		if (get('showMinSizeOneWarning') || get('showMinSizeHalfWarning')) {
> +		    return `${gettext('Min. Size')} <i class="fa fa-exclamation-triangle warning"></i>`;
> +		}
> +		return gettext('Min. Size');
> +	    },
> +	    showMinSizeOneWarning: (get) => get('minSize') === 1,
> +	    showMinSizeHalfWarning: (get) => {
> +		let minSize = get('minSize');
> +		let size = get('size');
> +		if (minSize === 1) {
> +		    return false;
> +		}
> +		return minSize < (size / 2) && minSize !== size;
> +	    },

mhmm... i generally don't want to have negated variable names,
but since we bind that to the 'hidden' property (negated)

would it maybe make sense to reverse the logic in here and rename them
to 'hide*Warning' ?

not sure about that though

> +	},
> +    },
> +
> +    controller: {
> +	xclass: 'Ext.app.ViewController',
> +
> +	init: function(view) {
> +	    let vm = this.getViewModel();
> +	    vm.set('size', view.defaultSize ? Number(view.defaultSize) : 3);
> +	    vm.set('minSize', view.defaultMinSize ? Number(view.defaultMinSize) : 2);
> +	},
> +	sizeChange: function(field, val) {
> +	    let vm = this.getViewModel();
> +	    let minSize = Math.round(val / 2);
> +	    if (minSize > 1) {
> +		vm.set('minSize', minSize);
> +	    }
> +	    vm.set('size', val); // bind does not work in a pmxDisplayEditField, update manually
> +	},
> +    },
> +
>       column1: [
>   	{
>   	    xtype: 'pmxDisplayEditField',
> @@ -34,12 +77,7 @@ Ext.define('PVE.CephPoolInputPanel', {
>   		maxValue: 7,
>   		allowBlank: false,
>   		listeners: {
> -		    change: function(field, val) {
> -			let size = Math.round(val / 2);
> -			if (size > 1) {
> -			    field.up('inputpanel').down('field[name=min_size]').setValue(size);
> -			}
> -		    },
> +		    change: 'sizeChange',
>   		},
>   	    },
>   	},
> @@ -77,10 +115,13 @@ Ext.define('PVE.CephPoolInputPanel', {
>       advancedColumn1: [
>   	{
>   	    xtype: 'proxmoxintegerfield',
> -	    fieldLabel: gettext('Min. Size'),
> +	    bind: {
> +		fieldLabel: '{minSizeLabel}',
> +		value: '{minSize}',
> +	    },
>   	    name: 'min_size',
> +	    reference: 'min_size',

it seems you don't actually use the reference, maybe a leftover?

>   	    cbind: {
> -		value: (get) => get('defaultMinSize') ?? 2,
>   		minValue: (get) => {
>   		    if (Number(get('defaultMinSize')) === 1) {
>   			return 1;
> @@ -91,28 +132,26 @@ Ext.define('PVE.CephPoolInputPanel', {
>   	    },
>   	    maxValue: 7,
>   	    allowBlank: false,
> -	    listeners: {
> -		change: function(field, minSize) {
> -		    let panel = field.up('inputpanel');
> -		    let size = panel.down('field[name=size]').getValue();
> -
> -		    let showWarning = minSize < (size / 2) && minSize !== size;
> -
> -		    let fieldLabel = gettext('Min. Size');
> -		    if (showWarning) {
> -			fieldLabel = gettext('Min. Size') + ' <i class="fa fa-exclamation-triangle warning"></i>';
> -		    }
> -		    panel.down('field[name=min_size-warning]').setHidden(!showWarning);
> -		    field.setFieldLabel(fieldLabel);
> -		},
> -	    },
>   	},
>   	{
>   	    xtype: 'displayfield',
> -	    name: 'min_size-warning',
> +	    name: 'min_size_half-warning',

a field that's not set/read does not really need a name,
so we can simply omit that

> +	    bind: {
> +		hidden: '{!showMinSizeHalfWarning}',
> +	    },
> +	    hidden: true,
>   	    userCls: 'pmx-hint',
>   	    value: gettext('min_size < size/2 can lead to data loss, incomplete PGs or unfound objects.'),
> +	},
> +	{
> +	    xtype: 'displayfield',
> +	    name: 'min_size_one-warning',

same here

> +	    bind: {
> +		hidden: '{!showMinSizeOneWarning}',
> +	    },
>   	    hidden: true,
> +	    userCls: 'pmx-hint',
> +	    value: gettext('a min_size of 1 is not recommended and can lead to data loss'),
>   	},
>   	{
>   	    xtype: 'pmxDisplayEditField',





More information about the pve-devel mailing list