Compare commits
No commits in common. "4ed319e22e844483578be1597e86816693e15a4d" and "fe5be1115bf5bd54f47acf3546d4dd34453576c0" have entirely different histories.
4ed319e22e
...
fe5be1115b
@ -1,12 +1,10 @@
|
|||||||
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
|
||||||
|
|
||||||
@ -42,7 +40,6 @@ 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",
|
||||||
@ -63,23 +60,5 @@ 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()
|
||||||
|
@ -2,7 +2,7 @@ import tomlkit
|
|||||||
from xdg_base_dirs import xdg_config_home
|
from xdg_base_dirs import xdg_config_home
|
||||||
|
|
||||||
# This code implements a singleton-like pattern.
|
# This code implements a singleton-like pattern.
|
||||||
#
|
#
|
||||||
# The global variable _raw_config contains the cached config loaded
|
# The global variable _raw_config contains the cached config loaded
|
||||||
# from a TOML config file.
|
# from a TOML config file.
|
||||||
#
|
#
|
||||||
@ -13,13 +13,12 @@ from xdg_base_dirs import xdg_config_home
|
|||||||
# or not.
|
# or not.
|
||||||
#
|
#
|
||||||
# Eventually, this approach could also enable a live-reload function.
|
# Eventually, this approach could also enable a live-reload function.
|
||||||
#
|
#
|
||||||
# A command could be introduced that would reset _raw_config to None,
|
# A command could be introduced that would reset _raw_config to None,
|
||||||
# and the next read would reload the fresh data.
|
# and the next read would reload the fresh data.
|
||||||
|
|
||||||
_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:
|
||||||
@ -36,7 +35,6 @@ 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:
|
||||||
@ -44,7 +42,6 @@ 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}
|
||||||
@ -55,7 +52,6 @@ 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,8 +1,10 @@
|
|||||||
|
|
||||||
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,7 +17,9 @@ def add_thing(
|
|||||||
Returns the created Thing instance.
|
Returns the created Thing instance.
|
||||||
"""
|
"""
|
||||||
with db.atomic():
|
with db.atomic():
|
||||||
thing = Thing.create(type=type, data=kwargs)
|
thing = Thing.create(
|
||||||
|
type=type, data=kwargs
|
||||||
|
)
|
||||||
return thing
|
return thing
|
||||||
|
|
||||||
|
|
||||||
@ -78,7 +80,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:
|
||||||
|
@ -12,7 +12,7 @@ from peewee import (
|
|||||||
from playhouse.sqlite_ext import JSONField
|
from playhouse.sqlite_ext import JSONField
|
||||||
|
|
||||||
# This module defines the core data types.
|
# This module defines the core data types.
|
||||||
#
|
#
|
||||||
|
|
||||||
db = SqliteDatabase(
|
db = SqliteDatabase(
|
||||||
xdg_data_home() / "tt/tt.db",
|
xdg_data_home() / "tt/tt.db",
|
||||||
|
@ -5,7 +5,6 @@ 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"""
|
||||||
|
|
||||||
@ -83,6 +82,7 @@ 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,6 +18,7 @@ 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 {
|
||||||
@ -131,7 +132,7 @@ class TableEditor(App):
|
|||||||
self.filters = self.view["filters"]
|
self.filters = self.view["filters"]
|
||||||
self.sort_string = self.view["sort"]
|
self.sort_string = self.view["sort"]
|
||||||
self.defaults = self.view["defaults"]
|
self.defaults = self.view["defaults"]
|
||||||
|
|
||||||
def _db_item_to_row(self, item):
|
def _db_item_to_row(self, item):
|
||||||
"""
|
"""
|
||||||
Convert db item to a row for display.
|
Convert db item to a row for display.
|
||||||
@ -222,12 +223,9 @@ 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,25 +92,20 @@ 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(
|
yield Label("""(h/j/k/l) move (0-9) quick select
|
||||||
"""(h/j/k/l) move (0-9) quick select
|
(enter) confirm (esc) quit""", classes="hints")
|
||||||
(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} "
|
f" {self.sel_idx} " + get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
||||||
+ 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} "
|
f"> {self.sel_idx} " + get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
||||||
+ get_color_enum(self.enum_by_idx[self.sel_idx], self._enum)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def action_cursor_down(self):
|
def action_cursor_down(self):
|
||||||
|
@ -7,9 +7,7 @@ from ..controller.generators import (
|
|||||||
update_generator,
|
update_generator,
|
||||||
generate_needed_things,
|
generate_needed_things,
|
||||||
)
|
)
|
||||||
from .editor import (
|
from .editor import ( TableEditor, )
|
||||||
TableEditor,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GenEditor(TableEditor):
|
class GenEditor(TableEditor):
|
||||||
|
@ -8,6 +8,7 @@ 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"),
|
||||||
@ -66,7 +67,6 @@ 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