From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 508146948E for ; Wed, 23 Mar 2022 11:35:49 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 3C0A725909 for ; Wed, 23 Mar 2022 11:34:55 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 666A0258E9 for ; Wed, 23 Mar 2022 11:34:52 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 3D0DC41A28 for ; Wed, 23 Mar 2022 11:34:52 +0100 (CET) From: Dominik Csapak To: pve-devel@lists.proxmox.com Date: Wed, 23 Mar 2022 11:34:40 +0100 Message-Id: <20220323103445.2075649-8-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220323103445.2075649-1-d.csapak@proxmox.com> References: <20220323103445.2075649-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.100 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment PROLO_LEO1 0.1 Meta Catches all Leo drug variations so far SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pve-devel] [PATCH manager v4 05/10] ui: add form/TagColorGrid 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: , X-List-Received-Date: Wed, 23 Mar 2022 10:35:49 -0000 this provides a basic grid to edit a list of tag color overrides. We'll use this for editing the datacenter.cfg overrides and the browser storage overrides. Signed-off-by: Dominik Csapak --- www/manager6/Makefile | 1 + www/manager6/form/TagColorGrid.js | 218 ++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 www/manager6/form/TagColorGrid.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index e6e01bd1..225dffba 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -73,6 +73,7 @@ JSSRC= \ form/VNCKeyboardSelector.js \ form/ViewSelector.js \ form/iScsiProviderSelector.js \ + form/TagColorGrid.js \ grid/BackupView.js \ grid/FirewallAliases.js \ grid/FirewallOptions.js \ diff --git a/www/manager6/form/TagColorGrid.js b/www/manager6/form/TagColorGrid.js new file mode 100644 index 00000000..bd8e539e --- /dev/null +++ b/www/manager6/form/TagColorGrid.js @@ -0,0 +1,218 @@ +Ext.define('PVE.form.ColorPicker', { + extend: 'Ext.Component', + alias: 'widget.pveColorPicker', + + defaultBindProperty: 'value', + + config: { + value: null, + }, + + height: 15, + maxHeight: 15, + + getValue: function() { + return this.realvalue.slice(1); + }, + + setValue: function(value = "000000") { + let me = this; + me.picker.value = value[0] !== '#' ? `#${value}` : value; + me.setColor(value); + }, + + setColor: function(value = "000000") { + let me = this; + let oldValue = me.realvalue; + me.realvalue = value; + me.setStyle('background-color', `#${value}`); + me.fireEvent('change', me, me.realvalue, oldValue); + }, + + initComponent: function() { + let me = this; + me.picker = document.createElement('input'); + me.picker.type = 'color'; + me.picker.style = `opacity: 0; border: 0px; width: 100%; height: ${me.height}px`; + me.picker.value = `${me.value}`; + me.contentEl = me.picker; + + me.callParent(); + me.picker.oninput = function() { + me.setColor(me.picker.value); + }; + }, +}); + +Ext.define('PVE.form.TagColorGrid', { + extend: 'Ext.grid.Panel', + alias: 'widget.pveTagColorGrid', + + mixins: [ + 'Ext.form.field.Field', + ], + + allowBlank: true, + selectAll: false, + isFormField: true, + deleteEmpty: false, + selModel: 'checkboxmodel', + + config: { + deleteEmpty: false, + }, + + emptyText: gettext('No Overrides'), + viewConfig: { + deferEmptyText: false, + }, + + setValue: function(value) { + let me = this; + if (!value) { + me.getStore().removeAll(); + me.checkChange(); + return me; + } + let entries = (value.split(/[;, ]/) || []).map((entry) => { + let [tag, color] = entry.split(/[=]/); + return { + tag, + color, + }; + }); + me.getStore().setData(entries); + me.checkChange(); + return me; + }, + + getValue: function() { + let me = this; + let values = []; + me.getStore().each((rec) => { + if (rec.data.tag) { + values.push(`${rec.data.tag}=${rec.data.color}`); + } + }); + return values.join(','); + }, + + getErrors: function(value) { + return []; + }, + + // override framework function to implement deleteEmpty behaviour + getSubmitData: function() { + let me = this, + data = null, + val; + if (!me.disabled && me.submitValue) { + val = me.getValue(); + if (val !== null && val !== '') { + data = {}; + data[me.getName()] = val; + } else if (me.getDeleteEmpty()) { + data = {}; + data.delete = me.getName(); + } + } + return data; + }, + + + controller: { + xclass: 'Ext.app.ViewController', + + addLine: function() { + let me = this; + me.getView().getStore().add({}); + }, + + removeSelection: function() { + let me = this; + let view = me.getView(); + let selection = view.getSelection(); + if (selection === undefined) { + return; + } + + selection.forEach((sel) => { + view.getStore().remove(sel); + }); + view.checkChange(); + }, + + fieldChange: function(field, newValue, oldValue) { + let me = this; + let view = me.getView(); + let rec = field.getWidgetRecord(); + let column = field.getWidgetColumn(); + rec.set(column.dataIndex, newValue); + view.checkChange(); + }, + }, + + tbar: [ + { + text: gettext('Add'), + handler: 'addLine', + }, + { + xtype: 'proxmoxButton', + text: gettext('Remove'), + handler: 'removeSelection', + disabled: true, + }, + ], + + columns: [ + { + header: 'Tag', + dataIndex: 'tag', + xtype: 'widgetcolumn', + onWidgetAttach: function(col, widget, rec) { + widget.getStore().setData(PVE.Utils.getTagList().map(v => ({ tag: v }))); + }, + widget: { + xtype: 'combobox', + isFormField: false, + maskRe: /[a-zA-Z0-9_.-]/, + queryMode: 'local', + displayField: 'tag', + valueField: 'tag', + store: {}, + listeners: { + change: 'fieldChange', + }, + }, + flex: 1, + }, + { + header: "Color", + xtype: 'widgetcolumn', + flex: 1, + dataIndex: 'color', + widget: { + xtype: 'pveColorPicker', + isFormField: false, + listeners: { + change: 'fieldChange', + }, + }, + }, + ], + + store: { + listeners: { + update: function() { + this.commitChanges(); + }, + }, + }, + + initComponent: function() { + let me = this; + me.callParent(); + me.initField(); + }, +}); -- 2.30.2