split out columns

This commit is contained in:
jpt 2025-04-13 11:14:24 -05:00
parent 547a65e19f
commit 1bc94bfd0a
2 changed files with 92 additions and 84 deletions

89
src/tt/tui/columns.py Normal file
View File

@ -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]

View File

@ -1,4 +1,3 @@
import datetime
from textual.app import App from textual.app import App
from textual.widgets import ( from textual.widgets import (
DataTable, DataTable,
@ -13,86 +12,10 @@ from ..utils import (
remove_rich_tag, remove_rich_tag,
filter_to_string, filter_to_string,
get_text_from_editor, get_text_from_editor,
get_color_enum,
get_colored_date,
) )
from .keymodal import KeyModal from .keymodal import KeyModal
from .modals import ChoiceModal, DateModal, ConfirmModal from .modals import ConfirmModal
from .columns import get_col_cls
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)
@ -187,11 +110,7 @@ class TableEditor(App):
# set up columns # set up columns
for col in view["columns"]: for col in view["columns"]:
field_type = col.get("field_type", "text") field_type = col.get("field_type", "text")
field_cls = { field_cls = get_col_cls(field_type)
"text": TableColumnConfig,
"enum": EnumColumnConfig,
"date": DateColumnConfig,
}[field_type]
field_name = col["field_name"] field_name = col["field_name"]
display_name = col.get("display_name", field_name.title()) display_name = col.get("display_name", field_name.title())
default = col.get("default") default = col.get("default")