From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <pdm-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 929C11FF15C for <inbox@lore.proxmox.com>; Fri, 16 May 2025 15:36:26 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 42204DC1C; Fri, 16 May 2025 15:36:51 +0200 (CEST) From: Dominik Csapak <d.csapak@proxmox.com> To: pdm-devel@lists.proxmox.com Date: Fri, 16 May 2025 15:36:06 +0200 Message-Id: <20250516133611.3499075-17-d.csapak@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250516133611.3499075-1-d.csapak@proxmox.com> References: <20250516133611.3499075-1-d.csapak@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.022 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pdm-devel] [PATCH datacenter-manager 16/21] ui: widget: add pve realm selector X-BeenThere: pdm-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Datacenter Manager development discussion <pdm-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pdm-devel>, <mailto:pdm-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pdm-devel/> List-Post: <mailto:pdm-devel@lists.proxmox.com> List-Help: <mailto:pdm-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel>, <mailto:pdm-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Proxmox Datacenter Manager development discussion <pdm-devel@lists.proxmox.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" <pdm-devel-bounces@lists.proxmox.com> similar to the general realm selector, but with a hostname/fingerprint property, so we can query the realms of any PVE instance. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> --- ui/src/widget/mod.rs | 3 + ui/src/widget/pve_realm_selector.rs | 125 ++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 ui/src/widget/pve_realm_selector.rs diff --git a/ui/src/widget/mod.rs b/ui/src/widget/mod.rs index ee9e799..9d7840c 100644 --- a/ui/src/widget/mod.rs +++ b/ui/src/widget/mod.rs @@ -13,6 +13,9 @@ pub use pve_storage_selector::PveStorageSelector; mod pve_migrate_mapping; pub use pve_migrate_mapping::PveMigrateMap; +mod pve_realm_selector; +pub use pve_realm_selector::PveRealmSelector; + mod resource_tree; pub use resource_tree::ResourceTree; diff --git a/ui/src/widget/pve_realm_selector.rs b/ui/src/widget/pve_realm_selector.rs new file mode 100644 index 0000000..8025c2d --- /dev/null +++ b/ui/src/widget/pve_realm_selector.rs @@ -0,0 +1,125 @@ +use anyhow::format_err; +use std::rc::Rc; + +use yew::html::IntoPropValue; +use yew::prelude::*; + +use pwt::props::RenderFn; +use pwt::state::Store; +use pwt::widget::data_table::{DataTable, DataTableColumn, DataTableHeader}; +use pwt::widget::form::{Selector, SelectorRenderArgs, ValidateFn}; +use pwt::widget::GridPicker; + +use proxmox_yew_comp::common_api_types::BasicRealmInfo; +use proxmox_yew_comp::percent_encoding::percent_encode_component; + +use pwt::props::{FieldBuilder, WidgetBuilder}; +use pwt_macros::{builder, widget}; + +#[widget(comp=PdmPveRealmSelector, @input)] +#[derive(Clone, Properties, PartialEq)] +#[builder] +pub struct PveRealmSelector { + /// The default value. + #[builder(IntoPropValue, into_prop_value)] + #[prop_or_default] + pub default: Option<AttrValue>, + + pub hostname: AttrValue, + + pub fingerprint: Option<AttrValue>, +} + +impl PveRealmSelector { + pub fn new( + hostname: impl IntoPropValue<AttrValue>, + fingerprint: impl IntoPropValue<Option<AttrValue>>, + ) -> Self { + yew::props!(Self { + hostname: hostname.into_prop_value(), + fingerprint: fingerprint.into_prop_value(), + }) + } +} + +pub struct PdmPveRealmSelector { + store: Store<BasicRealmInfo>, + validate: ValidateFn<(String, Store<BasicRealmInfo>)>, + picker: RenderFn<SelectorRenderArgs<Store<BasicRealmInfo>>>, +} + +impl Component for PdmPveRealmSelector { + type Message = (); + type Properties = PveRealmSelector; + + fn create(ctx: &Context<Self>) -> Self { + let store = Store::new().on_change(ctx.link().callback(|_| ())); // trigger redraw + + let validate = ValidateFn::new(|(realm, store): &(String, Store<BasicRealmInfo>)| { + store + .read() + .data() + .iter() + .find(|item| &item.realm == realm) + .map(drop) + .ok_or_else(|| format_err!("no such realm")) + }); + + let picker = RenderFn::new({ + let columns = columns(); + move |args: &SelectorRenderArgs<Store<BasicRealmInfo>>| { + let table = DataTable::new(columns.clone(), args.store.clone()).class("pwt-fit"); + + GridPicker::new(table) + .selection(args.selection.clone()) + .on_select(args.controller.on_select_callback()) + .into() + } + }); + + Self { + store, + validate, + picker, + } + } + + fn view(&self, ctx: &Context<Self>) -> Html { + let props = ctx.props(); + + let mut url = format!( + "/pve/realms?hostname={}", + percent_encode_component(&props.hostname) + ); + if let Some(fp) = &props.fingerprint { + url.push_str(&format!("&fingerprint={}", percent_encode_component(fp))); + } + + Selector::new(self.store.clone(), self.picker.clone()) + .with_std_props(&props.std_props) + .with_input_props(&props.input_props) + .required(true) + .default(props.default.as_deref().unwrap_or("pam").to_string()) + .loader(url) + .validate(self.validate.clone()) + .into() + } +} + +fn columns() -> Rc<Vec<DataTableHeader<BasicRealmInfo>>> { + Rc::new(vec![ + DataTableColumn::new("Realm") + .width("100px") + .sort_order(true) + .show_menu(false) + .get_property(|record: &BasicRealmInfo| &record.realm) + .into(), + DataTableColumn::new("Comment") + .width("300px") + .show_menu(false) + .get_property_owned(|record: &BasicRealmInfo| { + record.comment.clone().unwrap_or_default() + }) + .into(), + ]) +} -- 2.39.5 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel