[pve-devel] [PATCH manager v2 3/5] gui: add TagSelector

Dominik Csapak d.csapak at proxmox.com
Thu Oct 3 13:50:12 CEST 2019


this makes use of extjs TagField to be able to add Tags

we have to adapt some things for our custom color scheme and
list splitting behaviour

also atm, we do not preload the store so we have no tag suggestions,
this will come in a later patch, when we have a global taglist
(e.g. in the resource api call)

Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
 www/css/ext6-pve.css             |  12 ++++
 www/manager6/Makefile            |   1 +
 www/manager6/form/TagSelector.js | 117 +++++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+)
 create mode 100644 www/manager6/form/TagSelector.js

diff --git a/www/css/ext6-pve.css b/www/css/ext6-pve.css
index 3d90de59..186b661a 100644
--- a/www/css/ext6-pve.css
+++ b/www/css/ext6-pve.css
@@ -644,3 +644,15 @@ table.osds td:first-of-type {
 .tag-dark {
     color: #000;
 }
+
+/* overwrite extjs style */
+.x-form-text-default .x-tagfield-item {
+    border-radius: 5px;
+    border: 0px;
+    padding: 2px 19px 2px 4px;
+}
+
+/* we have more vertical padding, adapt position of 'x' */
+.x-form-text-default .x-tagfield-item-close {
+    top: 5px;
+}
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 82e25c79..198eea04 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -66,6 +66,7 @@ JSSRC= 				                 	\
 	form/CalendarEvent.js				\
 	form/CephPoolSelector.js			\
 	form/PermPathSelector.js			\
+	form/TagSelector.js				\
 	dc/Tasks.js					\
 	dc/Log.js					\
 	panel/StatusPanel.js				\
diff --git a/www/manager6/form/TagSelector.js b/www/manager6/form/TagSelector.js
new file mode 100644
index 00000000..c596d57e
--- /dev/null
+++ b/www/manager6/form/TagSelector.js
@@ -0,0 +1,117 @@
+Ext.define('PVE.form.TagSelector', {
+    extend: 'Ext.form.field.Tag',
+    xtype: 'pveTagSelector',
+
+    store: {
+	fields: ['name'],
+	data: [],
+    },
+    // if we can populate the store, we should remove this
+    hideTrigger: true,
+
+    getSubmitData: function() {
+	var me = this;
+	var data = me.callParent();
+	var name = me.getName();
+	if (Ext.isArray(data[name])) {
+	    data[name] = data[name].join(',');
+	}
+	if (data[name] == '') {
+	    data = {
+		delete: name
+	    };
+	}
+
+	return data;
+    },
+
+    setValue: function(value) {
+	var me = this;
+
+	if (Ext.isString(value) && me.multiSelect) {
+	    let delimiter = me.delimiterRegexp || me.delimiter || /[,; ]/;
+	    value = value.split(delimiter);
+	}
+
+	return me.callParent(arguments);
+    },
+
+    grow: true,
+    queryMode: 'local',
+
+    // overwrite to get the correct colors for the tags
+    // mostly copied from https://docs.sencha.com/extjs/6.0.1/classic/src/Tag.js.html
+    getMultiSelectItemMarkup: function() {
+        var me = this,
+            childElCls = (me._getChildElCls && me._getChildElCls()) || ''; // hook for rtl cls 
+
+	if (!me.labelTpl) {
+	    me.labelTpl = '{' + me.displayField + '}';
+	}
+	me.labelTpl = me.getTpl('labelTpl');
+
+	if (me.tipTpl) {
+	    me.tipTpl = me.getTpl('tipTpl');
+	}
+
+	me.multiSelectItemTpl = new Ext.XTemplate([
+	    '<tpl for=".">',
+	    '<li data-selectionIndex="{[xindex - 1]}" data-recordId="{internalId}" class="' + me.tagItemCls + childElCls,
+	    '<tpl if="this.isSelected(values)">',
+	    ' ' + me.tagSelectedCls,
+	    '</tpl>',
+	    '{%',
+	    'values = values.data;',
+	    '%}',
+	    ' tag"',
+	    'style="background-color: {[this.getBGColor(values)]}"',
+	    me.tipTpl ? ' data-qtip="{[this.getTip(values)]}">' : '>',
+	    '<div class="' + me.tagItemTextCls + ' {[this.getTxtCls(values)]}">{[this.getItemLabel(values)]}</div>',
+	    '<div class="' + me.tagItemCloseCls + childElCls + '"></div>' ,
+	    '</li>' ,
+	    '</tpl>',
+	    {
+		getTxtCls: function(values) {
+		    let rgb = PVE.Utils.stringToRGB(values.name);
+		    return PVE.Utils.rgbToLuminance(rgb) < 160 ? 'tag-light' : 'tag-dark';
+		},
+		getBGColor: function(values) {
+		    return PVE.Utils.rgbToCss(PVE.Utils.stringToRGB(values.name));
+		},
+		isSelected: function(rec) {
+		    return me.selectionModel.isSelected(rec);
+		},
+		getItemLabel: function(values) {
+		    return Ext.String.htmlEncode(me.labelTpl.apply(values));
+		},
+		getTip: function(values) {
+		    return Ext.String.htmlEncode(me.tipTpl.apply(values));
+		},
+		strict: true
+	    }
+	]);
+
+	return me.callParent();
+    },
+
+    maskRe: /[a-z0-9,;_\- ]/i,
+    delimiterRegexp: /[,; ]/,
+
+    displayField: 'name',
+    valueField: 'name',
+    createNewOnEnter: true,
+    createNewOnBlur: true,
+    forceSelection: false,
+    filterPickList: true,
+
+    initComponent: function() {
+	var me = this;
+
+	// save and restore a manual delimiterRegexp
+	var delimiterRegexp = me.delimiterRegexp;
+	me.callParent();
+	if (delimiterRegexp) {
+	    me.delimiterRegexp = delimiterRegexp;
+	}
+    }
+});
-- 
2.20.1





More information about the pve-devel mailing list