From cd469fcdccb1eae171ad04f402834b1547122a76 Mon Sep 17 00:00:00 2001 From: Marek Mihok Date: Fri, 9 Feb 2024 13:40:08 +0100 Subject: [PATCH] feat: Make ui.command to support path and download props #2224 (#2262) --- py/examples/toolbar.py | 2 +- py/h2o_lightwave/h2o_lightwave/types.py | 20 +++ py/h2o_lightwave/h2o_lightwave/ui.py | 6 + py/h2o_wave/h2o_wave/types.py | 20 +++ py/h2o_wave/h2o_wave/ui.py | 6 + r/R/ui.R | 12 +- .../resources/templates/wave-components.xml | 4 +- .../vscode-extension/component-snippets.json | 2 +- ui/src/button.test.tsx | 89 +++++++++++++ ui/src/card_menu.test.tsx | 49 +++++++ ui/src/card_menu.tsx | 39 +++--- ui/src/link.tsx | 2 +- ui/src/table.test.tsx | 126 +++++++++++++++--- ui/src/toolbar.test.tsx | 40 ++++++ ui/src/toolbar.tsx | 27 ++-- website/widgets/content/toolbar.md | 4 +- 16 files changed, 398 insertions(+), 50 deletions(-) diff --git a/py/examples/toolbar.py b/py/examples/toolbar.py index b9ea257526..4e7e6eedd4 100644 --- a/py/examples/toolbar.py +++ b/py/examples/toolbar.py @@ -18,7 +18,7 @@ async def serve(q: Q): ), ui.command(name='upload', label='Upload', icon='Upload'), ui.command(name='share', label='Share', icon='Share'), - ui.command(name='download', label='Download', icon='Download'), + ui.command(name='download', label='Download', icon='Download', path='https://wave.h2o.ai/img/logo.svg', download=True), ], secondary_items=[ ui.command(name='tile', caption='Grid View', icon='Tiles'), diff --git a/py/h2o_lightwave/h2o_lightwave/types.py b/py/h2o_lightwave/h2o_lightwave/types.py index 8887cc6b1e..28c5125f32 100644 --- a/py/h2o_lightwave/h2o_lightwave/types.py +++ b/py/h2o_lightwave/h2o_lightwave/types.py @@ -160,6 +160,8 @@ def __init__( icon: Optional[str] = None, items: Optional[List['Command']] = None, value: Optional[str] = None, + path: Optional[str] = None, + download: Optional[bool] = None, ): _guard_scalar('Command.name', name, (str,), True, False, False) _guard_scalar('Command.label', label, (str,), False, True, False) @@ -167,6 +169,8 @@ def __init__( _guard_scalar('Command.icon', icon, (str,), False, True, False) _guard_vector('Command.items', items, (Command,), False, True, False) _guard_scalar('Command.value', value, (str,), False, True, False) + _guard_scalar('Command.path', path, (str,), False, True, False) + _guard_scalar('Command.download', download, (bool,), False, True, False) self.name = name """An identifying name for this component. If the name is prefixed with a '#', the command sets the location hash to the name when executed.""" self.label = label @@ -179,6 +183,10 @@ def __init__( """Sub-commands, if any""" self.value = value """Data associated with this command, if any.""" + self.path = path + """The path or URL to link to. The 'items' and 'value' props are ignored when specified.""" + self.download = download + """True if the link should prompt the user to save the linked URL instead of navigating to it.""" def dump(self) -> Dict: """Returns the contents of this object as a dict.""" @@ -188,6 +196,8 @@ def dump(self) -> Dict: _guard_scalar('Command.icon', self.icon, (str,), False, True, False) _guard_vector('Command.items', self.items, (Command,), False, True, False) _guard_scalar('Command.value', self.value, (str,), False, True, False) + _guard_scalar('Command.path', self.path, (str,), False, True, False) + _guard_scalar('Command.download', self.download, (bool,), False, True, False) return _dump( name=self.name, label=self.label, @@ -195,6 +205,8 @@ def dump(self) -> Dict: icon=self.icon, items=None if self.items is None else [__e.dump() for __e in self.items], value=self.value, + path=self.path, + download=self.download, ) @staticmethod @@ -212,12 +224,18 @@ def load(__d: Dict) -> 'Command': _guard_vector('Command.items', __d_items, (dict,), False, True, False) __d_value: Any = __d.get('value') _guard_scalar('Command.value', __d_value, (str,), False, True, False) + __d_path: Any = __d.get('path') + _guard_scalar('Command.path', __d_path, (str,), False, True, False) + __d_download: Any = __d.get('download') + _guard_scalar('Command.download', __d_download, (bool,), False, True, False) name: str = __d_name label: Optional[str] = __d_label caption: Optional[str] = __d_caption icon: Optional[str] = __d_icon items: Optional[List['Command']] = None if __d_items is None else [Command.load(__e) for __e in __d_items] value: Optional[str] = __d_value + path: Optional[str] = __d_path + download: Optional[bool] = __d_download return Command( name, label, @@ -225,6 +243,8 @@ def load(__d: Dict) -> 'Command': icon, items, value, + path, + download, ) diff --git a/py/h2o_lightwave/h2o_lightwave/ui.py b/py/h2o_lightwave/h2o_lightwave/ui.py index 9967255f1d..fc21f8dbbc 100644 --- a/py/h2o_lightwave/h2o_lightwave/ui.py +++ b/py/h2o_lightwave/h2o_lightwave/ui.py @@ -58,6 +58,8 @@ def command( icon: Optional[str] = None, items: Optional[List[Command]] = None, value: Optional[str] = None, + path: Optional[str] = None, + download: Optional[bool] = None, ) -> Command: """Create a command. @@ -70,6 +72,8 @@ def command( icon: The icon to be displayed for this command. items: Sub-commands, if any value: Data associated with this command, if any. + path: The path or URL to link to. The 'items' and 'value' props are ignored when specified. + download: True if the link should prompt the user to save the linked URL instead of navigating to it. Returns: A `h2o_wave.types.Command` instance. """ @@ -80,6 +84,8 @@ def command( icon, items, value, + path, + download, ) diff --git a/py/h2o_wave/h2o_wave/types.py b/py/h2o_wave/h2o_wave/types.py index 8887cc6b1e..28c5125f32 100644 --- a/py/h2o_wave/h2o_wave/types.py +++ b/py/h2o_wave/h2o_wave/types.py @@ -160,6 +160,8 @@ def __init__( icon: Optional[str] = None, items: Optional[List['Command']] = None, value: Optional[str] = None, + path: Optional[str] = None, + download: Optional[bool] = None, ): _guard_scalar('Command.name', name, (str,), True, False, False) _guard_scalar('Command.label', label, (str,), False, True, False) @@ -167,6 +169,8 @@ def __init__( _guard_scalar('Command.icon', icon, (str,), False, True, False) _guard_vector('Command.items', items, (Command,), False, True, False) _guard_scalar('Command.value', value, (str,), False, True, False) + _guard_scalar('Command.path', path, (str,), False, True, False) + _guard_scalar('Command.download', download, (bool,), False, True, False) self.name = name """An identifying name for this component. If the name is prefixed with a '#', the command sets the location hash to the name when executed.""" self.label = label @@ -179,6 +183,10 @@ def __init__( """Sub-commands, if any""" self.value = value """Data associated with this command, if any.""" + self.path = path + """The path or URL to link to. The 'items' and 'value' props are ignored when specified.""" + self.download = download + """True if the link should prompt the user to save the linked URL instead of navigating to it.""" def dump(self) -> Dict: """Returns the contents of this object as a dict.""" @@ -188,6 +196,8 @@ def dump(self) -> Dict: _guard_scalar('Command.icon', self.icon, (str,), False, True, False) _guard_vector('Command.items', self.items, (Command,), False, True, False) _guard_scalar('Command.value', self.value, (str,), False, True, False) + _guard_scalar('Command.path', self.path, (str,), False, True, False) + _guard_scalar('Command.download', self.download, (bool,), False, True, False) return _dump( name=self.name, label=self.label, @@ -195,6 +205,8 @@ def dump(self) -> Dict: icon=self.icon, items=None if self.items is None else [__e.dump() for __e in self.items], value=self.value, + path=self.path, + download=self.download, ) @staticmethod @@ -212,12 +224,18 @@ def load(__d: Dict) -> 'Command': _guard_vector('Command.items', __d_items, (dict,), False, True, False) __d_value: Any = __d.get('value') _guard_scalar('Command.value', __d_value, (str,), False, True, False) + __d_path: Any = __d.get('path') + _guard_scalar('Command.path', __d_path, (str,), False, True, False) + __d_download: Any = __d.get('download') + _guard_scalar('Command.download', __d_download, (bool,), False, True, False) name: str = __d_name label: Optional[str] = __d_label caption: Optional[str] = __d_caption icon: Optional[str] = __d_icon items: Optional[List['Command']] = None if __d_items is None else [Command.load(__e) for __e in __d_items] value: Optional[str] = __d_value + path: Optional[str] = __d_path + download: Optional[bool] = __d_download return Command( name, label, @@ -225,6 +243,8 @@ def load(__d: Dict) -> 'Command': icon, items, value, + path, + download, ) diff --git a/py/h2o_wave/h2o_wave/ui.py b/py/h2o_wave/h2o_wave/ui.py index 9967255f1d..fc21f8dbbc 100644 --- a/py/h2o_wave/h2o_wave/ui.py +++ b/py/h2o_wave/h2o_wave/ui.py @@ -58,6 +58,8 @@ def command( icon: Optional[str] = None, items: Optional[List[Command]] = None, value: Optional[str] = None, + path: Optional[str] = None, + download: Optional[bool] = None, ) -> Command: """Create a command. @@ -70,6 +72,8 @@ def command( icon: The icon to be displayed for this command. items: Sub-commands, if any value: Data associated with this command, if any. + path: The path or URL to link to. The 'items' and 'value' props are ignored when specified. + download: True if the link should prompt the user to save the linked URL instead of navigating to it. Returns: A `h2o_wave.types.Command` instance. """ @@ -80,6 +84,8 @@ def command( icon, items, value, + path, + download, ) diff --git a/r/R/ui.R b/r/R/ui.R index 4f603b4053..6809ec908d 100644 --- a/r/R/ui.R +++ b/r/R/ui.R @@ -103,6 +103,8 @@ ui_text <- function( #' @param icon The icon to be displayed for this command. #' @param items Sub-commands, if any #' @param value Data associated with this command, if any. +#' @param path The path or URL to link to. The 'items' and 'value' props are ignored when specified. +#' @param download True if the link should prompt the user to save the linked URL instead of navigating to it. #' @return A Command instance. #' @export ui_command <- function( @@ -111,20 +113,26 @@ ui_command <- function( caption = NULL, icon = NULL, items = NULL, - value = NULL) { + value = NULL, + path = NULL, + download = NULL) { .guard_scalar("name", "character", name) .guard_scalar("label", "character", label) .guard_scalar("caption", "character", caption) .guard_scalar("icon", "character", icon) .guard_vector("items", "WaveCommand", items) .guard_scalar("value", "character", value) + .guard_scalar("path", "character", path) + .guard_scalar("download", "logical", download) .o <- list( name=name, label=label, caption=caption, icon=icon, items=items, - value=value) + value=value, + path=path, + download=download) class(.o) <- append(class(.o), c(.wave_obj, "WaveCommand")) return(.o) } diff --git a/tools/intellij-plugin/src/main/resources/templates/wave-components.xml b/tools/intellij-plugin/src/main/resources/templates/wave-components.xml index ae064bd8ab..a0008ad3e7 100644 --- a/tools/intellij-plugin/src/main/resources/templates/wave-components.xml +++ b/tools/intellij-plugin/src/main/resources/templates/wave-components.xml @@ -2680,12 +2680,14 @@