From: "Max R. Carrara" <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [RFC proxmox-widget-toolkit master v2 6/10] utils: introduce helper function getFieldDefFromPropertySchema
Date: Fri, 21 Nov 2025 17:58:35 +0100 [thread overview]
Message-ID: <20251121165858.818307-7-m.carrara@proxmox.com> (raw)
In-Reply-To: <20251121165858.818307-1-m.carrara@proxmox.com>
This helper takes the JSONSchema of a single property and transforms
it into an object representing an ExtJS field.
Currently, four types for properties are supported: string, integer,
number and boolean.
Additionally, the helper also takes "extra attributes" and a "context"
which allows for more fine-grained control over how the ExtJS field is
actually constructed and also makes it possible to express different
UI-specific behaviors that cannot be modeled via JSONSchema (for
example, whether a field's contents are sensitive).
Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
---
src/Utils.js | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
diff --git a/src/Utils.js b/src/Utils.js
index 5457ffa..a9bcb56 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -1571,6 +1571,112 @@ Ext.define('Proxmox.Utils', {
}
hiddenElement.click();
},
+
+ /**
+ * Takes a JSONSchema of a single property and transforms it into an
+ * object representing an ExtJS field.
+ *
+ * @param {string} fieldName - The value for the `name` property of the resulting object.
+ * @param {Object} propSchema - The JSONSchema of a property.
+ * @param {Object} extraAttributes - Additional attributes describing the
+ * field that are not or cannot be represented by the given JSONSchema.
+ * Note that none of these attributes represent any specific ExtJS property.
+ * @param {Boolean} extraAttributes.readonly - Whether the field shall be read-only.
+ * "Read-only" here means that the field's `xtype` will be set to
+ * `'displayfield'`, regardless of what data type the field will
+ * display. Additionally, checkboxes (booleans) will be displayed as
+ * "Yes" or "No" depending on their value (locale-aware).
+ * @param {Boolean} extraAttributes.sensitive - Whether the field
+ * contains sensitive data, such as a password or similar.
+ * @param {Object} context - The context within which the field is being used.
+ * @param {Boolean} context.isCreate - Whether the field will be used during creation.
+ */
+ getFieldDefFromPropertySchema: function (fieldName, propSchema, extraAttributes, context) {
+ const fieldPropsByType = {
+ string: {
+ xtype: 'proxmoxtextfield',
+ minLength: propSchema.minLength,
+ maxLength: propSchema.maxLength,
+ },
+ integer: {
+ xtype: 'proxmoxintegerfield',
+ minValue: propSchema.minimum,
+ maxValue: propSchema.maximum,
+ },
+ number: {
+ xtype: 'numberfield',
+ minValue: propSchema.minimum,
+ maxValue: propSchema.maximum,
+ },
+ boolean: {
+ xtype: 'proxmoxcheckbox',
+ uncheckedValue: 0,
+ },
+ };
+
+ const commonFieldProps = {
+ name: fieldName,
+ emptyText: propSchema.default || '',
+ allowBlank: propSchema.optional,
+ };
+
+ let fieldProps = fieldPropsByType[propSchema.type];
+ if (fieldProps === undefined) {
+ console.warn(`Unhandled property type '${propSchema.type}'`);
+ fieldProps = fieldPropsByType.string;
+ }
+
+ let field = {
+ ...fieldProps,
+ ...commonFieldProps,
+ };
+
+ if (propSchema.title) {
+ field.fieldLabel = Ext.htmlEncode(propSchema.title);
+ }
+
+ if (propSchema.description) {
+ field.autoEl = {
+ tag: 'div',
+ 'data-qtip': Ext.htmlEncode(Ext.htmlEncode(propSchema.description)),
+ };
+ }
+
+ if (context.isCreate && propSchema.default !== undefined) {
+ if (propSchema.type === 'boolean') {
+ field.checked = propSchema.default;
+ } else {
+ field.value = propSchema.default;
+ }
+ }
+
+ if (extraAttributes.sensitive) {
+ field.xtype = 'proxmoxtextfield';
+ field.inputType = 'password';
+
+ if (context.isCreate) {
+ field.value = '';
+ field.emptyText = Proxmox.Utils.NoneText;
+ } else {
+ field.emptyText = gettext('Unchanged');
+ }
+ }
+
+ if (extraAttributes.readonly) {
+ field.xtype = 'displayfield';
+
+ if (propSchema.type === 'boolean') {
+ field.renderer = Proxmox.Utils.format_boolean;
+ }
+
+ if (extraAttributes.sensitive) {
+ field.value = '*********';
+ field.emptyText = '';
+ }
+ }
+
+ return field;
+ },
},
singleton: true,
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-11-21 16:59 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-21 16:58 [pve-devel] [RFC pve-storage/proxmox-widget-toolkit/pve-manager master v2 00/10] GUI Support for Custom Storage Plugins Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-storage master v2 1/10] api: plugins/storage: add initial routes and endpoints Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-storage master v2 2/10] api: plugins/storage/plugin: include schema in plugin metadata Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-storage master v2 3/10] api: plugins/storage/plugin: mark sensitive properties in schema Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-storage master v2 4/10] api: plugins/storage/plugin: factor plugin metadata code into helper Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-storage master v2 5/10] api: plugins/storage/plugin: add plugins' 'content' to their metadata Max R. Carrara
2025-11-21 16:58 ` Max R. Carrara [this message]
2025-11-21 16:58 ` [pve-devel] [RFC proxmox-widget-toolkit master v2 7/10] acme: use helper to construct ExtJS fields from property schemas Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-manager master v2 08/10] api: add API routes 'plugins' and 'plugins/storage' Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-manager master v2 09/10] ui: storage view: display error when no editor for storage type exists Max R. Carrara
2025-11-21 16:58 ` [pve-devel] [RFC pve-manager master v2 10/10] ui: storage: add basic UI integration for custom storage plugins Max R. Carrara
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=20251121165858.818307-7-m.carrara@proxmox.com \
--to=m.carrara@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox