public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state
@ 2026-08-20  8:17 Dominik Csapak
  2026-08-20  8:17 ` [PATCH yew-widget-toolkit 1/3] widget: navigation drawer: fix first open for default collapsed menus Dominik Csapak
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Dominik Csapak @ 2026-08-20  8:17 UTC (permalink / raw)
  To: pdm-devel

By saving the state in the browsers local storage.

It also fixes an issue where menus that were collapsed by default wouldn't open
on the first click.

Note that for the pdm patches, pwt must be bumped and the new version must be
recorded in Cargo.toml.


proxmox-yew-widget-toolki:

Dominik Csapak (2):
  widget: navigation drawer: fix first open for default collapsed menus
  widget: navigation drawer: allow persisting the expanded state

 src/widget/nav/navigation_drawer.rs | 138 +++++++++++++++++++++++-----
 1 file changed, 115 insertions(+), 23 deletions(-)


proxmox-datacenter-manager:

Dominik Csapak (1):
  ui: main menu: make expanded/collapsed state persistent

 ui/src/main_menu.rs | 1 +
 1 file changed, 1 insertion(+)


Summary over all repositories:
  2 files changed, 116 insertions(+), 23 deletions(-)

-- 
Generated by murpp 0.11.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH yew-widget-toolkit 1/3] widget: navigation drawer: fix first open for default collapsed menus
  2026-08-20  8:17 [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Dominik Csapak
@ 2026-08-20  8:17 ` Dominik Csapak
  2026-08-20  8:17 ` [PATCH yew-widget-toolkit 2/3] widget: navigation drawer: allow persisting the expanded state Dominik Csapak
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2026-08-20  8:17 UTC (permalink / raw)
  To: pdm-devel

A menu item can have it's default expanded state have set to collapsed.
This was correctly displayed when the menu was created, but the first
toggle falsely relied on the fact that non-existent entries in the
`menu_states` HashMap should be interpreted as expanded.

Fix this by introducing a `MenuStates` struct that abstracts these
things away by first collecting the default states for all entries and
then only saving those which changed from the default.

This eliminates the multiple hardcoded default values and it keeps the
saved data minimal, by only saving the keys that have a collapsed
default (which should be in the minority) and only keeping the state of
the ones that changed.

For example when all menus are open by default and the user didn't
collapse any, the struct contains just two empty HashSets.

It also prepares us to save the data later, when we want to have the
collapsed/expanded state persistent.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/widget/nav/navigation_drawer.rs | 96 ++++++++++++++++++++++-------
 1 file changed, 75 insertions(+), 21 deletions(-)

diff --git a/src/widget/nav/navigation_drawer.rs b/src/widget/nav/navigation_drawer.rs
index 87f0743..b2bcd1e 100644
--- a/src/widget/nav/navigation_drawer.rs
+++ b/src/widget/nav/navigation_drawer.rs
@@ -1,4 +1,4 @@
-use std::collections::HashMap;
+use std::collections::HashSet;
 use std::rc::Rc;
 
 use yew::html::{IntoEventCallback, IntoPropValue};
@@ -146,6 +146,67 @@ impl NavigationDrawer {
     }
 }
 
+/// A struct that holds the current state of expanded/collapsed menu items
+///
+/// Only the deviation from the menu's defaults is tracked, which keeps the state minimal and lets
+/// a changed default still take effect for users that never toggled that item.
+struct MenuStates {
+    default_collapsed: HashSet<String>, // contains all keys that are collapsed by default
+    changed: HashSet<String>,           // contains all keys that deviate from their default
+}
+
+impl MenuStates {
+    /// Initializes the state from the menu config (default_collapsed).
+    fn new(menu: &Menu) -> Self {
+        let mut default_collapsed = HashSet::new();
+        Self::collect_default_collapse_states(&mut default_collapsed, menu);
+
+        Self {
+            default_collapsed,
+            changed: HashSet::new(),
+        }
+    }
+
+    // iterates over a menu and saves all submenus that are collapsed by default
+    fn collect_default_collapse_states(collapsed: &mut HashSet<String>, menu: &Menu) {
+        for entry in menu.children.iter() {
+            if let MenuEntry::Item(item) = entry {
+                if let Some(key) = &item.key
+                    && item.default_collapsed
+                {
+                    collapsed.insert(key.to_string());
+                }
+                if let Some(sub_menu) = &item.submenu {
+                    Self::collect_default_collapse_states(collapsed, sub_menu);
+                }
+            }
+        }
+    }
+
+    fn toggle(&mut self, key: &Key) {
+        self.set_state(key, !self.is_open(key));
+    }
+
+    fn is_open(&self, key: &Key) -> bool {
+        let key = key.to_string();
+        let changed = self.changed.contains(&key);
+        let default_collapsed = self.default_collapsed.contains(&key);
+        // open means either collapsed by default and toggled, or open by default and untouched
+        changed == default_collapsed
+    }
+
+    fn set_state(&mut self, key: &Key, open: bool) {
+        let key = key.to_string();
+        let default_open = !self.default_collapsed.contains(&key);
+        // only record the keys that deviate from their default, so the set stays minimal
+        if open == default_open {
+            self.changed.remove(&key);
+        } else {
+            self.changed.insert(key);
+        }
+    }
+}
+
 pub enum Msg {
     Select(Option<Key>, bool, bool),
     SelectionChange(Selection),
@@ -159,7 +220,7 @@ pub struct PwtNavigationDrawer {
     node_ref: NodeRef,
     active: Option<Key>,
     selection: Selection,
-    menu_states: HashMap<Key, bool>, // true = open
+    menu_states: MenuStates,
     _nav_ctx_handle: Option<ContextHandle<NavigationContext>>,
 }
 
@@ -269,16 +330,8 @@ impl PwtNavigationDrawer {
     ) {
         match item {
             MenuEntry::Item(child) => {
-                // An absent state means the user has not toggled this submenu yet, so fall back
-                // to its default: open, unless the item opted into starting collapsed. A submenu
-                // on the path to the active item is force-opened by open_ancestors, so a
-                // deep-linked target stays visible even under default_collapsed.
                 let open = match &child.key {
-                    Some(key) => self
-                        .menu_states
-                        .get(key)
-                        .copied()
-                        .unwrap_or(!child.default_collapsed),
+                    Some(key) => self.menu_states.is_open(key),
                     None => false,
                 };
 
@@ -373,7 +426,8 @@ impl PwtNavigationDrawer {
                     if item.selectable {
                         Some(entry)
                     } else {
-                        self.menu_states.insert(desired.clone(), true);
+                        // the selection moves on to a child, so make sure the submenu is visible
+                        self.menu_states.set_state(desired, true);
                         find_first_key_recursive(&submenu.children)
                     }
                 }
@@ -407,7 +461,7 @@ impl PwtNavigationDrawer {
         let mut path = Vec::new();
         if collect(&props.menu.children, key, &mut path) {
             for key in path {
-                self.menu_states.insert(key, true);
+                self.menu_states.set_state(&key, true);
             }
         }
     }
@@ -490,7 +544,7 @@ impl Component for PwtNavigationDrawer {
             node_ref: NodeRef::default(),
             active: active.clone(),
             selection,
-            menu_states: HashMap::new(),
+            menu_states: MenuStates::new(&props.menu),
             _nav_ctx_handle,
         };
 
@@ -562,9 +616,7 @@ impl Component for PwtNavigationDrawer {
                             self.emit_item_activate(&key, ctx);
                         }
                         if toggle {
-                            let entry =
-                                *self.menu_states.entry(key.clone()).or_insert_with(|| true);
-                            self.menu_states.insert(key, !entry);
+                            self.menu_states.toggle(&key);
                         }
                     }
                     return true;
@@ -592,16 +644,15 @@ impl Component for PwtNavigationDrawer {
                 true
             }
             Msg::MenuToggle(key) => {
-                let entry = *self.menu_states.entry(key.clone()).or_insert_with(|| true);
-                self.menu_states.insert(key, !entry);
+                self.menu_states.toggle(&key);
                 true
             }
             Msg::MenuClose(key) => {
-                self.menu_states.insert(key, false);
+                self.menu_states.set_state(&key, false);
                 true
             }
             Msg::MenuOpen(key) => {
-                self.menu_states.insert(key, true);
+                self.menu_states.set_state(&key, true);
                 true
             }
         }
@@ -612,6 +663,9 @@ impl Component for PwtNavigationDrawer {
         if props.selection != old_props.selection {
             self.selection = Self::init_selection(ctx, props.selection.clone(), &self.active);
         }
+        if props.menu != old_props.menu {
+            self.menu_states = MenuStates::new(&props.menu);
+        }
         true
     }
 
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH yew-widget-toolkit 2/3] widget: navigation drawer: allow persisting the expanded state
  2026-08-20  8:17 [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Dominik Csapak
  2026-08-20  8:17 ` [PATCH yew-widget-toolkit 1/3] widget: navigation drawer: fix first open for default collapsed menus Dominik Csapak
@ 2026-08-20  8:17 ` Dominik Csapak
  2026-08-20  8:17 ` [PATCH datacenter-manager 3/3] ui: main menu: make expanded/collapsed state persistent Dominik Csapak
  2026-08-31 13:02 ` [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Lukas Wagner
  3 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2026-08-20  8:17 UTC (permalink / raw)
  To: pdm-devel

By exposing a `stateful_id` property that is used to save the
`MenuStates` state in the browser local storage.

This is loaded on component creation and when either the menu or the
stateful id changes.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/widget/nav/navigation_drawer.rs | 60 +++++++++++++++++++++++------
 1 file changed, 49 insertions(+), 11 deletions(-)

diff --git a/src/widget/nav/navigation_drawer.rs b/src/widget/nav/navigation_drawer.rs
index b2bcd1e..114e463 100644
--- a/src/widget/nav/navigation_drawer.rs
+++ b/src/widget/nav/navigation_drawer.rs
@@ -10,9 +10,9 @@ use pwt_macros::builder;
 use crate::css::{OverflowX, OverflowY};
 use crate::props::{
     AsClassesMut, AsCssStylesMut, ContainerBuilder, CssBorderBuilder, CssPaddingBuilder, CssStyles,
-    EventSubscriber, IntoOptionalKey, IntoVTag, WidgetBuilder, WidgetStyleBuilder,
+    EventSubscriber, IntoOptionalKey, IntoVTag, StorageLocation, WidgetBuilder, WidgetStyleBuilder,
 };
-use crate::state::{NavigationContext, NavigationContextExt, Selection};
+use crate::state::{NavigationContext, NavigationContextExt, PersistentState, Selection};
 use crate::{impl_class_prop_builder, impl_yew_std_props_builder};
 
 use crate::dom::focus::roving_tabindex_next_recursive;
@@ -82,6 +82,14 @@ pub struct NavigationDrawer {
     #[builder]
     #[prop_or(true)]
     animated: bool,
+
+    /// If set, saves the open/collapsed state in the browser local storage
+    ///
+    /// The value is used as the storage key, so it has to be unique within the application. Only
+    /// the menu items that deviate from their default state are stored.
+    #[builder(IntoPropValue, into_prop_value)]
+    #[prop_or_default]
+    stateful_id: Option<AttrValue>,
 }
 
 impl AsClassesMut for NavigationDrawer {
@@ -153,18 +161,25 @@ impl NavigationDrawer {
 struct MenuStates {
     default_collapsed: HashSet<String>, // contains all keys that are collapsed by default
     changed: HashSet<String>,           // contains all keys that deviate from their default
+    id: Option<AttrValue>,              // local storage key, if the state should be persisted
 }
 
 impl MenuStates {
     /// Initializes the state from the menu config (default_collapsed).
-    fn new(menu: &Menu) -> Self {
+    ///
+    /// If an `id` is given, the state will be loaded from, and subsequently saved to, the browser
+    /// local storage with that identifier.
+    fn new(menu: &Menu, id: Option<AttrValue>) -> Self {
         let mut default_collapsed = HashSet::new();
         Self::collect_default_collapse_states(&mut default_collapsed, menu);
 
-        Self {
+        let mut this = Self {
             default_collapsed,
             changed: HashSet::new(),
-        }
+            id,
+        };
+        this.load_state();
+        this
     }
 
     // iterates over a menu and saves all submenus that are collapsed by default
@@ -199,10 +214,33 @@ impl MenuStates {
         let key = key.to_string();
         let default_open = !self.default_collapsed.contains(&key);
         // only record the keys that deviate from their default, so the set stays minimal
-        if open == default_open {
-            self.changed.remove(&key);
+        let modified = if open == default_open {
+            self.changed.remove(&key)
         } else {
-            self.changed.insert(key);
+            self.changed.insert(key)
+        };
+        // do not rewrite the local storage if the state did not actually change
+        if modified {
+            self.save_state();
+        }
+    }
+
+    /// Loads the deviations from the default state from the local storage, if an `id` is set.
+    fn load_state(&mut self) {
+        if let Some(id) = self.id.clone() {
+            let state = PersistentState::<Option<HashSet<String>>>::new(StorageLocation::Local(id));
+            if let Some(state) = state.into_inner() {
+                self.changed = state;
+            }
+        }
+    }
+
+    /// Saves the deviations from the default state to the local storage, if an `id` is set.
+    fn save_state(&self) {
+        if let Some(id) = self.id.clone() {
+            let mut state =
+                PersistentState::<Option<HashSet<String>>>::new(StorageLocation::Local(id));
+            state.update(Some(self.changed.clone()));
         }
     }
 }
@@ -544,7 +582,7 @@ impl Component for PwtNavigationDrawer {
             node_ref: NodeRef::default(),
             active: active.clone(),
             selection,
-            menu_states: MenuStates::new(&props.menu),
+            menu_states: MenuStates::new(&props.menu, props.stateful_id.clone()),
             _nav_ctx_handle,
         };
 
@@ -663,8 +701,8 @@ impl Component for PwtNavigationDrawer {
         if props.selection != old_props.selection {
             self.selection = Self::init_selection(ctx, props.selection.clone(), &self.active);
         }
-        if props.menu != old_props.menu {
-            self.menu_states = MenuStates::new(&props.menu);
+        if props.menu != old_props.menu || props.stateful_id != old_props.stateful_id {
+            self.menu_states = MenuStates::new(&props.menu, props.stateful_id.clone());
         }
         true
     }
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH datacenter-manager 3/3] ui: main menu: make expanded/collapsed state persistent
  2026-08-20  8:17 [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Dominik Csapak
  2026-08-20  8:17 ` [PATCH yew-widget-toolkit 1/3] widget: navigation drawer: fix first open for default collapsed menus Dominik Csapak
  2026-08-20  8:17 ` [PATCH yew-widget-toolkit 2/3] widget: navigation drawer: allow persisting the expanded state Dominik Csapak
@ 2026-08-20  8:17 ` Dominik Csapak
  2026-08-31 13:02 ` [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Lukas Wagner
  3 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2026-08-20  8:17 UTC (permalink / raw)
  To: pdm-devel

by usint the new `stateful_id` property.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 ui/src/main_menu.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ui/src/main_menu.rs b/ui/src/main_menu.rs
index 1fddfa6a..04cf302c 100644
--- a/ui/src/main_menu.rs
+++ b/ui/src/main_menu.rs
@@ -410,6 +410,7 @@ impl Component for PdmMainMenu {
 
         let drawer = NavigationDrawer::new(menu)
             .aria_label("Datacenter Manager")
+            .stateful_id("pdm-main-menu")
             .class("pwt-border-end")
             .class(css::Flex::None)
             .width(275)
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state
  2026-08-20  8:17 [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Dominik Csapak
                   ` (2 preceding siblings ...)
  2026-08-20  8:17 ` [PATCH datacenter-manager 3/3] ui: main menu: make expanded/collapsed state persistent Dominik Csapak
@ 2026-08-31 13:02 ` Lukas Wagner
  2026-08-31 13:11   ` Dominik Csapak
  3 siblings, 1 reply; 7+ messages in thread
From: Lukas Wagner @ 2026-08-31 13:02 UTC (permalink / raw)
  To: Dominik Csapak, pdm-devel

On Thu Aug 20, 2026 at 10:17 AM CEST, Dominik Csapak wrote:
> By saving the state in the browsers local storage.
>
> It also fixes an issue where menus that were collapsed by default wouldn't open
> on the first click.
>
> Note that for the pdm patches, pwt must be bumped and the new version must be
> recorded in Cargo.toml.
>
>
> proxmox-yew-widget-toolki:
>
> Dominik Csapak (2):
>   widget: navigation drawer: fix first open for default collapsed menus
>   widget: navigation drawer: allow persisting the expanded state
>
>  src/widget/nav/navigation_drawer.rs | 138 +++++++++++++++++++++++-----
>  1 file changed, 115 insertions(+), 23 deletions(-)
>
>
> proxmox-datacenter-manager:
>
> Dominik Csapak (1):
>   ui: main menu: make expanded/collapsed state persistent
>
>  ui/src/main_menu.rs | 1 +
>  1 file changed, 1 insertion(+)
>
>
> Summary over all repositories:
>   2 files changed, 116 insertions(+), 23 deletions(-)


LGTM in general, works fine and the code seems good too.

One thought, looking at the saved state in the web inspector in Firefox:
Would it maybe make sense for future extensions to slightly update the
serialized format from 

["sdn","administration"]

to something like:

{ collapsed: ["sdn", "administration"]}

That would make it much easier to add other keys as well in the future,
if we need to store additional state.

Not a blocker from my side though:

Reviewed-by: Lukas Wagner <l.wagner@proxmox.com>
Tested-by: Lukas Wagner <l.wagner@proxmox.com>




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state
  2026-08-31 13:02 ` [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Lukas Wagner
@ 2026-08-31 13:11   ` Dominik Csapak
  2026-08-31 13:28     ` Lukas Wagner
  0 siblings, 1 reply; 7+ messages in thread
From: Dominik Csapak @ 2026-08-31 13:11 UTC (permalink / raw)
  To: Lukas Wagner, pdm-devel



On 8/31/26 3:02 PM, Lukas Wagner wrote:
> On Thu Aug 20, 2026 at 10:17 AM CEST, Dominik Csapak wrote:
>> By saving the state in the browsers local storage.
>>
>> It also fixes an issue where menus that were collapsed by default wouldn't open
>> on the first click.
>>
>> Note that for the pdm patches, pwt must be bumped and the new version must be
>> recorded in Cargo.toml.
>>
>>
>> proxmox-yew-widget-toolki:
>>
>> Dominik Csapak (2):
>>    widget: navigation drawer: fix first open for default collapsed menus
>>    widget: navigation drawer: allow persisting the expanded state
>>
>>   src/widget/nav/navigation_drawer.rs | 138 +++++++++++++++++++++++-----
>>   1 file changed, 115 insertions(+), 23 deletions(-)
>>
>>
>> proxmox-datacenter-manager:
>>
>> Dominik Csapak (1):
>>    ui: main menu: make expanded/collapsed state persistent
>>
>>   ui/src/main_menu.rs | 1 +
>>   1 file changed, 1 insertion(+)
>>
>>
>> Summary over all repositories:
>>    2 files changed, 116 insertions(+), 23 deletions(-)
> 
> 
> LGTM in general, works fine and the code seems good too.
> 
> One thought, looking at the saved state in the web inspector in Firefox:
> Would it maybe make sense for future extensions to slightly update the
> serialized format from
> 
> ["sdn","administration"]
> 
> to something like:
> 
> { collapsed: ["sdn", "administration"]}
> 
> That would make it much easier to add other keys as well in the future,
> if we need to store additional state.

it's actually not collapsed, but changed from the default
(the main menu in pdm just happens to default to all expanded)

so it would be { "changed": [...] }

would that be ok?

we could of course do this in the future and interpret
an array as just the changed list and migrate automatically.

in practice this would look like (rough pseude code):

let try1: Result<NewStateFormat, _> = input.parse();
match try1 {
    Ok(state) => { /* return the state */ }
    Err(err) => {
        let legacy: Result<OldStateFormat, _> = input.parse();
        // either take legacy and convert to new state
        // or return original error 'err'
    }
}

> 
> Not a blocker from my side though:
> 
> Reviewed-by: Lukas Wagner <l.wagner@proxmox.com>
> Tested-by: Lukas Wagner <l.wagner@proxmox.com>





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state
  2026-08-31 13:11   ` Dominik Csapak
@ 2026-08-31 13:28     ` Lukas Wagner
  0 siblings, 0 replies; 7+ messages in thread
From: Lukas Wagner @ 2026-08-31 13:28 UTC (permalink / raw)
  To: Dominik Csapak, Lukas Wagner, pdm-devel

On Mon Aug 31, 2026 at 3:11 PM CEST, Dominik Csapak wrote:
>> 
>> LGTM in general, works fine and the code seems good too.
>> 
>> One thought, looking at the saved state in the web inspector in Firefox:
>> Would it maybe make sense for future extensions to slightly update the
>> serialized format from
>> 
>> ["sdn","administration"]
>> 
>> to something like:
>> 
>> { collapsed: ["sdn", "administration"]}
>> 
>> That would make it much easier to add other keys as well in the future,
>> if we need to store additional state.
>
> it's actually not collapsed, but changed from the default
> (the main menu in pdm just happens to default to all expanded)
>
> so it would be { "changed": [...] }
>
> would that be ok?

Maybe "changed-collapsed" so that it conveys that this is about the
collpase/expanded state and not anything else?

>
> we could of course do this in the future and interpret
> an array as just the changed list and migrate automatically.
>
> in practice this would look like (rough pseude code):
>
> let try1: Result<NewStateFormat, _> = input.parse();
> match try1 {
>     Ok(state) => { /* return the state */ }
>     Err(err) => {
>         let legacy: Result<OldStateFormat, _> = input.parse();
>         // either take legacy and convert to new state
>         // or return original error 'err'
>     }
> }

Yeah, migrating the format is of course also possible in the future, but
since this is completely new code, I'd favor making it extensible right
away.

Thanks!





^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-08-31 13:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20  8:17 [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Dominik Csapak
2026-08-20  8:17 ` [PATCH yew-widget-toolkit 1/3] widget: navigation drawer: fix first open for default collapsed menus Dominik Csapak
2026-08-20  8:17 ` [PATCH yew-widget-toolkit 2/3] widget: navigation drawer: allow persisting the expanded state Dominik Csapak
2026-08-20  8:17 ` [PATCH datacenter-manager 3/3] ui: main menu: make expanded/collapsed state persistent Dominik Csapak
2026-08-31 13:02 ` [PATCH datacenter-manager/yew-widget-toolkit 0/3] ui: persist the main menus expanded state Lukas Wagner
2026-08-31 13:11   ` Dominik Csapak
2026-08-31 13:28     ` Lukas Wagner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal