all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Noel Ullreich <n.ullreich@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH widget-toolkit] ui: Extend BandwithSelector with selecatble units
Date: Thu, 27 Jul 2023 11:53:12 +0200	[thread overview]
Message-ID: <20230727095312.29713-2-n.ullreich@proxmox.com> (raw)
In-Reply-To: <20230727095312.29713-1-n.ullreich@proxmox.com>

Work in progress! But today is my last day and I want to send what I have.
Comments and TODOS on what needs to still be done and what doesn't work
are inline.

Extends the BandwithSelector to add features:
* selectable units  via dropdown menu
* pass lists of minvalues/stepsize (TODO: maxvalue) for each unit
* set flag to autoconvert units (E.g. 1024 MiB -> 1 GiB)

Signed-off-by: Noel Ullreich <n.ullreich@proxmox.com>
---
 src/form/BandwidthSelector.js | 96 ++++++++++++++++++++++++++++++-----
 1 file changed, 84 insertions(+), 12 deletions(-)

diff --git a/src/form/BandwidthSelector.js b/src/form/BandwidthSelector.js
index 434ab62..fae10b7 100644
--- a/src/form/BandwidthSelector.js
+++ b/src/form/BandwidthSelector.js
@@ -8,6 +8,8 @@ Ext.define('Proxmox.form.SizeField', {
 	data: {
 	    unit: 'MiB',
 	    unitPostfix: '',
+	    step: 1,
+	    min: 1,
 	},
 	formulas: {
 	    unitlabel: (get) => get('unit') + get('unitPostfix'),
@@ -22,6 +24,7 @@ Ext.define('Proxmox.form.SizeField', {
     },
 
     // display unit (TODO: make (optionally) selectable)
+    unitname: 'unit',
     unit: 'MiB',
     unitPostfix: '',
 
@@ -37,6 +40,22 @@ Ext.define('Proxmox.form.SizeField', {
 
     emptyValue: null,
 
+    // if using the same minimum value for all units, set it here. otherwise pass a minarray
+    minvalue: 1,
+    // to have different min values for different units, pass an array of min values
+    minarray: false,
+
+    // array of units that are selectable, doesn't have to be consecutive units
+    datastore: Object.keys(Proxmox.Utils.SizeUnits),
+
+    // if using the same stepsize for all units, set it here. otherwise pass a steparray
+    step: 1,
+    // to have different stepsizes for different units, pass an array of stepsizes
+    steparray: false,
+
+    // in the setvalue, auto scale the units. e.g. 1024MiB->1GiB
+    autoscale: true,
+
     items: [
 	{
 	    xtype: 'numberfield',
@@ -45,32 +64,45 @@ Ext.define('Proxmox.form.SizeField', {
 		emptyText: '{emptyText}',
 		allowZero: '{allowZero}',
 		emptyValue: '{emptyValue}',
+		step: '{step}',
+		autoscale: '{autoscale}',
+		datastore: '{datastore}',
+		steparray: '{steparray}',
+		minValue: '{minvalue}',
+		minarray: '{minarray}',
+
 	    },
-	    minValue: 0,
-	    step: 1,
 	    submitLocaleSeparator: false,
 	    fieldStyle: 'text-align: right',
-	    flex: 1,
+	    flex: 2,
 	    enableKeyEvents: true,
 	    setValue: function(v) {
 		if (!this._transformed) {
+		    let me = this;
 		    let fieldContainer = this.up('fieldcontainer');
 		    let vm = fieldContainer.getViewModel();
-		    let unit = vm.get('unit');
 
 		    if (typeof v === "string") {
 			v = Proxmox.Utils.size_unit_to_bytes(v);
 		    }
-		    v /= Proxmox.Utils.SizeUnits[unit];
+		    v /= Proxmox.Utils.SizeUnits[vm.get('unit')];
 		    v *= fieldContainer.backendFactor;
 
+		    if (me.autoscale) {
+			for (let key of me.datastore) {
+			    if (v%(Proxmox.Utils.SizeUnits[key]/fieldContainer.backendFactor)===0) {
+				vm.set('unit', key);
+			    }
+			}
+			v = v*fieldContainer.backendFactor/Proxmox.Utils.SizeUnits[vm.get('unit')];
+		    }
+
 		    this._transformed = true;
 		}
 
 		if (Number(v) === 0 && !this.allowZero) {
 		    v = undefined;
 		}
-
 		return Ext.form.field.Text.prototype.setValue.call(this, v);
 	    },
 	    getSubmitValue: function() {
@@ -101,22 +133,62 @@ Ext.define('Proxmox.form.SizeField', {
 		// our setValue gets only called if we have a value, avoid
 		// transformation of the first user-entered value
 		keydown: function() { this._transformed = true; },
+		change: function(f, v) {
+		    let me = this;
+
+		    //TODO: atm this is called each time a value is changed,
+		    // update step somehwere else?
+		    if (me.steparray) {
+			me.step = f.up('fieldcontainer').getViewModel().get('step');
+		    }
+		    if (me.minarray) {
+			console.log(f.up('fieldcontainer').getViewModel().get('min'));
+			me.setMinValue(f.up('fieldcontainer').getViewModel().get('min'));
+		    }
+		},
 	    },
 	},
 	{
-	    xtype: 'displayfield',
-	    name: 'unit',
-	    submitValue: false,
-	    padding: '0 0 0 10',
+	    xtype: 'combobox',
+	    cbind: {
+		//TODO: not ideal, fish out values form store instead of
+		//`me.datastore.indexOf` below?
+		datastore: '{datastore}',
+		store: '{datastore}',
+		name: '{unitname}',
+		steparray: '{steparray}',
+		minarray: '{minarray}',
+		numberfieldName: '{name}',
+	    },
+	    itemId: 'unit',
+	    flex: 1,
+	    editable: false,
+	    allowBlank: false,
+	    //padding: '0 0 0 10',
 	    bind: {
 		value: '{unitlabel}',
 	    },
 	    listeners: {
-		change: (f, v) => {
+		change: function(f, v) {
+		    let me = this;
 		    f.originalValue = v;
+		    f.up('fieldcontainer').getViewModel().set('unit', v);
+
+		    // TODO: i don't know if making a viewmodel entry to change stepsize
+		    // is the best idea. Ideally I'd like to directly change `me.step` in
+		    // the valuefield directly, but me.down doesn't work with this layout.
+		    // plus, we need to run a `validate` on the valuefield
+		    // Is there a better way of doing this?
+		    if (me.steparray) {
+			let sa = me.steparray[me.datastore.indexOf(v)];
+			f.up('fieldcontainer').getViewModel().set('step', sa);
+		    }
+		    if (me.minarray) {
+			let ma = me.minarray[me.datastore.indexOf(v)];
+			f.up('fieldcontainer').getViewModel().set('min', ma);
+		    }
 		},
 	    },
-	    width: 40,
 	},
     ],
 
-- 
2.39.2





      reply	other threads:[~2023-07-27  9:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-27  9:53 [pve-devel] [PATCH widget-toolkit 0/1]ui: " Noel Ullreich
2023-07-27  9:53 ` Noel Ullreich [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230727095312.29713-2-n.ullreich@proxmox.com \
    --to=n.ullreich@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal