show next_at()
This commit is contained in:
parent
4980b2e7e5
commit
3279dd9e8c
@ -31,6 +31,8 @@ def update_generator(
|
||||
item_id: int,
|
||||
**kwargs,
|
||||
) -> TaskGenerator:
|
||||
# replace "val" with JSON
|
||||
if "val" in kwargs:
|
||||
config = {"val": kwargs.pop("val")}
|
||||
kwargs["config"] = json.dumps(config)
|
||||
with db.atomic():
|
||||
|
61
src/tt/db.py
61
src/tt/db.py
@ -1,4 +1,5 @@
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
from datetime import date, timedelta, datetime
|
||||
from enum import Enum
|
||||
from peewee import (
|
||||
BooleanField,
|
||||
@ -46,7 +47,6 @@ class Category(BaseModel):
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
# TODO: rename name
|
||||
text = TextField()
|
||||
status = CharField(
|
||||
choices=[(status.value, status.name) for status in TaskStatus],
|
||||
@ -81,32 +81,51 @@ class TaskGenerator(BaseModel):
|
||||
last_generated_at = DateTimeField(null=True)
|
||||
created_at = DateTimeField(default=datetime.now)
|
||||
|
||||
def should_generate(self) -> bool:
|
||||
def next_at(self) -> datetime.date:
|
||||
if self.deleted:
|
||||
return False
|
||||
return None
|
||||
|
||||
today = date.today()
|
||||
val = int(json.loads(self.config)["val"])
|
||||
|
||||
if self.type == GeneratorType.DAYS_BETWEEN.value:
|
||||
if not self.last_generated_at:
|
||||
return True
|
||||
return today
|
||||
return self.last_generated_at + timedelta(days=val)
|
||||
elif self.type == GeneratorType.MONTHLY.value:
|
||||
year, month, day = today.year, today.month, today.day
|
||||
day_of_month = val
|
||||
|
||||
now = datetime.now()
|
||||
if self.type == GeneratorType.DAYS_BETWEEN:
|
||||
days_between = self.config["val"]
|
||||
days_since = (now - self.last_generated_at).days
|
||||
return days_since >= days_between
|
||||
if day_of_month < day:
|
||||
month += 1
|
||||
if month == 13:
|
||||
month = 1
|
||||
year += 1
|
||||
|
||||
elif self.type == GeneratorType.MONTHLY:
|
||||
day_of_month = self.config["val"]
|
||||
if day_of_month >= 29 and month == 2:
|
||||
maybe_next = date(year, month, 28)
|
||||
else:
|
||||
maybe_next = date(year, month, day_of_month)
|
||||
|
||||
# check each day until now to see if target day occurred
|
||||
one_day = timedelta(days=1)
|
||||
check_date = self.last_generated_at + one_day
|
||||
while check_date <= now:
|
||||
if check_date.day == day_of_month:
|
||||
return True
|
||||
check_date += one_day
|
||||
|
||||
return False
|
||||
if not self.last_generated_at or self.last_generated_at < maybe_next:
|
||||
return maybe_next
|
||||
|
||||
# need to go forward one more month
|
||||
month += 1
|
||||
if month == 13:
|
||||
month = 1
|
||||
year += 1
|
||||
if day_of_month >= 29 and month == 2:
|
||||
maybe_next = date(year, month, 28)
|
||||
else:
|
||||
maybe_next = date(year, month, day_of_month)
|
||||
return maybe_next
|
||||
|
||||
def should_generate(self) -> bool:
|
||||
next = self.next_at()
|
||||
if not next:
|
||||
return False
|
||||
return next <= date.today()
|
||||
|
||||
|
||||
def initialize_db():
|
||||
|
@ -42,17 +42,19 @@ class TableColumnConfig:
|
||||
display_name: str,
|
||||
*,
|
||||
default=None,
|
||||
enable_editor=False,
|
||||
enum=None,
|
||||
filterable=True,
|
||||
preprocessor=None,
|
||||
enable_editor=False,
|
||||
filterable=True,
|
||||
read_only=False,
|
||||
):
|
||||
self.field = field
|
||||
self.display_name = display_name
|
||||
self.default = default
|
||||
self.enable_editor = enable_editor
|
||||
self.enum = enum
|
||||
self.enable_editor = enable_editor
|
||||
self.filterable = filterable
|
||||
self.read_only = read_only
|
||||
if preprocessor:
|
||||
self.preprocessor = preprocessor
|
||||
elif self.enum:
|
||||
@ -223,6 +225,8 @@ class TableEditor(App):
|
||||
# prepopulate with either the field default or the current filter
|
||||
prepopulated = {}
|
||||
for fc in self.TABLE_CONFIG:
|
||||
if fc.read_only:
|
||||
continue
|
||||
val = self.filters.get(fc.field, fc.default)
|
||||
if val is not None:
|
||||
# enums use comma separated filters
|
||||
@ -320,16 +324,21 @@ class TableEditor(App):
|
||||
self.saved_cursor_pos = (self.table.cursor_row, self.table.cursor_column)
|
||||
|
||||
def action_start_change(self):
|
||||
# invalid position
|
||||
if self.table.cursor_row is None or self.table.cursor_column == 0:
|
||||
return
|
||||
|
||||
# check if editable
|
||||
cconf = self._active_column_config()
|
||||
if cconf.read_only:
|
||||
return
|
||||
|
||||
self._save_cursor()
|
||||
current_value = self.table.get_cell_at(
|
||||
(self.table.cursor_row, self.table.cursor_column)
|
||||
)
|
||||
if current_value.endswith(ELLIPSIS):
|
||||
# TODO: flash message?
|
||||
# need to edit with e
|
||||
self.notify("multi-line text, use (e)dit")
|
||||
return
|
||||
current_value = remove_rich_tag(current_value)
|
||||
self._show_input("edit", current_value)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from ..controller.generators import (
|
||||
get_generator,
|
||||
@ -11,17 +10,9 @@ from ..db import GeneratorType
|
||||
from .editor import (
|
||||
TableEditor,
|
||||
TableColumnConfig,
|
||||
NotifyValidationError,
|
||||
)
|
||||
|
||||
|
||||
def due_preprocessor(val):
|
||||
try:
|
||||
return datetime.strptime(val, "%Y-%m-%d")
|
||||
except ValueError:
|
||||
raise NotifyValidationError("Invalid date format. Use YYYY-MM-DD")
|
||||
|
||||
|
||||
class TaskGenEditor(TableEditor):
|
||||
TABLE_CONFIG = (
|
||||
TableColumnConfig("id", "ID"),
|
||||
@ -32,7 +23,8 @@ class TaskGenEditor(TableEditor):
|
||||
default=GeneratorType.DAYS_BETWEEN.value,
|
||||
enum=GeneratorType,
|
||||
),
|
||||
TableColumnConfig("val", "Value", default=""),
|
||||
TableColumnConfig("val", "Value", default="1"),
|
||||
TableColumnConfig("next_at", "Next @", default="", read_only=True),
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
@ -45,14 +37,14 @@ class TaskGenEditor(TableEditor):
|
||||
items = get_generators()
|
||||
for item in items:
|
||||
self.table.add_row(
|
||||
str(item.id), item.template, item.type, json.loads(item.config)["val"]
|
||||
str(item.id),
|
||||
item.template,
|
||||
item.type,
|
||||
json.loads(item.config)["val"],
|
||||
str(item.next_at()),
|
||||
)
|
||||
|
||||
|
||||
def run():
|
||||
app = TaskGenEditor()
|
||||
app.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
|
Loading…
Reference in New Issue
Block a user