saving and loading views
This commit is contained in:
parent
20b95d087b
commit
35aaf17de2
@ -39,8 +39,10 @@ def new(
|
||||
|
||||
|
||||
@app.command()
|
||||
def browse():
|
||||
tui.run()
|
||||
def browse(
|
||||
view: Annotated[str, typer.Option("-v", "--view", help="saved view")] = "default",
|
||||
):
|
||||
tui.run(view)
|
||||
|
||||
|
||||
@app.command()
|
||||
|
@ -1,6 +1,14 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
from peewee import fn
|
||||
from .db import Task, Category, TaskStatus, db
|
||||
from .db import db, Task, Category, TaskStatus, SavedSearch
|
||||
|
||||
|
||||
def category_lookup(category):
|
||||
category_id = None
|
||||
if category:
|
||||
category, _ = Category.get_or_create(name=category)
|
||||
return category.id
|
||||
|
||||
|
||||
def add_task(
|
||||
@ -15,10 +23,7 @@ def add_task(
|
||||
Returns the created task instance.
|
||||
"""
|
||||
with db.atomic():
|
||||
category_id = None
|
||||
if category:
|
||||
category, _ = Category.get_or_create(name=category)
|
||||
category_id = category.id
|
||||
category_id = category_lookup(category)
|
||||
task = Task.create(
|
||||
text=text, type=type, status=status, due=due, category_id=category_id
|
||||
)
|
||||
@ -30,6 +35,8 @@ def update_task(
|
||||
**kwargs,
|
||||
) -> Task:
|
||||
with db.atomic():
|
||||
if category := kwargs.pop("category", None):
|
||||
kwargs["category_id"] = category_lookup(category)
|
||||
task = Task.get_by_id(task_id)
|
||||
query = Task.update(kwargs).where(Task.id == task_id)
|
||||
query.execute()
|
||||
@ -84,3 +91,17 @@ def get_tasks(
|
||||
|
||||
def get_categories() -> list[Category]:
|
||||
return list(Category.select().order_by(Category.name))
|
||||
|
||||
|
||||
def save_view(name: str, *, filters: dict, sort_string: str) -> SavedSearch:
|
||||
filters_json = json.dumps(filters)
|
||||
|
||||
return SavedSearch.create(name=name, filters=filters_json, sort_string=sort_string)
|
||||
|
||||
|
||||
def get_saved_view_names() -> list[str]:
|
||||
return [search.name for search in SavedSearch.select()]
|
||||
|
||||
|
||||
def get_saved_view(name: str) -> SavedSearch:
|
||||
return SavedSearch.get(SavedSearch.name == name)
|
||||
|
11
src/tt/db.py
11
src/tt/db.py
@ -58,9 +58,18 @@ class Task(BaseModel):
|
||||
return super(Task, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class SavedSearch(BaseModel):
|
||||
name = CharField(unique=True)
|
||||
filters = CharField()
|
||||
sort_string = CharField()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
def initialize_db():
|
||||
db.connect()
|
||||
db.create_tables([Category, Task])
|
||||
db.create_tables([Category, Task, SavedSearch])
|
||||
if not Category.select().exists():
|
||||
Category.create(name="default")
|
||||
db.close()
|
||||
|
@ -1,3 +1,4 @@
|
||||
import json
|
||||
from textual.app import App
|
||||
from textual.screen import ModalScreen
|
||||
from rich.table import Table
|
||||
@ -10,7 +11,14 @@ from textual.widgets import (
|
||||
from textual.containers import Container
|
||||
from datetime import datetime
|
||||
|
||||
from .controller import get_tasks, add_task, update_task, TaskStatus
|
||||
from .controller import (
|
||||
get_tasks,
|
||||
add_task,
|
||||
update_task,
|
||||
TaskStatus,
|
||||
save_view,
|
||||
get_saved_view,
|
||||
)
|
||||
from .db import initialize_db
|
||||
from .utils import (
|
||||
remove_rich_tag,
|
||||
@ -97,19 +105,31 @@ class TT(App):
|
||||
("a", "add_task", "add task"),
|
||||
("t", "toggle_cell", "toggle status"),
|
||||
("d", "delete_task", "delete (must be on row mode)"),
|
||||
# saved views
|
||||
("ctrl+s", "save_view", "save current view"),
|
||||
("ctrl+o", "load_view", "load saved view"),
|
||||
# other
|
||||
("q", "quit", "quit"),
|
||||
("?", "show_keys", "show keybindings"),
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, default_view="default"):
|
||||
super().__init__()
|
||||
self.search_query = ""
|
||||
self.filters = {}
|
||||
self.sort_string = "due,status"
|
||||
self.saved_cursor_pos = (0, 0)
|
||||
self._load_view(default_view)
|
||||
self.search_query = ""
|
||||
self.saved_cursor_pos = (1, 0)
|
||||
self.save_on_move = None
|
||||
|
||||
def _load_view(self, name):
|
||||
try:
|
||||
saved = get_saved_view(name)
|
||||
self.filters = json.loads(saved.filters)
|
||||
self.sort_string = saved.sort_string
|
||||
except Exception:
|
||||
self.notify(f"Could not load {name}")
|
||||
|
||||
def compose(self):
|
||||
self.header = Header()
|
||||
self.table = DataTable()
|
||||
@ -271,6 +291,10 @@ class TT(App):
|
||||
self.input_label.update("sort: ")
|
||||
elif mode == "filter":
|
||||
self.input_label.update("filter: ")
|
||||
elif mode == "save-view":
|
||||
self.input_label.update("view name: ")
|
||||
elif mode == "load-view":
|
||||
self.input_label.update("view name: ")
|
||||
else:
|
||||
raise ValueError(f"unknown mode: {mode}")
|
||||
self.set_focus(self.input_widget)
|
||||
@ -286,6 +310,12 @@ class TT(App):
|
||||
def action_start_search(self):
|
||||
self._show_input("search", "")
|
||||
|
||||
def action_save_view(self):
|
||||
self._show_input("save-view", "default")
|
||||
|
||||
def action_load_view(self):
|
||||
self._show_input("load-view", "")
|
||||
|
||||
def action_start_filter(self):
|
||||
# filter the currently selected column
|
||||
cur_col = self.table.cursor_column
|
||||
@ -330,6 +360,11 @@ class TT(App):
|
||||
self.right_status.update(self.sort_string)
|
||||
elif self.mode == "edit":
|
||||
self.apply_change(event.value)
|
||||
elif self.mode == "save-view":
|
||||
save_view(event.value, filters=self.filters, sort_string=self.sort_string)
|
||||
elif self.mode == "load-view":
|
||||
self._load_view(event.value)
|
||||
self.refresh_tasks(restore_cursor=False)
|
||||
else:
|
||||
raise ValueError(f"unknown mode: {self.mode}")
|
||||
self._hide_input()
|
||||
@ -411,9 +446,9 @@ class KeyBindingsScreen(ModalScreen):
|
||||
self.app.pop_screen()
|
||||
|
||||
|
||||
def run():
|
||||
def run(default_view):
|
||||
initialize_db()
|
||||
app = TT()
|
||||
app = TT(default_view)
|
||||
app.run()
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user