--- /dev/null
+ALTER TABLE todos ADD COLUMN calendarize BOOLEAN NOT NULL DEFAULT FALSE;
+ALTER TABLE processes ADD COLUMN calendarize BOOLEAN NOT NULL DEFAULT FALSE;
+++ /dev/null
-CREATE TABLE condition_descriptions (
- parent INTEGER NOT NULL,
- timestamp TEXT NOT NULL,
- description TEXT NOT NULL,
- PRIMARY KEY (parent, timestamp),
- FOREIGN KEY (parent) REFERENCES conditions(id)
-);
-CREATE TABLE condition_titles (
- parent INTEGER NOT NULL,
- timestamp TEXT NOT NULL,
- title TEXT NOT NULL,
- PRIMARY KEY (parent, timestamp),
- FOREIGN KEY (parent) REFERENCES conditions(id)
-);
-CREATE TABLE conditions (
- id INTEGER PRIMARY KEY,
- is_active BOOLEAN NOT NULL
-);
-CREATE TABLE days (
- id TEXT PRIMARY KEY,
- comment TEXT NOT NULL
-);
-CREATE TABLE process_conditions (
- process INTEGER NOT NULL,
- condition INTEGER NOT NULL,
- PRIMARY KEY (process, condition),
- FOREIGN KEY (process) REFERENCES processes(id),
- FOREIGN KEY (condition) REFERENCES conditions(id)
-);
-CREATE TABLE process_descriptions (
- parent INTEGER NOT NULL,
- timestamp TEXT NOT NULL,
- description TEXT NOT NULL,
- PRIMARY KEY (parent, timestamp),
- FOREIGN KEY (parent) REFERENCES processes(id)
-);
-CREATE TABLE process_disables (
- process INTEGER NOT NULL,
- condition INTEGER NOT NULL,
- PRIMARY KEY(process, condition),
- FOREIGN KEY (process) REFERENCES processes(id),
- FOREIGN KEY (condition) REFERENCES conditions(id)
-);
-CREATE TABLE process_efforts (
- parent INTEGER NOT NULL,
- timestamp TEXT NOT NULL,
- effort REAL NOT NULL,
- PRIMARY KEY (parent, timestamp),
- FOREIGN KEY (parent) REFERENCES processes(id)
-);
-CREATE TABLE process_enables (
- process INTEGER NOT NULL,
- condition INTEGER NOT NULL,
- PRIMARY KEY(process, condition),
- FOREIGN KEY (process) REFERENCES processes(id),
- FOREIGN KEY (condition) REFERENCES conditions(id)
-);
-CREATE TABLE process_steps (
- id INTEGER PRIMARY KEY,
- owner INTEGER NOT NULL,
- step_process INTEGER NOT NULL,
- parent_step INTEGER,
- FOREIGN KEY (owner) REFERENCES processes(id),
- FOREIGN KEY (step_process) REFERENCES processes(id),
- FOREIGN KEY (parent_step) REFERENCES process_steps(step_id)
-);
-CREATE TABLE process_titles (
- parent INTEGER NOT NULL,
- timestamp TEXT NOT NULL,
- title TEXT NOT NULL,
- PRIMARY KEY (parent, timestamp),
- FOREIGN KEY (parent) REFERENCES processes(id)
-);
-CREATE TABLE processes (
- id INTEGER PRIMARY KEY
-);
-CREATE TABLE todo_children (
- parent INTEGER NOT NULL,
- child INTEGER NOT NULL,
- PRIMARY KEY (parent, child),
- FOREIGN KEY (parent) REFERENCES todos(id),
- FOREIGN KEY (child) REFERENCES todos(id)
-);
-CREATE TABLE todo_conditions (
- todo INTEGER NOT NULL,
- condition INTEGER NOT NULL,
- PRIMARY KEY(todo, condition),
- FOREIGN KEY (todo) REFERENCES todos(id),
- FOREIGN KEY (condition) REFERENCES conditions(id)
-);
-CREATE TABLE todo_disables (
- todo INTEGER NOT NULL,
- condition INTEGER NOT NULL,
- PRIMARY KEY(todo, condition),
- FOREIGN KEY (todo) REFERENCES todos(id),
- FOREIGN KEY (condition) REFERENCES conditions(id)
-);
-CREATE TABLE todo_enables (
- todo INTEGER NOT NULL,
- condition INTEGER NOT NULL,
- PRIMARY KEY(todo, condition),
- FOREIGN KEY (todo) REFERENCES todos(id),
- FOREIGN KEY (condition) REFERENCES conditions(id)
-);
-CREATE TABLE todos (
- id INTEGER PRIMARY KEY,
- process INTEGER NOT NULL,
- is_done BOOLEAN NOT NULL,
- day TEXT NOT NULL,
- comment TEXT NOT NULL DEFAULT "",
- effort REAL,
- FOREIGN KEY (process) REFERENCES processes(id),
- FOREIGN KEY (day) REFERENCES days(id)
-);
--- /dev/null
+CREATE TABLE condition_descriptions (
+ parent INTEGER NOT NULL,
+ timestamp TEXT NOT NULL,
+ description TEXT NOT NULL,
+ PRIMARY KEY (parent, timestamp),
+ FOREIGN KEY (parent) REFERENCES conditions(id)
+);
+CREATE TABLE condition_titles (
+ parent INTEGER NOT NULL,
+ timestamp TEXT NOT NULL,
+ title TEXT NOT NULL,
+ PRIMARY KEY (parent, timestamp),
+ FOREIGN KEY (parent) REFERENCES conditions(id)
+);
+CREATE TABLE conditions (
+ id INTEGER PRIMARY KEY,
+ is_active BOOLEAN NOT NULL
+);
+CREATE TABLE days (
+ id TEXT PRIMARY KEY,
+ comment TEXT NOT NULL
+);
+CREATE TABLE process_conditions (
+ process INTEGER NOT NULL,
+ condition INTEGER NOT NULL,
+ PRIMARY KEY (process, condition),
+ FOREIGN KEY (process) REFERENCES processes(id),
+ FOREIGN KEY (condition) REFERENCES conditions(id)
+);
+CREATE TABLE process_descriptions (
+ parent INTEGER NOT NULL,
+ timestamp TEXT NOT NULL,
+ description TEXT NOT NULL,
+ PRIMARY KEY (parent, timestamp),
+ FOREIGN KEY (parent) REFERENCES processes(id)
+);
+CREATE TABLE process_disables (
+ process INTEGER NOT NULL,
+ condition INTEGER NOT NULL,
+ PRIMARY KEY(process, condition),
+ FOREIGN KEY (process) REFERENCES processes(id),
+ FOREIGN KEY (condition) REFERENCES conditions(id)
+);
+CREATE TABLE process_efforts (
+ parent INTEGER NOT NULL,
+ timestamp TEXT NOT NULL,
+ effort REAL NOT NULL,
+ PRIMARY KEY (parent, timestamp),
+ FOREIGN KEY (parent) REFERENCES processes(id)
+);
+CREATE TABLE process_enables (
+ process INTEGER NOT NULL,
+ condition INTEGER NOT NULL,
+ PRIMARY KEY(process, condition),
+ FOREIGN KEY (process) REFERENCES processes(id),
+ FOREIGN KEY (condition) REFERENCES conditions(id)
+);
+CREATE TABLE process_steps (
+ id INTEGER PRIMARY KEY,
+ owner INTEGER NOT NULL,
+ step_process INTEGER NOT NULL,
+ parent_step INTEGER,
+ FOREIGN KEY (owner) REFERENCES processes(id),
+ FOREIGN KEY (step_process) REFERENCES processes(id),
+ FOREIGN KEY (parent_step) REFERENCES process_steps(step_id)
+);
+CREATE TABLE process_titles (
+ parent INTEGER NOT NULL,
+ timestamp TEXT NOT NULL,
+ title TEXT NOT NULL,
+ PRIMARY KEY (parent, timestamp),
+ FOREIGN KEY (parent) REFERENCES processes(id)
+);
+CREATE TABLE processes (
+ id INTEGER PRIMARY KEY,
+ calendarize BOOLEAN NOT NULL DEFAULT FALSE
+);
+CREATE TABLE todo_children (
+ parent INTEGER NOT NULL,
+ child INTEGER NOT NULL,
+ PRIMARY KEY (parent, child),
+ FOREIGN KEY (parent) REFERENCES todos(id),
+ FOREIGN KEY (child) REFERENCES todos(id)
+);
+CREATE TABLE todo_conditions (
+ todo INTEGER NOT NULL,
+ condition INTEGER NOT NULL,
+ PRIMARY KEY(todo, condition),
+ FOREIGN KEY (todo) REFERENCES todos(id),
+ FOREIGN KEY (condition) REFERENCES conditions(id)
+);
+CREATE TABLE todo_disables (
+ todo INTEGER NOT NULL,
+ condition INTEGER NOT NULL,
+ PRIMARY KEY(todo, condition),
+ FOREIGN KEY (todo) REFERENCES todos(id),
+ FOREIGN KEY (condition) REFERENCES conditions(id)
+);
+CREATE TABLE todo_enables (
+ todo INTEGER NOT NULL,
+ condition INTEGER NOT NULL,
+ PRIMARY KEY(todo, condition),
+ FOREIGN KEY (todo) REFERENCES todos(id),
+ FOREIGN KEY (condition) REFERENCES conditions(id)
+);
+CREATE TABLE todos (
+ id INTEGER PRIMARY KEY,
+ process INTEGER NOT NULL,
+ is_done BOOLEAN NOT NULL,
+ 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)
+);
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'
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
"""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]
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}'
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
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]:
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:
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]] = []
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] = []
"""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'),
('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?)')
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[:]
<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 %}
<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>
<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>