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 2A4CC702A6 for ; Tue, 21 Jun 2022 11:20:44 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 723032C99 for ; Tue, 21 Jun 2022 11:20:26 +0200 (CEST) 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 034BA29D7 for ; Tue, 21 Jun 2022 11:20:16 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id CF7F34378F for ; Tue, 21 Jun 2022 11:20:15 +0200 (CEST) From: Dominik Csapak To: pve-devel@lists.proxmox.com Date: Tue, 21 Jun 2022 11:20:06 +0200 Message-Id: <20220621092012.1776825-19-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220621092012.1776825-1-d.csapak@proxmox.com> References: <20220621092012.1776825-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.101 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 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 v7 08/14] ui: add form/TagEdit.js 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: Tue, 21 Jun 2022 09:20:44 -0000 this is a wrapper container for holding a list of (editable) tags intended to be used in the lxc/qemu status toolbar Signed-off-by: Dominik Csapak --- www/manager6/Makefile | 1 + www/manager6/form/TagEdit.js | 151 +++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 www/manager6/form/TagEdit.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index 9d610f71..eb4be4c5 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -75,6 +75,7 @@ JSSRC= \ form/iScsiProviderSelector.js \ form/TagColorGrid.js \ form/Tag.js \ + form/TagEdit.js \ grid/BackupView.js \ grid/FirewallAliases.js \ grid/FirewallOptions.js \ diff --git a/www/manager6/form/TagEdit.js b/www/manager6/form/TagEdit.js new file mode 100644 index 00000000..5a267169 --- /dev/null +++ b/www/manager6/form/TagEdit.js @@ -0,0 +1,151 @@ +Ext.define('PVE.panel.TagEditContainer', { + extend: 'Ext.container.Container', + alias: 'widget.pveTagEditContainer', + + tagCount: 0, + + layout: { + type: 'hbox', + align: 'stretch', + }, + + loadTags: function(tagstring = '', inEdit, force = false) { + let me = this; + + if (me.oldTags === tagstring && !force) { + return; + } + + let tags = tagstring.split(/[;, ]/).filter((t) => !!t) || []; + me.suspendLayout = true; + me.tags = {}; + me.removeAllTags(); + tags.forEach((tag) => { + me.addTag(tag, inEdit); + }); + me.suspendLayout = false; + me.updateLayout(); + if (!force) { + me.oldTags = tagstring; + } + }, + + getEditBtnHtml: function() { + let me = this; + let cls = ''; + let qtip = ''; + if (me.editMode) { + qtip = gettext('Apply Changes'); + cls = 'check'; + } else { + qtip = gettext('Edit Tags'); + cls = 'pencil'; + } + return ` `; + }, + + toggleEdit: function(cancel) { + let me = this; + me.editMode = !me.editMode; + let tagCount = 0; + me.tagFields.forEach((tag) => { + tag.setMode(me.editMode ? 'editable' : 'normal'); + if (tag.isVisible() && !tag.addTag) { + tagCount++; + } + }); + + me.addTagBtn.setVisible(me.editMode); + me.editBtn.setHtml(me.getEditBtnHtml()); + me.noTagsField.setVisible(!me.editMode && tagCount === 0); + me.cancelBtn.setVisible(me.editMode); + + if (!me.editMode) { + let tags = []; + if (cancel) { + me.loadTags(me.oldTags, false, true); + } else { + me.tagFields.forEach((tag) => { + let tagValue = tag.getTag(); + if (tag.isVisible() && tagValue) { + tags.push(tagValue); + } + }); + tags = tags.join(','); + if (me.oldTags !== tags) { + me.oldTags = tags; + me.fireEvent('change', tags); + } + } + } + me.updateLayout(); + }, + + removeAllTags: function() { + let me = this; + me.tagFields.forEach((tag) => { + me.remove(tag); + }); + me.tagFields = []; + me.noTagsField.setVisible(true); + }, + + addTag: function(tag, inEdit) { + let me = this; + let tagField = me.insert(me.tagFields.length + 1, { + xtype: 'pmxTag', + tag, + mode: inEdit ? 'editable' : 'normal', + layoutCallback: () => me.updateLayout(), + }); + me.tagFields.push(tagField); + me.noTagsField.setVisible(false); + }, + + initComponent: function() { + let me = this; + me.tagFields = []; + me.callParent(); + me.noTagsField = me.add({ + xtype: 'box', + html: gettext('No Tags'), + }); + me.addTagBtn = me.add({ + xtype: 'pmxTag', + addTag: true, + hidden: true, + layoutCallback: () => me.updateLayout(), + listeners: { + change: function(tag) { + me.addTag(tag, true); + }, + }, + }); + me.cancelBtn = me.add({ + xtype: 'box', + html: ` `, + style: { + cursor: 'pointer', + }, + hidden: true, + listeners: { + click: () => me.toggleEdit(true), + element: 'el', + }, + }); + me.editBtn = me.add({ + xtype: 'box', + html: me.getEditBtnHtml(), + style: { + cursor: 'pointer', + }, + listeners: { + click: () => me.toggleEdit(false), + element: 'el', + }, + }); + if (me.tags) { + me.loadTags(me.tags); + } + }, +}); -- 2.30.2