home · contact · privacy
Re-factor Day.todos code.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 14 Jun 2024 13:53:33 +0000 (15:53 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 14 Jun 2024 13:53:33 +0000 (15:53 +0200)
plomtask/days.py
plomtask/http.py
plomtask/todos.py
templates/calendar.html
templates/day.html

index 2531a011f1875a4819337adcd7e59c7a08355af4..155ed03aabdbddacdf481267c04aa9d5a0fc29c0 100644 (file)
@@ -23,7 +23,7 @@ class Day(BaseModel[str]):
         super().__init__(id_)
         self.datetime = datetime.strptime(self.date, DATE_FORMAT)
         self.comment = comment
-        self.todos: list[Todo] | None = [] if init_empty_todo_list else None
+        self._todos: list[Todo] | None = [] if init_empty_todo_list else None
 
     def __lt__(self, other: Day) -> bool:
         return self.date < other.date
@@ -32,9 +32,25 @@ class Day(BaseModel[str]):
     def from_table_row(cls, db_conn: DatabaseConnection, row: Row | list[Any]
                        ) -> Day:
         """Make from DB row, with linked Todos."""
+        # pylint: disable=protected-access
+        # (since on ._todo we're only meddling within cls)
         day = super().from_table_row(db_conn, row)
         assert isinstance(day.id_, str)
-        day.todos = Todo.by_date(db_conn, day.id_)
+        day._todos = Todo.by_date(db_conn, day.id_)
+        return day
+
+    @classmethod
+    def by_id(cls,
+              db_conn: DatabaseConnection, id_: str | None,
+              create: bool = False,
+              init_empty_todo_list: bool = False
+              ) -> Day:
+        """Extend BaseModel.by_id with init_empty_todo_list flag."""
+        # pylint: disable=protected-access
+        # (since on ._todo we're only meddling within cls)
+        day = super().by_id(db_conn, id_, create)
+        if init_empty_todo_list and day._todos is None:
+            day._todos = []
         return day
 
     @classmethod
@@ -102,11 +118,22 @@ class Day(BaseModel[str]):
         return next_datetime.strftime(DATE_FORMAT)
 
     @property
-    def calendarized_todos(self) -> list[Todo]:
-        """Return only those of self.todos that have .calendarize set."""
-        if self.todos is None:
+    def todos(self) -> list[Todo]:
+        """Return self.todos if initialized, else raise Exception."""
+        if self._todos is None:
             msg = 'Trying to return from un-initialized Day.todos.'
             raise HandledException(msg)
-        # pylint: disable=not-an-iterable
-        # (after the above is-None test, self.todos _should_ be iterable!)
+        return list(self._todos)
+
+    @property
+    def calendarized_todos(self) -> list[Todo]:
+        """Return only those of self.todos that have .calendarize set."""
         return [t for t in self.todos if t.calendarize]
+
+    @property
+    def total_effort(self) -> float:
+        """"Sum all .performed_effort of self.todos."""
+        total_effort = 0.0
+        for todo in self.todos:
+            total_effort += todo.performed_effort
+        return total_effort
index 91db32601c24c91c49db75df4f9ca2b05fd9b944..230ed3f26c5d53398a27d87558a28abeb28ceff5 100644 (file)
@@ -205,12 +205,13 @@ class TaskHandler(BaseHTTPRequestHandler):
     def do_GET_day(self) -> dict[str, object]:
         """Show single Day of ?date=."""
         date = self._params.get_str('date', date_in_n_days(0))
+        day = Day.by_id(self.conn, date, create=True,
+                        init_empty_todo_list=True)
         make_type = self._params.get_str('make_type')
-        todays_todos = Todo.by_date(self.conn, date)
         conditions_present = []
         enablers_for = {}
         disablers_for = {}
-        for todo in todays_todos:
+        for todo in day.todos:
             for condition in todo.conditions + todo.blockers:
                 if condition not in conditions_present:
                     conditions_present += [condition]
@@ -222,9 +223,8 @@ class TaskHandler(BaseHTTPRequestHandler):
                                                     if condition in p.disables]
         seen_todos: set[int] = set()
         top_nodes = [t.get_step_tree(seen_todos)
-                     for t in todays_todos if not t.parents]
-        return {'day': Day.by_id(self.conn, date, create=True),
-                'total_effort': Todo.total_effort_at_date(self.conn, date),
+                     for t in day.todos if not t.parents]
+        return {'day': day,
                 'top_nodes': top_nodes,
                 'make_type': make_type,
                 'enablers_for': enablers_for,
index 008f7a275ab42aa9bbbcfed1933c81f491854211..fa009b12b8fb64e42b8a42f728fd0d4fb1740367 100644 (file)
@@ -155,16 +155,6 @@ class Todo(BaseModel[int], ConditionsRelations):
         """Collect all Todos for Day of date."""
         return cls.by_date_range(db_conn, (date, date))
 
-    @classmethod
-    def total_effort_at_date(cls, db_conn: DatabaseConnection, date: str
-                             ) -> float:
-        """Sum all .performed_effort of Todos at Day of date."""
-        total_effort = 0.0
-        days_todos = cls.by_date(db_conn, date)
-        for todo in days_todos:
-            total_effort += todo.performed_effort
-        return total_effort
-
     @property
     def is_doable(self) -> bool:
         """Decide whether .is_done settable based on children, Conditions."""
index 4e835734c026fa1612e2ec18d4a9dfb1bd10ac29..11ac2a8816800eb0c11516610fe9e71eecda4027 100644 (file)
@@ -28,6 +28,9 @@ td.day_name {
 td.today {
   font-weight: bold;
 }
+span.total_effort {
+  white-space: pre;
+}
 {% endblock %}
 
 
@@ -58,7 +61,10 @@ to <input name="end" class="date" value="{{end}}" />
 {% endif %}
 
 <tr class="day_row">
-<td class="day_name {% if day.date == today %}today{% endif %}"><a href="day?date={{day.date}}">{{day.weekday|truncate(2,True,'',0)}} {% if day.date == today %} {% endif %}{{day.date}}</a> {{day.comment|e}}</td>
+<td class="day_name {% if day.date == today %}today{% endif %}">
+<a href="day?date={{day.date}}">{{day.weekday|truncate(2,True,'',0)}} {% if day.date == today %} {% endif %}{{day.date}}</a>
+[<span class="total_effort">{{ '{:5.1f}'.format(day.total_effort) }}</span>]
+{{day.comment|e}}</td>
 </tr>
 
 {% for todo in day.calendarized_todos %}
index a34f05b3ad5a6c84135ad518fe83a44530815333..f980cd1f5ad93d271e8103c981c8cdf49523e8fe 100644 (file)
@@ -124,7 +124,7 @@ O&nbsp;
 
 
 {% block content %}
-<h3>{{day.date}} / {{day.weekday}} ({{total_effort|round(1)}})</h3>
+<h3>{{day.date}} / {{day.weekday}} ({{day.total_effort|round(1)}})</h3>
 <p>
 <a href="day?date={{day.prev_date}}">prev</a> | <a href="day?date={{day.next_date}}">next</a>
 </p>