]> git.proxmox.com Git - pve-manager.git/commitdiff
ui: wizards: allow adding tags in the qemu/lxc create wizard
authorDominik Csapak <d.csapak@proxmox.com>
Wed, 25 Oct 2023 11:09:38 +0000 (13:09 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Mon, 6 Nov 2023 16:02:08 +0000 (17:02 +0100)
in the general tab in the advanced section.

For that to work, we introduce a new option for the TagEditContainer
named 'editOnly', which controls now the cancel/finish buttons,
automatically enter edit mode and disable enter/escape keypresses.

We also prevent now the loading of tags while in edit mode, so the tags
don't change while editing (this can be jarring and unexpected).

Then we wrap that all in a FieldSet that implements the Field mixin, so
we can easily use that in the wizard. There we set a maxHeight so that
the field can grow so that it still fits in the wizard.

To properly align the input with the '+' button, we have to add a custom
css class there. (In the hbox we could set the alignment, but this is
not possible in the 'column' layout)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
www/css/ext6-pve.css
www/manager6/Makefile
www/manager6/form/TagEdit.js
www/manager6/form/TagFieldSet.js [new file with mode: 0644]
www/manager6/lxc/CreateWizard.js
www/manager6/qemu/CreateWizard.js

index 85cf4039f6c9d1231387a72453e9646c328eaac4..105adc45d6b5559d5b7b618568f79310ee7fd8a4 100644 (file)
@@ -721,3 +721,8 @@ table.osds td:first-of-type {
 .pmx-opacity-75 {
     opacity: 0.75;
 }
+
+/* tag edit fields must be aligned manually in the fieldset */
+.proxmox-tag-fieldset.proxmox-tags-full .x-component.x-column {
+    margin: 2px;
+}
index 57e1b48fad6848dfef3f03b6ac305c43eea75657..dccd2ba1c02622b89a7057e97c6f2a99772db21c 100644 (file)
@@ -87,6 +87,7 @@ JSSRC=                                                        \
        form/Tag.js                                     \
        form/TagEdit.js                                 \
        form/MultiFileButton.js                         \
+       form/TagFieldSet.js                             \
        grid/BackupView.js                              \
        grid/FirewallAliases.js                         \
        grid/FirewallOptions.js                         \
index 094f44626f677a70724ea1c0989ce8a3f04eb658..7d5b19ec32a38c6ed08a33e07bc91a1478858681 100644 (file)
@@ -9,6 +9,7 @@ Ext.define('PVE.panel.TagEditContainer', {
 
     // set to false to hide the 'no tags' field and the edit button
     canEdit: true,
+    editOnly: false,
 
     controller: {
        xclass: 'Ext.app.ViewController',
@@ -216,6 +217,9 @@ Ext.define('PVE.panel.TagEditContainer', {
                        me.tagsChanged();
                    },
                    keypress: function(key) {
+                       if (vm.get('hideFinishButtons')) {
+                           return;
+                       }
                        if (key === 'Enter') {
                            me.editClick();
                        } else if (key === 'Escape') {
@@ -253,20 +257,40 @@ Ext.define('PVE.panel.TagEditContainer', {
                me.loadTags(view.tags);
            }
            me.getViewModel().set('canEdit', view.canEdit);
+           me.getViewModel().set('editOnly', view.editOnly);
 
            me.mon(Ext.GlobalEvents, 'loadedUiOptions', () => {
+               let vm = me.getViewModel();
                view.toggleCls('hide-handles', PVE.UIOptions.shouldSortTags());
-               me.loadTags(me.oldTags, true); // refresh tag colors and order
+               me.loadTags(me.oldTags, !vm.get('editMode')); // refresh tag colors and order
            });
+
+           if (view.editOnly) {
+               me.toggleEdit();
+           }
        },
     },
 
+    getTags: function() {
+       let me =this;
+       let controller = me.getController();
+       let tags = [];
+           controller.forEachTag((cmp) => {
+               if (cmp.tag.length) {
+                   tags.push(cmp.tag);
+               }
+           });
+
+       return tags;
+    },
+
     viewModel: {
        data: {
            tagCount: 0,
            editMode: false,
            canEdit: true,
            isDirty: false,
+           editOnly: true,
        },
 
        formulas: {
@@ -276,6 +300,9 @@ Ext.define('PVE.panel.TagEditContainer', {
            hideEditBtn: function(get) {
                return get('editMode') || !get('canEdit');
            },
+           hideFinishButtons: function(get) {
+               return !get('editMode') || get('editOnly');
+           },
        },
     },
 
@@ -311,7 +338,7 @@ Ext.define('PVE.panel.TagEditContainer', {
            xtype: 'tbseparator',
            ui: 'horizontal',
            bind: {
-               hidden: '{!editMode}',
+               hidden: '{hideFinishButtons}',
            },
            hidden: true,
        },
@@ -320,7 +347,7 @@ Ext.define('PVE.panel.TagEditContainer', {
            iconCls: 'fa fa-times',
            tooltip: gettext('Cancel Edit'),
            bind: {
-               hidden: '{!editMode}',
+               hidden: '{hideFinishButtons}',
            },
            hidden: true,
            margin: '0 5 0 0',
@@ -332,7 +359,7 @@ Ext.define('PVE.panel.TagEditContainer', {
            iconCls: 'fa fa-check',
            tooltip: gettext('Finish Edit'),
            bind: {
-               hidden: '{!editMode}',
+               hidden: '{hideFinishButtons}',
                disabled: '{!isDirty}',
            },
            hidden: true,
diff --git a/www/manager6/form/TagFieldSet.js b/www/manager6/form/TagFieldSet.js
new file mode 100644 (file)
index 0000000..132b215
--- /dev/null
@@ -0,0 +1,64 @@
+Ext.define('PVE.form.TagFieldSet', {
+    extend: 'Ext.form.FieldSet',
+    alias: 'widget.pveTagFieldSet',
+    mixins: ['Ext.form.field.Field'],
+
+    title: gettext('Tags'),
+    padding: '0 5 5 5',
+
+    getValue: function() {
+       let me = this;
+       let tags = me.down('pveTagEditContainer').getTags().filter(t => t !== '');
+       return tags.join(';');
+    },
+
+    setValue: function(value) {
+       let me = this;
+       value ??= [];
+       if (!Ext.isArray(value)) {
+           value = value.split(/[;, ]/).filter(t => t !== '');
+       }
+       me.down('pveTagEditContainer').loadTags(value.join(';'));
+    },
+
+    getErrors: function(value) {
+       value ??= [];
+       if (!Ext.isArray(value)) {
+           value = value.split(/[;, ]/).filter(t => t !== '');
+       }
+       if (value.some(t => !t.match(PVE.Utils.tagCharRegex))) {
+           return [gettext("Tags contain invalid characters.")];
+       }
+       return [];
+    },
+
+    getSubmitData: function() {
+       let me = this;
+       let value = me.getValue();
+       if (me.disabled || !me.submitValue || value === '') {
+           return null;
+       }
+       let data = {};
+       data[me.getName()] = value;
+       return data;
+    },
+
+    layout: 'fit',
+
+    items: [
+       {
+           xtype: 'pveTagEditContainer',
+           userCls: 'proxmox-tags-full proxmox-tag-fieldset',
+           editOnly: true,
+           allowBlank: true,
+           layout: 'column',
+           scrollable: true,
+       },
+    ],
+
+    initComponent: function() {
+       let me = this;
+       me.callParent();
+       me.initField();
+    },
+});
index e363529747b1c0c5040b51ac5b439ccaaa89a1ed..b57b305001e41d8e9c5dc35c2c1b1a56f2684966 100644 (file)
@@ -178,6 +178,13 @@ Ext.define('PVE.lxc.CreateWizard', {
                    },
                },
            ],
+           advancedColumnB: [
+               {
+                   xtype: 'pveTagFieldSet',
+                   name: 'tags',
+                   maxHeight: 150,
+               },
+           ],
        },
        {
            xtype: 'inputpanel',
index a65067eae68ecb05efa30ae8295aa651b97fccc1..74b1feb61ac292c0ac683ab13630bd7bdf753107 100644 (file)
@@ -108,6 +108,15 @@ Ext.define('PVE.qemu.CreateWizard', {
                    fieldLabel: gettext('Shutdown timeout'),
                },
            ],
+
+           advancedColumnB: [
+               {
+                   xtype: 'pveTagFieldSet',
+                   name: 'tags',
+                   maxHeight: 150,
+               },
+           ],
+
            onGetValues: function(values) {
                ['name', 'pool', 'onboot', 'agent'].forEach(function(field) {
                    if (!values[field]) {