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
next prev 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