fix date modal

This commit is contained in:
jpt 2025-04-13 11:05:25 -05:00
parent 74ed6516b4
commit 547a65e19f
5 changed files with 56 additions and 33 deletions

View File

@ -84,8 +84,8 @@ def get_tasks(
query = query.where(fn.Lower(Task.text).contains(search_text.lower())) query = query.where(fn.Lower(Task.text).contains(search_text.lower()))
if statuses: if statuses:
query = query.where(Task.status.in_(statuses)) query = query.where(Task.status.in_(statuses))
#if projects: if projects:
# query = query.where(Task.project.in_(projects)) query = query.where(Task.project.in_(projects))
sort_expressions = _parse_sort_string(sort, statuses) sort_expressions = _parse_sort_string(sort, statuses)
query = query.order_by(*sort_expressions) query = query.order_by(*sort_expressions)

View File

@ -83,7 +83,7 @@ class EnumColumnConfig(TableColumnConfig):
class DateColumnConfig(TableColumnConfig): class DateColumnConfig(TableColumnConfig):
def preprocess(self, val): def preprocess(self, val):
try: try:
return datetime.strptime(val, "%Y-%m-%d") return datetime.datetime.strptime(val, "%Y-%m-%d")
except ValueError: except ValueError:
raise NotifyValidationError("Invalid date format. Use YYYY-MM-DD") raise NotifyValidationError("Invalid date format. Use YYYY-MM-DD")

View File

@ -37,6 +37,7 @@ class KeyModal(ModalScreen):
for binding in self.app.BINDINGS: for binding in self.app.BINDINGS:
if binding[0] not in ["h", "j", "k", "l", "g", "G", "escape"]: if binding[0] not in ["h", "j", "k", "l", "g", "G", "escape"]:
table.add_row(binding[0], binding[2]) table.add_row(binding[0], binding[2])
# TODO: MRO?
yield Static("tt keybindings", classes="title") yield Static("tt keybindings", classes="title")
yield Static(table) yield Static(table)

View File

@ -1,9 +1,10 @@
import datetime
from textual.screen import ModalScreen from textual.screen import ModalScreen
from textual.binding import Binding from textual.binding import Binding
from textual.widgets import RadioSet, RadioButton, Label from textual.widgets import Label
from .. import config
from ..utils import get_color_enum from ..utils import get_color_enum
class ConfirmModal(ModalScreen): class ConfirmModal(ModalScreen):
CSS = """ CSS = """
ConfirmModal { ConfirmModal {
@ -42,42 +43,56 @@ class ChoiceModal(ModalScreen):
ChoiceModal Label { ChoiceModal Label {
height: 1; height: 1;
} }
ChoiceModal Label#selected {
background: white;
}
""" """
BINDINGS = [ BINDINGS = [
("j,tab", "cursor_down", "Down"), ("j,tab", "cursor_down", "Down"),
("k", "cursor_up", "Up"), ("k,shift+tab", "cursor_up", "Up"),
Binding("enter", "select", "Select", priority=False), Binding("enter", "select", "Select", priority=True),
("escape", "cancel", "cancel"), ("escape", "cancel", "cancel"),
] ]
def __init__(self, enum, selected): def __init__(self, enum, selected):
self._enum = enum self._enum = enum
self.selected = selected self.enum_by_idx = list(self._enum)
# selection index
self.sel_idx = 0
# convert value back to index for initial selection
for idx, e in enumerate(self._enum):
if e.value == selected:
self.sel_idx = idx
break
super().__init__() super().__init__()
def compose(self): def compose(self):
yield RadioSet( for idx, e in enumerate(self._enum):
*[ yield Label(
RadioButton( ("> " if idx == self.sel_idx else " ") +
get_color_enum(e.value, config.STATUSES), value=self.selected == str(e.value) get_color_enum(e.value, self._enum),
) classes="selected" if idx == self.sel_idx else "",
for e in self._enum
]
) )
def _move_cursor(self, dir):
labels = self.query(Label)
# reset old
labels[self.sel_idx].update(" " + get_color_enum(self.enum_by_idx[self.sel_idx], self._enum))
# move cursor
self.sel_idx = (self.sel_idx + dir) % len(self._enum)
# reset new
labels[self.sel_idx].update("> " + get_color_enum(self.enum_by_idx[self.sel_idx], self._enum))
def action_cursor_down(self): def action_cursor_down(self):
self.query_one(RadioSet).action_next_button() self._move_cursor(1)
def action_cursor_up(self): def action_cursor_up(self):
self.query_one(RadioSet).action_previous_button() self._move_cursor(-1)
def action_select(self): async def action_select(self):
rs = self.query_one(RadioSet) self.dismiss(self.enum_by_idx[self.sel_idx])
# TODO: this doesn't work
#rs.action_toggle_button()
pressed = rs.pressed_button
self.dismiss(str(pressed.label))
def action_cancel(self): def action_cancel(self):
self.app.pop_screen() self.app.pop_screen()
@ -101,14 +116,18 @@ class DateModal(ModalScreen):
BINDINGS = [ BINDINGS = [
("j", "cursor_down", "Down"), ("j", "cursor_down", "Down"),
("k", "cursor_up", "Up"), ("k", "cursor_up", "Up"),
("h,tab", "cursor_left", "Left"), ("h,shift+tab", "cursor_left", "Left"),
("l", "cursor_right", "Right"), ("l,tab", "cursor_right", "Right"),
Binding("enter", "select", "Select", priority=True), Binding("enter", "select", "Select", priority=True),
("escape", "cancel", "cancel"), ("escape", "cancel", "cancel"),
] ]
def __init__(self, date): def __init__(self, date):
if date:
self.pieces = [int(p) for p in date.split("-")] self.pieces = [int(p) for p in date.split("-")]
else:
today = datetime.date.today()
self.pieces = [today.year, today.month, today.day]
self.selected = 1 # start on month self.selected = 1 # start on month
super().__init__() super().__init__()
@ -178,8 +197,7 @@ class DateModal(ModalScreen):
event.prevent_default() event.prevent_default()
def action_select(self): def action_select(self):
date = "-".join(str(p) for p in self.pieces) self.dismiss("-".join(str(p) for p in self.pieces))
self.dismiss(date)
def action_cancel(self): def action_cancel(self):
self.app.pop_screen() self.app.pop_screen()

View File

@ -56,10 +56,8 @@ class TT(TableEditor):
def refresh_items(self): def refresh_items(self):
items = get_tasks( items = get_tasks(
self.search_query, self.search_query,
projects=self.filters.get("project", "").split(","), projects=self._filters_to_list("project"),
statuses=self.filters.get("status", "").split(",") statuses=self._filters_to_list("status"),
if "status" in self.filters
else None,
sort=self.sort_string, sort=self.sort_string,
) )
for item in items: for item in items:
@ -68,6 +66,12 @@ class TT(TableEditor):
key=str(item.id), key=str(item.id),
) )
def _filters_to_list(self, key):
filters = self.filters.get(key)
if filters:
return filters.split(",")
else:
return None
def run(default_view): def run(default_view):
app = TT(default_view) app = TT(default_view)