public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [PATCH datacenter-manager v2 1/4] lib/api/ui: add location property to remote config
Date: Tue,  5 May 2026 09:31:56 +0200	[thread overview]
Message-ID: <20260505073203.398548-6-d.csapak@proxmox.com> (raw)
In-Reply-To: <20260505073203.398548-1-d.csapak@proxmox.com>

this will be used to show the remote on a map in a custom view.
Let's the user simply enter the longitude and latitude in the remote
edit window.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* use correct 'location' property for gui edit windows of remotes

 lib/pdm-api-types/src/remotes.rs | 22 +++++++++++++++++++++-
 server/src/api/pbs/mod.rs        |  2 ++
 server/src/api/pve/mod.rs        |  2 ++
 server/src/api/remotes/mod.rs    |  9 +++++++++
 ui/src/remotes/edit_remote.rs    | 30 +++++++++++++++++++++++++-----
 5 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/lib/pdm-api-types/src/remotes.rs b/lib/pdm-api-types/src/remotes.rs
index b226d190..d879fcfb 100644
--- a/lib/pdm-api-types/src/remotes.rs
+++ b/lib/pdm-api-types/src/remotes.rs
@@ -4,7 +4,7 @@ use http::Uri;
 use serde::{Deserialize, Serialize};
 
 use proxmox_schema::property_string::PropertyString;
-use proxmox_schema::{api, ApiType, Schema, StringSchema, Updater};
+use proxmox_schema::{api, ApiType, Schema, StringSchema, Updater, UpdaterType};
 use proxmox_section_config::typed::ApiSectionDataEntry;
 use proxmox_section_config::{SectionConfig, SectionConfigPlugin};
 
@@ -66,6 +66,17 @@ impl RemoteType {
 serde_plain::derive_display_from_serialize!(RemoteType);
 serde_plain::derive_fromstr_from_deserialize!(RemoteType);
 
+#[api]
+#[derive(Clone, Debug, Deserialize, Serialize, UpdaterType, PartialEq)]
+#[serde(rename_all = "kebab-case")]
+/// A location using the geographic coordinate system.
+pub struct RemoteLocation {
+    /// The latitude of the remote location.
+    pub latitude: f64,
+    /// The longitude of the remote location.
+    pub longitude: f64,
+}
+
 #[api(
     properties: {
         "id": { schema: REMOTE_ID_SCHEMA },
@@ -81,6 +92,10 @@ serde_plain::derive_fromstr_from_deserialize!(RemoteType);
             type: String,
             optional: true,
         },
+        "location": {
+            type: String,
+            optional: true,
+        },
     },
 )]
 /// The information required to connect to a remote instance.
@@ -120,6 +135,11 @@ pub struct Remote {
         skip_serializing_if = "Option::is_none"
     )]
     pub web_url: Option<Uri>,
+
+    /// The remotes physical location
+    #[updater(serde(skip_serializing_if = "Option::is_none"))]
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub location: Option<PropertyString<RemoteLocation>>,
 }
 
 impl ApiSectionDataEntry for Remote {
diff --git a/server/src/api/pbs/mod.rs b/server/src/api/pbs/mod.rs
index 32e6bf84..50161488 100644
--- a/server/src/api/pbs/mod.rs
+++ b/server/src/api/pbs/mod.rs
@@ -275,6 +275,7 @@ pub async fn scan_remote_pbs(
         authid: authid.clone(),
         token,
         web_url: None,
+        location: None,
     };
 
     let _client = connect_or_login(&remote)
@@ -327,6 +328,7 @@ pub async fn list_realm_remote_pbs(
         authid: "root@pam".parse()?,
         token: String::new(),
         web_url: None,
+        location: None,
     };
 
     let client = connection::make_pbs_client(&remote)?;
diff --git a/server/src/api/pve/mod.rs b/server/src/api/pve/mod.rs
index 20892f38..96aaf80d 100644
--- a/server/src/api/pve/mod.rs
+++ b/server/src/api/pve/mod.rs
@@ -460,6 +460,7 @@ pub async fn scan_remote_pve(
         authid: authid.clone(),
         token,
         web_url: None,
+        location: None,
     };
 
     let client = connect_or_login(&remote)
@@ -551,6 +552,7 @@ pub async fn list_realm_remote_pve(
         authid: "root@pam".parse()?,
         token: String::new(),
         web_url: None,
+        location: None,
     };
 
     let client = connection::make_pve_client(&remote)?;
diff --git a/server/src/api/remotes/mod.rs b/server/src/api/remotes/mod.rs
index a91ec97d..69a4e3af 100644
--- a/server/src/api/remotes/mod.rs
+++ b/server/src/api/remotes/mod.rs
@@ -340,6 +340,8 @@ pub async fn add_remote(mut entry: Remote, create_token: Option<String>) -> Resu
 pub enum DeletableProperty {
     /// Delete the web-url property.
     WebUrl,
+    /// Delete the location property.
+    Location,
 }
 
 // FIXME: Support `OneOf` in schema so we can use a derived Updater for all product types?
@@ -390,6 +392,9 @@ pub fn update_remote(
                 DeletableProperty::WebUrl => {
                     entry.web_url = None;
                 }
+                DeletableProperty::Location => {
+                    entry.location = None;
+                }
             }
         }
     }
@@ -408,6 +413,10 @@ pub fn update_remote(
         entry.web_url = updater.web_url;
     }
 
+    if updater.location.is_some() {
+        entry.location = updater.location;
+    }
+
     pdm_config::remotes::save_config(remotes)?;
 
     Ok(())
diff --git a/ui/src/remotes/edit_remote.rs b/ui/src/remotes/edit_remote.rs
index 925d11ad..99bc6c1a 100644
--- a/ui/src/remotes/edit_remote.rs
+++ b/ui/src/remotes/edit_remote.rs
@@ -7,10 +7,12 @@ use yew::virtual_dom::{VComp, VNode};
 
 use pwt::css::FlexFit;
 use pwt::prelude::*;
-use pwt::widget::form::{DisplayField, Field, FormContext, InputType};
+use pwt::widget::form::{DisplayField, Field, FormContext, InputType, Number};
 use pwt::widget::{Container, InputPanel};
 
-use proxmox_yew_comp::form::delete_empty_values;
+use proxmox_yew_comp::form::{
+    delete_empty_values, flatten_property_string, property_string_from_parts,
+};
 use proxmox_yew_comp::percent_encoding::percent_encode_component;
 use proxmox_yew_comp::{EditWindow, SchemaValidation};
 
@@ -21,6 +23,8 @@ use super::NodeUrlList;
 
 use pwt_macros::builder;
 
+use pdm_api_types::remotes::RemoteLocation;
+
 #[derive(PartialEq, Properties)]
 #[builder]
 pub struct EditRemote {
@@ -42,7 +46,13 @@ impl EditRemote {
 pub struct PdmEditRemote {}
 
 async fn load_remote(url: AttrValue) -> Result<ApiResponseData<Value>, Error> {
-    proxmox_yew_comp::http_get_full(&*url, None).await
+    let mut res = proxmox_yew_comp::http_get_full(&*url, None).await;
+
+    if let Ok(data) = res.as_mut() {
+        flatten_property_string::<RemoteLocation>(&mut data.data, "location")?;
+    }
+
+    res
 }
 
 impl Component for PdmEditRemote {
@@ -76,9 +86,11 @@ impl Component for PdmEditRemote {
                 move |form_ctx: FormContext| {
                     let url = url.clone();
                     async move {
-                        let data = form_ctx.get_submit_data();
+                        let mut data = form_ctx.get_submit_data();
+
+                        property_string_from_parts::<RemoteLocation>(&mut data, "location", true)?;
 
-                        let data = delete_empty_values(&data, &["web-url"], true);
+                        let data = delete_empty_values(&data, &["web-url", "location"], true);
 
                         proxmox_yew_comp::http_put(&url, Some(data)).await
                     }
@@ -120,6 +132,14 @@ fn edit_remote_input_panel(_form_ctx: &FormContext, remote_id: &str) -> Html {
                 .name("web-url")
                 .placeholder(tr!("Use first endpoint.")),
         )
+        .with_field(
+            tr!("Location Latitude"),
+            Number::new().name("_lat").min(-90.0).max(90.0),
+        )
+        .with_field(
+            tr!("Location Longitude"),
+            Number::new().name("_long").min(-180.0).max(180.0),
+        )
         .with_custom_child(
             Container::new()
                 .key("nodes-title")
-- 
2.47.3





  parent reply	other threads:[~2026-05-05  7:32 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-05  7:31 [PATCH datacenter-manager/yew-widget-toolkit/yew-widget-toolkit-assets v2 0/8] add a new map widget for custom views Dominik Csapak
2026-05-05  7:31 ` [PATCH yew-widget-toolkit v2 1/3] js-helper: add client-to-svg-coordinate conversion helper Dominik Csapak
2026-05-05  7:31 ` [PATCH yew-widget-toolkit v2 2/3] widget: charts: add interactive Map with zoom/pan and clustering Dominik Csapak
2026-05-05  7:31 ` [PATCH yew-widget-toolkit v2 3/3] widget: charts: add WorldMap with GeoJSON rendering Dominik Csapak
2026-05-05  7:31 ` [PATCH yew-widget-toolkit-assets v2 1/1] charts: add necessary classes for Map Dominik Csapak
2026-05-05  7:31 ` Dominik Csapak [this message]
2026-05-05  8:26   ` [PATCH datacenter-manager v2 1/4] lib/api/ui: add location property to remote config Thomas Lamprecht
2026-05-05  8:36     ` Dominik Csapak
2026-05-05  8:44       ` Thomas Lamprecht
2026-05-05  8:46         ` Dominik Csapak
2026-05-05  7:31 ` [PATCH datacenter-manager v2 2/4] lib/api: add new 'remote-list' info to the resource status Dominik Csapak
2026-05-05  7:31 ` [PATCH datacenter-manager v2 3/4] ui: add world map geojson update script Dominik Csapak
2026-05-05  7:31 ` [PATCH datacenter-manager v2 4/4] ui: views: add map component Dominik Csapak

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=20260505073203.398548-6-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 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