Re: [pve-devel] [PATCH access-control/manager v2] fix #3668: improving realm sync

2022-03-23 Thread Thomas Lamprecht
On 22.03.22 16:23, Dominik Csapak wrote:
> On 3/22/22 14:44, Thomas Lamprecht wrote:
>> On 22.03.22 07:11, Thomas Lamprecht wrote:
>>> On 04.02.22 15:24, Dominik Csapak wrote:
 this deprecates the 'full' sync option and replaces it with
 a 'mode' option, where we add a third one that updates
 the current users (while retaining their custom set attributes not
 exisiting in the source) and removing users that don't exist anymore
 in the source

>>> I'm not yet 100% sure about the specific mode names, as sync normally means
>>> 100% sync, I'll see if I find some other tool (rsync?) with similar option 
>>> naming
>>> problems. Independent from the specific names, this really needs a docs 
>>> patch,
>>> ideally with a table listing the modi as rows and having the various "user 
>>> added",
>>> "user removed", "properties added/updated", "properties removed" as 
>>> columns, for a
>>> better understanding of the effects..
>>>
>> A thought (train): what we decide with this isn't what gets added/updated, 
>> that's
>> always the same, only what gets removed if vanished on the source, so maybe:
>>
>> remove-vanished: < none | user | user-and-properties >
>>
>> Or if we can actually also remove either user *or* group then: 
>> s/user/entity/ ?
>>
>> ps. the web interface should probably do a s/Purge/Purge ACLs/ too; or with 
>> that
>> in mind we could actually drop that do and have:
>>
>> remove-vanished: < none | user | user-and-properties | 
>> user-and-properties-and-acl >
>>
>> And with that, we could go the separate semicolon-endcoded-flag-list like we 
>> do for
>> some CT features (or mount options) IIRC:
>>
>> remove-vanished: [];[];[acls]
>>
>> I.e., those three flags would replace your new mode + purge like:
>>
>> +++-+
>> |  Mode  | Purge  | -> removed-vanished |
>> +++-+
>> | update |  0 | "" (none)   |
>> | sync   |  0 | user    |
>> | full   |  0 | user;properties |
>> | update |  1 | acl |
>> | sync   |  1 | acl;user    |
>> | full   |  1 | acl;user;properties |
>> +++-+
>>
>> The selector for them could be either three check boxes on one line (similar 
>> to the
>> privilege level radio buttons from CT restore) or even a full blown combobox 
>> with all
>> the options spelled out.
>>
>> It's only slightly weird for acl, as there the "remove-vanished" somewhat 
>> implies that
>> we import acl's in the first place, if we really don't want that we could 
>> keep
>> "Purge ACLs" as separate option that is only enabled if "remove-vanished" 
>> "user" flag
>> is set, put IMO not _that_ of a big problem to understand compared to the 
>> status quo.
>>
>> Does (any of) this make sense to you?
> 
> yes this sounds sensible, but i agree about the possibly confusing 
> 'remove-vanished'
> implication for acls. Maybe 'remove-on-vanish' ?

sounds the same to me semantically, so see no improvement there.

> this would (semantically) decouple the 'vanished' thing from the 'removed' 
> thing,
> at least a little bit.

IMO purely subjective and if a real grammar/semantic connection would be there 
that
I just miss (always a possibility) it'd be to subtle.

I think that the confusion potential overall would get quite a bit reduced that 
getting
this slightly confusing one newly is still a net benefit and can be easily 
defused with
a short docs note.

> in either case the docs would have to be updated anyway (as you already said)
> 
> aside from that, i think line 4 in your table is not really practical,
> since it would remove the acls but leave the users ?

The user cannot do anything anymore (like auto-disable) but you still have a 
reference
to it and all its configured fields + TFA, either  to re-enable it later or to 
check
contact info if one would investigate a specific task, so IMO its still 
practical for
setups that want to auto-disable but not auto-remove.


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [pbs-devel] [PATCH proxmox-backup v3 1/6] fix #3067: api: add support for multi-line comments in node.cfg

2022-03-23 Thread Wolfgang Bumiller
On Fri, Mar 04, 2022 at 12:31:57PM +0100, Stefan Sterz wrote:
> add support for multi-line comments to node.cfg and the api, similar to
> how pve handles multi-line comments
> 
> Signed-off-by: Stefan Sterz 

Acked-by: Wolfgang Bumiller 


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



Re: [pve-devel] [PATCH access-control/manager v2] fix #3668: improving realm sync

2022-03-23 Thread Thomas Lamprecht
On 23.03.22 08:33, Thomas Lamprecht wrote:
>>> remove-vanished: [];[];[acls]
>>>
>>> I.e., those three flags would replace your new mode + purge like:
>>>
>>> +++-+
>>> |  Mode  | Purge  | -> removed-vanished |
>>> +++-+
>>> | update |  0 | "" (none)   |
>>> | sync   |  0 | user    |
>>> | full   |  0 | user;properties |
>>> | update |  1 | acl |
>>> | sync   |  1 | acl;user    |
>>> | full   |  1 | acl;user;properties |
>>> +++-+
>>>
>>> The selector for them could be either three check boxes on one line 
>>> (similar to the
>>> privilege level radio buttons from CT restore) or even a full blown 
>>> combobox with all
>>> the options spelled out.
>>>
>>> It's only slightly weird for acl, as there the "remove-vanished" somewhat 
>>> implies that
>>> we import acl's in the first place, if we really don't want that we could 
>>> keep
>>> "Purge ACLs" as separate option that is only enabled if "remove-vanished" 
>>> "user" flag
>>> is set, put IMO not _that_ of a big problem to understand compared to the 
>>> status quo.
>>>
>>> Does (any of) this make sense to you?
>> yes this sounds sensible, but i agree about the possibly confusing 
>> 'remove-vanished'
>> implication for acls. Maybe 'remove-on-vanish' ?
> sounds the same to me semantically, so see no improvement there.
> 
>> this would (semantically) decouple the 'vanished' thing from the 'removed' 
>> thing,
>> at least a little bit.
> IMO purely subjective and if a real grammar/semantic connection would be 
> there that
> I just miss (always a possibility) it'd be to subtle.
> 
> I think that the confusion potential overall would get quite a bit reduced 
> that getting
> this slightly confusing one newly is still a net benefit and can be easily 
> defused with
> a short docs note.
> 


FWIW, for a user interface we can also go for a more detailed, telling 
approach, e.g.,
with both, field and box labels:

Remove Vanished:
Users  [ ] Remove any realm-user not included in the sync response.
ACLs   [ ] Remove the ACLs of any realm-user not included in the sync 
response.
Properties [ ] Remove properties not included in the sync response.

(more concise sentences welcome ;-))

For properties we could add a " Note: breaks, among other things, TFA." hint as
tooltip or just in the docs.


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [pbs-devel] [PATCH proxmox-backup v3 1/6] fix #3067: api: add support for multi-line comments in node.cfg

2022-03-23 Thread Thomas Lamprecht
On 04.03.22 12:31, Stefan Sterz wrote:
> add support for multi-line comments to node.cfg and the api, similar to
> how pve handles multi-line comments
> 
> Signed-off-by: Stefan Sterz 
> ---
>  pbs-api-types/src/lib.rs |  9 +++
>  src/api2/node/config.rs  |  4 +++
>  src/config/node.rs   | 14 +-
>  src/tools/config.rs  | 56 ++--
>  4 files changed, 80 insertions(+), 3 deletions(-)
> 
>

applied, with Wolfgang's A-b tag, thanks!


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH cluster v4 1/1] datacenter.cfg: add option for tag-tree-style and tag-colors

2022-03-23 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 data/PVE/DataCenterConfig.pm | 13 +
 1 file changed, 13 insertions(+)

diff --git a/data/PVE/DataCenterConfig.pm b/data/PVE/DataCenterConfig.pm
index 6c0fa5b..e890820 100644
--- a/data/PVE/DataCenterConfig.pm
+++ b/data/PVE/DataCenterConfig.pm
@@ -222,6 +222,19 @@ my $datacenter_schema = {
maxLength => 64 * 1024,
optional => 1,
},
+   'tag-tree-style' => {
+   optional => 1,
+   type => 'string',
+   enum => ['full', 'circle', 'dense', 'none'],
+   default => 'circle',
+   description => "Tag style in tree.",
+   },
+   'tag-colors' => {
+   optional => 1,
+   type => 'string',
+   pattern => 
'(?:[a-zA-Z0-9_][a-zA-Z0-9_\-\+\.]*=[0-9a-fA-F]{6},)*(?:[a-zA-Z0-9_][a-zA-Z0-9_\-\+\.]*=[0-9a-fA-F]{6})',
+   description => "Manual color mapping for tags. Format is 
'='",
+   },
 },
 };
 
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 02/10] api: /version: add 'tag-colors' and 'tag-tree-style'

2022-03-23 Thread Dominik Csapak
to be able to get them in the gui directly after login

Signed-off-by: Dominik Csapak 
---
 PVE/API2.pm | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/PVE/API2.pm b/PVE/API2.pm
index a4256160..0592d4de 100644
--- a/PVE/API2.pm
+++ b/PVE/API2.pm
@@ -111,6 +111,16 @@ __PACKAGE__->register_method ({
optional => 1,
description => 'The default console viewer to use.',
},
+   'tag-colors' => {
+   type => 'string',
+   optional => 1,
+   description => 'Cluster wide tag color overrides',
+   },
+   'tag-tree-style' => {
+   type => 'string',
+   optional => 1,
+   description => 'Tag style in tree',
+   },
},
 },
 code => sub {
@@ -119,7 +129,7 @@ __PACKAGE__->register_method ({
my $res = {};
 
my $datacenter_confg = eval { 
PVE::Cluster::cfs_read_file('datacenter.cfg') } // {};
-   for my $k (qw(console)) {
+   for my $k (qw(console tag-colors tag-tree-style)) {
$res->{$k} = $datacenter_confg->{$k} if exists 
$datacenter_confg->{$k};
}
 
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 01/10] api: /cluster/resources: add tags to returned properties

2022-03-23 Thread Dominik Csapak
by querying 'lock' and 'tags' with 'get_guest_config_properties'

Signed-off-by: Dominik Csapak 
---
 PVE/API2/Cluster.pm | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
index 227c6814..69272fc7 100644
--- a/PVE/API2/Cluster.pm
+++ b/PVE/API2/Cluster.pm
@@ -360,7 +360,8 @@ __PACKAGE__->register_method({
 
# we try to generate 'numbers' by using "$X + 0"
if (!$param->{type} || $param->{type} eq 'vm') {
-   my $locked_vms = PVE::Cluster::get_guest_config_property('lock');
+   my $prop_list = [qw(lock tags)];
+   my $props = PVE::Cluster::get_guest_config_properties($prop_list);
 
for my $vmid (sort keys %$idlist) {
 
@@ -392,8 +393,10 @@ __PACKAGE__->register_method({
# only skip now to next to ensure that the pool stats above are 
filled, if eligible
next if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' 
], 1);
 
-   if (defined(my $lock = $locked_vms->{$vmid}->{lock})) {
-   $entry->{lock} = $lock;
+   for my $prop (@$prop_list) {
+   if (defined(my $value = $props->{$vmid}->{$prop})) {
+   $entry->{$prop} = $value;
+   }
}
 
if (defined($entry->{pool}) &&
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 09/10] ui: tree/ResourceTree: show Tags in tree

2022-03-23 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/lxc/Config.js| 4 +++-
 www/manager6/qemu/Config.js   | 4 +++-
 www/manager6/tree/ResourceTree.js | 4 
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/www/manager6/lxc/Config.js b/www/manager6/lxc/Config.js
index 4e2b4bb8..80c5642b 100644
--- a/www/manager6/lxc/Config.js
+++ b/www/manager6/lxc/Config.js
@@ -216,8 +216,10 @@ Ext.define('PVE.lxc.Config', {
},
});
 
+   let vm_text = `${vm.vmid} (${vm.name})`;
+
Ext.apply(me, {
-   title: Ext.String.format(gettext("Container {0} on node '{1}'"), 
vm.text, nodename),
+   title: Ext.String.format(gettext("Container {0} on node '{1}'"), 
vm_text, nodename),
hstateid: 'lxctab',
tbarSpacing: false,
tbar: [statusTxt, tagsContainer, '-', tagAddBtn, '->', startBtn, 
shutdownBtn, migrateBtn, consoleBtn, moreBtn],
diff --git a/www/manager6/qemu/Config.js b/www/manager6/qemu/Config.js
index df5f688f..c1865b7f 100644
--- a/www/manager6/qemu/Config.js
+++ b/www/manager6/qemu/Config.js
@@ -251,8 +251,10 @@ Ext.define('PVE.qemu.Config', {
},
});
 
+   let vm_text = `${vm.vmid} (${vm.name})`;
+
Ext.apply(me, {
-   title: Ext.String.format(gettext("Virtual Machine {0} on node 
'{1}'"), vm.text, nodename),
+   title: Ext.String.format(gettext("Virtual Machine {0} on node 
'{1}'"), vm_text, nodename),
hstateid: 'kvmtab',
tbarSpacing: false,
tbar: [statusTxt, tagsContainer, '-', tagAddBtn, '->', resumeBtn, 
startBtn, shutdownBtn, migrateBtn, consoleBtn, moreBtn],
diff --git a/www/manager6/tree/ResourceTree.js 
b/www/manager6/tree/ResourceTree.js
index 301f7557..049194ee 100644
--- a/www/manager6/tree/ResourceTree.js
+++ b/www/manager6/tree/ResourceTree.js
@@ -5,6 +5,8 @@ Ext.define('PVE.tree.ResourceTree', {
 extend: 'Ext.tree.TreePanel',
 alias: ['widget.pveResourceTree'],
 
+userCls: 'proxmox-tags-circle',
+
 statics: {
typeDefaults: {
node: {
@@ -114,6 +116,8 @@ Ext.define('PVE.tree.ResourceTree', {
}
}
 
+   info.text += PVE.Utils.renderTags(info.tags);
+
info.text = status + info.text;
 },
 
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 08/10] ui: {lxc, qemu}/Config: show Tags and make them editable

2022-03-23 Thread Dominik Csapak
add the tags in the status line, and add a button for adding new ones

Signed-off-by: Dominik Csapak 
---
 www/manager6/lxc/Config.js  | 68 +++--
 www/manager6/qemu/Config.js | 66 +--
 2 files changed, 130 insertions(+), 4 deletions(-)

diff --git a/www/manager6/lxc/Config.js b/www/manager6/lxc/Config.js
index 89b59c9b..4e2b4bb8 100644
--- a/www/manager6/lxc/Config.js
+++ b/www/manager6/lxc/Config.js
@@ -4,6 +4,8 @@ Ext.define('PVE.lxc.Config', {
 
 onlineHelp: 'chapter_pct',
 
+userCls: 'proxmox-tags-full',
+
 initComponent: function() {
 var me = this;
var vm = me.pveSelNode.data;
@@ -182,12 +184,43 @@ Ext.define('PVE.lxc.Config', {
],
});
 
+   let tagsContainer = Ext.create('Ext.container.Container', {
+   userCls: 'proxmox-tags-full',
+   layout: {
+   type: 'hbox',
+   align: 'stretch',
+   },
+   });
+
+   let tagAddBtn = Ext.create('Proxmox.Tag', {
+   xtype: 'pmxTag',
+   addTag: true,
+   layoutCallback: () => 
me.query('>toolbar[dock=top]')?.[0].updateLayout(),
+   updateCallback: function(newTag) {
+   let rec = me.statusStore.data.get('tags');
+   let tags = rec?.data?.value?.split(/[;, ]/) || [];
+   tags.push(newTag);
+   Proxmox.Utils.API2Request({
+   url: base_url + '/config',
+   method: 'PUT',
+   params: {
+   tags: tags.filter(t => !!t).join(','),
+   },
+   success: function() {
+   me.statusStore.load();
+   },
+   failure: function(response) {
+   Ext.Msg.alert('Error', response.htmlStatus);
+   },
+   });
+   },
+   });
 
Ext.apply(me, {
title: Ext.String.format(gettext("Container {0} on node '{1}'"), 
vm.text, nodename),
hstateid: 'lxctab',
tbarSpacing: false,
-   tbar: [statusTxt, '->', startBtn, shutdownBtn, migrateBtn, 
consoleBtn, moreBtn],
+   tbar: [statusTxt, tagsContainer, '-', tagAddBtn, '->', startBtn, 
shutdownBtn, migrateBtn, consoleBtn, moreBtn],
defaults: { statusStore: me.statusStore },
items: [
{
@@ -344,10 +377,12 @@ Ext.define('PVE.lxc.Config', {
me.mon(me.statusStore, 'load', function(s, records, success) {
var status;
var lock;
+   var rec;
+
if (!success) {
status = 'unknown';
} else {
-   var rec = s.data.get('status');
+   rec = s.data.get('status');
status = rec ? rec.data.value : 'unknown';
rec = s.data.get('template');
template = rec ? rec.data.value : false;
@@ -357,6 +392,35 @@ Ext.define('PVE.lxc.Config', {
 
statusTxt.update({ lock: lock });
 
+   rec = s.data.get('tags');
+   if (me.oldtags === undefined || me.oldtags !== rec?.data?.value) {
+   let tags = rec?.data?.value.split(/[,; ]/).filter(t => !!t) ?? 
[];
+   me.oldtags = rec?.data?.value;
+   tagsContainer.removeAll();
+   for (let i = 0; i < tags.length; i++) {
+   let tag = tags[i];
+   tagsContainer.add({
+   xtype: 'pmxTag',
+   tag,
+   layoutCallback: () => tagsContainer.updateLayout(),
+   updateCallback: function(newTag) {
+   tags[i] = newTag;
+   Proxmox.Utils.API2Request({
+   url: base_url + '/config',
+   method: 'PUT',
+   params: {
+   tags: tags.filter(t => !!t).join(','),
+   },
+   failure: function(response) {
+   Ext.Msg.alert('Error', response.htmlStatus);
+   },
+   });
+   me.oldtags = tags.join(',');
+   },
+   });
+   }
+   }
+
startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 
'running' || template);
shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 
'running');
me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || 
status !== 'stopped');
diff --git a/www/manager6/qemu/Config.js b/www/manager6/qemu/Config.js
index 9fe933df..df5f688f 100644
--- a/www/manager6/qemu/Config.js
+++ b/www/manager6/qemu/Config.js
@@ -3,6 +3,7 @@ Ext.define('PVE.qemu.Config', {
 alias: 'widget.PVE.qemu.Config',
 
 onlineHelp: 'chapter_virtual_machines'

[pve-devel] [PATCH widget-toolkit v4 1/1] add tag related helpers

2022-03-23 Thread Dominik Csapak
helpers to
* generate a color from a string consistently
* generate a html tag for a tag
* related css classes

Signed-off-by: Dominik Csapak 
---
 src/Utils.js | 35 +
 src/css/ext6-pmx.css | 52 
 2 files changed, 87 insertions(+)

diff --git a/src/Utils.js b/src/Utils.js
index 6a03057..3130b2a 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -1272,6 +1272,41 @@ utilities: {
.map(val => val.charCodeAt(0)),
);
 },
+
+stringToRGB: function(string) {
+   let hash = 0;
+   if (!string) {
+   return hash;
+   }
+   string += 'prox'; // give short strings more variance
+   for (let i = 0; i < string.length; i++) {
+   hash = string.charCodeAt(i) + ((hash << 5) - hash);
+   hash = hash & hash; // to int
+   }
+   return [
+   hash & 255,
+   (hash >> 8) & 255,
+   (hash >> 16) & 255,
+   0.8, // make the colors a little lighter
+   ];
+},
+
+rgbToCss: function(rgb) {
+   return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${rgb[3]})`;
+},
+
+rgbToLuminance: function(rgb) {
+   // https://en.wikipedia.org/wiki/Relative_luminance
+   return (0.2126 * rgb[0] + 0.7152*rgb[1] + 0.0722*rgb[2])/rgb[3];
+},
+
+getTagElement: function(string, color_overrides) {
+   let rgb = color_overrides?.[string] || 
Proxmox.Utils.stringToRGB(string);
+   let bgcolor = Proxmox.Utils.rgbToCss(rgb);
+   let txtCls = Proxmox.Utils.rgbToLuminance(rgb) < 160 ? 'light' : 'dark';
+   let cls = `proxmox-tag-${txtCls}`;
+   return `${string}`;
+},
 },
 
 singleton: true,
diff --git a/src/css/ext6-pmx.css b/src/css/ext6-pmx.css
index 1d815c6..7c01d2f 100644
--- a/src/css/ext6-pmx.css
+++ b/src/css/ext6-pmx.css
@@ -6,6 +6,58 @@
 background-color: LightYellow;
 }
 
+.proxmox-tags-full .proxmox-tag-light,
+.proxmox-tags-full .proxmox-tag-dark {
+border-radius: 9px;
+padding: 1px 8px;
+margin: 0px 1px;
+}
+
+.proxmox-tags-circle .proxmox-tag-light,
+.proxmox-tags-circle .proxmox-tag-dark {
+margin: 0px 1px;
+position: relative;
+top: 2px;
+border-radius: 6px;
+height: 12px;
+width: 12px;
+display: inline-block;
+color: transparent;
+overflow: hidden;
+}
+
+.proxmox-tags-none .proxmox-tag-light,
+.proxmox-tags-none .proxmox-tag-dark {
+display: none;
+}
+
+.proxmox-tags-dense .proxmox-tag-light,
+.proxmox-tags-dense .proxmox-tag-dark {
+width: 5px;
+display: inline-block;
+color: transparent;
+overflow: hidden;
+vertical-align: bottom;
+}
+
+.proxmox-tags-full .proxmox-tag-light {
+color: #fff;
+background-color: #383838;
+}
+
+.proxmox-tags-full .proxmox-tag-light span::selection {
+background-color: #000;
+}
+
+.proxmox-tags-full .proxmox-tag-dark {
+color: #000;
+background-color: #f0f0f0;
+}
+
+.proxmox-tags-full .proxmox-tag-dark span::selection {
+background-color: #FFF;
+}
+
 .x-mask-msg-text {
 text-align: center;
 }
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 03/10] ui: parse and save tag color overrides from /version

2022-03-23 Thread Dominik Csapak
and implement a convenience function that also parses the 'color'
state from the browser storage for overrides

Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js | 34 ++
 www/manager6/Workspace.js | 13 +
 2 files changed, 47 insertions(+)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index aafe359a..0ad3a482 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1803,6 +1803,40 @@ Ext.define('PVE.Utils', {
 
return undefined;
 },
+
+parseTagOverrides: function(overrides) {
+   let colors = {};
+   (overrides || "").split(/[;, ]/).forEach(color => {
+   if (!color) {
+   return;
+   }
+   let [tag, color_hex] = color.split('=', 2);
+   let r = parseInt(color_hex.slice(0, 2), 16);
+   let g = parseInt(color_hex.slice(2, 4), 16);
+   let b = parseInt(color_hex.slice(4, 6), 16);
+   colors[tag] = [r, g, b, 1.0];
+   });
+   return colors;
+},
+
+getTagOverrides: function() {
+   let sp = Ext.state.Manager.getProvider();
+   let color_state = sp.get('colors', '');
+   let browser_colors = PVE.Utils.parseTagOverrides(color_state);
+   return Ext.apply({}, browser_colors, PVE.TagColors);
+},
+
+updateTagSettings: function(overrides, style) {
+   if (overrides) {
+   PVE.TagColors = PVE.Utils.parseTagOverrides(overrides);
+   }
+
+   if (style === undefined || style === '__default__') {
+   style = 'circle';
+   }
+
+   
Ext.ComponentQuery.query('pveResourceTree')[0].setUserCls(`proxmox-tags-${style}`);
+},
 },
 
 singleton: true,
diff --git a/www/manager6/Workspace.js b/www/manager6/Workspace.js
index 37d772b8..d9875c18 100644
--- a/www/manager6/Workspace.js
+++ b/www/manager6/Workspace.js
@@ -155,6 +155,7 @@ Ext.define('PVE.StdWorkspace', {
success: function(response) {
PVE.VersionInfo = response.result.data;
me.updateVersionInfo();
+   me.updateTags();
},
});
 
@@ -213,6 +214,18 @@ Ext.define('PVE.StdWorkspace', {
ui.updateLayout();
 },
 
+updateTags: function() {
+   let me = this;
+   let colors = PVE.VersionInfo?.['tag-colors'];
+   let style = PVE.VersionInfo?.['tag-tree-style'];
+
+   PVE.Utils.updateTagSettings(colors, style);
+   if (colors) {
+   // refresh tree once
+   PVE.data.ResourceStore.fireEvent('load');
+   }
+},
+
 initComponent: function() {
let me = this;
 
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 06/10] ui: dc/OptionView: add editors for tag settings

2022-03-23 Thread Dominik Csapak
namely for 'tag-tree-style' and 'tag-colors'.
display the tag overrides directly as they will appear as tags

Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js | 20 
 www/manager6/dc/OptionView.js | 43 ++-
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 16a81127..9097af42 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1845,6 +1845,26 @@ Ext.define('PVE.Utils', {
 

Ext.ComponentQuery.query('pveResourceTree')[0].setUserCls(`proxmox-tags-${style}`);
 },
+
+tagTreeStyles: {
+   '__default__': Proxmox.Utils.defaultText,
+   'full': gettext('Full'),
+   'circle': gettext('Circle'),
+   'dense': gettext('Dense'),
+   'none': Proxmox.Utils.NoneText,
+},
+
+renderTags: function(tagstext) {
+   let text = '';
+   if (tagstext) {
+   let tags = (tagstext.split(/[,; ]/) || []).filter(t => !!t);
+   text += ' ';
+   tags.forEach((tag) => {
+   text += Proxmox.Utils.getTagElement(tag, 
PVE.Utils.getTagOverrides());
+   });
+   }
+   return text;
+},
 },
 
 singleton: true,
diff --git a/www/manager6/dc/OptionView.js b/www/manager6/dc/OptionView.js
index 6b30ede9..677ffa90 100644
--- a/www/manager6/dc/OptionView.js
+++ b/www/manager6/dc/OptionView.js
@@ -5,6 +5,7 @@ Ext.define('PVE.dc.OptionView', {
 onlineHelp: 'datacenter_configuration_file',
 
 monStoreErrors: true,
+userCls: 'proxmox-tags-full',
 
 add_inputpanel_row: function(name, text, opts) {
var me = this;
@@ -284,7 +285,43 @@ Ext.define('PVE.dc.OptionView', {
minValue: 1,
maxValue: 64, // arbitrary but generous limit as limits are good
});
-
+   me.add_combobox_row('tag-tree-style', gettext('Tag Tree Style'), {
+   renderer: (value) => PVE.Utils.tagTreeStyles[value] ?? value,
+   comboItems: Object.entries(PVE.Utils.tagTreeStyles),
+   defaultValue: '__default__',
+   deleteEmpty: true,
+   });
+   me.rows['tag-colors'] = {
+   required: true,
+   renderer: (value) => {
+   if (value === undefined) {
+   return gettext('No Overrides');
+   }
+   let overrides = PVE.Utils.parseTagOverrides(value);
+   let txt = '';
+   for (const tag of Object.keys(overrides)) {
+   txt += Proxmox.Utils.getTagElement(tag, overrides);
+   }
+   return txt;
+   },
+   header: gettext('Tag Colors'),
+   editor: {
+   xtype: 'proxmoxWindowEdit',
+   width: 450,
+   bodyPadding: 0,
+   subject: gettext('Tag Colors'),
+   fieldDefaults: {
+   labelWidth: 100,
+   },
+   url: '/api2/extjs/cluster/options',
+   items: [{
+   name: 'tag-colors',
+   xtype: 'pveTagColorGrid',
+   deleteEmpty: true,
+   height: 300,
+   }],
+   },
+   };
me.selModel = Ext.create('Ext.selection.RowModel', {});
 
Ext.apply(me, {
@@ -319,6 +356,10 @@ Ext.define('PVE.dc.OptionView', {
if (rec.data.value === '__default__') {
delete PVE.VersionInfo.console;
}
+
+   let colors = store.getById('tag-colors')?.data?.value;
+   let style = store.getById('tag-tree-style')?.data?.value;
+   PVE.Utils.updateTagSettings(colors, style);
});
 
me.on('activate', me.rstore.startUpdate);
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 04/10] ui: tree/ResourceTree: collect tags on update

2022-03-23 Thread Dominik Csapak
into a global list, so that we have it avaiable anywhere

add a convenience 'getTagList' function, that also gets tags from
the overrides from datacenter.cfg and browser-storage

Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js  |  8 
 www/manager6/data/ResourceStore.js |  6 ++
 www/manager6/tree/ResourceTree.js  | 16 ++--
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 0ad3a482..16a81127 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1804,6 +1804,14 @@ Ext.define('PVE.Utils', {
return undefined;
 },
 
+tagList: new Set(),
+
+getTagList: function() {
+   let overrides = PVE.Utils.getTagOverrides();
+   let override_tags = Object.keys(overrides);
+   return [...new Set([...PVE.Utils.tagList, ...override_tags])].sort();
+},
+
 parseTagOverrides: function(overrides) {
let colors = {};
(overrides || "").split(/[;, ]/).forEach(color => {
diff --git a/www/manager6/data/ResourceStore.js 
b/www/manager6/data/ResourceStore.js
index c7b72306..b18f7dd8 100644
--- a/www/manager6/data/ResourceStore.js
+++ b/www/manager6/data/ResourceStore.js
@@ -293,6 +293,12 @@ Ext.define('PVE.data.ResourceStore', {
sortable: true,
width: 100,
},
+   tags: {
+   header: gettext('Tags'),
+   type: 'string',
+   hidden: true,
+   sortable: true,
+   },
};
 
let fields = [];
diff --git a/www/manager6/tree/ResourceTree.js 
b/www/manager6/tree/ResourceTree.js
index be90d4f7..301f7557 100644
--- a/www/manager6/tree/ResourceTree.js
+++ b/www/manager6/tree/ResourceTree.js
@@ -226,6 +226,10 @@ Ext.define('PVE.tree.ResourceTree', {
 
let stateid = 'rid';
 
+   const changedFields = [
+   'text', 'running', 'template', 'status', 'qmpstatus', 'hastate', 
'lock', 'tags',
+   ];
+
let updateTree = function() {
store.suspendEvents();
 
@@ -261,7 +265,7 @@ Ext.define('PVE.tree.ResourceTree', {
}
 
// tree item has been updated
-   for (const field of ['text', 'running', 'template', 
'status', 'qmpstatus', 'hastate', 'lock']) {
+   for (const field of changedFields) {
if (item.data[field] !== olditem.data[field]) {
changed = true;
break;
@@ -294,7 +298,14 @@ Ext.define('PVE.tree.ResourceTree', {
}
}
 
-   rstore.each(function(item) { // add new items
+   let tags = new Set();
+
+   rstore.each(function(item) { // add new items and collect tags
+   if (item.data.tags) {
+   item.data.tags.split(/[,; ]/).filter(t => 
!!t).forEach((tag) => {
+   tags.add(tag);
+   });
+   }
let olditem = index[item.data.id];
if (olditem) {
return;
@@ -310,6 +321,7 @@ Ext.define('PVE.tree.ResourceTree', {
}
});
 
+   PVE.Utils.tagList = tags;
store.resumeEvents();
store.fireEvent('refresh', store);
 
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 10/10] ui: form/GlobalSearchField: display tags and allow to search for them

2022-03-23 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/form/GlobalSearchField.js | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/www/manager6/form/GlobalSearchField.js 
b/www/manager6/form/GlobalSearchField.js
index 267a480d..7a27cb29 100644
--- a/www/manager6/form/GlobalSearchField.js
+++ b/www/manager6/form/GlobalSearchField.js
@@ -15,6 +15,7 @@ Ext.define('PVE.form.GlobalSearchField', {
 
 grid: {
xtype: 'gridpanel',
+   userCls: 'proxmox-tags-full',
focusOnToFront: false,
floating: true,
emptyText: Proxmox.Utils.noneText,
@@ -23,7 +24,7 @@ Ext.define('PVE.form.GlobalSearchField', {
scrollable: {
xtype: 'scroller',
y: true,
-   x: false,
+   x: true,
},
store: {
model: 'PVEResources',
@@ -78,6 +79,10 @@ Ext.define('PVE.form.GlobalSearchField', {
text: gettext('Description'),
flex: 1,
dataIndex: 'text',
+   renderer: function(value, mD, rec) {
+   let tags = PVE.Utils.renderTags(rec.data.tags);
+   return `${value}${tags}`;
+   },
},
{
text: gettext('Node'),
@@ -104,16 +109,20 @@ Ext.define('PVE.form.GlobalSearchField', {
'storage': ['type', 'pool', 'node', 'storage'],
'default': ['name', 'type', 'node', 'pool', 'vmid'],
};
-   let fieldArr = fieldMap[item.data.type] || fieldMap.default;
+   let fields = fieldMap[item.data.type] || fieldMap.default;
+   let fieldArr = fields.map(field => 
item.data[field]?.toString().toLowerCase());
+   if (item.data.tags) {
+   let tags = item.data.tags.split(/[;, ]/);
+   fieldArr.push(...tags);
+   }
 
let filterWords = me.filterVal.split(/\s+/);
 
// all text is case insensitive and each split-out word is searched for 
separately.
// a row gets 1 point for every partial match, and and additional point 
for every exact match
let match = 0;
-   for (let field of fieldArr) {
-   let fieldValue = item.data[field]?.toString().toLowerCase();
-   if (fieldValue === undefined) {
+   for (let fieldValue of fieldArr) {
+   if (fieldValue === undefined || fieldValue === "") {
continue;
}
for (let filterWord of filterWords) {
-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH cluster/widget-toolkit/manager v4] add tags to ui

2022-03-23 Thread Dominik Csapak
this series is a continuation of my previous attempt in 2019.
note that this requires my previous patch for pve-cluster that
introduces the 'get properties' pmxcfs message[0]

this is a bit "rough" on various points, but i wanted to send what i have
before i code myself into a hole i cannot easily get out of^^, namely:
* having gui config options in datacenter.cfg
  (gui console is a precedence here, but maybe there is still a better place?)
  also if /version is the right place to get it or if we should make another
  dedicated api call for such things
* the datacenter tags=color regex (could refactor the tags regex out in
  pve-common)
* the color editing grid in the gui:
  this is very basic but usable. on short notice i did not really find
  a better way to have that mapping from arbitrarily tags (but
  selectable from existing ones) to color
* there is no drag&drop (like @thomas wished the last time), but with
  the new inline editing it's maybe not necessary?
* no gui for the browser-settings yet:
  since there is not much space left in the 'my settings' window, i'd
  have to reorganize it, but did not come around to that yet, this can
  ofc also be done at a later stage if we ignore browser set color
  overrides for now
* the tree styling:
  not sure if it makes sense at all to have multiple styles here, though
  i always find such options nice. the 'dense' option i am a bit
  conflicted myself, it provides a better experience when having many
  tags, but you lose some contrast depending on the colors
* probably many more...

changes from v3:
* show the tags in the tree (with multiple styles)
* they are now inline editable instead of having a pop up with the editor
* able to override colors in datacenter cfg
* show a dropdown on editing with existing tags (from tree+overrides)
* show the tags in the global search grid (and make them searchable)

changes from v2:
* rebase on master (drop applied patch, merge with lxc pending changes)
* move utilities to widget-toolkit
* prefix css classes
* remove tags from options and add edit button to the tags directly
* show 'no tags' when no tags are defined
* improve statusTxt style

changes from v1:
* slightly different format (use [a-z...] instead of \w)
* add comment in JSONSchema
* better commit message
* add the tags to the status api call of guests (for gui)
* show the tags in the gui
* make the tags editable in the gui

0: https://lists.proxmox.com/pipermail/pve-devel/2022-March/052174.html

pve-cluster:

Dominik Csapak (1):
  datacenter.cfg: add option for tag-tree-style and tag-colors

 data/PVE/DataCenterConfig.pm | 13 +
 1 file changed, 13 insertions(+)

proxmox-widget-toolkit:

Dominik Csapak (1):
  add tag related helpers

 src/Utils.js | 35 +
 src/css/ext6-pmx.css | 52 
 2 files changed, 87 insertions(+)

pve-manager:

Dominik Csapak (10):
  api: /cluster/resources: add tags to returned properties
  api: /version: add 'tag-colors' and 'tag-tree-style'
  ui: parse and save tag color overrides from /version
  ui: tree/ResourceTree: collect tags on update
  ui: add form/TagColorGrid
  ui: dc/OptionView: add editors for tag settings
  ui: add form/Tag
  ui: {lxc,qemu}/Config: show Tags and make them editable
  ui: tree/ResourceTree: show Tags in tree
  ui: form/GlobalSearchField: display tags and allow to search for them

 PVE/API2.pm|  12 +-
 PVE/API2/Cluster.pm|   9 +-
 www/manager6/Makefile  |   2 +
 www/manager6/Utils.js  |  62 +++
 www/manager6/Workspace.js  |  13 ++
 www/manager6/data/ResourceStore.js |   6 +
 www/manager6/dc/OptionView.js  |  43 -
 www/manager6/form/GlobalSearchField.js |  19 ++-
 www/manager6/form/Tag.js   | 207 +++
 www/manager6/form/TagColorGrid.js  | 218 +
 www/manager6/lxc/Config.js |  72 +++-
 www/manager6/qemu/Config.js|  70 +++-
 www/manager6/tree/ResourceTree.js  |  20 ++-
 13 files changed, 735 insertions(+), 18 deletions(-)
 create mode 100644 www/manager6/form/Tag.js
 create mode 100644 www/manager6/form/TagColorGrid.js

-- 
2.30.2



___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



[pve-devel] [PATCH manager v4 05/10] ui: add form/TagColorGrid

2022-03-23 Thread Dominik Csapak
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 ..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 = "00") {
+   let me = this;
+   me.picker.value = value[0] !== '#' ? `#${value}` : value;
+   me.setColor(value);
+},
+
+setColor: function(value = "00") {
+   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.getW

[pve-devel] [PATCH manager v4 07/10] ui: add form/Tag

2022-03-23 Thread Dominik Csapak
displays a single tag, with the ability to edit inline on click. This brings
up a list of globally available tags for simple selection.

Also has a mode for adding a new Tag.

This has a 'updateCallback' which is called when the value changes
so that the parent component can update the config, and a
'layoutCallback' which will be called on input, so that the parent
component can update the layout when the content changes.
This is necessary since we circumvent the extjs logic for updating.

Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile|   1 +
 www/manager6/form/Tag.js | 207 +++
 2 files changed, 208 insertions(+)
 create mode 100644 www/manager6/form/Tag.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 225dffba..45862e71 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -74,6 +74,7 @@ JSSRC=
\
form/ViewSelector.js\
form/iScsiProviderSelector.js   \
form/TagColorGrid.js\
+   form/Tag.js \
grid/BackupView.js  \
grid/FirewallAliases.js \
grid/FirewallOptions.js \
diff --git a/www/manager6/form/Tag.js b/www/manager6/form/Tag.js
new file mode 100644
index ..5c308f51
--- /dev/null
+++ b/www/manager6/form/Tag.js
@@ -0,0 +1,207 @@
+Ext.define('Proxmox.Tag', {
+extend: 'Ext.Component',
+alias: 'widget.pmxTag',
+
+// if set to true, displays 'Add Tag' and a plus symbol
+addTag: false,
+
+// callback to update the config
+updateCallback: Ext.emptyFn,
+
+// callback to update the layout in the containing element
+// this is necessary since we circumvent extjs layout with 
'contentEditable'
+layoutCallback: Ext.emptyFn,
+
+inEdit: false,
+style: {
+   'padding-right': '1px',
+   'white-space': 'nowrap',
+},
+
+icons: {
+   addTag: 'plus',
+   normal: 'times',
+   edit: 'check',
+},
+
+// we need to do this in mousedown, because that triggers before
+// focusleave (which triggers before click)
+onMouseDown: function(event) {
+   let me = this;
+   if (event.target.tagName === "I" && (!me.addTag || me.inEdit)) {
+   if (!me.inEdit) {
+   me.setVisible(false);
+   me.setText('');
+   }
+   me.finishEdit();
+   }
+},
+
+onClick: function(event) {
+   let me = this;
+   if ((me.addTag || event.target.tagName === "SPAN") && !me.inEdit) {
+   if (me.addTag) {
+   me.setText('');
+   me.setStyle('cursor');
+   }
+   me.inEdit = true;
+   me.tagEl().contentEditable = true;
+   me.iconEl().classList = `fa fa-fw fa-${me.icons.edit}-circle`;
+
+   // select text in the element
+   let range = document.createRange();
+   range.selectNodeContents(me.tagEl());
+   let sel = window.getSelection();
+   sel.removeAllRanges();
+   sel.addRange(range);
+
+   me.showPicker();
+   }
+},
+
+showPicker: function() {
+   let me = this;
+   if (!me.picker) {
+   me.picker = Ext.widget({
+   xtype: 'boundlist',
+   minWidth: 70,
+   scrollable: true,
+   floating: true,
+   hidden: true,
+   userCls: 'proxmox-tags-circle',
+   displayField: 'tag',
+   itemTpl: [
+   '{[Proxmox.Utils.getTagElement(values.tag, 
PVE.Utils.getTagOverrides())]} {tag}',
+   ],
+   store: [],
+   listeners: {
+   select: function(picker, rec) {
+   me.setText(rec.data.tag);
+   me.finishEdit();
+   },
+   },
+   });
+   }
+   me.picker.getStore().clearFilter();
+   let taglist = PVE.Utils.getTagList().map(v => ({ tag: v }));
+   if (taglist.length < 1) {
+   return;
+   }
+   me.picker.getStore().setData(taglist);
+   me.picker.showBy(me, 'tl-bl');
+   me.picker.setMaxHeight(200);
+},
+
+finishEdit: function(update = true) {
+   let me = this;
+   me.picker?.hide();
+
+   let tag = me.tagEl().innerHTML;
+   let mode;
+   if (me.addTag) {
+   me.setText(me.tag);
+   me.setStyle('cursor', 'pointer');
+   mode = 'addTag';
+   } else {
+   me.tag = tag;
+   mode = 'normal';
+   }
+   me.iconEl().classList = `fa fa-fw fa-${me.icons[mode]}-circle`;
+   me.updateColor(me.tag);
+
+
+   if (update) {
+   me.updateCallback(tag);
+   }
+   me.tagEl().contentEditable = false;
+   me.inEdit = false;
+},
+
+s

Re: [pve-devel] [PATCH widget-toolkit v3 4/6] toolkit: add markdown based NotesView and NotesEdit

2022-03-23 Thread Thomas Lamprecht
On 04.03.22 12:32, Stefan Sterz wrote:
> move these from pve to the widget toolkit to be ablte to use them in
> pbs
> 

this is no 1:1 move but the commit messages fails to describe the changes
made nor the rationale.

> Signed-off-by: Stefan Sterz 
> ---
>  src/Makefile|   2 +
>  src/panel/NotesView.js  | 155 
>  src/window/NotesEdit.js |  38 ++
>  3 files changed, 195 insertions(+)
>  create mode 100644 src/panel/NotesView.js
>  create mode 100644 src/window/NotesEdit.js
> 
> diff --git a/src/Makefile b/src/Makefile
> index de34531..ae20947 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -65,6 +65,7 @@ JSSRC=  \
>   panel/ACMEDomains.js\
>   panel/StatusView.js \
>   panel/TfaView.js\
> + panel/NotesView.js  \
>   window/Edit.js  \
>   window/PasswordEdit.js  \
>   window/SafeDestroy.js   \
> @@ -86,6 +87,7 @@ JSSRC=  \
>   window/AddWebauthn.js   \
>   window/AddYubico.js \
>   window/TfaEdit.js   \
> + window/NotesEdit.js \
>   node/APT.js \
>   node/APTRepositories.js \
>   node/NetworkEdit.js \
> diff --git a/src/panel/NotesView.js b/src/panel/NotesView.js
> new file mode 100644
> index 000..df5e688
> --- /dev/null
> +++ b/src/panel/NotesView.js
> @@ -0,0 +1,155 @@
> +Ext.define('Proxmox.panel.NotesView', {
> +extend: 'Ext.panel.Panel',
> +xtype: 'pmxNotesView',
> +mixins: ['Proxmox.Mixin.CBind'],
> +
> +title: gettext("Notes"),
> +bodyPadding: 10,
> +scrollable: true,
> +animCollapse: false,
> +maxLength: 64 * 1024,
> +
> +cbindData: function(initalConfig) {
> + let me = this;
> +
> + if (me.node) {
> + me.url = `/api2/extjs/nodes/${me.node}/config`;
> + me.maxLength = 64 * 1022;

why factor 1022 ?! And why override it uncoditionally, leaving no control for 
the
caller?

also half of initialization logic now gets handled by cbind and half by 
initComponent,
why the split-approach? This could just be an `else` for the initComponent's if 
(!node)
clause.

> + }
> +
> + return {};
> +},
> +
> +

^- extra whitespace
> +run_editor: function() {
> + let me = this;
> + Ext.create('Proxmox.window.NotesEdit', {
> + url: me.url,
> + listeners: {
> + destroy: () => me.load(),
> + },
> + autoShow: true,
> + }).setMaxLength(me.maxLength);
> +},
> +
> +setNotes: function(value) {
> + let me = this;
> + var data = value || '';

use let for new code, could also just drop intermediate variable and make 
either the
caller fallback, or  use `value || ''` for the parse and !data for the 
setCollapsed.

> +
> + let mdHtml = Proxmox.Markdown.parse(data);
> + me.update(mdHtml);
> +
> + if (me.collapsible && me.collapseMode === 'auto') {
> + me.setCollapsed(data === '');
> + }
> +},
> +
> +load: function() {
> + var me = this;
> +
> + Proxmox.Utils.API2Request({
> + url: me.url,
> + waitMsgTarget: me,
> + failure: function(response, opts) {
> + me.update(gettext('Error') + " " + response.htmlStatus);
> + me.setCollapsed(false);
> + },
> + success: function(response, opts) {
> + let text = response.result.data.description;

useless intermediate variable

> + me.setNotes(text);

me.setNotes(response.result.data.description || '');

or alternatively:

success: ({ result }) => me.setNotes(result.data.description || ''),

> + },
> + });
> +},
> +
> +listeners: {
> + render: function(c) {
> + var me = this;
> + me.getEl().on('dblclick', me.run_editor, me);
> + },
> + afterlayout: function() {
> + let me = this;
> + if (me.collapsible && !me.getCollapsed() && me.collapseMode === 
> 'always') {
> + me.setCollapsed(true);
> + me.collapseMode = ''; // only once, on initial load!
> + }
> + },
> +},
> +
> +tools: [{
> + type: 'gear',
> + handler: function() {
> + this.up('panel').run_editor();
> + },
> +}],
> +
> +tbar: {

no hard feelings on moving tbar from top of file here, but it makes slightly 
diff'ing harder.

> + itemId: 'tbar',
> + hidden: true,
> + items: [
> + {
> + text: gettext('Edit'),
> + handler: function() {
> + this.up('panel').run_editor();

I'd keep the `let view = `

> + },
> + },
> + ],
> +},
> +
> +initComponent: function() {
> + const me = this;
> + let type = '';
> +
> + if (!me.node) {
> + if (me.pveSelNode.data.id === 'root') {
> +

Re: [pve-devel] [PATCH proxmox-backup v3 3/6] fix #3607: ui: add a separate notes view for longer markdown notes

2022-03-23 Thread Thomas Lamprecht
On 04.03.22 12:31, Stefan Sterz wrote:
> since markdown notes might be rather long, this commit adds a tab
> similar to pve's datacenter or node notes.
> 
> Signed-off-by: Stefan Sterz 
> ---
>  www/Makefile   |   2 +
>  www/NavigationTree.js  |   6 ++
>  www/NodeNotes.js   |  22 +++
>  www/panel/MarkdownNotes.js | 130 +
>  4 files changed, 160 insertions(+)
>  create mode 100644 www/NodeNotes.js
>  create mode 100644 www/panel/MarkdownNotes.js
> 

> diff --git a/www/panel/MarkdownNotes.js b/www/panel/MarkdownNotes.js
> new file mode 100644
> index ..6d601401
> --- /dev/null
> +++ b/www/panel/MarkdownNotes.js> @@ -0,0 +1,130 @@
> +Ext.define('PBS.panel.MarkdownNotes', {
> +extend: 'Ext.panel.Panel',
> +xtype: 'pbsMarkdownNotes',
> +mixins: ['Proxmox.Mixin.CBind'],
> +

why add this if we move a almost identical one to widget toolkit?

If there are some changes required that cannot be easily passed via a config, 
we should still
reuse most by extending the NotesView wtk component, and not panel.Panel


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



Re: [pve-devel] [PATCH proxmox-backup v3 5/6] fix #3607: ui: refactor notes by moving the panel/window to widget kit

2022-03-23 Thread Thomas Lamprecht
On 04.03.22 12:32, Stefan Sterz wrote:
> for better re-use between pbs and pve move the markdown notes panel
> and editor window to the widget kit and unify them there.
> 

ah ok, now I get it, rather please just leave the intermediate addition of
a notes view and directly use the wtk version and just note here that a wtk
bump is required.


___
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel