From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 463D51FF16B for ; Fri, 21 Nov 2025 17:59:32 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 78E35B8C; Fri, 21 Nov 2025 17:59:14 +0100 (CET) From: "Max R. Carrara" To: pve-devel@lists.proxmox.com Date: Fri, 21 Nov 2025 17:58:35 +0100 Message-ID: <20251121165858.818307-7-m.carrara@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251121165858.818307-1-m.carrara@proxmox.com> References: <20251121165858.818307-1-m.carrara@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1763744318269 X-SPAM-LEVEL: Spam detection results: 0 AWL -1.214 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy ENA_SUBJ_ODD_CASE 2.6 Subject has odd case KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [RFC proxmox-widget-toolkit master v2 6/10] utils: introduce helper function getFieldDefFromPropertySchema X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" 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 --- 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