all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH datacenter-manager 6/9] ui: refactor RemoteConfigPanel into own module
Date: Mon, 20 Jan 2025 10:30:03 +0100	[thread overview]
Message-ID: <20250120093006.927014-14-d.csapak@proxmox.com> (raw)
In-Reply-To: <20250120093006.927014-1-d.csapak@proxmox.com>

we'll use the 'remote' module for a more general component where we use
the RemoteConfigPanel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 ui/src/remotes/config.rs | 392 +++++++++++++++++++++++++++++++++++++++
 ui/src/remotes/mod.rs    | 392 +--------------------------------------
 2 files changed, 394 insertions(+), 390 deletions(-)
 create mode 100644 ui/src/remotes/config.rs

diff --git a/ui/src/remotes/config.rs b/ui/src/remotes/config.rs
new file mode 100644
index 0000000..d9d16ae
--- /dev/null
+++ b/ui/src/remotes/config.rs
@@ -0,0 +1,392 @@
+use std::future::Future;
+use std::pin::Pin;
+use std::rc::Rc;
+
+use anyhow::Error;
+
+use proxmox_schema::property_string::PropertyString;
+
+use crate::remotes::edit_remote::EditRemote;
+//use pwt::widget::form::{Field, FormContext, InputType};
+
+use pdm_api_types::remotes::Remote;
+//use proxmox_schema::{property_string::PropertyString, ApiType};
+use proxmox_yew_comp::percent_encoding::percent_encode_component;
+
+//use pbs_api_types::CERT_FINGERPRINT_SHA256_SCHEMA;
+
+//use proxmox_schema::api_types::{CERT_FINGERPRINT_SHA256_SCHEMA, DNS_NAME_OR_IP_SCHEMA};
+
+use serde_json::Value;
+use yew::virtual_dom::{Key, VComp, VNode};
+
+use pwt::prelude::*;
+use pwt::state::{Selection, Store};
+use pwt::widget::data_table::{DataTable, DataTableColumn, DataTableHeader};
+//use pwt::widget::form::{delete_empty_values, Field, FormContext, InputType};
+use pwt::widget::{
+    //menu::{Menu, MenuButton, MenuItem},
+    Button,
+    Column,
+    Toolbar,
+    Tooltip,
+};
+//use pwt::widget::InputPanel;
+
+//use proxmox_yew_comp::EditWindow;
+use proxmox_yew_comp::{
+    ConfirmButton, LoadableComponent, LoadableComponentContext, LoadableComponentMaster,
+};
+
+use pdm_api_types::remotes::{NodeUrl, RemoteType};
+
+async fn load_remotes() -> Result<Vec<Remote>, Error> {
+    proxmox_yew_comp::http_get("/remotes", None).await
+}
+
+async fn delete_item(key: Key) -> Result<(), Error> {
+    let id = key.to_string();
+    let url = format!("/remotes/{}", percent_encode_component(&id));
+    proxmox_yew_comp::http_delete(&url, None).await?;
+    Ok(())
+}
+
+pub async fn create_remote(mut data: Value, remote_type: RemoteType) -> Result<(), Error> {
+    if data.get("nodes").is_none() {
+        let nodes = vec![PropertyString::new(NodeUrl {
+            hostname: data["hostname"].as_str().unwrap_or_default().to_string(),
+            fingerprint: data["fingerprint"].as_str().map(|fp| fp.to_string()),
+        })];
+        data["nodes"] = serde_json::to_value(nodes)?;
+    }
+    data["type"] = match remote_type {
+        RemoteType::Pve => "pve",
+        RemoteType::Pbs => "pbs",
+    }
+    .into();
+
+    let remote: Remote = serde_json::from_value(data.clone())?;
+
+    let mut params = serde_json::to_value(remote)?;
+    if let Some(token) = data["create-token"].as_str() {
+        params["create-token"] = token.into();
+    }
+
+    proxmox_yew_comp::http_post("/remotes", Some(params)).await
+}
+
+/*
+async fn update_item(form_ctx: FormContext) -> Result<(), Error> {
+    let data = form_ctx.get_submit_data();
+
+    let data = delete_empty_values(&data, &["fingerprint", "comment", "port"], true);
+
+    let name = form_ctx.read().get_field_text("name");
+
+    let url = format!("/config/remote/{}", percent_encode_component(&name));
+
+    proxmox_yew_comp::http_put(&url, Some(data)).await
+}
+*/
+
+#[derive(PartialEq, Properties)]
+pub struct RemoteConfigPanel;
+
+impl RemoteConfigPanel {
+    pub fn new() -> Self {
+        yew::props!(Self {})
+    }
+}
+
+#[derive(PartialEq)]
+pub enum ViewState {
+    Add(RemoteType),
+    Edit,
+}
+
+pub enum Msg {
+    SelectionChange,
+    RemoveItem,
+}
+
+pub struct PbsRemoteConfigPanel {
+    store: Store<Remote>,
+    selection: Selection,
+    remote_list_columns: Rc<Vec<DataTableHeader<Remote>>>,
+}
+
+impl LoadableComponent for PbsRemoteConfigPanel {
+    type Message = Msg;
+    type Properties = RemoteConfigPanel;
+    type ViewState = ViewState;
+
+    fn load(
+        &self,
+        _ctx: &LoadableComponentContext<Self>,
+    ) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
+        let store = self.store.clone();
+        Box::pin(async move {
+            let data = load_remotes().await?;
+            store.write().set_data(data);
+            Ok(())
+        })
+    }
+
+    fn create(ctx: &LoadableComponentContext<Self>) -> Self {
+        let store = Store::with_extract_key(|record: &Remote| Key::from(record.id.clone()));
+
+        let selection = Selection::new().on_select(ctx.link().callback(|_| Msg::SelectionChange));
+
+        let remote_list_columns = remote_list_columns();
+
+        Self {
+            store,
+            selection,
+            remote_list_columns,
+        }
+    }
+
+    fn update(&mut self, ctx: &LoadableComponentContext<Self>, msg: Self::Message) -> bool {
+        match msg {
+            Msg::SelectionChange => true,
+            Msg::RemoveItem => {
+                if let Some(key) = self.selection.selected_key() {
+                    let link = ctx.link();
+                    link.clone().spawn(async move {
+                        if let Err(err) = delete_item(key).await {
+                            link.show_error(tr!("Unable to delete item"), err, true);
+                        }
+                        link.send_reload();
+                    })
+                }
+                false
+            }
+        }
+    }
+
+    fn toolbar(&self, ctx: &LoadableComponentContext<Self>) -> Option<Html> {
+        let link = ctx.link();
+
+        let disabled = self.selection.is_empty();
+
+        let toolbar = Toolbar::new()
+            .class("pwt-overflow-hidden")
+            .class("pwt-border-bottom")
+            .with_child({
+                Button::new(tr!("Add Proxmox VE"))
+                    .icon_class("fa fa-building")
+                    .onclick(link.change_view_callback(|_| Some(ViewState::Add(RemoteType::Pve))))
+                // FIXME: add PBS support
+                //MenuButton::new(tr!("Add")).show_arrow(true).menu(
+                //    Menu::new()
+                //        .with_item(
+                //            MenuItem::new("Proxmox VE")
+                //                .icon_class("fa fa-building")
+                //                .on_select(link.change_view_callback(|_| {
+                //                    Some(ViewState::Add(RemoteType::Pve))
+                //                })),
+                //        )
+                //        .with_item(
+                //            MenuItem::new("Proxmox Backup Server")
+                //                .icon_class("fa fa-floppy-o")
+                //                .on_select(link.change_view_callback(|_| {
+                //                    Some(ViewState::Add(RemoteType::Pbs))
+                //                })),
+                //        ),
+                //)
+            })
+            .with_spacer()
+            .with_child(
+                Button::new(tr!("Edit"))
+                    .disabled(disabled)
+                    .onclick(link.change_view_callback(|_| Some(ViewState::Edit))),
+            )
+            .with_child(
+                ConfirmButton::new(tr!("Remove"))
+                    .confirm_message(tr!("Are you sure you want to remove this remote?"))
+                    .disabled(disabled)
+                    .on_activate(link.callback(|_| Msg::RemoveItem)),
+            )
+            .with_flex_spacer()
+            .with_child({
+                let loading = ctx.loading();
+                let link = ctx.link();
+                Button::refresh(loading).onclick(move |_| link.send_reload())
+            });
+
+        Some(toolbar.into())
+    }
+
+    fn main_view(&self, ctx: &LoadableComponentContext<Self>) -> Html {
+        let columns = Rc::clone(&self.remote_list_columns);
+        let link = ctx.link();
+        DataTable::new(columns, self.store.clone())
+            .class(pwt::css::FlexFit)
+            .selection(self.selection.clone())
+            .on_row_dblclick(move |_: &mut _| {
+                link.change_view(Some(ViewState::Edit));
+            })
+            .into()
+    }
+
+    fn dialog_view(
+        &self,
+        ctx: &LoadableComponentContext<Self>,
+        view_state: &Self::ViewState,
+    ) -> Option<Html> {
+        match view_state {
+            ViewState::Add(ty) => Some(self.create_add_dialog(ctx, *ty)),
+            ViewState::Edit => self
+                .selection
+                .selected_key()
+                .map(|key| self.create_edit_dialog(ctx, key)),
+        }
+    }
+}
+
+/*
+fn add_remote_input_panel(_form_ctx: &FormContext) -> Html {
+    InputPanel::new()
+        .padding(4)
+        .with_field(tr!("Remote ID"), Field::new().name("id").required(true))
+        .with_right_field(
+            tr!("Fingerprint"),
+            Field::new()
+                .name("fingerprint")
+                .schema(&CERT_FINGERPRINT_SHA256_SCHEMA),
+        )
+        .with_field(
+            tr!("Server address"),
+            Field::new().name("server").required(true),
+        )
+        .with_field(
+            tr!("User/Token"),
+            Field::new()
+                .name("authid")
+                .schema(&pdm_api_types::Authid::API_SCHEMA)
+                .required(true),
+        )
+        .with_field(
+            tr!("Password/Secret"),
+            Field::new()
+                .name("token")
+                .input_type(InputType::Password)
+                .required(true),
+        )
+        .into()
+}
+*/
+
+impl PbsRemoteConfigPanel {
+    fn create_add_dialog(
+        &self,
+        ctx: &LoadableComponentContext<Self>,
+        remote_type: RemoteType,
+    ) -> Html {
+        super::AddWizard::new(remote_type)
+            .on_close(ctx.link().change_view_callback(|_| None))
+            .on_submit(move |ctx| create_remote(ctx, remote_type))
+            .into()
+
+        // EditWindow::new(tr!("Add") + ": " + &tr!("Remote"))
+        //     .renderer(add_remote_input_panel)
+        //     .on_submit(move |ctx: FormContext| create_item(ctx.get_submit_data(), remote_type))
+        //     .on_done(ctx.link().change_view_callback(|_| None))
+        //     .into()
+    }
+
+    fn create_edit_dialog(&self, ctx: &LoadableComponentContext<Self>, key: Key) -> Html {
+        EditRemote::new(&*key)
+            .on_done(ctx.link().change_view_callback(|_| None))
+            .into()
+    }
+}
+
+impl Into<VNode> for RemoteConfigPanel {
+    fn into(self) -> VNode {
+        let comp = VComp::new::<LoadableComponentMaster<PbsRemoteConfigPanel>>(Rc::new(self), None);
+        VNode::from(comp)
+    }
+}
+
+fn remote_list_columns() -> Rc<Vec<DataTableHeader<Remote>>> {
+    Rc::new(vec![
+        DataTableColumn::new(tr!("Remote ID"))
+            .width("200px")
+            .render(|item: &Remote| {
+                html! {
+                    &item.id
+                }
+            })
+            .sorter(|a: &Remote, b: &Remote| a.id.cmp(&b.id))
+            .sort_order(true)
+            .into(),
+        DataTableColumn::new(tr!("Type"))
+            .width("60px")
+            .render(|item: &Remote| {
+                html! {
+                    &item.ty
+                }
+            })
+            .sorter(|a: &Remote, b: &Remote| a.ty.cmp(&b.ty))
+            .into(),
+        DataTableColumn::new(tr!("AuthId"))
+            .width("200px")
+            .render(|item: &Remote| {
+                html! {
+                    &item.authid
+                }
+            })
+            .sorter(|a: &Remote, b: &Remote| a.authid.cmp(&b.authid))
+            .into(),
+        DataTableColumn::new(tr!("Nodes"))
+            .flex(1)
+            .render(|item: &Remote| {
+                if item.nodes.is_empty() {
+                    html! {tr!("None")}
+                } else {
+                    let nodes = item
+                        .nodes
+                        .iter()
+                        .map(|n| n.hostname.as_str())
+                        .collect::<Vec<_>>()
+                        .join(", ");
+                    let mut tip = Column::new();
+                    tip.add_children(item.nodes.iter().map(|n| {
+                        let text = match n.fingerprint.clone() {
+                            Some(fp) => format!("{} ({fp})", n.hostname),
+                            None => n.hostname.to_string(),
+                        };
+                        html! {<div>{text}</div>}
+                    }));
+                    Tooltip::new(nodes).rich_tip(tip).into()
+                }
+            })
+            .into(),
+        /*
+        DataTableColumn::new(tr!("Auth ID"))
+            .width("200px")
+            .render(|item: &Remote| html!{
+                item.config.auth_id.clone()
+            })
+            .sorter(|a: &Remote, b: &Remote| {
+                a.config.auth_id.cmp(&b.config.auth_id)
+            })
+            .into(),
+
+        DataTableColumn::new(tr!("Fingerprint"))
+            .width("200px")
+            .render(|item: &Remote| html!{
+                item.config.fingerprint.clone().unwrap_or(String::new())
+            })
+            .into(),
+
+        DataTableColumn::new(tr!("Comment"))
+            .flex(1)
+            .render(|item: &Remote| html!{
+                item.config.comment.clone().unwrap_or(String::new())
+            })
+            .into()
+            */
+    ])
+}
diff --git a/ui/src/remotes/mod.rs b/ui/src/remotes/mod.rs
index d11c5e0..f221777 100644
--- a/ui/src/remotes/mod.rs
+++ b/ui/src/remotes/mod.rs
@@ -1,5 +1,4 @@
 mod wizard_page_connect;
-use proxmox_schema::property_string::PropertyString;
 use wizard_page_connect::WizardPageConnect;
 
 mod wizard_page_nodes;
@@ -19,392 +18,5 @@ pub use node_url_list::NodeUrlList;
 
 mod edit_remote;
 
-use std::future::Future;
-use std::pin::Pin;
-use std::rc::Rc;
-
-use anyhow::Error;
-use edit_remote::EditRemote;
-//use pwt::widget::form::{Field, FormContext, InputType};
-
-use pdm_api_types::remotes::Remote;
-//use proxmox_schema::{property_string::PropertyString, ApiType};
-use proxmox_yew_comp::percent_encoding::percent_encode_component;
-
-//use pbs_api_types::CERT_FINGERPRINT_SHA256_SCHEMA;
-
-//use proxmox_schema::api_types::{CERT_FINGERPRINT_SHA256_SCHEMA, DNS_NAME_OR_IP_SCHEMA};
-
-use serde_json::Value;
-use yew::virtual_dom::{Key, VComp, VNode};
-
-use pwt::prelude::*;
-use pwt::state::{Selection, Store};
-use pwt::widget::data_table::{DataTable, DataTableColumn, DataTableHeader};
-//use pwt::widget::form::{delete_empty_values, Field, FormContext, InputType};
-use pwt::widget::{
-    //menu::{Menu, MenuButton, MenuItem},
-    Button,
-    Column,
-    Toolbar,
-    Tooltip,
-};
-//use pwt::widget::InputPanel;
-
-//use proxmox_yew_comp::EditWindow;
-use proxmox_yew_comp::{
-    ConfirmButton, LoadableComponent, LoadableComponentContext, LoadableComponentMaster,
-};
-
-use pdm_api_types::remotes::{NodeUrl, RemoteType};
-
-async fn load_remotes() -> Result<Vec<Remote>, Error> {
-    proxmox_yew_comp::http_get("/remotes", None).await
-}
-
-async fn delete_item(key: Key) -> Result<(), Error> {
-    let id = key.to_string();
-    let url = format!("/remotes/{}", percent_encode_component(&id));
-    proxmox_yew_comp::http_delete(&url, None).await?;
-    Ok(())
-}
-
-pub(crate) async fn create_remote(mut data: Value, remote_type: RemoteType) -> Result<(), Error> {
-    if data.get("nodes").is_none() {
-        let nodes = vec![PropertyString::new(NodeUrl {
-            hostname: data["hostname"].as_str().unwrap_or_default().to_string(),
-            fingerprint: data["fingerprint"].as_str().map(|fp| fp.to_string()),
-        })];
-        data["nodes"] = serde_json::to_value(nodes)?;
-    }
-    data["type"] = match remote_type {
-        RemoteType::Pve => "pve",
-        RemoteType::Pbs => "pbs",
-    }
-    .into();
-
-    let remote: Remote = serde_json::from_value(data.clone())?;
-
-    let mut params = serde_json::to_value(remote)?;
-    if let Some(token) = data["create-token"].as_str() {
-        params["create-token"] = token.into();
-    }
-
-    proxmox_yew_comp::http_post("/remotes", Some(params)).await
-}
-
-/*
-async fn update_item(form_ctx: FormContext) -> Result<(), Error> {
-    let data = form_ctx.get_submit_data();
-
-    let data = delete_empty_values(&data, &["fingerprint", "comment", "port"], true);
-
-    let name = form_ctx.read().get_field_text("name");
-
-    let url = format!("/config/remote/{}", percent_encode_component(&name));
-
-    proxmox_yew_comp::http_put(&url, Some(data)).await
-}
-*/
-
-#[derive(PartialEq, Properties)]
-pub struct RemoteConfigPanel;
-
-impl RemoteConfigPanel {
-    pub fn new() -> Self {
-        yew::props!(Self {})
-    }
-}
-
-#[derive(PartialEq)]
-pub enum ViewState {
-    Add(RemoteType),
-    Edit,
-}
-
-pub enum Msg {
-    SelectionChange,
-    RemoveItem,
-}
-
-pub struct PbsRemoteConfigPanel {
-    store: Store<Remote>,
-    selection: Selection,
-    remote_list_columns: Rc<Vec<DataTableHeader<Remote>>>,
-}
-
-impl LoadableComponent for PbsRemoteConfigPanel {
-    type Message = Msg;
-    type Properties = RemoteConfigPanel;
-    type ViewState = ViewState;
-
-    fn load(
-        &self,
-        _ctx: &LoadableComponentContext<Self>,
-    ) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
-        let store = self.store.clone();
-        Box::pin(async move {
-            let data = load_remotes().await?;
-            store.write().set_data(data);
-            Ok(())
-        })
-    }
-
-    fn create(ctx: &LoadableComponentContext<Self>) -> Self {
-        let store = Store::with_extract_key(|record: &Remote| Key::from(record.id.clone()));
-
-        let selection = Selection::new().on_select(ctx.link().callback(|_| Msg::SelectionChange));
-
-        let remote_list_columns = remote_list_columns();
-
-        Self {
-            store,
-            selection,
-            remote_list_columns,
-        }
-    }
-
-    fn update(&mut self, ctx: &LoadableComponentContext<Self>, msg: Self::Message) -> bool {
-        match msg {
-            Msg::SelectionChange => true,
-            Msg::RemoveItem => {
-                if let Some(key) = self.selection.selected_key() {
-                    let link = ctx.link();
-                    link.clone().spawn(async move {
-                        if let Err(err) = delete_item(key).await {
-                            link.show_error(tr!("Unable to delete item"), err, true);
-                        }
-                        link.send_reload();
-                    })
-                }
-                false
-            }
-        }
-    }
-
-    fn toolbar(&self, ctx: &LoadableComponentContext<Self>) -> Option<Html> {
-        let link = ctx.link();
-
-        let disabled = self.selection.is_empty();
-
-        let toolbar = Toolbar::new()
-            .class("pwt-overflow-hidden")
-            .class("pwt-border-bottom")
-            .with_child({
-                Button::new(tr!("Add Proxmox VE"))
-                    .icon_class("fa fa-building")
-                    .onclick(link.change_view_callback(|_| Some(ViewState::Add(RemoteType::Pve))))
-                // FIXME: add PBS support
-                //MenuButton::new(tr!("Add")).show_arrow(true).menu(
-                //    Menu::new()
-                //        .with_item(
-                //            MenuItem::new("Proxmox VE")
-                //                .icon_class("fa fa-building")
-                //                .on_select(link.change_view_callback(|_| {
-                //                    Some(ViewState::Add(RemoteType::Pve))
-                //                })),
-                //        )
-                //        .with_item(
-                //            MenuItem::new("Proxmox Backup Server")
-                //                .icon_class("fa fa-floppy-o")
-                //                .on_select(link.change_view_callback(|_| {
-                //                    Some(ViewState::Add(RemoteType::Pbs))
-                //                })),
-                //        ),
-                //)
-            })
-            .with_spacer()
-            .with_child(
-                Button::new(tr!("Edit"))
-                    .disabled(disabled)
-                    .onclick(link.change_view_callback(|_| Some(ViewState::Edit))),
-            )
-            .with_child(
-                ConfirmButton::new(tr!("Remove"))
-                    .confirm_message(tr!("Are you sure you want to remove this remote?"))
-                    .disabled(disabled)
-                    .on_activate(link.callback(|_| Msg::RemoveItem)),
-            )
-            .with_flex_spacer()
-            .with_child({
-                let loading = ctx.loading();
-                let link = ctx.link();
-                Button::refresh(loading).onclick(move |_| link.send_reload())
-            });
-
-        Some(toolbar.into())
-    }
-
-    fn main_view(&self, ctx: &LoadableComponentContext<Self>) -> Html {
-        let columns = Rc::clone(&self.remote_list_columns);
-        let link = ctx.link();
-        DataTable::new(columns, self.store.clone())
-            .class(pwt::css::FlexFit)
-            .selection(self.selection.clone())
-            .on_row_dblclick(move |_: &mut _| {
-                link.change_view(Some(ViewState::Edit));
-            })
-            .into()
-    }
-
-    fn dialog_view(
-        &self,
-        ctx: &LoadableComponentContext<Self>,
-        view_state: &Self::ViewState,
-    ) -> Option<Html> {
-        match view_state {
-            ViewState::Add(ty) => Some(self.create_add_dialog(ctx, *ty)),
-            ViewState::Edit => self
-                .selection
-                .selected_key()
-                .map(|key| self.create_edit_dialog(ctx, key)),
-        }
-    }
-}
-
-/*
-fn add_remote_input_panel(_form_ctx: &FormContext) -> Html {
-    InputPanel::new()
-        .padding(4)
-        .with_field(tr!("Remote ID"), Field::new().name("id").required(true))
-        .with_right_field(
-            tr!("Fingerprint"),
-            Field::new()
-                .name("fingerprint")
-                .schema(&CERT_FINGERPRINT_SHA256_SCHEMA),
-        )
-        .with_field(
-            tr!("Server address"),
-            Field::new().name("server").required(true),
-        )
-        .with_field(
-            tr!("User/Token"),
-            Field::new()
-                .name("authid")
-                .schema(&pdm_api_types::Authid::API_SCHEMA)
-                .required(true),
-        )
-        .with_field(
-            tr!("Password/Secret"),
-            Field::new()
-                .name("token")
-                .input_type(InputType::Password)
-                .required(true),
-        )
-        .into()
-}
-*/
-
-impl PbsRemoteConfigPanel {
-    fn create_add_dialog(
-        &self,
-        ctx: &LoadableComponentContext<Self>,
-        remote_type: RemoteType,
-    ) -> Html {
-        AddWizard::new(remote_type)
-            .on_close(ctx.link().change_view_callback(|_| None))
-            .on_submit(move |ctx| create_remote(ctx, remote_type))
-            .into()
-
-        // EditWindow::new(tr!("Add") + ": " + &tr!("Remote"))
-        //     .renderer(add_remote_input_panel)
-        //     .on_submit(move |ctx: FormContext| create_item(ctx.get_submit_data(), remote_type))
-        //     .on_done(ctx.link().change_view_callback(|_| None))
-        //     .into()
-    }
-
-    fn create_edit_dialog(&self, ctx: &LoadableComponentContext<Self>, key: Key) -> Html {
-        EditRemote::new(&*key)
-            .on_done(ctx.link().change_view_callback(|_| None))
-            .into()
-    }
-}
-
-impl Into<VNode> for RemoteConfigPanel {
-    fn into(self) -> VNode {
-        let comp = VComp::new::<LoadableComponentMaster<PbsRemoteConfigPanel>>(Rc::new(self), None);
-        VNode::from(comp)
-    }
-}
-
-fn remote_list_columns() -> Rc<Vec<DataTableHeader<Remote>>> {
-    Rc::new(vec![
-        DataTableColumn::new(tr!("Remote ID"))
-            .width("200px")
-            .render(|item: &Remote| {
-                html! {
-                    &item.id
-                }
-            })
-            .sorter(|a: &Remote, b: &Remote| a.id.cmp(&b.id))
-            .sort_order(true)
-            .into(),
-        DataTableColumn::new(tr!("Type"))
-            .width("60px")
-            .render(|item: &Remote| {
-                html! {
-                    &item.ty
-                }
-            })
-            .sorter(|a: &Remote, b: &Remote| a.ty.cmp(&b.ty))
-            .into(),
-        DataTableColumn::new(tr!("AuthId"))
-            .width("200px")
-            .render(|item: &Remote| {
-                html! {
-                    &item.authid
-                }
-            })
-            .sorter(|a: &Remote, b: &Remote| a.authid.cmp(&b.authid))
-            .into(),
-        DataTableColumn::new(tr!("Nodes"))
-            .flex(1)
-            .render(|item: &Remote| {
-                if item.nodes.is_empty() {
-                    html! {tr!("None")}
-                } else {
-                    let nodes = item
-                        .nodes
-                        .iter()
-                        .map(|n| n.hostname.as_str())
-                        .collect::<Vec<_>>()
-                        .join(", ");
-                    let mut tip = Column::new();
-                    tip.add_children(item.nodes.iter().map(|n| {
-                        let text = match n.fingerprint.clone() {
-                            Some(fp) => format!("{} ({fp})", n.hostname),
-                            None => n.hostname.to_string(),
-                        };
-                        html! {<div>{text}</div>}
-                    }));
-                    Tooltip::new(nodes).rich_tip(tip).into()
-                }
-            })
-            .into(),
-        /*
-        DataTableColumn::new(tr!("Auth ID"))
-            .width("200px")
-            .render(|item: &Remote| html!{
-                item.config.auth_id.clone()
-            })
-            .sorter(|a: &Remote, b: &Remote| {
-                a.config.auth_id.cmp(&b.config.auth_id)
-            })
-            .into(),
-
-        DataTableColumn::new(tr!("Fingerprint"))
-            .width("200px")
-            .render(|item: &Remote| html!{
-                item.config.fingerprint.clone().unwrap_or(String::new())
-            })
-            .into(),
-
-        DataTableColumn::new(tr!("Comment"))
-            .flex(1)
-            .render(|item: &Remote| html!{
-                item.config.comment.clone().unwrap_or(String::new())
-            })
-            .into()
-            */
-    ])
-}
+mod config;
+pub use config::{create_remote, RemoteConfigPanel};
-- 
2.39.5



_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


  parent reply	other threads:[~2025-01-20  9:30 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-20  9:29 [pdm-devel] [PATCH yew-comp/datacenter-manager] ui: implement remote task list Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 1/7] tasks: make date filter functional Dominik Csapak
2025-01-20 11:30   ` Thomas Lamprecht
2025-01-20 12:10     ` Dominik Csapak
2025-01-21  8:33       ` Thomas Lamprecht
2025-01-21  9:46         ` Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 2/7] tasks: load more tasks on end of list Dominik Csapak
2025-01-20 17:29   ` Thomas Lamprecht
2025-01-21  9:43     ` Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 3/7] utils: factor out task description into own function Dominik Csapak
2025-01-20 17:29   ` Thomas Lamprecht
2025-01-21  9:44     ` Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 4/7] running tasks: make TaskListItem renderer configurable Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 5/7] running tasks: make buttons configurable Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 6/7] tasks: make columns configurable Dominik Csapak
2025-01-20 17:37   ` Thomas Lamprecht
2025-01-20  9:29 ` [pdm-devel] [PATCH yew-comp 7/7] tasks: make the 'show task' action configurable Dominik Csapak
2025-01-20  9:29 ` [pdm-devel] [PATCH datacenter-manager 1/9] server: factor out task filters into `TaskFilters` type Dominik Csapak
2025-01-20 17:42   ` Thomas Lamprecht
2025-01-20  9:29 ` [pdm-devel] [PATCH datacenter-manager 2/9] server: task cache: skip remotes with errors on fetch Dominik Csapak
2025-01-20 17:45   ` Thomas Lamprecht
2025-01-21  8:29     ` Dietmar Maurer
2025-01-20  9:30 ` [pdm-devel] [PATCH datacenter-manager 3/9] server: task cache: add filter options Dominik Csapak
2025-01-20  9:30 ` [pdm-devel] [PATCH datacenter-manager 4/9] server: task cache: reverse task order Dominik Csapak
2025-01-20  9:30 ` [pdm-devel] [PATCH datacenter-manager 5/9] pdm-client: export PveUpid Dominik Csapak
2025-01-20  9:30 ` Dominik Csapak [this message]
2025-01-20  9:30 ` [pdm-devel] [PATCH datacenter-manager 7/9] ui: remotes: add tasks to global remote panel Dominik Csapak
2025-01-20  9:30 ` [pdm-devel] [PATCH datacenter-manager 8/9] ui: register pve tasks Dominik Csapak
2025-01-20  9:30 ` [pdm-devel] [PATCH datacenter-manager 9/9] ui: also show running remote tasks in 'running tasks' list Dominik Csapak
2025-01-20 11:27 ` [pdm-devel] applied: [PATCH yew-comp/datacenter-manager] ui: implement remote task list Dietmar Maurer
2025-01-20 11:34   ` Thomas Lamprecht
2025-01-21  8:41 ` [pdm-devel] " Lukas Wagner

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=20250120093006.927014-14-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=pdm-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