From: Shannon Sterz <s.sterz@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [PATCH yew-mobile-gui 16/20] lxc: add support for a rudimentary firewall tab for lxc guests
Date: Fri, 8 May 2026 17:05:31 +0200 [thread overview]
Message-ID: <20260508150535.420205-17-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_lxc_status/firewall_panel.rs | 172 ++++++++++++++++++++
src/pages/page_lxc_status/mod.rs | 17 ++
2 files changed, 189 insertions(+)
create mode 100644 src/pages/page_lxc_status/firewall_panel.rs
diff --git a/src/pages/page_lxc_status/firewall_panel.rs b/src/pages/page_lxc_status/firewall_panel.rs
new file mode 100644
index 0000000..10d76dd
--- /dev/null
+++ b/src/pages/page_lxc_status/firewall_panel.rs
@@ -0,0 +1,172 @@
+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::{FirewallOptionsGuestPanel, FirewallRulesPanel};
+use proxmox_yew_comp::form::pve::PveGuestType;
+
+#[derive(Clone, PartialEq, Properties)]
+pub struct LxcFirewallPanel {
+ vmid: u32,
+ node: AttrValue,
+}
+
+impl LxcFirewallPanel {
+ pub fn new(node: impl Into<AttrValue>, vmid: u32) -> Self {
+ Self {
+ node: node.into(),
+ vmid,
+ }
+ }
+}
+
+#[derive(Copy, Clone, Default, PartialEq, Serialize, Deserialize)]
+pub enum ViewState {
+ #[default]
+ Rules,
+ Options,
+ //Alias,
+ //IPSet,
+ //Log,
+}
+pub struct PveLxcFirewallPanel {
+ view_state: PersistentState<ViewState>,
+}
+
+pub enum Msg {
+ SetViewState(ViewState),
+}
+
+impl Component for PveLxcFirewallPanel {
+ type Message = Msg;
+ type Properties = LxcFirewallPanel;
+
+ fn create(ctx: &Context<Self>) -> Self {
+ let props = ctx.props();
+
+ let view_state = PersistentState::new(StorageLocation::session(format!(
+ "ct-{}-firewall-tab-bar-state",
+ props.vmid
+ )));
+
+ 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::guest_firewall(
+ PveGuestType::Lxc,
+ props.node.clone(),
+ props.vmid,
+ )
+ .mobile(true)
+ .readonly(true)
+ .into(),
+ ),
+ ViewState::Options => (
+ "options",
+ FirewallOptionsGuestPanel::new(PveGuestType::Lxc, props.node.clone(), props.vmid)
+ .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<LxcFirewallPanel> for VNode {
+ fn from(val: LxcFirewallPanel) -> Self {
+ let comp = VComp::new::<PveLxcFirewallPanel>(Rc::new(val), None);
+ VNode::from(comp)
+ }
+}
diff --git a/src/pages/page_lxc_status/mod.rs b/src/pages/page_lxc_status/mod.rs
index 4092dd5..7d616eb 100644
--- a/src/pages/page_lxc_status/mod.rs
+++ b/src/pages/page_lxc_status/mod.rs
@@ -14,7 +14,9 @@ use pwt::widget::{Column, MiniScroll, TabBar, TabBarItem};
use crate::widgets::{GuestBackupPanel, TopNavBar};
mod dashboard_panel;
+mod firewall_panel;
pub use dashboard_panel::LxcDashboardPanel;
+use firewall_panel::LxcFirewallPanel;
use proxmox_yew_comp::configuration::pve::LxcOptionsPanel;
@@ -39,6 +41,7 @@ pub enum ViewState {
Dashboard,
Options,
Backup,
+ Firewall,
}
pub enum Msg {
@@ -92,6 +95,10 @@ impl Component for PvePageLxcStatus {
.readonly(true)
.into(),
),
+ ViewState::Firewall => (
+ "firewall",
+ LxcFirewallPanel::new(props.node.clone(), props.vmid).into(),
+ ),
};
let tab_bar = TabBar::new()
@@ -127,6 +134,16 @@ impl Component for PvePageLxcStatus {
ctx.link()
.callback(|_| Msg::SetViewState(ViewState::Backup)),
),
+ )
+ .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
next prev parent reply other threads:[~2026-05-08 15:05 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 ` Shannon Sterz [this message]
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 ` [PATCH yew-mobile-gui 18/20] node: add a rudimentary firewall tab for cluster nodes Shannon Sterz
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-17-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox