From 1bc94bfd0a2b0c1ad8a880eb1b70010005abdaba Mon Sep 17 00:00:00 2001 From: jpt Date: Sun, 13 Apr 2025 11:14:24 -0500 Subject: [PATCH] split out columns --- src/tt/tui/columns.py | 89 +++++++++++++++++++++++++++++++++++++++++++ src/tt/tui/editor.py | 87 ++---------------------------------------- 2 files changed, 92 insertions(+), 84 deletions(-) create mode 100644 src/tt/tui/columns.py diff --git a/src/tt/tui/columns.py b/src/tt/tui/columns.py new file mode 100644 index 0000000..2d9be7c --- /dev/null +++ b/src/tt/tui/columns.py @@ -0,0 +1,89 @@ +import datetime +from ..utils import ( + get_color_enum, + get_colored_date, +) +from .modals import ChoiceModal, DateModal + +class NotifyValidationError(Exception): + """will notify and continue if raised""" + + +ELLIPSIS = "…" + + +class TableColumnConfig: + def __init__( + self, + field: str, + display_name: str, + *, + default=None, + enable_editor=False, + filterable=True, + read_only=False, + ): + self.field = field + self.display_name = display_name + self.default = default + self.enable_editor = enable_editor + self.filterable = filterable + self.read_only = read_only + + def preprocess(self, val): + return val # no-op + + def start_change(self, app, current_value): + if current_value.endswith(ELLIPSIS): + app.action_start_edit() + else: + # default edit mode + app._show_input("edit", current_value) + + def format_for_display(self, val): + val = str(val) + if "\n" in val: + val = val.split("\n")[0] + ELLIPSIS + return val + + +class EnumColumnConfig(TableColumnConfig): + def __init__(self, field: str, display_name: str, enum, **kwargs): + super().__init__(field, display_name, **kwargs) + self.enum = enum + + def preprocess(self, val): + if val in self.enum: + return val + else: + raise NotifyValidationError(f"Invalid value {val}. Use: {list(self.enum)}") + + def format_for_display(self, val): + return get_color_enum(val, self.enum) + + def start_change(self, app, current_value): + # a weird hack? pass app here and correct modal gets pushed + app.push_screen(ChoiceModal(self.enum, current_value), app.apply_change) + + +class DateColumnConfig(TableColumnConfig): + def preprocess(self, val): + try: + return datetime.datetime.strptime(val, "%Y-%m-%d") + except ValueError: + raise NotifyValidationError("Invalid date format. Use YYYY-MM-DD") + + def format_for_display(self, val): + return get_colored_date(val) + + def start_change(self, app, current_value): + app.push_screen(DateModal(current_value), app.apply_change) + + + +def get_col_cls(field_type): + return { + "text": TableColumnConfig, + "enum": EnumColumnConfig, + "date": DateColumnConfig, + }[field_type] diff --git a/src/tt/tui/editor.py b/src/tt/tui/editor.py index 0bf0e53..f88abc1 100644 --- a/src/tt/tui/editor.py +++ b/src/tt/tui/editor.py @@ -1,4 +1,3 @@ -import datetime from textual.app import App from textual.widgets import ( DataTable, @@ -13,86 +12,10 @@ from ..utils import ( remove_rich_tag, filter_to_string, get_text_from_editor, - get_color_enum, - get_colored_date, ) from .keymodal import KeyModal -from .modals import ChoiceModal, DateModal, ConfirmModal - - -class NotifyValidationError(Exception): - """will notify and continue if raised""" - - -ELLIPSIS = "…" - -class TableColumnConfig: - def __init__( - self, - field: str, - display_name: str, - *, - default=None, - enable_editor=False, - filterable=True, - read_only=False, - ): - self.field = field - self.display_name = display_name - self.default = default - self.enable_editor = enable_editor - self.filterable = filterable - self.read_only = read_only - - def preprocess(self, val): - return val # no-op - - def start_change(self, app, current_value): - if current_value.endswith(ELLIPSIS): - app.action_start_edit() - else: - # default edit mode - app._show_input("edit", current_value) - - def format_for_display(self, val): - val = str(val) - if "\n" in val: - val = val.split("\n")[0] + ELLIPSIS - return val - - -class EnumColumnConfig(TableColumnConfig): - def __init__(self, field: str, display_name: str, enum, **kwargs): - super().__init__(field, display_name, **kwargs) - self.enum = enum - - def preprocess(self, val): - if val in self.enum: - return val - else: - raise NotifyValidationError(f"Invalid value {val}. Use: {list(self.enum)}") - - def format_for_display(self, val): - return get_color_enum(val, self.enum) - - def start_change(self, app, current_value): - # a weird hack? pass app here and correct modal gets pushed - app.push_screen(ChoiceModal(self.enum, current_value), app.apply_change) - - -class DateColumnConfig(TableColumnConfig): - def preprocess(self, val): - try: - return datetime.datetime.strptime(val, "%Y-%m-%d") - except ValueError: - raise NotifyValidationError("Invalid date format. Use YYYY-MM-DD") - - def format_for_display(self, val): - return get_colored_date(val) - - def start_change(self, app, current_value): - app.push_screen(DateModal(current_value), app.apply_change) - +from .modals import ConfirmModal +from .columns import get_col_cls @@ -187,11 +110,7 @@ class TableEditor(App): # set up columns for col in view["columns"]: field_type = col.get("field_type", "text") - field_cls = { - "text": TableColumnConfig, - "enum": EnumColumnConfig, - "date": DateColumnConfig, - }[field_type] + field_cls = get_col_cls(field_type) field_name = col["field_name"] display_name = col.get("display_name", field_name.title()) default = col.get("default")