public inbox for yew-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: yew-devel@lists.proxmox.com
Subject: [yew-devel] [RFC PATCH yew-comp 2/2] syslog: use new DateField for selecting the date
Date: Wed, 17 Dec 2025 12:10:51 +0100	[thread overview]
Message-ID: <20251217111205.1400585-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20251217111205.1400585-1-d.csapak@proxmox.com>

The native browser date/datetime-local interface is rather bad on
desktop, so using our own here is much better ux.

We currently only have a 'date' field, so use a separate field for the
time (browser native time input).

In the future we can replace both again with a single date time selector
when we implement one.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
sending as rfc because we might want to wait with this change until we
have a datetime selector, not sure when that will arrive though.

In the meantime the usability of this is still better than before.

 src/syslog.rs | 140 +++++++++++++++++++++++---------------------------
 1 file changed, 64 insertions(+), 76 deletions(-)

diff --git a/src/syslog.rs b/src/syslog.rs
index 5635c22..ecca15e 100644
--- a/src/syslog.rs
+++ b/src/syslog.rs
@@ -1,6 +1,8 @@
 use std::rc::Rc;
 
-use pwt::widget::form::InputType;
+use js_sys::Date;
+
+use pwt::widget::form::{DateField, InputType, PlainDate};
 use pwt::widget::{Button, Container, Row, SegmentedButton};
 use yew::html::IntoPropValue;
 use yew::virtual_dom::{VComp, VNode};
@@ -46,40 +48,34 @@ impl Syslog {
 pub enum Msg {
     ChangeMode(bool),
     LoadingChange((usize, bool)),
-    Since(String),
-    Until(String),
+    SinceDate(Option<PlainDate>),
+    SinceTime(String),
+    UntilDate(Option<PlainDate>),
+    UntilTime(String),
 }
 
 pub struct ProxmoxSyslog {
     active: bool,
-    since: js_sys::Date,
+    since: PlainDate,
+    since_time: String,
     since_label_id: AttrValue,
-    until: js_sys::Date,
+    until: PlainDate,
+    until_time: String,
     until_label_id: AttrValue,
     pending: bool,
 }
 
-fn date_to_input_value(date: &js_sys::Date) -> String {
-    if date.get_date() == 0 {
-        // invalid data (clear field creates this)
-        String::new()
-    } else {
-        format!(
-            "{:04}-{:02}-{:02}T{:02}:{:02}",
-            date.get_full_year(),
-            date.get_month() + 1,
-            date.get_date(),
-            date.get_hours(),
-            date.get_minutes(),
-        )
-    }
+fn date_time_to_epoch(date: &PlainDate, time: &str) -> Option<i64> {
+    let (hours, minutes) = time.split_once(':')?;
+    let d = date.to_date();
+    d.set_hours(hours.parse().ok()?);
+    d.set_minutes(minutes.parse().ok()?);
+    let res = d.get_time() / 1000.0;
+    res.is_finite().then_some(res.round() as i64)
 }
 
 impl ProxmoxSyslog {
     fn create_toolbar(&self, ctx: &Context<Self>) -> Html {
-        let since = date_to_input_value(&self.since);
-        let until = date_to_input_value(&self.until);
-
         Toolbar::new()
             .with_optional_child(
                 self.pending.then_some(
@@ -117,14 +113,23 @@ impl ProxmoxSyslog {
             )
             .with_child(
                 Container::new().with_child(
-                    Field::new()
+                    DateField::new()
                         .label_id(self.since_label_id.clone())
-                        .input_type(InputType::DatetimeLocal)
+                        .required(true)
+                        .disabled(self.active)
+                        .on_change(ctx.link().callback(Msg::SinceDate))
+                        .value(self.since.to_string()),
+                ),
+            )
+            .with_child(
+                Container::new().with_child(
+                    Field::new()
+                        .input_type(InputType::Time)
                         .required(true) // avoid clear button in firefox
                         .disabled(self.active)
                         .class("pwt-input-hide-clear-button")
-                        .on_change(ctx.link().callback(Msg::Since))
-                        .value(since),
+                        .on_change(ctx.link().callback(Msg::SinceTime))
+                        .value(self.since_time.to_string()),
                 ),
             )
             .with_child(
@@ -135,15 +140,25 @@ impl ProxmoxSyslog {
                     .class(self.active.then_some("pwt-label-disabled"))
                     .with_child("Until:"),
             )
+            .with_child(
+                Container::new().with_child(
+                    DateField::new()
+                        .label_id(self.until_label_id.clone())
+                        .required(true) // avoid clear button in firefox
+                        .disabled(self.active)
+                        .on_change(ctx.link().callback(Msg::UntilDate))
+                        .value(self.until.to_string()),
+                ),
+            )
             .with_child(
                 Container::new().with_child(
                     Field::new()
                         .label_id(self.until_label_id.clone())
-                        .input_type(InputType::DatetimeLocal)
+                        .input_type(InputType::Time)
                         .required(true) // avoid clear button in firefox
                         .disabled(self.active)
-                        .on_change(ctx.link().callback(Msg::Until))
-                        .value(until),
+                        .on_change(ctx.link().callback(Msg::UntilTime))
+                        .value(self.until_time.to_string()),
                 ),
             )
             .border_bottom(true)
@@ -159,26 +174,12 @@ impl ProxmoxSyslog {
                 }))
                 .into()
         } else {
-            let since = if self.since.get_date() == 0 {
-                // invalid data (clear field creates this)
-                get_default_since()
-            } else {
-                self.since.clone()
-            };
-
-            let until = if self.until.get_date() == 0 {
-                // invalid data (clear field creates this)
-                None
-            } else {
-                Some((self.until.get_time() / 1000.0) as i64)
-            };
-
             LogView::new(props.base_url.clone())
                 .padding(2)
                 .class("pwt-flex-fill")
                 .service(props.service.clone())
-                .since((since.get_time() / 1000.0) as i64)
-                .until(until)
+                .since(date_time_to_epoch(&self.since, &self.since_time))
+                .until(date_time_to_epoch(&self.until, &self.until_time))
                 .active(false)
                 .on_pending_change(ctx.link().callback(Msg::LoadingChange))
                 .into()
@@ -186,27 +187,6 @@ impl ProxmoxSyslog {
     }
 }
 
-fn get_default_since() -> js_sys::Date {
-    let since = js_sys::Date::new_0();
-
-    since.set_hours(0);
-    since.set_minutes(0);
-    since.set_seconds(0);
-    since.set_milliseconds(0);
-
-    since
-}
-
-fn get_default_until() -> js_sys::Date {
-    let until = js_sys::Date::new_0();
-
-    until.set_hours(23);
-    until.set_minutes(59);
-    until.set_seconds(59);
-    until.set_milliseconds(999);
-
-    until
-}
 impl Component for ProxmoxSyslog {
     type Message = Msg;
     type Properties = Syslog;
@@ -214,9 +194,11 @@ impl Component for ProxmoxSyslog {
     fn create(_ctx: &Context<Self>) -> Self {
         Self {
             active: true,
-            since: get_default_since(),
+            since: PlainDate::today(),
+            since_time: "00:00".to_string(),
             since_label_id: AttrValue::from(pwt::widget::get_unique_element_id()),
-            until: get_default_until(),
+            until: PlainDate::today(),
+            until_time: "23:59".to_string(),
             until_label_id: AttrValue::from(pwt::widget::get_unique_element_id()),
             pending: false,
         }
@@ -224,16 +206,22 @@ impl Component for ProxmoxSyslog {
 
     fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
         match msg {
-            Msg::Since(datetime) => {
-                let since = js_sys::Date::parse(&datetime);
-                let since = js_sys::Date::new(&since.into());
-                self.since = since;
+            Msg::SinceDate(Some(date)) => {
+                self.since = date;
+                true
+            }
+            Msg::SinceDate(None) => false,
+            Msg::SinceTime(time) => {
+                self.since_time = time;
+                true
+            }
+            Msg::UntilDate(Some(date)) => {
+                self.until = date;
                 true
             }
-            Msg::Until(datetime) => {
-                let until = js_sys::Date::parse(&datetime);
-                let until = js_sys::Date::new(&until.into());
-                self.until = until;
+            Msg::UntilDate(None) => false,
+            Msg::UntilTime(time) => {
+                self.until_time = time;
                 true
             }
             Msg::LoadingChange((num, tail_view)) => {
-- 
2.47.3



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


  reply	other threads:[~2025-12-17 11:11 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-17 11:10 [yew-devel] [PATCH yew-comp 1/2] syslog: fix toolbar spacing Dominik Csapak
2025-12-17 11:10 ` Dominik Csapak [this message]
2025-12-17 11:34 ` [yew-devel] applied: " Dietmar Maurer

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=20251217111205.1400585-2-d.csapak@proxmox.com \
    --to=d.csapak@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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal