From 5f9362f2451e7d07700bf7f817f2fa6ac0181b3c Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 27 Oct 2023 13:30:44 -0600 Subject: [PATCH 01/12] Added the dateinput widget for toga/web --- web/src/toga_web/widgets/dateinput.py | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 web/src/toga_web/widgets/dateinput.py diff --git a/web/src/toga_web/widgets/dateinput.py b/web/src/toga_web/widgets/dateinput.py new file mode 100644 index 0000000000..e265d33dca --- /dev/null +++ b/web/src/toga_web/widgets/dateinput.py @@ -0,0 +1,31 @@ +from toga_web.libs import create_proxy + +from .base import Widget + + +class DateInput(Widget): + def create(self): + self._return_listener = None + self.native = self._create_native_widget("sl-input") + self.native.setAttribute("type", "date") + self.native.addEventListener("sl-change", create_proxy(self.dom_onchange)) + + def set_value(self, value): + self.native.value = value + + def dom_onchange(self, event): + self.interface.on_change(None) + + def get_min_date(self): + return self.native.min + + def get_max_date(self): + return self.native.max + + def set_min_date(self, value): + # you might have to + self.native.min = value + + def set_max_date(self, value): + # you might have to + self.native.max = value From e06a1d8243622b487fb8a5b857378a100b3645ee Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 27 Oct 2023 13:39:11 -0600 Subject: [PATCH 02/12] Added date input to the toga web factory --- web/src/toga_web/factory.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/src/toga_web/factory.py b/web/src/toga_web/factory.py index 153c845462..777716ed79 100644 --- a/web/src/toga_web/factory.py +++ b/web/src/toga_web/factory.py @@ -11,6 +11,7 @@ from .widgets.activityindicator import ActivityIndicator from .widgets.box import Box from .widgets.button import Button +from .widgets.dateinput import DateInput from .widgets.divider import Divider # from .widgets.canvas import Canvas @@ -59,6 +60,7 @@ def not_implemented(feature): "Box", "Button", # 'Canvas', + "DateInput", "Divider", # 'DetailedList', # 'ImageView', From 0ebfe94d8c113cee76211ffeeadca53f0957291a Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 27 Oct 2023 13:45:28 -0600 Subject: [PATCH 03/12] Added change description --- changes/2176.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/2176.feature.rst diff --git a/changes/2176.feature.rst b/changes/2176.feature.rst new file mode 100644 index 0000000000..8c32cccd8d --- /dev/null +++ b/changes/2176.feature.rst @@ -0,0 +1 @@ +Added the DateInput widget to the toga web project. From 2d6a61dcc10dd1bd780076943d034db4a2a96e91 Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 27 Oct 2023 13:53:48 -0600 Subject: [PATCH 04/12] Added the a documentation note for partial functionality for toga web date input widget --- docs/reference/data/widgets_by_platform.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/data/widgets_by_platform.csv b/docs/reference/data/widgets_by_platform.csv index 923ffbd4e2..ca5d10cadf 100644 --- a/docs/reference/data/widgets_by_platform.csv +++ b/docs/reference/data/widgets_by_platform.csv @@ -5,7 +5,7 @@ MainWindow,Core Component,:class:`~toga.MainWindow`,The main window of the appli ActivityIndicator,General Widget,:class:`~toga.ActivityIndicator`,A spinning activity animation,|y|,|y|,,,,|b|, Button,General Widget,:class:`~toga.Button`,Basic clickable Button,|y|,|y|,|y|,|y|,|y|,|b|,|b| Canvas,General Widget,:class:`~toga.Canvas`,A drawing area for 2D vector graphics.,|y|,|y|,|y|,|y|,|y|,, -DateInput,General Widget,:class:`~toga.DateInput`,A widget to select a calendar date,,,|y|,,|y|,, +DateInput,General Widget,:class:`~toga.DateInput`,A widget to select a calendar date,,,|y|,,|y|,|b|, DetailedList,General Widget,:class:`~toga.DetailedList`,"An ordered list of content where each item has an icon, a main heading, and a line of supplementary text.",|y|,|y|,|b|,|y|,|y|,, Divider,General Widget,:class:`~toga.Divider`,A horizontal or vertical line,|y|,|y|,|y|,,,|b|, ImageView,General Widget,:class:`~toga.ImageView`,A widget that displays an image,|y|,|y|,|y|,|y|,|y|,, From 8e915a54432f1b993ba1e22c1a90ffd072698930 Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Tue, 31 Oct 2023 12:16:25 -0600 Subject: [PATCH 05/12] Made changes to dateinput to make it workable --- web/src/toga_web/widgets/dateinput.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/web/src/toga_web/widgets/dateinput.py b/web/src/toga_web/widgets/dateinput.py index e265d33dca..57905e4844 100644 --- a/web/src/toga_web/widgets/dateinput.py +++ b/web/src/toga_web/widgets/dateinput.py @@ -1,31 +1,45 @@ +import datetime + from toga_web.libs import create_proxy from .base import Widget +def py_date(native_date): + return datetime.datetime.strptime(native_date, "%m/%d/%y").date() + + class DateInput(Widget): def create(self): self._return_listener = None self.native = self._create_native_widget("sl-input") self.native.setAttribute("type", "date") - self.native.addEventListener("sl-change", create_proxy(self.dom_onchange)) + self.set_value(datetime.date.today().strftime("%m/%d/%y")) + self.native.addEventListener("sl-change", create_proxy(self.on_change)) + + def get_value(self): + return py_date(self.native.value) def set_value(self, value): + if value is None: + self.native.value = "" self.native.value = value - def dom_onchange(self, event): + def on_change(self, event): self.interface.on_change(None) def get_min_date(self): - return self.native.min + if self.native.min: + return self.native.min + return datetime.date(1800, 1, 1) def get_max_date(self): - return self.native.max + if self.native.max: + return self.native.max + return datetime.date(8999, 12, 31) def set_min_date(self, value): - # you might have to self.native.min = value def set_max_date(self, value): - # you might have to self.native.max = value From e893f3b0df5ed596e5c73ae2f391fa357c204a6f Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Tue, 31 Oct 2023 17:14:07 -0600 Subject: [PATCH 06/12] Added native date with manual testing --- web/src/toga_web/widgets/dateinput.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/web/src/toga_web/widgets/dateinput.py b/web/src/toga_web/widgets/dateinput.py index 57905e4844..cbd263611e 100644 --- a/web/src/toga_web/widgets/dateinput.py +++ b/web/src/toga_web/widgets/dateinput.py @@ -6,7 +6,11 @@ def py_date(native_date): - return datetime.datetime.strptime(native_date, "%m/%d/%y").date() + return datetime.datetime.strptime(native_date, "%Y-%m-%d").date() + + +def native_date(py_date): + return py_date.strftime("%Y-%m-%d") class DateInput(Widget): @@ -14,7 +18,8 @@ def create(self): self._return_listener = None self.native = self._create_native_widget("sl-input") self.native.setAttribute("type", "date") - self.set_value(datetime.date.today().strftime("%m/%d/%y")) + + self.set_value(datetime.date.today().strftime("%Y-%m-%d")) self.native.addEventListener("sl-change", create_proxy(self.on_change)) def get_value(self): @@ -30,16 +35,16 @@ def on_change(self, event): def get_min_date(self): if self.native.min: - return self.native.min + return py_date(self.native.min) return datetime.date(1800, 1, 1) def get_max_date(self): if self.native.max: - return self.native.max + return py_date(self.native.max) return datetime.date(8999, 12, 31) def set_min_date(self, value): - self.native.min = value + self.native.min = native_date(value) def set_max_date(self, value): - self.native.max = value + self.native.max = native_date(value) From 84d80fdede2985cbcb6818527ca205fce79091dc Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Wed, 1 Nov 2023 11:04:36 -0600 Subject: [PATCH 07/12] Added time input component, in progress --- web/src/toga_web/factory.py | 2 ++ web/src/toga_web/widgets/timeinput.py | 50 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 web/src/toga_web/widgets/timeinput.py diff --git a/web/src/toga_web/factory.py b/web/src/toga_web/factory.py index 777716ed79..c30bb2ba1e 100644 --- a/web/src/toga_web/factory.py +++ b/web/src/toga_web/factory.py @@ -33,6 +33,7 @@ # from .widgets.table import Table from .widgets.textinput import TextInput +from .widgets.timeinput import TimeInput # from .widgets.tree import Tree # from .widgets.webview import WebView @@ -78,6 +79,7 @@ def not_implemented(feature): "Switch", # 'Table', "TextInput", + "TimeInput", # 'Tree', # 'WebView', # 'Window', diff --git a/web/src/toga_web/widgets/timeinput.py b/web/src/toga_web/widgets/timeinput.py new file mode 100644 index 0000000000..91cde435f5 --- /dev/null +++ b/web/src/toga_web/widgets/timeinput.py @@ -0,0 +1,50 @@ +import datetime + +from toga_web.libs import create_proxy + +from .base import Widget + + +def py_time(native_time): + return datetime.time.fromisoformat(native_time) + + +def native_time(py_time): + return py_time.strftime("%H:%M") + + +class TimeInput(Widget): + def create(self): + self._return_listener = None + self.native = self._create_native_widget("sl-input") + self.native.setAttribute("type", "time") + + self.set_value(datetime.datetime.now().time().strftime("%H:%M")) + self.native.addEventListener("sl-change", create_proxy(self.on_change)) + + def on_change(self, event): + self.interface.on_change(None) + + def get_value(self): + return py_time(self.native.value) + + def set_value(self, value): + if value is None: + self.native.value = "" + self.native.value = value + + def set_min_time(self, value): + self.native.min = native_time(value) + + def set_max_time(self, value): + self.native.max = native_time(value) + + def get_min_time(self): + if self.native.min: + return py_time(self.native.min) + return datetime.time(0, 0, 0) + + def get_max_time(self): + if self.native.max: + return py_time(self.native.max) + return datetime.time(23, 59, 59) From 308cc1e4c02eb8b3e7f8a183d19ab96522827267 Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 3 Nov 2023 09:44:23 -0600 Subject: [PATCH 08/12] Added toga web time component --- web/src/toga_web/widgets/timeinput.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/web/src/toga_web/widgets/timeinput.py b/web/src/toga_web/widgets/timeinput.py index 91cde435f5..03776a9bf9 100644 --- a/web/src/toga_web/widgets/timeinput.py +++ b/web/src/toga_web/widgets/timeinput.py @@ -20,6 +20,8 @@ def create(self): self.native.setAttribute("type", "time") self.set_value(datetime.datetime.now().time().strftime("%H:%M")) + # self.set_value(datetime.time(0, 0, 0).strftime("%H:%M")) + # breakpoint() self.native.addEventListener("sl-change", create_proxy(self.on_change)) def on_change(self, event): @@ -31,13 +33,13 @@ def get_value(self): def set_value(self, value): if value is None: self.native.value = "" - self.native.value = value + self.native.value = self._format_time(value) def set_min_time(self, value): - self.native.min = native_time(value) + self.native.min = self._format_time(value) def set_max_time(self, value): - self.native.max = native_time(value) + self.native.max = self._format_time(value) def get_min_time(self): if self.native.min: @@ -48,3 +50,10 @@ def get_max_time(self): if self.native.max: return py_time(self.native.max) return datetime.time(23, 59, 59) + + def _format_time(self, value): + if isinstance(value, str): + value = native_time(py_time(value)) + if isinstance(value, datetime.time): + value = native_time(value) + return value From 6c1d45b2d144f505084ed7217b52ec0ac53c846c Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 3 Nov 2023 13:24:45 -0600 Subject: [PATCH 09/12] removed commented code --- web/src/toga_web/widgets/timeinput.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/toga_web/widgets/timeinput.py b/web/src/toga_web/widgets/timeinput.py index 03776a9bf9..791e2c3372 100644 --- a/web/src/toga_web/widgets/timeinput.py +++ b/web/src/toga_web/widgets/timeinput.py @@ -20,8 +20,6 @@ def create(self): self.native.setAttribute("type", "time") self.set_value(datetime.datetime.now().time().strftime("%H:%M")) - # self.set_value(datetime.time(0, 0, 0).strftime("%H:%M")) - # breakpoint() self.native.addEventListener("sl-change", create_proxy(self.on_change)) def on_change(self, event): From b52bc7ac91cf25c9a927dc59ff7b902175caf50f Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 3 Nov 2023 13:26:02 -0600 Subject: [PATCH 10/12] Modified changes to reflect adding of TimeInput --- changes/2176.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes/2176.feature.rst b/changes/2176.feature.rst index 8c32cccd8d..f0fbf5fa31 100644 --- a/changes/2176.feature.rst +++ b/changes/2176.feature.rst @@ -1 +1 @@ -Added the DateInput widget to the toga web project. +Added the DateInput and TimeInput widgets implementations to the toga web project. From 191d6e7e6a5205bb39592a386f6339bbc16f8811 Mon Sep 17 00:00:00 2001 From: dgmouris Date: Mon, 6 Nov 2023 15:34:44 -0700 Subject: [PATCH 11/12] Update changes/2176.feature.rst Co-authored-by: Russell Keith-Magee --- changes/2176.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes/2176.feature.rst b/changes/2176.feature.rst index f0fbf5fa31..52db43eb84 100644 --- a/changes/2176.feature.rst +++ b/changes/2176.feature.rst @@ -1 +1 @@ -Added the DateInput and TimeInput widgets implementations to the toga web project. +DateInput and TimeInput widgets were added to the Web backend. From df9d70e01c721e6571d28f047b24a387dc29ad85 Mon Sep 17 00:00:00 2001 From: Daniel Mouris Date: Fri, 10 Nov 2023 12:37:30 -0700 Subject: [PATCH 12/12] removed default date --- web/src/toga_web/widgets/dateinput.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/toga_web/widgets/dateinput.py b/web/src/toga_web/widgets/dateinput.py index cbd263611e..9ccc0b2925 100644 --- a/web/src/toga_web/widgets/dateinput.py +++ b/web/src/toga_web/widgets/dateinput.py @@ -18,8 +18,6 @@ def create(self): self._return_listener = None self.native = self._create_native_widget("sl-input") self.native.setAttribute("type", "date") - - self.set_value(datetime.date.today().strftime("%Y-%m-%d")) self.native.addEventListener("sl-change", create_proxy(self.on_change)) def get_value(self):