From 41f24ba3416bc5be3773983356fc8288543b0c42 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 07:20:33 +0200 Subject: [PATCH 01/16] Fix pre-commit hook not aborting commit on failed unit tests. --- scripts/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pre-commit b/scripts/pre-commit index 19ec806..c92a5eb 100755 --- a/scripts/pre-commit +++ b/scripts/pre-commit @@ -9,8 +9,8 @@ for dir in $(echo '.' 'plomtask' 'tests'); do python3 -m pylint ${dir}/*.py done echo "Running unittest-parallel on tests/." -set +e unittest-parallel -t . -s tests/ -p '*.py' +set +e rm test_db:*.* set -e exit 0 -- 2.30.2 From f79031c51b888d66448d18b159f17fbe28c7885c Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 07:23:41 +0200 Subject: [PATCH 02/16] Fix broken date range test. --- tests/days.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/days.py b/tests/days.py index 9e12d3f..0556164 100644 --- a/tests/days.py +++ b/tests/days.py @@ -81,13 +81,13 @@ class TestsWithDB(TestCaseWithDB): []) # check fill_gaps= instantiates unsaved dates within date range # (but does not store them) - day4 = Day('2024-01-04') day5 = Day('2024-01-05') day6 = Day('2024-01-06') day6.save(self.db_conn) - self.assertEqual(Day.all(self.db_conn, (date2, '2024-01-07'), + day7 = Day('2024-01-07') + self.assertEqual(Day.all(self.db_conn, (day5.date, day7.date), fill_gaps=True), - [day2, day3, day4, day5, day6]) + [day5, day6, day7]) self.check_storage([day1, day2, day3, day6]) # check 'today' is interpreted as today's date today = Day(todays_date()) -- 2.30.2 From f92de64d072009c8c4bf96b9eeb9fa245045662b Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 08:12:33 +0200 Subject: [PATCH 03/16] Use same date ranging code for Day and Todo filtering. --- plomtask/dating.py | 24 ++++++++++++++++++++++++ plomtask/days.py | 36 +++--------------------------------- plomtask/db.py | 24 ++++++++++++++++++++++++ plomtask/http.py | 11 +++++------ plomtask/todos.py | 15 ++++++++++----- tests/days.py | 3 ++- tests/todos.py | 3 ++- 7 files changed, 70 insertions(+), 46 deletions(-) create mode 100644 plomtask/dating.py diff --git a/plomtask/dating.py b/plomtask/dating.py new file mode 100644 index 0000000..e143fb6 --- /dev/null +++ b/plomtask/dating.py @@ -0,0 +1,24 @@ +"""Various utilities for handling dates.""" +from datetime import datetime +from plomtask.exceptions import BadFormatException + +DATE_FORMAT = '%Y-%m-%d' +MIN_RANGE_DATE = '2024-01-01' +MAX_RANGE_DATE = '2030-12-31' + + +def valid_date(date_str: str) -> str: + """Validate date against DATE_FORMAT or 'today', return in DATE_FORMAT.""" + if date_str == 'today': + date_str = todays_date() + try: + dt = datetime.strptime(date_str, DATE_FORMAT) + except (ValueError, TypeError) as e: + msg = f'Given date of wrong format: {date_str}' + raise BadFormatException(msg) from e + return dt.strftime(DATE_FORMAT) + + +def todays_date() -> str: + """Return current date in DATE_FORMAT.""" + return datetime.now().strftime(DATE_FORMAT) diff --git a/plomtask/days.py b/plomtask/days.py index e3d56d7..d7083b4 100644 --- a/plomtask/days.py +++ b/plomtask/days.py @@ -1,30 +1,9 @@ """Collecting Day and date-related items.""" 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' -MAX_RANGE_DATE = '2030-12-31' - - -def valid_date(date_str: str) -> str: - """Validate date against DATE_FORMAT or 'today', return in DATE_FORMAT.""" - if date_str == 'today': - date_str = todays_date() - try: - dt = datetime.strptime(date_str, DATE_FORMAT) - except (ValueError, TypeError) as e: - msg = f'Given date of wrong format: {date_str}' - raise BadFormatException(msg) from e - return dt.strftime(DATE_FORMAT) - - -def todays_date() -> str: - """Return current date in DATE_FORMAT.""" - return datetime.now().strftime(DATE_FORMAT) +from plomtask.dating import (DATE_FORMAT, valid_date) class Day(BaseModel[str]): @@ -48,20 +27,11 @@ class Day(BaseModel[str]): fill_gaps: bool = False) -> list[Day]: """Return list of Days in database within (open) date_range interval. - If no range values provided, defaults them to MIN_RANGE_DATE and - MAX_RANGE_DATE. Also knows to properly interpret 'today' as value. - On fill_gaps=True, will instantiate (without saving) Days of all dates within the date range that don't exist yet. """ - min_date = '2024-01-01' - max_date = '2030-12-31' - start_date = valid_date(date_range[0] if date_range[0] else min_date) - end_date = valid_date(date_range[1] if date_range[1] else max_date) - days = [] - sql = 'SELECT id FROM days WHERE id >= ? AND id <= ?' - for row in db_conn.exec(sql, (start_date, end_date)): - days += [cls.by_id(db_conn, row[0])] + ret = cls.by_date_range_with_limits(db_conn, date_range, 'id') + days, start_date, end_date = ret days.sort() if fill_gaps: if start_date not in [d.date for d in days]: diff --git a/plomtask/db.py b/plomtask/db.py index 548381e..4396b44 100644 --- a/plomtask/db.py +++ b/plomtask/db.py @@ -6,6 +6,7 @@ from difflib import Differ from sqlite3 import connect as sql_connect, Cursor, Row from typing import Any, Self, TypeVar, Generic from plomtask.exceptions import HandledException, NotFoundException +from plomtask.dating import (MIN_RANGE_DATE, MAX_RANGE_DATE, valid_date) EXPECTED_DB_VERSION = 4 MIGRATIONS_DIR = 'migrations' @@ -354,6 +355,29 @@ class BaseModel(Generic[BaseModelId]): items[item.id_] = item return list(items.values()) + @classmethod + def by_date_range_with_limits(cls: type[BaseModelInstance], + db_conn: DatabaseConnection, + date_range: tuple[str, str] = ('', ''), + date_col: str = 'day' + ) -> tuple[list[BaseModelInstance], str, + str]: + """Return list of Days in database within (open) date_range interval. + + If no range values provided, defaults them to MIN_RANGE_DATE and + MAX_RANGE_DATE. Also knows to properly interpret 'today' as value. + """ + min_date = MIN_RANGE_DATE + max_date = MAX_RANGE_DATE + start_date = valid_date(date_range[0] if date_range[0] else min_date) + end_date = valid_date(date_range[1] if date_range[1] else max_date) + items = [] + sql = f'SELECT id FROM {cls.table_name} ' + sql += f'WHERE {date_col} >= ? AND {date_col} <= ?' + for row in db_conn.exec(sql, (start_date, end_date)): + items += [cls.by_id(db_conn, row[0])] + return items, start_date, end_date + @classmethod def matching(cls: type[BaseModelInstance], db_conn: DatabaseConnection, pattern: str) -> list[BaseModelInstance]: diff --git a/plomtask/http.py b/plomtask/http.py index b81083b..a2e8fa6 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -5,7 +5,8 @@ from http.server import HTTPServer from urllib.parse import urlparse, parse_qs from os.path import split as path_split from jinja2 import Environment as JinjaEnv, FileSystemLoader as JinjaFSLoader -from plomtask.days import Day, todays_date +from plomtask.dating import todays_date +from plomtask.days import Day from plomtask.exceptions import HandledException, BadFormatException, \ NotFoundException from plomtask.db import DatabaseConnection, DatabaseFile @@ -160,11 +161,9 @@ class TaskHandler(BaseHTTPRequestHandler): process_id = self.params.get_int_or_none('process_id') comment_pattern = self.params.get_str('comment_pattern') todos = [] - for t in Todo.matching(self.conn, comment_pattern): - # pylint: disable=too-many-boolean-expressions - if (start and t.date < start)\ - or (end and t.date > end)\ - or (process_id and t.process.id_ != process_id): + for t in Todo.by_date_range(self.conn, (start, end)): + if (process_id and t.process.id_ != process_id)\ + or (comment_pattern not in t.comment): continue todos += [t] if sort_by == 'doneness': diff --git a/plomtask/todos.py b/plomtask/todos.py index ffef677..46a353d 100644 --- a/plomtask/todos.py +++ b/plomtask/todos.py @@ -9,6 +9,7 @@ from plomtask.versioned_attributes import VersionedAttribute from plomtask.conditions import Condition, ConditionsRelations from plomtask.exceptions import (NotFoundException, BadFormatException, HandledException) +from plomtask.dating import valid_date @dataclass @@ -46,7 +47,7 @@ class Todo(BaseModel[int], ConditionsRelations): raise NotFoundException('Process of Todo without ID (not saved?)') self.process = process self._is_done = is_done - self.date = date + self.date = valid_date(date) self.comment = comment self.effort = effort self.children: list[Todo] = [] @@ -59,6 +60,13 @@ class Todo(BaseModel[int], ConditionsRelations): self.enables = self.process.enables[:] self.disables = self.process.disables[:] + @classmethod + def by_date_range(cls, db_conn: DatabaseConnection, + date_range: tuple[str, str] = ('', '')) -> list[Todo]: + """Collect Todos of Days within date_range.""" + todos, _, _ = cls.by_date_range_with_limits(db_conn, date_range) + return todos + @classmethod def create_with_children(cls, db_conn: DatabaseConnection, date: str, process_ids: list[int]) -> list[Todo]: @@ -117,10 +125,7 @@ class Todo(BaseModel[int], ConditionsRelations): @classmethod def by_date(cls, db_conn: DatabaseConnection, date: str) -> list[Todo]: """Collect all Todos for Day of date.""" - todos = [] - for id_ in db_conn.column_where('todos', 'id', 'day', date): - todos += [cls.by_id(db_conn, id_)] - return todos + return cls.by_date_range(db_conn, (date, date)) @property def is_doable(self) -> bool: diff --git a/tests/days.py b/tests/days.py index 0556164..c1e1343 100644 --- a/tests/days.py +++ b/tests/days.py @@ -2,7 +2,8 @@ from unittest import TestCase from datetime import datetime from tests.utils import TestCaseWithDB, TestCaseWithServer -from plomtask.days import Day, todays_date +from plomtask.dating import todays_date +from plomtask.days import Day from plomtask.exceptions import BadFormatException diff --git a/tests/todos.py b/tests/todos.py index 4ba5a1c..86986b6 100644 --- a/tests/todos.py +++ b/tests/todos.py @@ -63,7 +63,8 @@ class TestsWithDB(TestCaseWithDB): t2.save(self.db_conn) self.assertEqual(Todo.by_date(self.db_conn, self.date1), [t1, t2]) self.assertEqual(Todo.by_date(self.db_conn, self.date2), []) - self.assertEqual(Todo.by_date(self.db_conn, 'foo'), []) + with self.assertRaises(BadFormatException): + self.assertEqual(Todo.by_date(self.db_conn, 'foo'), []) def test_Todo_on_conditions(self) -> None: """Test effect of Todos on Conditions.""" -- 2.30.2 From 8945aa6762977c04538c49c320417311b38232be Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 08:17:54 +0200 Subject: [PATCH 04/16] For date range inputs, allow "yesterday" and "tomorrow" next to "today". --- plomtask/dating.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plomtask/dating.py b/plomtask/dating.py index e143fb6..711da95 100644 --- a/plomtask/dating.py +++ b/plomtask/dating.py @@ -1,5 +1,5 @@ """Various utilities for handling dates.""" -from datetime import datetime +from datetime import datetime, timedelta from plomtask.exceptions import BadFormatException DATE_FORMAT = '%Y-%m-%d' @@ -8,9 +8,18 @@ MAX_RANGE_DATE = '2030-12-31' def valid_date(date_str: str) -> str: - """Validate date against DATE_FORMAT or 'today', return in DATE_FORMAT.""" + """Validate date against DATE_FORMAT or 'today'/'yesterday'/'tomorrow. + + In any case, returns in DATE_FORMAT. + """ if date_str == 'today': date_str = todays_date() + elif date_str == 'yesterday': + date = datetime.now() - timedelta(days=1) + date_str = date.strftime(DATE_FORMAT) + elif date_str == 'tomorrow': + date = datetime.now() + timedelta(days=1) + date_str = date.strftime(DATE_FORMAT) try: dt = datetime.strptime(date_str, DATE_FORMAT) except (ValueError, TypeError) as e: -- 2.30.2 From eff89a3ebc0b3bf5b340b0ebd2b32fa136d8f640 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 08:57:46 +0200 Subject: [PATCH 05/16] Re-factor date ranging and default to range 'yesterday' to 'tomorrow'. --- plomtask/dating.py | 2 -- plomtask/days.py | 48 ++++++++++++++++++++++++---------------------- plomtask/db.py | 16 ++++++++-------- plomtask/http.py | 14 ++++++++------ tests/days.py | 24 +++++++++++------------ 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/plomtask/dating.py b/plomtask/dating.py index 711da95..c55d847 100644 --- a/plomtask/dating.py +++ b/plomtask/dating.py @@ -3,8 +3,6 @@ from datetime import datetime, timedelta from plomtask.exceptions import BadFormatException DATE_FORMAT = '%Y-%m-%d' -MIN_RANGE_DATE = '2024-01-01' -MAX_RANGE_DATE = '2030-12-31' def valid_date(date_str: str) -> str: diff --git a/plomtask/days.py b/plomtask/days.py index d7083b4..0815b9b 100644 --- a/plomtask/days.py +++ b/plomtask/days.py @@ -22,31 +22,33 @@ class Day(BaseModel[str]): return self.date < other.date @classmethod - def all(cls, db_conn: DatabaseConnection, - date_range: tuple[str, str] = ('', ''), - fill_gaps: bool = False) -> list[Day]: - """Return list of Days in database within (open) date_range interval. - - On fill_gaps=True, will instantiate (without saving) Days of all dates - within the date range that don't exist yet. - """ - ret = cls.by_date_range_with_limits(db_conn, date_range, 'id') + def by_date_range_filled(cls, db_conn: DatabaseConnection, + start: str, end: str) -> list[Day]: + """Return days existing and non-existing between dates start/end.""" + ret = cls.by_date_range_with_limits(db_conn, (start, end), 'id') days, start_date, end_date = ret + return cls.with_filled_gaps(days, start_date, end_date) + + @classmethod + def with_filled_gaps(cls, days: list[Day], start_date: str, end_date: str + ) -> list[Day]: + """In days, fill with (un-saved) Days gaps between start/end_date.""" + if start_date > end_date: + return days days.sort() - if fill_gaps: - if start_date not in [d.date for d in days]: - days = [Day(start_date)] + days - if end_date not in [d.date for d in days]: - days += [Day(end_date)] - if len(days) > 1: - gapless_days = [] - for i, day in enumerate(days): - gapless_days += [day] - if i < len(days) - 1: - while day.next_date != days[i+1].date: - day = Day(day.next_date) - gapless_days += [day] - days = gapless_days + if start_date not in [d.date for d in days]: + days[:] = [Day(start_date)] + days + if end_date not in [d.date for d in days]: + days += [Day(end_date)] + if len(days) > 1: + gapless_days = [] + for i, day in enumerate(days): + gapless_days += [day] + if i < len(days) - 1: + while day.next_date != days[i+1].date: + day = Day(day.next_date) + gapless_days += [day] + days[:] = gapless_days return days @property diff --git a/plomtask/db.py b/plomtask/db.py index 4396b44..b5461a5 100644 --- a/plomtask/db.py +++ b/plomtask/db.py @@ -6,7 +6,7 @@ from difflib import Differ from sqlite3 import connect as sql_connect, Cursor, Row from typing import Any, Self, TypeVar, Generic from plomtask.exceptions import HandledException, NotFoundException -from plomtask.dating import (MIN_RANGE_DATE, MAX_RANGE_DATE, valid_date) +from plomtask.dating import valid_date EXPECTED_DB_VERSION = 4 MIGRATIONS_DIR = 'migrations' @@ -358,19 +358,19 @@ class BaseModel(Generic[BaseModelId]): @classmethod def by_date_range_with_limits(cls: type[BaseModelInstance], db_conn: DatabaseConnection, - date_range: tuple[str, str] = ('', ''), + date_range: tuple[str, str], date_col: str = 'day' ) -> tuple[list[BaseModelInstance], str, str]: """Return list of Days in database within (open) date_range interval. - If no range values provided, defaults them to MIN_RANGE_DATE and - MAX_RANGE_DATE. Also knows to properly interpret 'today' as value. + If no range values provided, defaults them to 'yesterday' and + 'tomorrow'. Knows to properly interpret these and 'today' as value. """ - min_date = MIN_RANGE_DATE - max_date = MAX_RANGE_DATE - start_date = valid_date(date_range[0] if date_range[0] else min_date) - end_date = valid_date(date_range[1] if date_range[1] else max_date) + start_str = date_range[0] if date_range[0] else 'yesterday' + end_str = date_range[1] if date_range[1] else 'tomorrow' + start_date = valid_date(start_str) + end_date = valid_date(end_str) items = [] sql = f'SELECT id FROM {cls.table_name} ' sql += f'WHERE {date_col} >= ? AND {date_col} <= ?' diff --git a/plomtask/http.py b/plomtask/http.py index a2e8fa6..cf7bb08 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -113,7 +113,9 @@ class TaskHandler(BaseHTTPRequestHandler): """Show Days from ?start= to ?end=.""" start = self.params.get_str('start') end = self.params.get_str('end') - days = Day.all(self.conn, date_range=(start, end), fill_gaps=True) + ret = Day.by_date_range_with_limits(self.conn, (start, end), 'id') + days, start, end = ret + days = Day.with_filled_gaps(days, start, end) for day in days: day.collect_calendarized_todos(self.conn) return {'start': start, 'end': end, 'days': days} @@ -161,11 +163,11 @@ class TaskHandler(BaseHTTPRequestHandler): process_id = self.params.get_int_or_none('process_id') comment_pattern = self.params.get_str('comment_pattern') todos = [] - for t in Todo.by_date_range(self.conn, (start, end)): - if (process_id and t.process.id_ != process_id)\ - or (comment_pattern not in t.comment): - continue - todos += [t] + ret = Todo.by_date_range_with_limits(self.conn, (start, end)) + todos_by_date_range, start, end = ret + todos = [t for t in todos_by_date_range + if comment_pattern in t.comment + and ((not process_id) or t.process.id_ == process_id)] if sort_by == 'doneness': todos.sort(key=lambda t: t.is_done) elif sort_by == '-doneness': diff --git a/tests/days.py b/tests/days.py index c1e1343..4727fac 100644 --- a/tests/days.py +++ b/tests/days.py @@ -60,25 +60,21 @@ class TestsWithDB(TestCaseWithDB): """Test .by_id().""" self.check_by_id() - def test_Day_all(self) -> None: - """Test Day.all(), especially in regards to date range filtering.""" + def test_Day_by_date_range_filled(self) -> None: + """Test Day.by_date_range_filled.""" date1, date2, date3 = self.default_ids day1, day2, day3 = self.check_all() - self.assertEqual(Day.all(self.db_conn, ('', '')), - [day1, day2, day3]) # check date range is a closed interval - self.assertEqual(Day.all(self.db_conn, (date1, date3)), + self.assertEqual(Day.by_date_range_filled(self.db_conn, date1, date3), [day1, day2, day3]) # check first date range value excludes what's earlier - self.assertEqual(Day.all(self.db_conn, (date2, date3)), + self.assertEqual(Day.by_date_range_filled(self.db_conn, date2, date3), [day2, day3]) - self.assertEqual(Day.all(self.db_conn, (date3, '')), - [day3]) # check second date range value excludes what's later - self.assertEqual(Day.all(self.db_conn, ('', date2)), + self.assertEqual(Day.by_date_range_filled(self.db_conn, date1, date2), [day1, day2]) # check swapped (impossible) date range returns emptiness - self.assertEqual(Day.all(self.db_conn, (date3, date1)), + self.assertEqual(Day.by_date_range_filled(self.db_conn, date3, date1), []) # check fill_gaps= instantiates unsaved dates within date range # (but does not store them) @@ -86,14 +82,16 @@ class TestsWithDB(TestCaseWithDB): day6 = Day('2024-01-06') day6.save(self.db_conn) day7 = Day('2024-01-07') - self.assertEqual(Day.all(self.db_conn, (day5.date, day7.date), - fill_gaps=True), + self.assertEqual(Day.by_date_range_filled(self.db_conn, + day5.date, day7.date), [day5, day6, day7]) self.check_storage([day1, day2, day3, day6]) # check 'today' is interpreted as today's date today = Day(todays_date()) today.save(self.db_conn) - self.assertEqual(Day.all(self.db_conn, ('today', 'today')), [today]) + self.assertEqual(Day.by_date_range_filled(self.db_conn, + 'today', 'today'), + [today]) def test_Day_remove(self) -> None: """Test .remove() effects on DB and cache.""" -- 2.30.2 From f1795f22a6ea2409fc1c7c0ea921dc530e7625c2 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 09:05:17 +0200 Subject: [PATCH 06/16] Default calendar date range end to 60 days later. --- plomtask/dating.py | 15 +++++++-------- plomtask/http.py | 6 ++++-- tests/days.py | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/plomtask/dating.py b/plomtask/dating.py index c55d847..26b3ce3 100644 --- a/plomtask/dating.py +++ b/plomtask/dating.py @@ -11,13 +11,11 @@ def valid_date(date_str: str) -> str: In any case, returns in DATE_FORMAT. """ if date_str == 'today': - date_str = todays_date() + date_str = date_in_n_days(0) elif date_str == 'yesterday': - date = datetime.now() - timedelta(days=1) - date_str = date.strftime(DATE_FORMAT) + date_str = date_in_n_days(-1) elif date_str == 'tomorrow': - date = datetime.now() + timedelta(days=1) - date_str = date.strftime(DATE_FORMAT) + date_str = date_in_n_days(1) try: dt = datetime.strptime(date_str, DATE_FORMAT) except (ValueError, TypeError) as e: @@ -26,6 +24,7 @@ def valid_date(date_str: str) -> str: return dt.strftime(DATE_FORMAT) -def todays_date() -> str: - """Return current date in DATE_FORMAT.""" - return datetime.now().strftime(DATE_FORMAT) +def date_in_n_days(n: int) -> str: + """Return in DATE_FORMAT date from today + n days.""" + date = datetime.now() + timedelta(days=n) + return date.strftime(DATE_FORMAT) diff --git a/plomtask/http.py b/plomtask/http.py index cf7bb08..280b0f5 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -5,7 +5,7 @@ from http.server import HTTPServer from urllib.parse import urlparse, parse_qs from os.path import split as path_split from jinja2 import Environment as JinjaEnv, FileSystemLoader as JinjaFSLoader -from plomtask.dating import todays_date +from plomtask.dating import date_in_n_days from plomtask.days import Day from plomtask.exceptions import HandledException, BadFormatException, \ NotFoundException @@ -113,6 +113,8 @@ class TaskHandler(BaseHTTPRequestHandler): """Show Days from ?start= to ?end=.""" start = self.params.get_str('start') end = self.params.get_str('end') + if not end: + end = date_in_n_days(60) ret = Day.by_date_range_with_limits(self.conn, (start, end), 'id') days, start, end = ret days = Day.with_filled_gaps(days, start, end) @@ -122,7 +124,7 @@ class TaskHandler(BaseHTTPRequestHandler): def do_GET_day(self) -> dict[str, object]: """Show single Day of ?date=.""" - date = self.params.get_str('date', todays_date()) + date = self.params.get_str('date', date_in_n_days(0)) todays_todos = Todo.by_date(self.conn, date) conditions_present = [] enablers_for = {} diff --git a/tests/days.py b/tests/days.py index 4727fac..d34d7ba 100644 --- a/tests/days.py +++ b/tests/days.py @@ -2,7 +2,7 @@ from unittest import TestCase from datetime import datetime from tests.utils import TestCaseWithDB, TestCaseWithServer -from plomtask.dating import todays_date +from plomtask.dating import date_in_n_days from plomtask.days import Day from plomtask.exceptions import BadFormatException @@ -87,7 +87,7 @@ class TestsWithDB(TestCaseWithDB): [day5, day6, day7]) self.check_storage([day1, day2, day3, day6]) # check 'today' is interpreted as today's date - today = Day(todays_date()) + today = Day(date_in_n_days(0)) today.save(self.db_conn) self.assertEqual(Day.by_date_range_filled(self.db_conn, 'today', 'today'), -- 2.30.2 From d916781d66c1aaf4e3a04580153dce61744d5729 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 09:09:33 +0200 Subject: [PATCH 07/16] In Calendar view, highlight today's date. --- plomtask/http.py | 3 ++- templates/calendar.html | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plomtask/http.py b/plomtask/http.py index 280b0f5..537f21f 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -120,7 +120,8 @@ class TaskHandler(BaseHTTPRequestHandler): days = Day.with_filled_gaps(days, start, end) for day in days: day.collect_calendarized_todos(self.conn) - return {'start': start, 'end': end, 'days': days} + today = date_in_n_days(0) + return {'start': start, 'end': end, 'days': days, 'today': today} def do_GET_day(self) -> dict[str, object]: """Show single Day of ?date=.""" diff --git a/templates/calendar.html b/templates/calendar.html index 4d67242..d7ec545 100644 --- a/templates/calendar.html +++ b/templates/calendar.html @@ -16,6 +16,9 @@ tr.month_row td { td.day_name { padding-right: 0.5em; } +td.today { + font-weight: bold; +} {% endblock %} @@ -45,7 +48,7 @@ to {{day.weekday|truncate(2,True,'',0)}} -{{day.date}} +{{day.date}} {{day.comment|e}} -- 2.30.2 From 6b9970ff864e0e63527213fea5c0bed40ba877a7 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 10:06:59 +0200 Subject: [PATCH 08/16] Minor template fixes. --- plomtask/http.py | 4 ++-- templates/process.html | 2 +- templates/todo.html | 2 +- templates/todos.html | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plomtask/http.py b/plomtask/http.py index 537f21f..944f79a 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -175,9 +175,9 @@ class TaskHandler(BaseHTTPRequestHandler): todos.sort(key=lambda t: t.is_done) elif sort_by == '-doneness': todos.sort(key=lambda t: t.is_done, reverse=True) - elif sort_by == 'process': + elif sort_by == 'title': todos.sort(key=lambda t: t.title_then) - elif sort_by == '-process': + elif sort_by == '-title': todos.sort(key=lambda t: t.title_then, reverse=True) elif sort_by == 'comment': todos.sort(key=lambda t: t.comment) diff --git a/templates/process.html b/templates/process.html index 8944c95..9df8b45 100644 --- a/templates/process.html +++ b/templates/process.html @@ -22,7 +22,7 @@ {% if step_node.is_explicit %} -add sub-step: +add sub-step: {% endif %} diff --git a/templates/todo.html b/templates/todo.html index 41d894b..80eb5c7 100644 --- a/templates/todo.html +++ b/templates/todo.html @@ -69,7 +69,7 @@ children -{{ macros.simple_checkbox_table("adopt", todo.children, "adopt", "todo_candidates", "adopt", true) }} +{{ macros.simple_checkbox_table("adopt", todo.children, "todo", "todo_candidates", "adopt", true) }} diff --git a/templates/todos.html b/templates/todos.html index 6cbf0bc..6b733e0 100644 --- a/templates/todos.html +++ b/templates/todos.html @@ -19,14 +19,14 @@ in comment done date -process +title comment {% for todo in todos %} [{% if todo.is_done %}x{% else %} {% endif %}] {{todo.date}} -{{todo.title_then}} +{{todo.title_then}} {{todo.comment}} {% endfor %} -- 2.30.2 From d7b039106e74a250d343ab036fdf90ad1a27eb3f Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 30 May 2024 12:00:58 +0200 Subject: [PATCH 09/16] Fix some ProcessStepping bugs. --- plomtask/http.py | 8 +++-- plomtask/processes.py | 1 - tests/processes.py | 83 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/plomtask/http.py b/plomtask/http.py index 944f79a..fd20603 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -379,9 +379,6 @@ class TaskHandler(BaseHTTPRequestHandler): if step_id not in self.form_data.get_all_int('steps'): raise BadFormatException('trying to keep unknown step') for step_id in self.form_data.get_all_int('steps'): - for step_process_id in self.form_data.get_all_int( - f'new_step_to_{step_id}'): - steps += [(None, step_process_id, step_id)] if step_id not in self.form_data.get_all_int('keep_step'): continue step_process_id = self.form_data.get_int( @@ -389,8 +386,13 @@ class TaskHandler(BaseHTTPRequestHandler): parent_id = self.form_data.get_int_or_none( f'step_{step_id}_parent_id') steps += [(step_id, step_process_id, parent_id)] + for step_id in self.form_data.get_all_int('steps'): + for step_process_id in self.form_data.get_all_int( + f'new_step_to_{step_id}'): + steps += [(None, step_process_id, step_id)] for step_process_id in self.form_data.get_all_int('new_top_step'): steps += [(None, step_process_id, None)] + process.uncache() process.set_steps(self.conn, steps) process.save(self.conn) return f'/process?id={process.id_}' diff --git a/plomtask/processes.py b/plomtask/processes.py index 684dec8..027e975 100644 --- a/plomtask/processes.py +++ b/plomtask/processes.py @@ -124,7 +124,6 @@ class Process(BaseModel[int], ConditionsRelations): just deleted under its feet), or if the parent step would not be owned by the current Process. """ - def walk_steps(node: ProcessStep) -> None: if node.step_process_id == self.id_: raise BadFormatException('bad step selection causes recursion') diff --git a/tests/processes.py b/tests/processes.py index 127a3f6..7d1d0f1 100644 --- a/tests/processes.py +++ b/tests/processes.py @@ -95,32 +95,49 @@ class TestsWithDB(TestCaseWithDB): assert isinstance(p2.id_, int) assert isinstance(p3.id_, int) steps_p1: list[tuple[int | None, int, int | None]] = [] + # add step of process p2 as first (top-level) step to p1 add_step(p1, steps_p1, (None, p2.id_, None), 1) p1_dict: dict[int, ProcessStepsNode] = {} p1_dict[1] = ProcessStepsNode(p2, None, True, {}, False) self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) + # add step of process p3 as second (top-level) step to p1 add_step(p1, steps_p1, (None, p3.id_, None), 2) step_2 = p1.explicit_steps[-1] p1_dict[2] = ProcessStepsNode(p3, None, True, {}, False) self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) + # add step of process p3 as first (top-level) step to p2, + # expect it as implicit sub-step of p1's second (p3) step steps_p2: list[tuple[int | None, int, int | None]] = [] add_step(p2, steps_p2, (None, p3.id_, None), 3) p1_dict[1].steps[3] = ProcessStepsNode(p3, None, False, {}, False) self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) + # add step of process p2 as explicit sub-step to p1's first sub-step add_step(p1, steps_p1, (None, p2.id_, step_2.id_), 4) step_3 = ProcessStepsNode(p3, None, False, {}, True) p1_dict[2].steps[4] = ProcessStepsNode(p2, step_2.id_, True, {3: step_3}, False) self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) + # add step of process p3 as explicit sub-step to non-existing p1 + # sub-step (of id=999), expect it to become another p1 top-level step add_step(p1, steps_p1, (None, p3.id_, 999), 5) p1_dict[5] = ProcessStepsNode(p3, None, True, {}, False) self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) + # add step of process p3 as explicit sub-step to p1's implicit p3 + # sub-step, expect it to become another p1 top-level step add_step(p1, steps_p1, (None, p3.id_, 3), 6) p1_dict[6] = ProcessStepsNode(p3, None, True, {}, False) self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) self.assertEqual(p1.used_as_step_by(self.db_conn), []) self.assertEqual(p2.used_as_step_by(self.db_conn), [p1]) self.assertEqual(p3.used_as_step_by(self.db_conn), [p1, p2]) + # add step of process p2 as explicit sub-step to p1's second (p3) + # top-level step + add_step(p1, steps_p1, (None, p3.id_, 2), 7) + p1_dict[2].steps[7] = ProcessStepsNode(p3, 2, True, {}, False) + # import pprint + # pprint.pp(p1.get_steps(self.db_conn, None)) + # pprint.pp(p1_dict) + self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict) def test_Process_conditions(self) -> None: """Test setting Process.conditions/enables/disables.""" @@ -245,9 +262,11 @@ class TestsWithServer(TestCaseWithServer): def test_do_POST_process_steps(self) -> None: """Test behavior of ProcessStep posting.""" + # pylint: disable=too-many-statements form_data_1 = self.post_process(1) self.post_process(2) self.post_process(3) + # post first (top-level) step of process 2 to process 1 form_data_1['new_top_step'] = [2] self.post_process(1, form_data_1) retrieved_process = Process.by_id(self.db_conn, 1) @@ -256,12 +275,15 @@ class TestsWithServer(TestCaseWithServer): self.assertEqual(retrieved_step.step_process_id, 2) self.assertEqual(retrieved_step.owner_id, 1) self.assertEqual(retrieved_step.parent_step_id, None) + # post empty steps list to process, expect clean slate, and old step to + # completely disappear form_data_1['new_top_step'] = [] self.post_process(1, form_data_1) retrieved_process = Process.by_id(self.db_conn, 1) self.assertEqual(retrieved_process.explicit_steps, []) with self.assertRaises(NotFoundException): ProcessStep.by_id(self.db_conn, retrieved_step.id_) + # post new first (top_level) step of process 3 to process 1 form_data_1['new_top_step'] = [3] self.post_process(1, form_data_1) retrieved_process = Process.by_id(self.db_conn, 1) @@ -269,17 +291,21 @@ class TestsWithServer(TestCaseWithServer): self.assertEqual(retrieved_step.step_process_id, 3) self.assertEqual(retrieved_step.owner_id, 1) self.assertEqual(retrieved_step.parent_step_id, None) + # post to process steps list without keeps, expect clean slate form_data_1['new_top_step'] = [] form_data_1['steps'] = [retrieved_step.id_] self.post_process(1, form_data_1) retrieved_process = Process.by_id(self.db_conn, 1) self.assertEqual(retrieved_process.explicit_steps, []) + # post to process empty steps list but keep, expect 400 form_data_1['steps'] = [] form_data_1['keep_step'] = [retrieved_step.id_] self.check_post(form_data_1, '/process?id=1', 400, '/process?id=1') + # post to process steps list with keep on non-created step, expect 400 form_data_1['steps'] = [retrieved_step.id_] form_data_1['keep_step'] = [retrieved_step.id_] self.check_post(form_data_1, '/process?id=1', 400, '/process?id=1') + # post to process steps list with keep and process ID, expect 200 form_data_1[f'step_{retrieved_step.id_}_process_id'] = [2] self.post_process(1, form_data_1) retrieved_process = Process.by_id(self.db_conn, 1) @@ -288,12 +314,69 @@ class TestsWithServer(TestCaseWithServer): self.assertEqual(retrieved_step.step_process_id, 2) self.assertEqual(retrieved_step.owner_id, 1) self.assertEqual(retrieved_step.parent_step_id, None) + # post nonsensical new_top_step id and otherwise zero'd steps, expect + # 400 and preservation of previous state form_data_1['new_top_step'] = ['foo'] form_data_1['steps'] = [] form_data_1['keep_step'] = [] self.check_post(form_data_1, '/process?id=1', 400, '/process?id=1') retrieved_process = Process.by_id(self.db_conn, 1) self.assertEqual(len(retrieved_process.explicit_steps), 1) + retrieved_step = retrieved_process.explicit_steps[0] + self.assertEqual(retrieved_step.step_process_id, 2) + self.assertEqual(retrieved_step.owner_id, 1) + self.assertEqual(retrieved_step.parent_step_id, None) + # post to process steps list with keep and process ID, expect 200 + form_data_1['new_top_step'] = [3] + form_data_1['steps'] = [retrieved_step.id_] + form_data_1['keep_step'] = [retrieved_step.id_] + self.post_process(1, form_data_1) + retrieved_process = Process.by_id(self.db_conn, 1) + self.assertEqual(len(retrieved_process.explicit_steps), 2) + retrieved_step_0 = retrieved_process.explicit_steps[0] + self.assertEqual(retrieved_step_0.step_process_id, 2) + self.assertEqual(retrieved_step_0.owner_id, 1) + self.assertEqual(retrieved_step_0.parent_step_id, None) + retrieved_step_1 = retrieved_process.explicit_steps[1] + self.assertEqual(retrieved_step_1.step_process_id, 3) + self.assertEqual(retrieved_step_1.owner_id, 1) + self.assertEqual(retrieved_step_1.parent_step_id, None) + # post to process steps list with keeps etc., but trigger recursion + form_data_1['new_top_step'] = [] + form_data_1['steps'] = [retrieved_step_0.id_, retrieved_step_1.id_] + form_data_1['keep_step'] = [retrieved_step_0.id_, retrieved_step_1.id_] + form_data_1[f'step_{retrieved_step_0.id_}_process_id'] = [2] + form_data_1[f'step_{retrieved_step_1.id_}_process_id'] = [1] + self.check_post(form_data_1, '/process?id=1', 400, '/process?id=1') + # check previous status preserved despite failed steps setting + retrieved_process = Process.by_id(self.db_conn, 1) + self.assertEqual(len(retrieved_process.explicit_steps), 2) + retrieved_step_0 = retrieved_process.explicit_steps[0] + self.assertEqual(retrieved_step_0.step_process_id, 2) + self.assertEqual(retrieved_step_0.owner_id, 1) + self.assertEqual(retrieved_step_0.parent_step_id, None) + retrieved_step_1 = retrieved_process.explicit_steps[1] + self.assertEqual(retrieved_step_1.step_process_id, 3) + self.assertEqual(retrieved_step_1.owner_id, 1) + self.assertEqual(retrieved_step_1.parent_step_id, None) + form_data_1[f'step_{retrieved_step_1.id_}_process_id'] = [3] + # post sub-step to step + form_data_1[f'new_step_to_{retrieved_step_1.id_}'] = [3] + self.post_process(1, form_data_1) + retrieved_process = Process.by_id(self.db_conn, 1) + self.assertEqual(len(retrieved_process.explicit_steps), 3) + retrieved_step_0 = retrieved_process.explicit_steps[0] + self.assertEqual(retrieved_step_0.step_process_id, 2) + self.assertEqual(retrieved_step_0.owner_id, 1) + self.assertEqual(retrieved_step_0.parent_step_id, None) + retrieved_step_1 = retrieved_process.explicit_steps[1] + self.assertEqual(retrieved_step_1.step_process_id, 3) + self.assertEqual(retrieved_step_1.owner_id, 1) + self.assertEqual(retrieved_step_1.parent_step_id, None) + retrieved_step_2 = retrieved_process.explicit_steps[2] + self.assertEqual(retrieved_step_2.step_process_id, 3) + self.assertEqual(retrieved_step_2.owner_id, 1) + self.assertEqual(retrieved_step_2.parent_step_id, retrieved_step_1.id_) def test_do_GET(self) -> None: """Test /process and /processes response codes.""" -- 2.30.2 From 20ee4c41027582f761a63d947ed4c46e5b02bdab Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sun, 2 Jun 2024 17:38:54 +0200 Subject: [PATCH 10/16] Improve/extend automatic creation and adoption of Todos to fulfill ProcessSteps requirements. --- plomtask/http.py | 4 +-- plomtask/todos.py | 91 ++++++++++++++++++++++------------------------- tests/todos.py | 63 ++++++++++++++------------------ 3 files changed, 71 insertions(+), 87 deletions(-) diff --git a/plomtask/http.py b/plomtask/http.py index fd20603..8ddef65 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -302,8 +302,8 @@ class TaskHandler(BaseHTTPRequestHandler): day = Day.by_id(self.conn, date, create=True) day.comment = self.form_data.get_str('day_comment') day.save(self.conn) - Todo.create_with_children(self.conn, date, - self.form_data.get_all_int('new_todo')) + for process_id in sorted(self.form_data.get_all_int('new_todo')): + Todo.create_with_children(self.conn, process_id, date) done_ids = self.form_data.get_all_int('done') comments = self.form_data.get_all_str('comment') efforts = self.form_data.get_all_str('effort') diff --git a/plomtask/todos.py b/plomtask/todos.py index 46a353d..9fac63b 100644 --- a/plomtask/todos.py +++ b/plomtask/todos.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from typing import Any from sqlite3 import Row from plomtask.db import DatabaseConnection, BaseModel -from plomtask.processes import Process +from plomtask.processes import Process, ProcessStepsNode from plomtask.versioned_attributes import VersionedAttribute from plomtask.conditions import Condition, ConditionsRelations from plomtask.exceptions import (NotFoundException, BadFormatException, @@ -68,25 +68,48 @@ class Todo(BaseModel[int], ConditionsRelations): return todos @classmethod - def create_with_children(cls, db_conn: DatabaseConnection, date: str, - process_ids: list[int]) -> list[Todo]: - """Create Todos of process_ids for date, ensure children.""" - new_todos = [] - for process_id in process_ids: - process = Process.by_id(db_conn, process_id) - todo = Todo(None, process, False, date) - todo.save(db_conn) - new_todos += [todo] - nothing_to_adopt = False - while not nothing_to_adopt: - nothing_to_adopt = True - existing_todos = Todo.by_date(db_conn, date) - for todo in new_todos: - if todo.adopt_from(existing_todos): - nothing_to_adopt = False - todo.make_missing_children(db_conn) - todo.save(db_conn) - return new_todos + def create_with_children(cls, db_conn: DatabaseConnection, + process_id: int, date: str) -> Todo: + """Create Todo of process for date, ensure children.""" + + def key_order_func(n: ProcessStepsNode) -> int: + assert isinstance(n.process.id_, int) + return n.process.id_ + + def walk_steps(parent: Todo, step_node: ProcessStepsNode) -> Todo: + adoptables = [t for t in cls.by_date(db_conn, date) + if (t not in parent.children) + and (t != parent) + and step_node.process == t.process] + satisfier = None + for adoptable in adoptables: + satisfier = adoptable + break + if not satisfier: + satisfier = cls(None, step_node.process, False, date) + satisfier.save(db_conn) + sub_step_nodes = list(step_node.steps.values()) + sub_step_nodes.sort(key=key_order_func) + for sub_node in sub_step_nodes: + n_slots = len([n for n in sub_step_nodes + if n.process == sub_node.process]) + filled_slots = len([t for t in satisfier.children + if t.process == sub_node.process]) + # if we did not newly create satisfier, it may already fill + # some step dependencies, so only fill what remains open + if n_slots - filled_slots > 0: + satisfier.add_child(walk_steps(satisfier, sub_node)) + satisfier.save(db_conn) + return satisfier + + process = Process.by_id(db_conn, process_id) + todo = cls(None, process, False, date) + todo.save(db_conn) + steps_tree = process.get_steps(db_conn) + for step_node in steps_tree.values(): + todo.add_child(walk_steps(todo, step_node)) + todo.save(db_conn) + return todo @classmethod def from_table_row(cls, db_conn: DatabaseConnection, @@ -155,16 +178,6 @@ class Todo(BaseModel[int], ConditionsRelations): """Needed for super().save to save Processes as attributes.""" return self.process.id_ - @property - def unsatisfied_dependencies(self) -> list[int]: - """Return Process IDs of .process.explicit_steps not in .children.""" - unsatisfied = [s.step_process_id for s in self.process.explicit_steps - if s.parent_step_id is None] - for child_process_id in [c.process.id_ for c in self.children]: - if child_process_id in unsatisfied: - unsatisfied.remove(child_process_id) - return unsatisfied - @property def is_done(self) -> bool: """Wrapper around self._is_done so we can control its setter.""" @@ -201,24 +214,6 @@ class Todo(BaseModel[int], ConditionsRelations): assert isinstance(effort_then, float) return effort_then - def adopt_from(self, todos: list[Todo]) -> bool: - """As far as possible, fill unsatisfied dependencies from todos.""" - adopted = False - for process_id in self.unsatisfied_dependencies: - for todo in [t for t in todos if t.process.id_ == process_id - and t not in self.children]: - self.add_child(todo) - adopted = True - break - return adopted - - def make_missing_children(self, db_conn: DatabaseConnection) -> None: - """Fill unsatisfied dependencies with new Todos.""" - new_todos = self.__class__.create_with_children( - db_conn, self.date, self.unsatisfied_dependencies) - for todo in new_todos: - self.add_child(todo) - def get_step_tree(self, seen_todos: set[int]) -> TodoNode: """Return tree of depended-on Todos.""" diff --git a/tests/todos.py b/tests/todos.py index 86986b6..ecf2089 100644 --- a/tests/todos.py +++ b/tests/todos.py @@ -154,11 +154,9 @@ class TestsWithDB(TestCaseWithDB): node_0.children += [node_4] self.assertEqual(todo_1.get_step_tree(set()), node_0) - def test_Todo_unsatisfied_steps(self) -> None: - """Test options of satisfying unfulfilled Process.explicit_steps.""" + def test_Todo_create_with_children(self) -> None: + """Test parenthood guaranteeds of Todo.create_with_children.""" assert isinstance(self.proc.id_, int) - todo_1 = Todo(None, self.proc, False, self.date1) - todo_1.save(self.db_conn) proc2 = Process(None) proc2.save(self.db_conn) assert isinstance(proc2.id_, int) @@ -168,35 +166,30 @@ class TestsWithDB(TestCaseWithDB): proc4 = Process(None) proc4.save(self.db_conn) assert isinstance(proc4.id_, int) + # make proc4 step of proc3 proc3.set_steps(self.db_conn, [(None, proc4.id_, None)]) + # give proc2 three steps; 2× proc1, 1× proc3 proc2.set_steps(self.db_conn, [(None, self.proc.id_, None), (None, self.proc.id_, None), (None, proc3.id_, None)]) - todo_2 = Todo(None, proc2, False, self.date1) - todo_2.save(self.db_conn) - # test empty adoption does nothing - todo_2.adopt_from([]) - self.assertEqual(todo_2.children, []) - # test basic adoption - todo_2.adopt_from([todo_1]) - self.assertEqual(todo_2.children, [todo_1]) - self.assertEqual(todo_1.parents, [todo_2]) - # test making missing children - todo_2.make_missing_children(self.db_conn) - todo_3 = Todo.by_id(self.db_conn, 3) - todo_4 = Todo.by_id(self.db_conn, 4) - self.assertEqual(todo_2.children, [todo_1, todo_3, todo_4]) - self.assertEqual(todo_3.process, self.proc) - self.assertEqual(todo_3.parents, [todo_2]) - self.assertEqual(todo_3.children, []) - self.assertEqual(todo_4.process, proc3) - self.assertEqual(todo_4.parents, [todo_2]) - # test .make_missing_children lower down the tree - todo_4.make_missing_children(self.db_conn) - todo_5 = Todo.by_id(self.db_conn, 5) - self.assertEqual(todo_5.process, proc4) - self.assertEqual(todo_4.children, [todo_5]) - self.assertEqual(todo_5.parents, [todo_4]) + # test mere creation does nothing + todo_ignore = Todo(None, proc2, False, self.date1) + todo_ignore.save(self.db_conn) + self.assertEqual(todo_ignore.children, []) + # test create_with_children on step-less does nothing + todo_1 = Todo.create_with_children(self.db_conn, self.proc.id_, + self.date1) + self.assertEqual(todo_1.children, []) + self.assertEqual(len(Todo.all(self.db_conn)), 2) + # test create_with_children adopts and creates, and down tree too + todo_2 = Todo.create_with_children(self.db_conn, proc2.id_, self.date1) + self.assertEqual(3, len(todo_2.children)) + self.assertEqual(todo_1, todo_2.children[0]) + self.assertEqual(self.proc, todo_2.children[1].process) + self.assertEqual(proc3, todo_2.children[2].process) + todo_3 = todo_2.children[2] + self.assertEqual(len(todo_3.children), 1) + self.assertEqual(todo_3.children[0].process, proc4) def test_Todo_singularity(self) -> None: """Test pointers made for single object keep pointing to it.""" @@ -353,8 +346,8 @@ class TestsWithServer(TestCaseWithServer): assert isinstance(t.process.id_, int) return t.process.id_ - def check_adoption(date: str, new_todo: list[int]) -> None: - form_data = {'day_comment': '', 'new_todo': new_todo} + def check_adoption(date: str, new_todos: list[int]) -> None: + form_data = {'day_comment': '', 'new_todo': new_todos} self.check_post(form_data, f'/day?date={date}', 302) day_todos = Todo.by_date(self.db_conn, date) day_todos.sort(key=key_order_func) @@ -367,7 +360,6 @@ class TestsWithServer(TestCaseWithServer): def check_nesting_adoption(process_id: int, date: str, new_top_steps: list[int]) -> None: - result_reversed = new_top_steps[1] < new_top_steps[0] form_data = self.post_process() form_data = self.post_process(process_id, form_data | @@ -380,15 +372,12 @@ class TestsWithServer(TestCaseWithServer): todo1 = day_todos[0] # process of process_id todo2 = day_todos[1] # process 2 todo3 = day_todos[2] # process 1 - if result_reversed: - self.assertEqual(todo1.children, [todo2, todo3]) - else: - self.assertEqual(todo1.children, [todo3, todo2]) + self.assertEqual(sorted(todo1.children), sorted([todo2, todo3])) self.assertEqual(todo1.parents, []) self.assertEqual(todo2.children, [todo3]) self.assertEqual(todo2.parents, [todo1]) self.assertEqual(todo3.children, []) - self.assertEqual(todo3.parents, [todo2, todo1]) + self.assertEqual(sorted(todo3.parents), sorted([todo2, todo1])) form_data = self.post_process() form_data = self.post_process(2, form_data | {'new_top_step': 1}) -- 2.30.2 From 2337eb37f27fdc60e3cb000052f00218d815c49f Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sun, 2 Jun 2024 23:00:54 +0200 Subject: [PATCH 11/16] Mostly superficial template design improvements. --- templates/_base.html | 1 + templates/calendar.html | 21 +++++++++++---------- templates/todo.html | 6 +++++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/templates/_base.html b/templates/_base.html index d192631..0e38465 100644 --- a/templates/_base.html +++ b/templates/_base.html @@ -19,6 +19,7 @@ div.btn-to-right { } td, th, tr, table { vertical-align: top; + margin-top: 1em; padding: 0; } {% block css %} diff --git a/templates/calendar.html b/templates/calendar.html index d7ec545..4674262 100644 --- a/templates/calendar.html +++ b/templates/calendar.html @@ -4,7 +4,7 @@ {% block css %} tr.week_row td { - height: 0.1em; + height: 0.3em; background-color: black; padding: 0; margin: 0; @@ -12,6 +12,11 @@ tr.week_row td { tr.month_row td { border: 0.1em solid black; text-align: center; + color: white; + background-color: #555555; +} +tr.day_row td { + background-color: #cccccc; } td.day_name { padding-right: 0.5em; @@ -36,27 +41,23 @@ to {% if day.first_of_month %} -{{ day.month_name }} +{{ day.month_name }} {% endif %} {% if day.weekday == "Monday" %} - + {% endif %} - -{{day.weekday|truncate(2,True,'',0)}} -{{day.date}} -{{day.comment|e}} + +{{day.weekday|truncate(2,True,'',0)}} {% if day.date == today %} {% endif %}{{day.date}} {{day.comment|e}} {% for todo in day.calendarized_todos %} -[{% if todo.is_done %}X{% else %} {% endif %}] -{{todo.title_then|e}} -{{todo.comment|e}} +[{% if todo.is_done %}X{% else %} {% endif %}] {{todo.title_then|e}}{% if todo.comment %} · {{todo.comment|e}}{% endif %} {% endfor %} diff --git a/templates/todo.html b/templates/todo.html index 80eb5c7..0d4773c 100644 --- a/templates/todo.html +++ b/templates/todo.html @@ -77,5 +77,9 @@ {{ macros.datalist_of_titles("condition_candidates", condition_candidates) }} -{{ macros.datalist_of_titles("todo_candidates", todo_candidates) }} + +{% for candidate in todo_candidates %} + +{% endfor %} + {% endblock %} -- 2.30.2 From 0630d9cfdc47e306b96ad05b4077ee96eec71226 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 3 Jun 2024 00:50:35 +0200 Subject: [PATCH 12/16] Fix bug of relationships writing for todo_children writing in wrong column. --- plomtask/.db.py.swp | Bin 0 -> 40960 bytes plomtask/.http.py.swp | Bin 0 -> 32768 bytes plomtask/.versioned_attributes.py.swp | Bin 0 -> 12288 bytes plomtask/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 162 bytes .../__pycache__/conditions.cpython-311.pyc | Bin 0 -> 5656 bytes plomtask/__pycache__/dating.cpython-311.pyc | Bin 0 -> 1782 bytes plomtask/__pycache__/days.cpython-311.pyc | Bin 0 -> 6458 bytes plomtask/__pycache__/db.cpython-311.pyc | Bin 0 -> 28984 bytes .../__pycache__/exceptions.cpython-311.pyc | Bin 0 -> 1122 bytes plomtask/__pycache__/http.cpython-311.pyc | Bin 0 -> 36429 bytes plomtask/__pycache__/misc.cpython-311.pyc | Bin 0 -> 4802 bytes .../__pycache__/processes.cpython-311.pyc | Bin 0 -> 13696 bytes plomtask/__pycache__/task.cpython-311.pyc | Bin 0 -> 4437 bytes plomtask/__pycache__/todos.cpython-311.pyc | Bin 0 -> 17018 bytes .../versioned_attributes.cpython-311.pyc | Bin 0 -> 5245 bytes plomtask/db.py | 20 ++++++++++++------ plomtask/processes.py | 8 +++---- plomtask/todos.py | 12 +++++------ 18 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 plomtask/.db.py.swp create mode 100644 plomtask/.http.py.swp create mode 100644 plomtask/.versioned_attributes.py.swp create mode 100644 plomtask/__pycache__/__init__.cpython-311.pyc create mode 100644 plomtask/__pycache__/conditions.cpython-311.pyc create mode 100644 plomtask/__pycache__/dating.cpython-311.pyc create mode 100644 plomtask/__pycache__/days.cpython-311.pyc create mode 100644 plomtask/__pycache__/db.cpython-311.pyc create mode 100644 plomtask/__pycache__/exceptions.cpython-311.pyc create mode 100644 plomtask/__pycache__/http.cpython-311.pyc create mode 100644 plomtask/__pycache__/misc.cpython-311.pyc create mode 100644 plomtask/__pycache__/processes.cpython-311.pyc create mode 100644 plomtask/__pycache__/task.cpython-311.pyc create mode 100644 plomtask/__pycache__/todos.cpython-311.pyc create mode 100644 plomtask/__pycache__/versioned_attributes.cpython-311.pyc diff --git a/plomtask/.db.py.swp b/plomtask/.db.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..b62d92eaf0d1f323ef01182ddbfb6e142020b516 GIT binary patch literal 40960 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 literal 0 HcmV?d00001 diff --git a/plomtask/.http.py.swp b/plomtask/.http.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..003e5d3bd3946762d66592ba164f72136ada1280 GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/plomtask/.versioned_attributes.py.swp b/plomtask/.versioned_attributes.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..1c5a54423ed22ed4fca7d4659d98c0e0b2da2c7a GIT binary patch literal 12288 zcmeHN&5smC6tCsOZ_t1j4JMB@o7oAo%?uk7calX{z=+8r0fd-gGpU)bVLRJjbk#6S zL@=7@*^8Wzll}u5E*?F2){`gW(RkL#N&QvzH@hopxM-@gzwPeo*RS6D)vsRlW^2&C zaB7v7oDReB3}avZdTHd&T%Wmdd@qarDA3IhIwnUK+YhqQ&u?glhvV_U_lEsM#F0F# zTNIZY<;7KzNG}S7+viFp-e9bRbmHmX@o#M`1D1hp7#OS3!b^MD;*pM-t1r$Tr2YHe z+Q!&6TLvrxmI2FvWxz6E8L$jk1}p>rM+Q_p!)_w69a(a3WapXt&e^R!Sq3ZvmI2Fv zWxz6E8L$jk1}p=X0n318z%uY3WPrPjUEImotz8Hn|Nqbb{{QM}#%=>20wHh_XaR?S zUBFIY2k_Hg#_j;00v`cOzyaX5J&b)1d=7jD+yWxtIPfg6AJ`52_!MIw10ir4cpi8T z`1wir1a1Rofc?Ne;Oi$C8v`!`i@*Wk-s6nj1p>eay1>2182b+R7Pt+(2^<3cc$Bek zfIGlVU=?@)_~jACegM7zJ^WUF1=8bpiI^m?!lo*p z>p0~<;HXu210&}+7~--PErHs^6S76vj71|ak%}f>EGY6_0vEDIrG$rnM`R+@IH?oW z!+3&uYz9+aAf)0!Tqdtc*!-N9sjw|F)28|uB!X`+bD90}Mx{9&qbp;9RMYOdg`pnD z!l@a|D5(V{d!6oDX}@Jua??BQdM?%cAxb{>RS^NgY}4{G`68U(m_mPb`BihLL(9~lBa7XmOZah?mX;dTSacXw^QMli(=OvM(@m=ea=Oa>F~m|O zIuw|&kWtk~Ix*F{pqNWl(-c>kqN?^?k}5G15@)(jBR}G*GA~Uj$nxza(L_%iu%WMx zl*A*@lh>38-MZvWkr3BnBR(>C8HLe%azaq zb3(k|bdbH)On9Bib ziBmWpMuD!?S?v5W_dLt5G_G@$ zC_!!%HWUrl#c+cP?+{0pAcbmStfNA_S9&Aws4sbcuS06fZ|Y(m2*} zn66@2d3x7sncC@U924#-T`4K>hDo#_1=cjTWys0P8l_x#G77a@6LT2~s9teh{h&I! zni~$~nwWB)ups7qO3HFY*J)&Wtpk&pM2%$3G|H#XR${G|r3c8W7z!u?%$4Q*FUwg~ zb)_)V3ZfT;>NuE?TLiruB667_`5G}Ih}E=KLQ*D7;+t!R4)>KfiDHo`>@?Q5`p7dd zHPyVD&nqXZpS^`nt(2TibFM~QtQ)m(HciP|WGM?3&M74(_Uag z{k|7^s^3o)nhu2)f3X#uChHMqtFntQ!Fx7wXM=gf^7jG09t-?8qv1M-3x+SuYdF*VggpWB!k mnl{TTKEBl!^Cws%GV^Kdg_rYY(3m#oYeW7Zzh@7Hmp=hoE!%$p literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/__init__.cpython-311.pyc b/plomtask/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67ebc21772973750904d84d340676a7754abc78f GIT binary patch literal 162 zcmZ3^%ge<81l4BWQbF`%5CH>>P{wCAAY(d13PUi1CZpdy?A%PfhH*DI*}#bJ}1pHiBWYFESxGzDZ& UF+Y&_z|6?V_<;dN6fpzE0CYnprT_o{ literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/conditions.cpython-311.pyc b/plomtask/__pycache__/conditions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23e3c3b63a2389c73cce1cfd1cf1da5c8892704c GIT binary patch literal 5656 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 literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/dating.cpython-311.pyc b/plomtask/__pycache__/dating.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc6f1cd477343b22891bd342b4e7d9aea7a94495 GIT binary patch literal 1782 zcmZ`(Piq@j5P$ne(ylgAoC>$8ZJbT4jVl~Uv?Umt#9$Mrq_iodCM4=XY_%(A6YZ}0 z_9?PdDVWlO8Upd9*iZ~UxhZbHKo14?6G%n}v0x~a9()t{5^`zh?MjxEy2EPT%$u2~ znK!?AKSd&81oUB$7e#CpbI@+1YOj^U!a6kRqmODh=G zs;sF*cTz|6{}Ze$P?Z>_?uwLadV#13#(ir^)o$6?RLSyMPA?L}wyJ{iAgP#1Me~EQ z4#92^>!gIO9Mda@F0?c#7ae~JyPK#6g*;}d0gsU(KaJf5ZSQ2Kj;uNGann8{Imeqth`;;v+WwgdUKxL-J?1Tmp18F3qk^6z>idB41Ef}eeCqf(xu8}LrU^lDu3JjZ@b?Rf|iEjD1*?GB)Z2%mg z4{-F6d?z8eQJQyPWB)IuwAk#Md9DAKIp#E*5MvT`YZ7FmhR}7j4JeA*%CuAV6L)9I0Z( z4L_k*4C%qmorjYs1f1W2t)p%j31b`c2cd~(XyPz-apz(y7H`Mm4WS`)#B&>89*A;N zl&R%XE2gw#O5c(>5HB>v3nMXImJcKkBjfGJ^w!$1ldZ_rcI0YmWL;mRwZZUFr08boKJFRnei_QN+VX{IgB zH2E2a*0Rq{EKZ~S>2pgWx1Szg;<-Qg0LU)$KO_7Uf;Q3ccs)89*j=#g!Otf``_iKt z`h^)Cfht()6!b%b*!M;wV>TKGpl7S;yWS)720DF|<*{wb9zf+enIf;^q~QJHsgMZx z_~IUev9akbkJNA&2`Xw x&C|XP`k*=b{TV&KE_H)rOnfWWMX>Dnizg4U%N%ogBiBW+Z25~PpT@jQ{{>l{tl0nn literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/days.cpython-311.pyc b/plomtask/__pycache__/days.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..393a8bb1b68f44d5e72a72ef44ce368ee7d9568f GIT binary patch literal 6458 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

h5@Nc~dnRPfym;%iz+fcRu&v^uu8|2xME1Knq$8 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 literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/exceptions.cpython-311.pyc b/plomtask/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85b2cdc05b068b93be1ab786b4e4421cc9cd82bb GIT binary patch literal 1122 zcmbVK&2AGh5cdA0O+t%8L5SRZY*Z;x4;89}IDjbS&n zKo3CQ093)l)MftbterI?e&3J}{^iMe$19jXaEl7;0P4s!gr7L+!Rp z9VqWkD#u<-Lq_vkhA&$Ja|)GtFu=K6;f|*m#UjS6pD@7l0Q!l)UY!X6+5AIS=>x396muO~szkb^2 ziHJ3lP(+O+?S$MXk|jcA9_^_Qw+72;swV?!_|KFJhN^-(%h%XF8M!Cp%EPlaX32Yt z+&j>>^TMM?LPnm>nHuh`ArPpGyfA=l;Eu;hs#Tqz8=|D?QksdIH?w7|`wLY9V+F#& z$URtsU=G{?!h@#JMo{&_8mia}wN>23wZ;mAE) zLSb^7wSp|dJ}Kp_&R;a+BrEwZS=Ys9^Wl0fci@~Eef0&@)UhmUjP^%pf4X5?kEUo< eoezE+@6~Onyqc69993)oo%&>VIW@1Jz40H`F%WM6 literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/http.cpython-311.pyc b/plomtask/__pycache__/http.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edbb8eadaa831eddcf832ee2c761b0b252a9881e GIT binary patch literal 36429 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 W+0B?F`Jw3T{t5H?X@LN2s{9|@iuH^D literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/misc.cpython-311.pyc b/plomtask/__pycache__/misc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30b4ccfda20c063dbfec821b78a1a2984263128f GIT binary patch literal 4802 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 IWmcf{Ka=rzkN^Mx literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/processes.cpython-311.pyc b/plomtask/__pycache__/processes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bebfbe316c7193e45fa216644b494f65122f031f GIT binary patch literal 13696 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 literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/task.cpython-311.pyc b/plomtask/__pycache__/task.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..173d529e17a765c681b734d323c397c0239a3e90 GIT binary patch literal 4437 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 AjQ{`u literal 0 HcmV?d00001 diff --git a/plomtask/__pycache__/versioned_attributes.cpython-311.pyc b/plomtask/__pycache__/versioned_attributes.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c20eb29bb810b4a5ed8fd44c61a7b9c0e0d17cd GIT binary patch literal 5245 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 literal 0 HcmV?d00001 diff --git a/plomtask/db.py b/plomtask/db.py index b5461a5..90ec833 100644 --- a/plomtask/db.py +++ b/plomtask/db.py @@ -172,11 +172,17 @@ class DatabaseConnection: self.conn.close() def rewrite_relations(self, table_name: str, key: str, target: int | str, - rows: list[list[Any]]) -> None: - """Rewrite relations in table_name to target, with rows values.""" + rows: list[list[Any]], key_index: int = 0) -> None: + # pylint: disable=too-many-arguments + """Rewrite relations in table_name to target, with rows values. + + Note that single rows are expected without the column and value + identified by key and target, which are inserted inside the function + at key_index. + """ self.delete_where(table_name, key, target) for row in rows: - values = tuple([target] + row) + values = tuple(row[:key_index] + [target] + row[key_index:]) q_marks = self.__class__.q_marks_from_values(values) self.exec(f'INSERT INTO {table_name} VALUES {q_marks}', values) @@ -229,7 +235,7 @@ class BaseModel(Generic[BaseModelId]): table_name = '' to_save: list[str] = [] to_save_versioned: list[str] = [] - to_save_relations: list[tuple[str, str, str]] = [] + to_save_relations: list[tuple[str, str, str, int]] = [] id_: None | BaseModelId cache_: dict[BaseModelId, Self] to_search: list[str] = [] @@ -420,11 +426,11 @@ class BaseModel(Generic[BaseModelId]): self.cache() for attr_name in self.to_save_versioned: getattr(self, attr_name).save(db_conn) - for table, column, attr_name in self.to_save_relations: + for table, column, attr_name, key_index in self.to_save_relations: assert isinstance(self.id_, (int, str)) db_conn.rewrite_relations(table, column, self.id_, [[i.id_] for i - in getattr(self, attr_name)]) + in getattr(self, attr_name)], key_index) def remove(self, db_conn: DatabaseConnection) -> None: """Remove from DB and cache, including dependencies.""" @@ -432,7 +438,7 @@ class BaseModel(Generic[BaseModelId]): raise HandledException('cannot remove unsaved item') for attr_name in self.to_save_versioned: getattr(self, attr_name).remove(db_conn) - for table, column, attr_name in self.to_save_relations: + for table, column, attr_name, _ in self.to_save_relations: db_conn.delete_where(table, column, self.id_) self.uncache() db_conn.delete_where(self.table_name, 'id', self.id_) diff --git a/plomtask/processes.py b/plomtask/processes.py index 027e975..bfadc2b 100644 --- a/plomtask/processes.py +++ b/plomtask/processes.py @@ -26,10 +26,10 @@ class Process(BaseModel[int], ConditionsRelations): table_name = 'processes' to_save = ['calendarize'] to_save_versioned = ['title', 'description', 'effort'] - to_save_relations = [('process_conditions', 'process', 'conditions'), - ('process_blockers', 'process', 'blockers'), - ('process_enables', 'process', 'enables'), - ('process_disables', 'process', 'disables')] + to_save_relations = [('process_conditions', 'process', 'conditions', 0), + ('process_blockers', 'process', 'blockers', 0), + ('process_enables', 'process', 'enables', 0), + ('process_disables', 'process', 'disables', 0)] to_search = ['title.newest', 'description.newest'] def __init__(self, id_: int | None, calendarize: bool = False) -> None: diff --git a/plomtask/todos.py b/plomtask/todos.py index 9fac63b..775ef48 100644 --- a/plomtask/todos.py +++ b/plomtask/todos.py @@ -26,12 +26,12 @@ class Todo(BaseModel[int], ConditionsRelations): table_name = 'todos' to_save = ['process_id', 'is_done', 'date', 'comment', 'effort', 'calendarize'] - to_save_relations = [('todo_conditions', 'todo', 'conditions'), - ('todo_blockers', 'todo', 'blockers'), - ('todo_enables', 'todo', 'enables'), - ('todo_disables', 'todo', 'disables'), - ('todo_children', 'parent', 'children'), - ('todo_children', 'child', 'parents')] + to_save_relations = [('todo_conditions', 'todo', 'conditions', 0), + ('todo_blockers', 'todo', 'blockers', 0), + ('todo_enables', 'todo', 'enables', 0), + ('todo_disables', 'todo', 'disables', 0), + ('todo_children', 'parent', 'children', 0), + ('todo_children', 'child', 'parents', 1)] to_search = ['comment'] # pylint: disable=too-many-arguments -- 2.30.2 From d31168fca24980f4e5f996bc187ed773eb504629 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 3 Jun 2024 04:15:50 +0200 Subject: [PATCH 13/16] Remove accidentally committed file garbage. --- plomtask/.db.py.swp | Bin 40960 -> 0 bytes plomtask/.http.py.swp | Bin 32768 -> 0 bytes plomtask/.versioned_attributes.py.swp | Bin 12288 -> 0 bytes plomtask/__pycache__/__init__.cpython-311.pyc | Bin 162 -> 0 bytes plomtask/__pycache__/conditions.cpython-311.pyc | Bin 5656 -> 0 bytes plomtask/__pycache__/dating.cpython-311.pyc | Bin 1782 -> 0 bytes plomtask/__pycache__/days.cpython-311.pyc | Bin 6458 -> 0 bytes plomtask/__pycache__/db.cpython-311.pyc | Bin 28984 -> 0 bytes plomtask/__pycache__/exceptions.cpython-311.pyc | Bin 1122 -> 0 bytes plomtask/__pycache__/http.cpython-311.pyc | Bin 36429 -> 0 bytes plomtask/__pycache__/misc.cpython-311.pyc | Bin 4802 -> 0 bytes plomtask/__pycache__/processes.cpython-311.pyc | Bin 13696 -> 0 bytes plomtask/__pycache__/task.cpython-311.pyc | Bin 4437 -> 0 bytes plomtask/__pycache__/todos.cpython-311.pyc | Bin 17018 -> 0 bytes .../versioned_attributes.cpython-311.pyc | Bin 5245 -> 0 bytes 15 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plomtask/.db.py.swp delete mode 100644 plomtask/.http.py.swp delete mode 100644 plomtask/.versioned_attributes.py.swp delete mode 100644 plomtask/__pycache__/__init__.cpython-311.pyc delete mode 100644 plomtask/__pycache__/conditions.cpython-311.pyc delete mode 100644 plomtask/__pycache__/dating.cpython-311.pyc delete mode 100644 plomtask/__pycache__/days.cpython-311.pyc delete mode 100644 plomtask/__pycache__/db.cpython-311.pyc delete mode 100644 plomtask/__pycache__/exceptions.cpython-311.pyc delete mode 100644 plomtask/__pycache__/http.cpython-311.pyc delete mode 100644 plomtask/__pycache__/misc.cpython-311.pyc delete mode 100644 plomtask/__pycache__/processes.cpython-311.pyc delete mode 100644 plomtask/__pycache__/task.cpython-311.pyc delete mode 100644 plomtask/__pycache__/todos.cpython-311.pyc delete mode 100644 plomtask/__pycache__/versioned_attributes.cpython-311.pyc diff --git a/plomtask/.db.py.swp b/plomtask/.db.py.swp deleted file mode 100644 index b62d92eaf0d1f323ef01182ddbfb6e142020b516..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40960 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 diff --git a/plomtask/.http.py.swp b/plomtask/.http.py.swp deleted file mode 100644 index 003e5d3bd3946762d66592ba164f72136ada1280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 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 diff --git a/plomtask/.versioned_attributes.py.swp b/plomtask/.versioned_attributes.py.swp deleted file mode 100644 index 1c5a54423ed22ed4fca7d4659d98c0e0b2da2c7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeHN&5smC6tCsOZ_t1j4JMB@o7oAo%?uk7calX{z=+8r0fd-gGpU)bVLRJjbk#6S zL@=7@*^8Wzll}u5E*?F2){`gW(RkL#N&QvzH@hopxM-@gzwPeo*RS6D)vsRlW^2&C zaB7v7oDReB3}avZdTHd&T%Wmdd@qarDA3IhIwnUK+YhqQ&u?glhvV_U_lEsM#F0F# zTNIZY<;7KzNG}S7+viFp-e9bRbmHmX@o#M`1D1hp7#OS3!b^MD;*pM-t1r$Tr2YHe z+Q!&6TLvrxmI2FvWxz6E8L$jk1}p>rM+Q_p!)_w69a(a3WapXt&e^R!Sq3ZvmI2Fv zWxz6E8L$jk1}p=X0n318z%uY3WPrPjUEImotz8Hn|Nqbb{{QM}#%=>20wHh_XaR?S zUBFIY2k_Hg#_j;00v`cOzyaX5J&b)1d=7jD+yWxtIPfg6AJ`52_!MIw10ir4cpi8T z`1wir1a1Rofc?Ne;Oi$C8v`!`i@*Wk-s6nj1p>eay1>2182b+R7Pt+(2^<3cc$Bek zfIGlVU=?@)_~jACegM7zJ^WUF1=8bpiI^m?!lo*p z>p0~<;HXu210&}+7~--PErHs^6S76vj71|ak%}f>EGY6_0vEDIrG$rnM`R+@IH?oW z!+3&uYz9+aAf)0!Tqdtc*!-N9sjw|F)28|uB!X`+bD90}Mx{9&qbp;9RMYOdg`pnD z!l@a|D5(V{d!6oDX}@Jua??BQdM?%cAxb{>RS^NgY}4{G`68U(m_mPb`BihLL(9~lBa7XmOZah?mX;dTSacXw^QMli(=OvM(@m=ea=Oa>F~m|O zIuw|&kWtk~Ix*F{pqNWl(-c>kqN?^?k}5G15@)(jBR}G*GA~Uj$nxza(L_%iu%WMx zl*A*@lh>38-MZvWkr3BnBR(>C8HLe%azaq zb3(k|bdbH)On9Bib ziBmWpMuD!?S?v5W_dLt5G_G@$ zC_!!%HWUrl#c+cP?+{0pAcbmStfNA_S9&Aws4sbcuS06fZ|Y(m2*} zn66@2d3x7sncC@U924#-T`4K>hDo#_1=cjTWys0P8l_x#G77a@6LT2~s9teh{h&I! zni~$~nwWB)ups7qO3HFY*J)&Wtpk&pM2%$3G|H#XR${G|r3c8W7z!u?%$4Q*FUwg~ zb)_)V3ZfT;>NuE?TLiruB667_`5G}Ih}E=KLQ*D7;+t!R4)>KfiDHo`>@?Q5`p7dd zHPyVD&nqXZpS^`nt(2TibFM~QtQ)m(HciP|WGM?3&M74(_Uag z{k|7^s^3o)nhu2)f3X#uChHMqtFntQ!Fx7wXM=gf^7jG09t-?8qv1M-3x+SuYdF*VggpWB!k mnl{TTKEBl!^Cws%GV^Kdg_rYY(3m#oYeW7Zzh@7Hmp=hoE!%$p diff --git a/plomtask/__pycache__/__init__.cpython-311.pyc b/plomtask/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 67ebc21772973750904d84d340676a7754abc78f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162 zcmZ3^%ge<81l4BWQbF`%5CH>>P{wCAAY(d13PUi1CZpdy?A%PfhH*DI*}#bJ}1pHiBWYFESxGzDZ& UF+Y&_z|6?V_<;dN6fpzE0CYnprT_o{ diff --git a/plomtask/__pycache__/conditions.cpython-311.pyc b/plomtask/__pycache__/conditions.cpython-311.pyc deleted file mode 100644 index 23e3c3b63a2389c73cce1cfd1cf1da5c8892704c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5656 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 diff --git a/plomtask/__pycache__/dating.cpython-311.pyc b/plomtask/__pycache__/dating.cpython-311.pyc deleted file mode 100644 index dc6f1cd477343b22891bd342b4e7d9aea7a94495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1782 zcmZ`(Piq@j5P$ne(ylgAoC>$8ZJbT4jVl~Uv?Umt#9$Mrq_iodCM4=XY_%(A6YZ}0 z_9?PdDVWlO8Upd9*iZ~UxhZbHKo14?6G%n}v0x~a9()t{5^`zh?MjxEy2EPT%$u2~ znK!?AKSd&81oUB$7e#CpbI@+1YOj^U!a6kRqmODh=G zs;sF*cTz|6{}Ze$P?Z>_?uwLadV#13#(ir^)o$6?RLSyMPA?L}wyJ{iAgP#1Me~EQ z4#92^>!gIO9Mda@F0?c#7ae~JyPK#6g*;}d0gsU(KaJf5ZSQ2Kj;uNGann8{Imeqth`;;v+WwgdUKxL-J?1Tmp18F3qk^6z>idB41Ef}eeCqf(xu8}LrU^lDu3JjZ@b?Rf|iEjD1*?GB)Z2%mg z4{-F6d?z8eQJQyPWB)IuwAk#Md9DAKIp#E*5MvT`YZ7FmhR}7j4JeA*%CuAV6L)9I0Z( z4L_k*4C%qmorjYs1f1W2t)p%j31b`c2cd~(XyPz-apz(y7H`Mm4WS`)#B&>89*A;N zl&R%XE2gw#O5c(>5HB>v3nMXImJcKkBjfGJ^w!$1ldZ_rcI0YmWL;mRwZZUFr08boKJFRnei_QN+VX{IgB zH2E2a*0Rq{EKZ~S>2pgWx1Szg;<-Qg0LU)$KO_7Uf;Q3ccs)89*j=#g!Otf``_iKt z`h^)Cfht()6!b%b*!M;wV>TKGpl7S;yWS)720DF|<*{wb9zf+enIf;^q~QJHsgMZx z_~IUev9akbkJNA&2`Xw x&C|XP`k*=b{TV&KE_H)rOnfWWMX>Dnizg4U%N%ogBiBW+Z25~PpT@jQ{{>l{tl0nn diff --git a/plomtask/__pycache__/days.cpython-311.pyc b/plomtask/__pycache__/days.cpython-311.pyc deleted file mode 100644 index 393a8bb1b68f44d5e72a72ef44ce368ee7d9568f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6458 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

h5@Nc~dnRPfym;%iz+fcRu&v^uu8|2xME1Knq$8 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 diff --git a/plomtask/__pycache__/exceptions.cpython-311.pyc b/plomtask/__pycache__/exceptions.cpython-311.pyc deleted file mode 100644 index 85b2cdc05b068b93be1ab786b4e4421cc9cd82bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1122 zcmbVK&2AGh5cdA0O+t%8L5SRZY*Z;x4;89}IDjbS&n zKo3CQ093)l)MftbterI?e&3J}{^iMe$19jXaEl7;0P4s!gr7L+!Rp z9VqWkD#u<-Lq_vkhA&$Ja|)GtFu=K6;f|*m#UjS6pD@7l0Q!l)UY!X6+5AIS=>x396muO~szkb^2 ziHJ3lP(+O+?S$MXk|jcA9_^_Qw+72;swV?!_|KFJhN^-(%h%XF8M!Cp%EPlaX32Yt z+&j>>^TMM?LPnm>nHuh`ArPpGyfA=l;Eu;hs#Tqz8=|D?QksdIH?w7|`wLY9V+F#& z$URtsU=G{?!h@#JMo{&_8mia}wN>23wZ;mAE) zLSb^7wSp|dJ}Kp_&R;a+BrEwZS=Ys9^Wl0fci@~Eef0&@)UhmUjP^%pf4X5?kEUo< eoezE+@6~Onyqc69993)oo%&>VIW@1Jz40H`F%WM6 diff --git a/plomtask/__pycache__/http.cpython-311.pyc b/plomtask/__pycache__/http.cpython-311.pyc deleted file mode 100644 index edbb8eadaa831eddcf832ee2c761b0b252a9881e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36429 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 W+0B?F`Jw3T{t5H?X@LN2s{9|@iuH^D diff --git a/plomtask/__pycache__/misc.cpython-311.pyc b/plomtask/__pycache__/misc.cpython-311.pyc deleted file mode 100644 index 30b4ccfda20c063dbfec821b78a1a2984263128f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4802 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 IWmcf{Ka=rzkN^Mx diff --git a/plomtask/__pycache__/processes.cpython-311.pyc b/plomtask/__pycache__/processes.cpython-311.pyc deleted file mode 100644 index bebfbe316c7193e45fa216644b494f65122f031f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13696 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 diff --git a/plomtask/__pycache__/task.cpython-311.pyc b/plomtask/__pycache__/task.cpython-311.pyc deleted file mode 100644 index 173d529e17a765c681b734d323c397c0239a3e90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4437 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 AjQ{`u diff --git a/plomtask/__pycache__/versioned_attributes.cpython-311.pyc b/plomtask/__pycache__/versioned_attributes.cpython-311.pyc deleted file mode 100644 index 7c20eb29bb810b4a5ed8fd44c61a7b9c0e0d17cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5245 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 -- 2.30.2 From 8542cd471f1aeea1abbe0b237a94f7863fb12dd0 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 3 Jun 2024 04:16:48 +0200 Subject: [PATCH 14/16] Enhance layouts. --- templates/_base.html | 4 ++ templates/_macros.html | 2 +- templates/calendar.html | 8 +++- templates/day.html | 87 +++++++++++++++++++++++++++-------------- templates/todo.html | 8 ++-- templates/todos.html | 4 +- 6 files changed, 74 insertions(+), 39 deletions(-) diff --git a/templates/_base.html b/templates/_base.html index 0e38465..7c10506 100644 --- a/templates/_base.html +++ b/templates/_base.html @@ -21,6 +21,10 @@ td, th, tr, table { vertical-align: top; margin-top: 1em; padding: 0; + border-collapse: collapse; +} +a { + color: black; } {% block css %} {% endblock %} diff --git a/templates/_macros.html b/templates/_macros.html index b1f0104..cb1bb45 100644 --- a/templates/_macros.html +++ b/templates/_macros.html @@ -25,7 +25,7 @@ -{% if historical %}{{item.title_then}}{% else %}{{item.title.newest|e}}{% endif %} +{% if historical is true %}{{item.title_then}}{% else %}{{item.title.newest|e}}{% endif %} {% endfor %} diff --git a/templates/calendar.html b/templates/calendar.html index 4674262..42c821a 100644 --- a/templates/calendar.html +++ b/templates/calendar.html @@ -8,15 +8,19 @@ tr.week_row td { background-color: black; padding: 0; margin: 0; + border-top: 0.2em solid white; } tr.month_row td { - border: 0.1em solid black; - text-align: center; + border-top: 0.2em solid white; color: white; background-color: #555555; } +table { + width: 100%; +} tr.day_row td { background-color: #cccccc; + border-top: 0.2em solid white; } td.day_name { padding-right: 0.5em; diff --git a/templates/day.html b/templates/day.html index 2e1a380..0165c9e 100644 --- a/templates/day.html +++ b/templates/day.html @@ -8,23 +8,45 @@ td, th, tr, table { padding: 0; margin: 0; } +table { + border-collapse: collapse; +} th { border: 1px solid black; } -td.min_width { - min-width: 1em; -} td.cond_line_0 { - background-color: #ffbbbb; + border-top: 1px solid white; + background-color: #dddddd; } td.cond_line_1 { - background-color: #bbffbb; + border-top: 1px solid white; + background-color: #efefef; } td.cond_line_2 { - background-color: #bbbbff; + border-top: 1px solid white; + background-color: #fffff; +} +td.cond_line_corner { + max-width: 0px; + white-space: nowrap; + overflow: hidden; + text-overflow: clip; } td.todo_line { - border-bottom: 1px solid #bbbbbb; + border-bottom: 1px solid #dddddd; + height: 1.7em; +} +tr.inactive td.todo_line { + background-color: #efefef; +} +td.left_border { + border-left: 1px solid black; +} +td.right_border { + border-right: 1px solid black; +} +input { + height: 100%; } {% endblock %} @@ -32,38 +54,42 @@ td.todo_line { {% macro show_node_undone(node, indent) %} {% if not node.todo.is_done %} - + {% if not node.seen %} {% endif %} {% for condition in conditions_present %} -{% if condition in node.todo.conditions and not condition.is_active %}O{% elif condition in node.todo.blockers and condition.is_active %}!{% endif %} + +{% if condition in node.todo.conditions and not condition.is_active %} +O  +{% elif condition in node.todo.blockers and condition.is_active %} +!  +{% endif %} + {% endfor %} --> {% if node.seen %} - + {% if node.todo.effort %}{{ node.todo.effort }}{% endif %} {% else %} - + {% endif %} - -{% for i in range(indent) %}  {% endfor %} + + +{% for i in range(indent) %}    {% endfor %} + {% if node.seen %}({% endif %}{{node.todo.title_then|e}}{% if node.seen %}){% endif %} --> {% for condition in conditions_present|reverse %} -{% if condition in node.todo.enables %}+{% elif condition in node.todo.disables %}!{% endif %} +{% if condition in node.todo.enables %} +{% elif condition in node.todo.disables %} !{% endif %} {% endfor %} - + {% if node.seen %} {{node.todo.comment|e}} {% else %} - + {% endif %} @@ -122,14 +148,12 @@ comment:
add todo: -

todo

+

to do

- - - + @@ -141,24 +165,27 @@ add todo: {% for _ in conditions_present %} {% if outer_loop.index > loop.index %} {% endfor %} - + {% for _ in conditions_present %} -{% if outer_loop.index0 + loop.index0 < conditions_present|length %} +{% if outer_loop.index0 + loop.index < conditions_present|length %} {{ macros.datalist_of_titles(list_name, enablers_for[condition.id_]) }} @@ -174,11 +201,11 @@ add todo: {% for condition in conditions_present %} {% endfor %} - + {% for condition in conditions_present %} {% endfor %} - + {% for node in top_nodes %} {{ show_node_undone(node, 0) }} diff --git a/templates/todo.html b/templates/todo.html index 0d4773c..a2ef536 100644 --- a/templates/todo.html +++ b/templates/todo.html @@ -40,22 +40,22 @@ - + - + - + - + diff --git a/templates/todos.html b/templates/todos.html index 6b733e0..3dd1f3f 100644 --- a/templates/todos.html +++ b/templates/todos.html @@ -25,9 +25,9 @@ in comment {% for todo in todos %} - + - + {% endfor %}
cstateststates add enabler add disabler
-{% else %} +{% elif outer_loop.index < loop.index %} -{% endif %} -{% if outer_loop.index == loop.index %} +{% else %} +X {% endif %} [{% if condition.is_active %}X{% else %} {% endif %}]{{condition.title.at(day.date)|e}}{{condition.title.at(day.date)|e}} -{% else %} +{% elif outer_loop.index0 + loop.index > conditions_present|length %} +{% else %} + X {% endif %} {% endfor %} + {% set list_name = "todos_for_%s"|format(condition.id_) %} doablesdoablescommentscomments
conditions{{ macros.simple_checkbox_table("condition", todo.conditions, "condition", "condition_candidates", historical=true) }}{{ macros.simple_checkbox_table("condition", todo.conditions, "condition", "condition_candidates") }}
blockers{{ macros.simple_checkbox_table("blocker", todo.blockers, "condition", "condition_candidates", historical=true) }}{{ macros.simple_checkbox_table("blocker", todo.blockers, "condition", "condition_candidates") }}
enables{{ macros.simple_checkbox_table("enables", todo.enables, "condition", "condition_candidates", historical=true) }}{{ macros.simple_checkbox_table("enables", todo.enables, "condition", "condition_candidates") }}
disables{{ macros.simple_checkbox_table("disables", todo.disables, "condition", "condition_candidates", historical=true) }}{{ macros.simple_checkbox_table("disables", todo.disables, "condition", "condition_candidates") }}
[{% if todo.is_done %}x{% else %} {% endif %}]{{todo.date}}{{todo.date}} {{todo.title_then}}{{todo.comment}}{{todo.comment}}
-- 2.30.2 From 0c668bad3efe0db132452b63ecfef05320ca9e48 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 3 Jun 2024 04:22:17 +0200 Subject: [PATCH 15/16] To Processes listing, add sortable effort column. --- plomtask/http.py | 4 ++++ templates/processes.html | 2 ++ 2 files changed, 6 insertions(+) diff --git a/plomtask/http.py b/plomtask/http.py index 8ddef65..249de32 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -269,6 +269,10 @@ class TaskHandler(BaseHTTPRequestHandler): processes.sort(key=lambda p: len(p.explicit_steps)) elif sort_by == '-steps': processes.sort(key=lambda p: len(p.explicit_steps), reverse=True) + elif sort_by == 'effort': + processes.sort(key=lambda p: p.effort.newest) + elif sort_by == '-effort': + processes.sort(key=lambda p: p.effort.newest, reverse=True) elif sort_by == '-title': processes.sort(key=lambda p: p.title.newest, reverse=True) else: diff --git a/templates/processes.html b/templates/processes.html index 9b282bf..42beafc 100644 --- a/templates/processes.html +++ b/templates/processes.html @@ -11,11 +11,13 @@ + {% for process in processes %} + {% endfor %} -- 2.30.2 From c64a6dcd83cd13f5cc534325feac0554cf289a81 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 3 Jun 2024 04:54:58 +0200 Subject: [PATCH 16/16] Minor template improvements. --- templates/_base.html | 3 +++ templates/day.html | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/templates/_base.html b/templates/_base.html index 7c10506..0d2debe 100644 --- a/templates/_base.html +++ b/templates/_base.html @@ -23,6 +23,9 @@ td, th, tr, table { padding: 0; border-collapse: collapse; } +th, td { + padding-right: 1em; +} a { color: black; } diff --git a/templates/day.html b/templates/day.html index 0165c9e..627923b 100644 --- a/templates/day.html +++ b/templates/day.html @@ -37,7 +37,7 @@ td.todo_line { height: 1.7em; } tr.inactive td.todo_line { - background-color: #efefef; + background-color: #dddddd; } td.left_border { border-left: 1px solid black; @@ -45,8 +45,11 @@ td.left_border { td.right_border { border-right: 1px solid black; } -input { - height: 100%; +input[type="text"] { + width: 98%; +} +input[name="day_comment"] { + width: 100em; } {% endblock %} @@ -82,14 +85,14 @@ O  {% for condition in conditions_present|reverse %} - + {% endfor %} @@ -144,16 +147,19 @@ O  prev | next

-comment: -
-add todo: + +

+comment: + + +

to do

stepseffort title
{{ process.explicit_steps|count }}{{ process.effort.newest }} {{process.title.newest}}
{% if condition in node.todo.enables %} +{% elif condition in node.todo.disables %} !{% endif %}{% if condition in node.todo.enables %} +{% elif condition in node.todo.disables %} !{% endif %} {% if node.seen %} {{node.todo.comment|e}} {% else %} - + {% endif %}
- + @@ -168,12 +174,12 @@ add todo: {% elif outer_loop.index < loop.index %} {% endfor %} - + {% for _ in conditions_present %} @@ -182,7 +188,7 @@ add todo: {% elif outer_loop.index0 + loop.index > conditions_present|length %} {% endfor %} - + +{% for condition in conditions_present %} + +{% endfor %} + + + +{% for condition in conditions_present %} + +{% endfor %} + + + {% for condition in conditions_present %} {% endfor %} -- 2.30.2
statesconditions add enabler add disabler
{% else %} -X +× {% endif %} [{% if condition.is_active %}X{% else %} {% endif %}] {{condition.title.at(day.date)|e}} {% else %} - X + Ã— {% endif %} {% endfor %} @@ -201,7 +207,19 @@ add todo: {% for condition in conditions_present %} doablesdoables
add: