diff --git a/src/tt/tui.py b/src/tt/tui.py index 6354ddf..ee48415 100644 --- a/src/tt/tui.py +++ b/src/tt/tui.py @@ -14,6 +14,7 @@ from .controller import get_tasks, add_task, update_task, TaskStatus from .db import initialize_db from .utils import ( remove_rich_tag, + filter_to_string, advance_enum_val, get_colored_category, get_colored_status, @@ -21,7 +22,6 @@ from .utils import ( ) # Parity -# TODO: add filtering on status # TODO: saved searches # Nice to Have # TODO: CLI @@ -32,11 +32,12 @@ from .utils import ( COLUMNS = ("ID", "Task", "Status", "Type", "Due", "Category") column_to_field = { + 0: "ID", 1: "text", 2: "status", 3: "type", 4: "due", - 5: "category_name", + 5: "category", } @@ -113,7 +114,7 @@ class TT(App): def __init__(self): super().__init__() self.search_query = "" - self.search_category = "" + self.filters = {} self.sort_string = "due,status" self.saved_cursor_pos = (0, 0) self.save_on_move = None @@ -174,7 +175,12 @@ class TT(App): self.table.clear() tasks = get_tasks( - self.search_query, category=self.search_category, sort=self.sort_string + self.search_query, + category=self.filters.get("category"), + statuses=self.filters.get("status", "").split(",") + if "status" in self.filters + else None, + sort=self.sort_string, ) for task in tasks: category = get_colored_category( @@ -194,12 +200,8 @@ class TT(App): ) # update footer - if self.search_query: - self.left_status.update( - f"{len(tasks)} |{' ' if self.search_category else ''}{self.search_category} matching '{self.search_query}'" - ) - else: - self.left_status.update(f"{len(tasks)} | {self.search_category}") + filter_display = filter_to_string(self.filters, self.search_query) + self.left_status.update(f"{len(tasks)} |{filter_display}") # restore cursor if restore_cursor: @@ -288,12 +290,21 @@ class TT(App): def action_cancel_edit(self): self._hide_input() + self.table.cursor_type = "cell" def action_start_search(self): self._show_input("search", "") def action_start_filter(self): - self._show_input("filter", self.search_category) + # filter the currently selected column + cur_col = self.table.cursor_column + active_col_name = column_to_field[cur_col] + # # only allow filtering these columns + if active_col_name not in ("status", "type", "due", "category"): + return + cur_filter_val = self.filters.get(active_col_name) or "" + self._show_input("filter", cur_filter_val) + self.table.cursor_type = "column" def action_start_sort(self): self._show_input("sort", self.sort_string) @@ -317,8 +328,11 @@ class TT(App): self.search_query = event.value self.refresh_tasks(restore_cursor=False) elif self.mode == "filter": - self.search_category = event.value + cur_col = self.table.cursor_column + active_col_name = column_to_field[cur_col] + self.filters[active_col_name] = event.value self.refresh_tasks(restore_cursor=False) + self.table.cursor_type = "cel" elif self.mode == "sort": self.sort_string = event.value self.refresh_tasks(restore_cursor=False) @@ -356,6 +370,7 @@ class TT(App): except Exception as e: self.notify(f"Error updating task: {str(e)}") finally: + # no longer in edit mode self.action_cancel_edit() def action_show_keys(self): diff --git a/src/tt/utils.py b/src/tt/utils.py index 7cf7e6f..9522995 100644 --- a/src/tt/utils.py +++ b/src/tt/utils.py @@ -1,6 +1,18 @@ import re import datetime -from rich.text import Text + + +def filter_to_string(filters, search_query): + pieces = [] + category = filters.get("category") + status = filters.get("status") + if category: + pieces += [f" category:{category}"] + if status: + pieces += [f" status:{status}"] + if search_query: + pieces += [f" search:'{search_query}"] + return "".join(pieces) def remove_rich_tag(text): @@ -40,14 +52,14 @@ def get_colored_date(date: datetime.date) -> str: as_str = date.strftime("%Y-%m-%d") today = datetime.date.today() if date.date() < today: - return Text(as_str, style="black on red") + return f"[#eeeeee on #dd1111]{as_str}[/]" else: # Calculate weeks into future delta = date.date() - today weeks = delta.days // 7 colors = [ - "#FF4000", + # "#FF4000", "#FF8000", "#FFA533", "#FFD24D",