From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id E2F901FF09C for ; Mon, 05 Oct 2026 13:01:03 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 0F6DC21608; Mon, 05 Oct 2026 13:00:55 +0200 (CEST) From: Dominik Csapak To: pdm-devel@lists.proxmox.com Subject: [PATCH datacenter-manager v6 07/11] ui: pve: tree: render guest tags directly after their name Date: Mon, 5 Oct 2026 12:57:34 +0200 Message-ID: <20261005110049.1851404-8-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261005110049.1851404-1-d.csapak@proxmox.com> References: <20261005110049.1851404-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.400 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: XZTLAFZW37WBMAOXHKD6LSVLPVFVNNQW X-Message-ID-Hash: XZTLAFZW37WBMAOXHKD6LSVLPVFVNNQW X-MailFrom: d.csapak@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: instead of putting them in to a separate column. This increases the space available for the name when there are no (or small) tags, vs always reserving space for tags that might not exist. To show an ellipsis on the tags, add the overflow and text-overflow css classes for each tag and the overall tags container, To shrink the tag container before the guest name, use a flexbox trick: by setting the flex-shrink value to an much higher value than the remaining flex items, it shrinks the tags "first" (technically both shrink, but the text box now only a fraction of a pixel, which is not visible) and only when they reach a very small width the name box shrinks. This is rather a hack, but without reworking how we render the tree column as a whole, there is not really a better way. This also makes it more consistent with how tags are rendered in PVEs resource tree. Signed-off-by: Dominik Csapak --- ui/css/pdm.scss | 3 +++ ui/src/pve/tree.rs | 23 ++++++++++------------- ui/src/pve/utils.rs | 6 +++++- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/ui/css/pdm.scss b/ui/css/pdm.scss index bd6bd02b..2a8fa1ce 100644 --- a/ui/css/pdm.scss +++ b/ui/css/pdm.scss @@ -51,7 +51,10 @@ .pve-tags { text-overflow: ellipsis; + overflow: hidden; .pve-tag { + text-overflow: ellipsis; + overflow: hidden; border-radius: var(--pwt-button-corner-shape); padding-inline: var(--pwt-spacer-2) } diff --git a/ui/src/pve/tree.rs b/ui/src/pve/tree.rs index 4ea5716a..db492092 100644 --- a/ui/src/pve/tree.rs +++ b/ui/src/pve/tree.rs @@ -591,6 +591,7 @@ fn columns( .flex(1) .tree_column(store) .render(move |entry: &PveTreeNode| { + let mut extra = None; let (icon, text) = match entry { PveTreeNode::Root if loading => ( Container::from_tag("i").class("pwt-loading-icon"), @@ -601,23 +602,19 @@ fn columns( tr!("Datacenter"), ), PveTreeNode::Resource(r) => { + let tags = match r { + PveResource::Qemu(q) if !q.tags.is_empty() => Some(&q.tags), + PveResource::Lxc(l) if !l.tags.is_empty() => Some(&l.tags), + _ => None, + }; + extra = tags.map(|tags| render_guest_tags(tags)); (render_status_icon(r), render_resource_name(r, true)) } }; - render_tree_column(icon.into(), text).into() - }) - .into(), - DataTableColumn::new(tr!("Tags")) - .flex(1) - .render(move |entry: &PveTreeNode| match entry { - PveTreeNode::Resource(PveResource::Lxc(lxc)) => { - render_guest_tags(&lxc.tags[..]).into() - } - PveTreeNode::Resource(PveResource::Qemu(qemu)) => { - render_guest_tags(&qemu.tags[..]).into() - } - _ => html! {}, + render_tree_column(icon.into(), text) + .with_optional_child(extra) + .into() }) .into(), DataTableColumn::new(tr!("Actions")) diff --git a/ui/src/pve/utils.rs b/ui/src/pve/utils.rs index 995eab9b..25fa910b 100644 --- a/ui/src/pve/utils.rs +++ b/ui/src/pve/utils.rs @@ -122,7 +122,11 @@ pub fn render_storage_status_icon(node: &PveStorageResource) -> Container { /// Returns a [`pwt::widget::Row`] with an element for each tag pub fn render_guest_tags(tags: &[String]) -> Row { - let mut row = Row::new().class("pve-tags").gap(2); + let mut row = Row::new() + .class("pve-tags") + .gap(2) + // use an absurdly high value to shrink the tags first + .style("flex-shrink", "100000"); for tag in tags { if tag.is_empty() { -- 2.47.3