From f50d718c0cb8a60835d8bf71c6a4bb0bb8263e2f Mon Sep 17 00:00:00 2001 From: Cian Hughes Date: Thu, 9 Nov 2023 15:02:45 +0000 Subject: [PATCH] Did a bit of UI polishing --- src/node_deployer_gui/assets/logo_dark.png | Bin 0 -> 26110 bytes src/node_deployer_gui/assets/logo_light.png | Bin 0 -> 15641 bytes src/node_deployer_gui/gui.py | 115 ++++++++++++++------ 3 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 src/node_deployer_gui/assets/logo_dark.png create mode 100644 src/node_deployer_gui/assets/logo_light.png diff --git a/src/node_deployer_gui/assets/logo_dark.png b/src/node_deployer_gui/assets/logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2cc31c5f87a80ef8c1e0b3146cd900734da52ae9 GIT binary patch literal 26110 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 Callable[[ft.KeyboardEvent], None]: + def dummy_func(e: ft.KeyboardEvent) -> None: + pass + + return dummy_func + + +HOTKEY_MAP: DefaultDict[str, Callable[[ft.KeyboardEvent], None]] = defaultdict(_no_hotkey) + + def main(page: ft.Page) -> None: page.title = "I-Form Server Node Deployer" page.vertical_alignment = ft.MainAxisAlignment.CENTER - # TODO: Add a logo # TODO: Add a progress bar - # TODO: Finalise arrangement of fields # TODO: Add save/load functionality? + # Lets start with the easiest part: a logo in the top left + if page.platform_brightness == ft.ThemeMode.DARK: + logo = ft.Image(str(Path(__file__).parent / "assets/logo_dark.png"), width=210) + else: + logo = ft.Image(str(Path(__file__).parent / "assets/logo_light.png"), width=210) + + logo_container = ft.Container( + content=logo, + padding=10, + alignment=ft.alignment.top_left, + ) + page.add(logo_container) + # These fields are used to get the parameters for the disk creation disk, dd_element = disk_dropdown(tooltip="Select the disk to write to", label="Disk") - hostname = ft.TextField(value="host", label="Hostname", text_align=ft.TextAlign.LEFT) - password = ft.TextField( - label="Password", password=True, can_reveal_password=True, text_align=ft.TextAlign.LEFT + hostname = ft.TextField( + value="host", label="Hostname", text_align=ft.TextAlign.LEFT, width=page.window_width // 3 ) - switch_ip = ft.TextField(label="Switch IP", text_align=ft.TextAlign.LEFT) - switch_port = ft.TextField(label="Switch Port", value="4789", text_align=ft.TextAlign.LEFT) - swarm_token = ft.TextField(label="Swarm Token", text_align=ft.TextAlign.LEFT) - + password = ft.TextField( + label="Password", + password=True, + can_reveal_password=True, + text_align=ft.TextAlign.LEFT, + width=page.window_width // 3, + ) + switch_ip = ft.TextField( + label="Switch IP", text_align=ft.TextAlign.LEFT, width=page.window_width // 3 + ) + switch_port = ft.TextField( + label="Switch Port", + value="4789", + text_align=ft.TextAlign.LEFT, + width=page.window_width // 3, + ) + swarm_token = ft.TextField( + label="Swarm Token", text_align=ft.TextAlign.LEFT, width=int((2 * page.window_width) // 3) + ) + # Add varnames, as they will be useful for unpacking later disk.__varname__ = "disk" hostname.__varname__ = "hostname" @@ -38,7 +76,11 @@ def main(page: ft.Page) -> None: swarm_token.__varname__ = "swarm_token" # This wrapper validates the value of the field before passing it to the function - def validate_value[F](func: Callable[[], F]) -> Callable[[], Optional[F]]: # mypy PEP 695 support can't come quickly enough # noqa + def validate_value[ + F + ](func: Callable[[], F]) -> Callable[ + [], Optional[F] + ]: # mypy PEP 695 support can't come quickly enough # noqa #! It is important that bool(F) evaluates to False if the value is invalid @wraps(func) def wrapped() -> Optional[F]: @@ -125,8 +167,8 @@ def main(page: ft.Page) -> None: field.border_color = None field.update() typed_val = target_type(value) - vals[varname] = typed_val # type: ignore #! This is a false positive, an invalid literal would have been caught by the if statement above - + vals[varname] = typed_val # type: ignore #! This is a false positive, an invalid literal would have been caught by the if statement above + if invalid_values: return @@ -143,6 +185,11 @@ def main(page: ft.Page) -> None: # side-effects here though... def close_dlg(*_) -> None: dlg.open = False + if "Y" in HOTKEY_MAP.keys(): + del HOTKEY_MAP["Y"] + if "N" in HOTKEY_MAP.keys(): + del HOTKEY_MAP["N"] + HOTKEY_MAP["Enter"] = confirm_disk_creation page.update() # This closure is called when the confirm disk creation button is pressed @@ -182,14 +229,20 @@ def main(page: ft.Page) -> None: actions_alignment=ft.MainAxisAlignment.END, ) - # Finally, we open the dialog popup + # Finally, we open the dialog popup and switch the hotkeys over page.dialog = dlg dlg.open = True + if "Enter" in HOTKEY_MAP.keys(): + del HOTKEY_MAP["Enter"] + HOTKEY_MAP["Y"] = trigger_disk_creation + HOTKEY_MAP["N"] = close_dlg page.update() + disk_creation_dialog = ft.FilledButton( text="Create Ignition Disk", on_click=confirm_disk_creation, + width=page.window_width // 3, ) # Then, we arrange the fields into rows and columns @@ -217,35 +270,33 @@ def main(page: ft.Page) -> None: alignment=ft.MainAxisAlignment.CENTER, ) + swarm_token_row = ft.Row( + controls=[ + swarm_token, + ], + alignment=ft.MainAxisAlignment.CENTER, + ) + stacked_rows = ft.Column( - [disk_row, node_row, switch_row, swarm_token], + [disk_row, node_row, switch_row, swarm_token_row], alignment=ft.MainAxisAlignment.CENTER, ) # Finally, we finish constructing the UI by adding the rows to the page page.add(stacked_rows) - # As a final task, we define the hotkey events - # We do this using a dict to avoid a big, slow if-elif-else chain - def no_hotkey() -> Callable[[ft.KeyboardEvent], None]: - def dummy_func(e: ft.KeyboardEvent) -> None: - pass - return dummy_func + # As a final task, we define the opening screen hotkey events + HOTKEY_MAP["Enter"] = confirm_disk_creation def quit_app(e: ft.KeyboardEvent) -> None: if e.ctrl: page.window_close() - - hotkey_map: DefaultDict[str, Callable[[ft.KeyboardEvent], None]] = defaultdict( - no_hotkey, - Enter=confirm_disk_creation, - Q=quit_app, - ) - + + HOTKEY_MAP["Q"] = quit_app + def on_key_press(e: ft.KeyboardEvent) -> None: - print(e.key) - hotkey_map[e.key](e) - + HOTKEY_MAP[e.key](e) + page.on_keyboard_event = on_key_press - - page.update() # This shouldn't be necessary, but ensures the UI is rendered correctly \ No newline at end of file + + page.update() # This shouldn't be necessary, but ensures the UI is rendered correctly