Compare commits
2 Commits
fe5be1115b
...
4ed319e22e
Author | SHA1 | Date | |
---|---|---|---|
4ed319e22e | |||
8ae7d5ad2d |
@ -1,10 +1,12 @@
|
|||||||
import typer
|
import typer
|
||||||
import httpx
|
import httpx
|
||||||
import lxml.html
|
import lxml.html
|
||||||
|
import sqlite3
|
||||||
from typing_extensions import Annotated
|
from typing_extensions import Annotated
|
||||||
from .db import initialize_db
|
from .db import initialize_db
|
||||||
from .tui.things import run as things_tui
|
from .tui.things import run as things_tui
|
||||||
#from .tui.overview import run as overview_tui
|
|
||||||
|
# from .tui.overview import run as overview_tui
|
||||||
from .tui.recurring import run as recurring_tui
|
from .tui.recurring import run as recurring_tui
|
||||||
from .controller.things import add_thing
|
from .controller.things import add_thing
|
||||||
|
|
||||||
@ -40,6 +42,7 @@ def new(
|
|||||||
add_thing(name, category, due)
|
add_thing(name, category, due)
|
||||||
typer.echo("Created new thing!")
|
typer.echo("Created new thing!")
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def table(
|
def table(
|
||||||
view: Annotated[str, typer.Option("-v", "--view", help="saved view")] = "default",
|
view: Annotated[str, typer.Option("-v", "--view", help="saved view")] = "default",
|
||||||
@ -60,5 +63,23 @@ def overview():
|
|||||||
overview_tui()
|
overview_tui()
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def backup(backup_path: str):
|
||||||
|
"""
|
||||||
|
Perform a SQLite backup using the .backup dot command
|
||||||
|
"""
|
||||||
|
from tt.db import db
|
||||||
|
|
||||||
|
conn = db.connection()
|
||||||
|
|
||||||
|
backup_conn = None
|
||||||
|
try:
|
||||||
|
backup_conn = sqlite3.connect(backup_path)
|
||||||
|
conn.backup(backup_conn)
|
||||||
|
finally:
|
||||||
|
if backup_conn:
|
||||||
|
backup_conn.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app()
|
app()
|
||||||
|
@ -19,6 +19,7 @@ from xdg_base_dirs import xdg_config_home
|
|||||||
|
|
||||||
_raw_config = None
|
_raw_config = None
|
||||||
|
|
||||||
|
|
||||||
def _load_config():
|
def _load_config():
|
||||||
global _raw_config
|
global _raw_config
|
||||||
if not _raw_config:
|
if not _raw_config:
|
||||||
@ -35,6 +36,7 @@ def get_enum(name):
|
|||||||
|
|
||||||
raise ValueError(f"no such enum! {name}")
|
raise ValueError(f"no such enum! {name}")
|
||||||
|
|
||||||
|
|
||||||
def get_view(name):
|
def get_view(name):
|
||||||
for view in _load_config().get("views", []):
|
for view in _load_config().get("views", []):
|
||||||
if view["name"] == name:
|
if view["name"] == name:
|
||||||
@ -42,6 +44,7 @@ def get_view(name):
|
|||||||
|
|
||||||
raise ValueError(f"no such view! {name}")
|
raise ValueError(f"no such view! {name}")
|
||||||
|
|
||||||
|
|
||||||
def get_column(name):
|
def get_column(name):
|
||||||
if name in ("id", "type"):
|
if name in ("id", "type"):
|
||||||
return {"field_name": name, "display_name": name, "read_only": True}
|
return {"field_name": name, "display_name": name, "read_only": True}
|
||||||
@ -52,6 +55,7 @@ def get_column(name):
|
|||||||
|
|
||||||
raise ValueError(f"no such column! {name}")
|
raise ValueError(f"no such column! {name}")
|
||||||
|
|
||||||
|
|
||||||
# Valid statuses & projects are read dynamically from the user's config.
|
# Valid statuses & projects are read dynamically from the user's config.
|
||||||
STATUSES = get_enum("status")
|
STATUSES = get_enum("status")
|
||||||
PROJECTS = get_enum("projects")
|
PROJECTS = get_enum("projects")
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
|
|
||||||
SPECIAL_DATES_PIECES = {
|
SPECIAL_DATES_PIECES = {
|
||||||
"future": (3000,1,1),
|
"future": (3000, 1, 1),
|
||||||
"unclassified": (1999,1,1),
|
"unclassified": (1999, 1, 1),
|
||||||
}
|
}
|
||||||
SPECIAL_DATES_DISPLAY = {
|
SPECIAL_DATES_DISPLAY = {
|
||||||
"3000-01-01": "[#333333]future[/]",
|
"3000-01-01": "[#333333]future[/]",
|
||||||
"1999-01-01": "[#cccccc]unclassified[/]",
|
"1999-01-01": "[#cccccc]unclassified[/]",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,7 @@ def add_thing(
|
|||||||
Returns the created Thing instance.
|
Returns the created Thing instance.
|
||||||
"""
|
"""
|
||||||
with db.atomic():
|
with db.atomic():
|
||||||
thing = Thing.create(
|
thing = Thing.create(type=type, data=kwargs)
|
||||||
type=type, data=kwargs
|
|
||||||
)
|
|
||||||
return thing
|
return thing
|
||||||
|
|
||||||
|
|
||||||
@ -80,7 +78,7 @@ def get_things(
|
|||||||
|
|
||||||
if search_text:
|
if search_text:
|
||||||
# TODO: which fields are searchable should by dynamic
|
# TODO: which fields are searchable should by dynamic
|
||||||
query = query.where(fn.Lower(Thing.data['text']).contains(search_text.lower()))
|
query = query.where(fn.Lower(Thing.data["text"]).contains(search_text.lower()))
|
||||||
|
|
||||||
for param, val in filters.items():
|
for param, val in filters.items():
|
||||||
if val is not None:
|
if val is not None:
|
||||||
|
@ -5,6 +5,7 @@ from ..utils import (
|
|||||||
)
|
)
|
||||||
from .modals import ChoiceModal, DateModal
|
from .modals import ChoiceModal, DateModal
|
||||||
|
|
||||||
|
|
||||||
class NotifyValidationError(Exception):
|
class NotifyValidationError(Exception):
|
||||||
"""will notify and continue if raised"""
|
"""will notify and continue if raised"""
|
||||||
|
|
||||||
@ -82,7 +83,6 @@ class DateColumnConfig(TableColumnConfig):
|
|||||||
app.push_screen(DateModal(current_value), app.apply_change)
|
app.push_screen(DateModal(current_value), app.apply_change)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_col_cls(field_type):
|
def get_col_cls(field_type):
|
||||||
return {
|
return {
|
||||||
"text": TableColumnConfig,
|
"text": TableColumnConfig,
|
||||||
|
@ -18,7 +18,6 @@ from .modals import ConfirmModal
|
|||||||
from .columns import get_col_cls, NotifyValidationError
|
from .columns import get_col_cls, NotifyValidationError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TableEditor(App):
|
class TableEditor(App):
|
||||||
CSS = """
|
CSS = """
|
||||||
#footer {
|
#footer {
|
||||||
@ -223,9 +222,12 @@ class TableEditor(App):
|
|||||||
def action_delete_item(self):
|
def action_delete_item(self):
|
||||||
if self.table.cursor_column == 0:
|
if self.table.cursor_column == 0:
|
||||||
current_value = self.table.get_cell_at(
|
current_value = self.table.get_cell_at(
|
||||||
(self.table.cursor_row, 1) # assumes col 1 is name
|
(self.table.cursor_row, 1) # assumes col 1 is name
|
||||||
|
)
|
||||||
|
self.push_screen(
|
||||||
|
ConfirmModal(f"delete [green]{current_value}[/]?"),
|
||||||
|
self._delete_item_callback,
|
||||||
)
|
)
|
||||||
self.push_screen(ConfirmModal(f"delete [green]{current_value}[/]?"), self._delete_item_callback)
|
|
||||||
|
|
||||||
def _delete_item_callback(self, confirm):
|
def _delete_item_callback(self, confirm):
|
||||||
if confirm and self.table.cursor_column == 0:
|
if confirm and self.table.cursor_column == 0:
|
||||||
|
@ -92,20 +92,25 @@ class ChoiceModal(ModalScreen):
|
|||||||
+ get_color_enum(e.value, self._enum),
|
+ get_color_enum(e.value, self._enum),
|
||||||
classes="selected" if idx == self.sel_idx else "",
|
classes="selected" if idx == self.sel_idx else "",
|
||||||
)
|
)
|
||||||
yield Label("""(h/j/k/l) move (0-9) quick select
|
yield Label(
|
||||||
(enter) confirm (esc) quit""", classes="hints")
|
"""(h/j/k/l) move (0-9) quick select
|
||||||
|
(enter) confirm (esc) quit""",
|
||||||
|
classes="hints",
|
||||||
|
)
|
||||||
|
|
||||||
def _move_cursor(self, dir):
|
def _move_cursor(self, dir):
|
||||||
labels = self.query(Label)
|
labels = self.query(Label)
|
||||||
# reset old
|
# reset old
|
||||||
labels[self.sel_idx].update(
|
labels[self.sel_idx].update(
|
||||||
f" {self.sel_idx} " + get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
f" {self.sel_idx} "
|
||||||
|
+ get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
||||||
)
|
)
|
||||||
# move cursor
|
# move cursor
|
||||||
self.sel_idx = (self.sel_idx + dir) % len(self._enum)
|
self.sel_idx = (self.sel_idx + dir) % len(self._enum)
|
||||||
# reset new
|
# reset new
|
||||||
labels[self.sel_idx].update(
|
labels[self.sel_idx].update(
|
||||||
f"> {self.sel_idx} " + get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
f"> {self.sel_idx} "
|
||||||
|
+ get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
||||||
)
|
)
|
||||||
|
|
||||||
def action_cursor_down(self):
|
def action_cursor_down(self):
|
||||||
|
@ -7,7 +7,9 @@ from ..controller.generators import (
|
|||||||
update_generator,
|
update_generator,
|
||||||
generate_needed_things,
|
generate_needed_things,
|
||||||
)
|
)
|
||||||
from .editor import ( TableEditor, )
|
from .editor import (
|
||||||
|
TableEditor,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GenEditor(TableEditor):
|
class GenEditor(TableEditor):
|
||||||
|
@ -8,7 +8,6 @@ from .editor import TableEditor
|
|||||||
|
|
||||||
|
|
||||||
class ThingTable(TableEditor):
|
class ThingTable(TableEditor):
|
||||||
|
|
||||||
# BINDINGS = [
|
# BINDINGS = [
|
||||||
# # saved views
|
# # saved views
|
||||||
# ("ctrl+s", "save_view", "save current view"),
|
# ("ctrl+s", "save_view", "save current view"),
|
||||||
@ -67,6 +66,7 @@ class ThingTable(TableEditor):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def run(default_view):
|
def run(default_view):
|
||||||
app = ThingTable(default_view)
|
app = ThingTable(default_view)
|
||||||
app.run()
|
app.run()
|
||||||
|
Loading…
Reference in New Issue
Block a user