all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Shannon Sterz <s.sterz@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [PATCH yew-mobile-gui 18/20] node: add a rudimentary firewall tab for cluster nodes
Date: Fri,  8 May 2026 17:05:33 +0200	[thread overview]
Message-ID: <20260508150535.420205-19-s.sterz@proxmox.com> (raw)
In-Reply-To: <20260508150535.420205-1-s.sterz@proxmox.com>

Signed-off-by: Shannon Sterz <s.sterz@proxmox.com>
---
 src/pages/page_node_status/firewall_panel.rs | 163 +++++++++++++++++++
 src/pages/page_node_status/mod.rs            |  18 ++
 2 files changed, 181 insertions(+)
 create mode 100644 src/pages/page_node_status/firewall_panel.rs

diff --git a/src/pages/page_node_status/firewall_panel.rs b/src/pages/page_node_status/firewall_panel.rs
new file mode 100644
index 0000000..c64c05e
--- /dev/null
+++ b/src/pages/page_node_status/firewall_panel.rs
@@ -0,0 +1,163 @@
+use std::rc::Rc;
+
+use serde::{Deserialize, Serialize};
+use yew::virtual_dom::{VComp, VNode};
+
+use pwt::prelude::*;
+use pwt::props::StorageLocation;
+use pwt::state::PersistentState;
+use pwt::widget::{Column, MiniScroll, TabBar, TabBarItem};
+
+use proxmox_yew_comp::configuration::pve::{FirewallOptionsNodePanel, FirewallRulesPanel};
+
+#[derive(Clone, PartialEq, Properties)]
+pub struct NodeFirewallPanel {
+    node: AttrValue,
+}
+
+impl NodeFirewallPanel {
+    pub fn new(node: impl Into<AttrValue>) -> Self {
+        Self { node: node.into() }
+    }
+}
+
+#[derive(Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
+pub enum ViewState {
+    #[default]
+    Rules,
+    Options,
+    //Alias,
+    //IPSet,
+    //Log,
+}
+pub struct PveNodeFirewallPanel {
+    view_state: PersistentState<ViewState>,
+}
+
+pub enum Msg {
+    SetViewState(ViewState),
+}
+
+impl Component for PveNodeFirewallPanel {
+    type Message = Msg;
+    type Properties = NodeFirewallPanel;
+
+    fn create(ctx: &Context<Self>) -> Self {
+        let props = ctx.props();
+
+        let view_state = PersistentState::new(StorageLocation::session(format!(
+            "node-{}-firewall-tab-bar-state",
+            props.node
+        )));
+
+        Self { view_state }
+    }
+
+    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
+        match msg {
+            Msg::SetViewState(view_state) => {
+                self.view_state.update(view_state);
+            }
+        }
+        true
+    }
+    fn view(&self, ctx: &Context<Self>) -> Html {
+        let props = ctx.props();
+
+        let (active_tab, content): (_, Html) = match *self.view_state {
+            ViewState::Rules => (
+                "rules",
+                FirewallRulesPanel::node_firewall(props.node.clone())
+                    .mobile(true)
+                    .readonly(true)
+                    .into(),
+            ),
+            ViewState::Options => (
+                "options",
+                FirewallOptionsNodePanel::new(props.node.clone())
+                    .mobile(true)
+                    .readonly(true)
+                    .into(),
+            ),
+            /*ViewState::Alias => (
+                "alias",
+                html! {
+                    <div>{ format!("Firewall alias for VM {}", props.vmid) }</div>
+                },
+            ),
+            ViewState::IPSet => (
+                "ipset",
+                html! {
+                    <div>{ format!("Firewall ipset for VM {}", props.vmid) }</div>
+                },
+            ),
+            ViewState::Log => (
+                "log",
+                html! {
+                    <div>{ format!("Firewall log for VM {}", props.vmid) }</div>
+                },
+            ),*/
+        };
+
+        let tab_bar = TabBar::new()
+            .style(pwt::widget::TabBarStyle::MaterialSecondary)
+            .class(pwt::css::JustifyContent::Center)
+            .class("pwt-flex-fill")
+            .active(active_tab)
+            .with_item(
+                TabBarItem::new()
+                    .key("rules")
+                    .label(tr!("Rules"))
+                    .icon_class("fa fa-shield")
+                    .on_activate(ctx.link().callback(|_| Msg::SetViewState(ViewState::Rules))),
+            )
+            .with_item(
+                TabBarItem::new()
+                    .key("options")
+                    .label(tr!("Options"))
+                    .icon_class("fa fa-gear")
+                    .on_activate(
+                        ctx.link()
+                            .callback(|_| Msg::SetViewState(ViewState::Options)),
+                    ),
+            )
+            /*.with_item(
+                TabBarItem::new()
+                    .key("alias")
+                    .label(tr!("Alias"))
+                    .icon_class("fa fa-external-link")
+                    .on_activate(ctx.link().callback(|_| Msg::SetViewState(ViewState::Alias))),
+            )
+            .with_item(
+                TabBarItem::new()
+                    .key("ipset")
+                    .label(tr!("IPSet"))
+                    .icon_class("fa fa-list-ol")
+                    .on_activate(ctx.link().callback(|_| Msg::SetViewState(ViewState::IPSet))),
+            )
+            .with_item(
+                TabBarItem::new()
+                    .key("log")
+                    .label(tr!("Log"))
+                    .icon_class("fa fa-list")
+                    .on_activate(ctx.link().callback(|_| Msg::SetViewState(ViewState::Log))),
+            )*/;
+
+        Column::new()
+            .class(pwt::css::FlexFit)
+            .with_child(
+                MiniScroll::new(tab_bar)
+                    .class("pwt-flex-none")
+                    .scroll_mode(pwt::widget::MiniScrollMode::Native),
+            )
+            .with_child(content)
+            .into()
+    }
+}
+
+impl From<NodeFirewallPanel> for VNode {
+    fn from(val: NodeFirewallPanel) -> Self {
+        let comp = VComp::new::<PveNodeFirewallPanel>(Rc::new(val), None);
+        VNode::from(comp)
+    }
+}
diff --git a/src/pages/page_node_status/mod.rs b/src/pages/page_node_status/mod.rs
index a566179..efb3d92 100644
--- a/src/pages/page_node_status/mod.rs
+++ b/src/pages/page_node_status/mod.rs
@@ -28,6 +28,9 @@ pub use services_panel::NodeServicesPanel;
 mod updates_panel;
 pub use updates_panel::NodeUpdatesPanel;
 
+mod firewall_panel;
+use firewall_panel::NodeFirewallPanel;
+
 #[derive(Clone, PartialEq, Properties)]
 pub struct PageNodeStatus {
     node: AttrValue,
@@ -47,6 +50,7 @@ pub enum ViewState {
     Dashboard,
     Services,
     Updates,
+    Firewall,
 }
 
 pub enum Msg {
@@ -119,6 +123,10 @@ impl Component for PvePageNodeStatus {
                 NodeServicesPanel::new(props.node.clone(), standalone).into(),
             ),
             ViewState::Updates => ("updates", NodeUpdatesPanel::new(props.node.clone()).into()),
+            ViewState::Firewall => (
+                "firewall",
+                NodeFirewallPanel::new(props.node.clone()).into(),
+            ),
         };
 
         let tab_bar = TabBar::new()
@@ -154,6 +162,16 @@ impl Component for PvePageNodeStatus {
                         ctx.link()
                             .callback(|_| Msg::SetViewState(ViewState::Updates)),
                     ),
+            )
+            .with_item(
+                TabBarItem::new()
+                    .label(tr!("Firewall"))
+                    .icon_class("fa fa-shield")
+                    .key("firewall")
+                    .on_activate(
+                        ctx.link()
+                            .callback(|_| Msg::SetViewState(ViewState::Firewall)),
+                    ),
             );
 
         Column::new()
-- 
2.47.3





  parent reply	other threads:[~2026-05-08 15:16 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-08 15:05 [PATCH yew-comp/yew-mobile-gui 00/20] firewall tabs and clean up for pve-yew-mobile-gui Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-comp 01/20] firewall rules panel: correct the url for the pve cluster firewall rules Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 02/20] cargo.toml: globally ignore certain clippy lints Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 03/20] main: avoid unnecessary clones Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 04/20] tree-wide: collapse if statements Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 05/20] tree-wide: implement the `From` trait instead of the `Into` trait Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 06/20] tree-wide: implement `Default` for types with an `new()` constructor Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 07/20] tree-wide: remove unnecessary lazy evaluations Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 08/20] tree-wide: remove needless borrows Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 09/20] configuration page: remove redundant static lifetimes Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 10/20] resources/configuration page: remove useless `.into()` calls Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 11/20] tree-wide: fix several clippy lints Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 12/20] dashboard: use proper plural translation string instead of "CPU(s)" Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 13/20] configuration: clarify that "Firewall" shows the cluster's firewall Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 14/20] cluster/qemu firewall: use rules panel and comment out unused tabs Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 15/20] lxc page: align layout for lxc guest with qemu guests Shannon Sterz
2026-05-08 15:43   ` Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 16/20] lxc: add support for a rudimentary firewall tab for lxc guests Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 17/20] node status: align layout for node status with guest pages Shannon Sterz
2026-05-08 15:05 ` Shannon Sterz [this message]
2026-05-08 15:05 ` [PATCH yew-mobile-gui 19/20] api types: remove unused file Shannon Sterz
2026-05-08 15:05 ` [PATCH yew-mobile-gui 20/20] resources page: map subscription level analogous to dashboard Shannon Sterz
2026-05-08 15:22   ` Shan Shaji
2026-05-08 15:59 ` Superseded: Re: [PATCH yew-comp/yew-mobile-gui 00/20] firewall tabs and clean up for pve-yew-mobile-gui Shannon Sterz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260508150535.420205-19-s.sterz@proxmox.com \
    --to=s.sterz@proxmox.com \
    --cc=yew-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal