From e150bee233a648950061b716dc1780581105ede6 Mon Sep 17 00:00:00 2001 From: Christian Heller <c.heller@plomlompom.de> Date: Sat, 18 May 2024 08:04:10 +0200 Subject: [PATCH] Add Todo. and Process.calendarize to identify what Todos to show in calendar. --- migrations/3_add_Todo_and_Process_calendarize.sql | 2 ++ migrations/{init_2.sql => init_3.sql} | 4 +++- plomtask/days.py | 7 +++++++ plomtask/db.py | 5 ++++- plomtask/http.py | 4 ++++ plomtask/processes.py | 7 ++++--- plomtask/todos.py | 14 ++++++++++---- templates/calendar.html | 8 ++++++++ templates/process.html | 5 +++++ templates/todo.html | 5 +++++ 10 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 migrations/3_add_Todo_and_Process_calendarize.sql rename migrations/{init_2.sql => init_3.sql} (96%) diff --git a/migrations/3_add_Todo_and_Process_calendarize.sql b/migrations/3_add_Todo_and_Process_calendarize.sql new file mode 100644 index 0000000..dcd65b2 --- /dev/null +++ b/migrations/3_add_Todo_and_Process_calendarize.sql @@ -0,0 +1,2 @@ +ALTER TABLE todos ADD COLUMN calendarize BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE processes ADD COLUMN calendarize BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/migrations/init_2.sql b/migrations/init_3.sql similarity index 96% rename from migrations/init_2.sql rename to migrations/init_3.sql index 17e2db5..f261fd7 100644 --- a/migrations/init_2.sql +++ b/migrations/init_3.sql @@ -72,7 +72,8 @@ CREATE TABLE process_titles ( FOREIGN KEY (parent) REFERENCES processes(id) ); CREATE TABLE processes ( - id INTEGER PRIMARY KEY + id INTEGER PRIMARY KEY, + calendarize BOOLEAN NOT NULL DEFAULT FALSE ); CREATE TABLE todo_children ( parent INTEGER NOT NULL, @@ -109,6 +110,7 @@ CREATE TABLE todos ( day TEXT NOT NULL, comment TEXT NOT NULL DEFAULT "", effort REAL, + calendarize BOOLEAN NOT NULL DEFAULT FALSE, FOREIGN KEY (process) REFERENCES processes(id), FOREIGN KEY (day) REFERENCES days(id) ); diff --git a/plomtask/days.py b/plomtask/days.py index 5e97560..fe1ba44 100644 --- a/plomtask/days.py +++ b/plomtask/days.py @@ -3,6 +3,7 @@ from __future__ import annotations from datetime import datetime, timedelta from plomtask.exceptions import BadFormatException from plomtask.db import DatabaseConnection, BaseModel +from plomtask.todos import Todo DATE_FORMAT = '%Y-%m-%d' MIN_RANGE_DATE = '2024-01-01' @@ -36,6 +37,7 @@ class Day(BaseModel[str]): super().__init__(id_) self.datetime = datetime.strptime(self.date, DATE_FORMAT) self.comment = comment + self.calendarized_todos: list[Todo] = [] def __lt__(self, other: Day) -> bool: return self.date < other.date @@ -105,3 +107,8 @@ class Day(BaseModel[str]): """Return date succeeding date of this Day.""" next_datetime = self.datetime + timedelta(days=1) return next_datetime.strftime(DATE_FORMAT) + + def collect_calendarized_todos(self, db_conn: DatabaseConnection) -> None: + """Fill self.calendarized_todos.""" + self.calendarized_todos = [t for t in Todo.by_date(db_conn, self.date) + if t.calendarize] diff --git a/plomtask/db.py b/plomtask/db.py index 0e7df15..b4dc3e9 100644 --- a/plomtask/db.py +++ b/plomtask/db.py @@ -7,7 +7,7 @@ from sqlite3 import connect as sql_connect, Cursor, Row from typing import Any, Self, TypeVar, Generic from plomtask.exceptions import HandledException, NotFoundException -EXPECTED_DB_VERSION = 2 +EXPECTED_DB_VERSION = 3 MIGRATIONS_DIR = 'migrations' FILENAME_DB_SCHEMA = f'init_{EXPECTED_DB_VERSION}.sql' PATH_DB_SCHEMA = f'{MIGRATIONS_DIR}/{FILENAME_DB_SCHEMA}' @@ -131,6 +131,9 @@ class DatabaseFile: # pylint: disable=too-few-public-methods new_row += [f' {segment}'] new_row[0] = new_row[0].lstrip() new_row[-1] = new_row[-1].lstrip() + if new_row[-1] != ')' and new_row[-3][-1] != ',': + new_row[-3] = new_row[-3] + ',' + new_row[-2:] = [' ' + new_row[-1][:-1]] + [')'] new_rows += ['\n'.join(new_row)] return new_rows diff --git a/plomtask/http.py b/plomtask/http.py index d76ac05..080af8c 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -113,6 +113,8 @@ class TaskHandler(BaseHTTPRequestHandler): start = self.params.get_str('start') end = self.params.get_str('end') days = Day.all(self.conn, date_range=(start, end), fill_gaps=True) + for day in days: + day.collect_calendarized_todos(self.conn) return {'start': start, 'end': end, 'days': days} def do_GET_day(self) -> dict[str, object]: @@ -302,6 +304,7 @@ class TaskHandler(BaseHTTPRequestHandler): todo.set_enables(self.conn, self.form_data.get_all_int('enables')) todo.set_disables(self.conn, self.form_data.get_all_int('disables')) todo.is_done = len(self.form_data.get_all_str('done')) > 0 + todo.calendarize = len(self.form_data.get_all_str('calendarize')) > 0 todo.comment = self.form_data.get_str('comment', ignore_strict=True) todo.save(self.conn) for condition in todo.enables: @@ -325,6 +328,7 @@ class TaskHandler(BaseHTTPRequestHandler): self.form_data.get_all_int('condition')) process.set_enables(self.conn, self.form_data.get_all_int('enables')) process.set_disables(self.conn, self.form_data.get_all_int('disables')) + process.calendarize = self.form_data.get_all_str('calendarize') != [] process.save(self.conn) process.explicit_steps = [] steps: list[tuple[int | None, int, int | None]] = [] diff --git a/plomtask/processes.py b/plomtask/processes.py index 1778e4f..e136421 100644 --- a/plomtask/processes.py +++ b/plomtask/processes.py @@ -22,20 +22,21 @@ class ProcessStepsNode: class Process(BaseModel[int], ConditionsRelations): """Template for, and metadata for, Todos, and their arrangements.""" + # pylint: disable=too-many-instance-attributes table_name = 'processes' + to_save = ['calendarize'] to_save_versioned = ['title', 'description', 'effort'] to_save_relations = [('process_conditions', 'process', 'conditions'), ('process_enables', 'process', 'enables'), ('process_disables', 'process', 'disables')] - # pylint: disable=too-many-instance-attributes - - def __init__(self, id_: int | None) -> None: + def __init__(self, id_: int | None, calendarize: bool = False) -> None: super().__init__(id_) self.title = VersionedAttribute(self, 'process_titles', 'UNNAMED') self.description = VersionedAttribute(self, 'process_descriptions', '') self.effort = VersionedAttribute(self, 'process_efforts', 1.0) self.explicit_steps: list[ProcessStep] = [] + self.calendarize = calendarize self.conditions: list[Condition] = [] self.enables: list[Condition] = [] self.disables: list[Condition] = [] diff --git a/plomtask/todos.py b/plomtask/todos.py index 7cbe989..0fea234 100644 --- a/plomtask/todos.py +++ b/plomtask/todos.py @@ -23,7 +23,8 @@ class Todo(BaseModel[int], ConditionsRelations): """Individual actionable.""" # pylint: disable=too-many-instance-attributes table_name = 'todos' - to_save = ['process_id', 'is_done', 'date', 'comment', 'effort'] + to_save = ['process_id', 'is_done', 'date', 'comment', 'effort', + 'calendarize'] to_save_relations = [('todo_conditions', 'todo', 'conditions'), ('todo_enables', 'todo', 'enables'), ('todo_disables', 'todo', 'disables'), @@ -31,9 +32,12 @@ class Todo(BaseModel[int], ConditionsRelations): ('todo_children', 'child', 'parents')] # pylint: disable=too-many-arguments - def __init__(self, id_: int | None, process: Process, - is_done: bool, date: str, comment: str = '', - effort: None | float = None) -> None: + def __init__(self, id_: int | None, + process: Process, + is_done: bool, + date: str, comment: str = '', + effort: None | float = None, + calendarize: bool = False) -> None: super().__init__(id_) if process.id_ is None: raise NotFoundException('Process of Todo without ID (not saved?)') @@ -44,10 +48,12 @@ class Todo(BaseModel[int], ConditionsRelations): self.effort = effort self.children: list[Todo] = [] self.parents: list[Todo] = [] + self.calendarize = calendarize self.conditions: list[Condition] = [] self.enables: list[Condition] = [] self.disables: list[Condition] = [] if not self.id_: + self.calendarize = self.process.calendarize self.conditions = self.process.conditions[:] self.enables = self.process.enables[:] self.disables = self.process.disables[:] diff --git a/templates/calendar.html b/templates/calendar.html index 220e9bb..7724203 100644 --- a/templates/calendar.html +++ b/templates/calendar.html @@ -49,6 +49,14 @@ to <input name="end" value="{{end}}" /> <td>{{day.comment|e}}</td> </tr> +{% for todo in day.calendarized_todos %} +<tr> +<td>[{% if todo.is_done %}X{% else %} {% endif %}]</td> +<td><a href="todo?id={{todo.id_}}">{{todo.title.newest|e}}</td> +<td>{{todo.comment|e}}</td> +</tr> +{% endfor %} + {% endfor %} </table> {% endblock %} diff --git a/templates/process.html b/templates/process.html index d833c52..6dea493 100644 --- a/templates/process.html +++ b/templates/process.html @@ -55,6 +55,11 @@ add: <input name="new_step_to_{{step_id}}" list="candidates" autocomplete="off" <td><textarea name="description">{{process.description.newest|e}}</textarea><br />{% if process.id_ %} [<a href="process_descriptions?id={{process.id_}}">history</a>]{% endif %}</td> </tr> +<tr> +<th>calendarize</th> +<td><input type="checkbox" name="calendarize" {% if process.calendarize %}checked {% endif %}</td> +</tr> + <tr> <th>conditions</th> <td>{{ macros.simple_checkbox_table("condition", process.conditions, "condition", "condition_candidates") }}</td> diff --git a/templates/todo.html b/templates/todo.html index 6817cb9..efaabdd 100644 --- a/templates/todo.html +++ b/templates/todo.html @@ -33,6 +33,11 @@ <td><input name="comment" value="{{todo.comment|e}}"/></td> </tr> +<tr> +<th>calendarize</th> +<td><input type="checkbox" name="calendarize" {% if todo.calendarize %}checked {% endif %}</td> +</tr> + <tr> <th>conditions</th> <td>{{ macros.simple_checkbox_table("condition", todo.conditions, "condition", "condition_candidates") }}</td> -- 2.30.2