home · contact · privacy
Improve todo accounting.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 12 Dec 2023 21:32:03 +0000 (22:32 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 12 Dec 2023 21:32:03 +0000 (22:32 +0100)
todo.py

diff --git a/todo.py b/todo.py
index 88684acff1068a989f103715ba7535a7211d30f0..42639a11c9f28fdfbe34991af191e3bd8dc122ee 100644 (file)
--- a/todo.py
+++ b/todo.py
@@ -12,25 +12,28 @@ DATE_FORMAT = '%Y-%m-%d'
 
 html_head = """
 <style>
+body { font-family: monospace; }
 table.alternating tr:nth-child(even) {
     background-color: #f2f2f2;
 }
 table.alternating tr:nth-child(odd) {
     background-color: #ffffff;
 }
-th, td { border: 1px solid black; text-align: left; vertical_align: top; }
+th, td { text-align: left; vertical_align: top; border-bottom: 1px dotted black; }
 td details { display: inline }
 td.input { width: 100%; }
-td.checkbox { width: 0.7em; }
-th.checkbox { width: 0.7em; }
+td.number { text-align: right; }
+td.checkbox { width: 0.1em; height: 0.1em; padding: 0em; text-align: center; }
 tr.week_row td { height: 0.1em; border: 0px; background-color: black; }
-tr.day_row td { background-color: #f2f2f2; }
+tr.day_row td { background-color: #f2f2f2 }
+input { font-family: monospace; padding: 0em; margin: 0em; }
+input[type="number"] { font-family: monospace; text-align: right; }
 input[type="text"] { width: 100%; box-sizing: border-box; }
 </style>
 <body>
 tasks: <a href="{{db.prefix}}/tasks">list</a> <a href="{{db.prefix}}/add_task">add</a> | day: 
 <a href="{{db.prefix}}/day{% if date %}?date={{date}}{% endif %}">choose tasks</a>
-<a href="{{db.prefix}}/day?{% if date %}date={{date}}&{% endif %}hide_unchosen=1">do tasks</a>
+<a href="{{db.prefix}}/day?{% if date %}date={{date}}&{% endif %}hide_unchosen=1&hide_done=1">do tasks</a>
 | <a href="{{db.prefix}}/calendar?t_and=calendar">calendar</a>
 <hr />
 """
@@ -46,8 +49,8 @@ to: <input name="end" {% if end_date %}value="{{ end_date }}"{% endif %} placeho
 </p>
 <table>
 {% for date, day in days.items() | sort() %}
-{% if day.weekday == "Monday" %}<tr class="week_row"><td colspan=3></td></tr>{% endif %}
-<tr class="day_row"><td colspan=3><a href="{{db.prefix}}/day?date={{date}}&hide_unchosen=1">{{ date }}</a> {{ day.weekday }} ({{ day.todos_sum|round(2) }}) {{ day.comment|e }}</td></tr>
+{% if day.weekday == "Mo" %}<tr class="week_row"><td colspan=3></td></tr>{% endif %}
+<tr class="day_row"><td colspan=3><a href="{{db.prefix}}/day?date={{date}}&hide_unchosen=1">{{ day.weekday }} {{ date }}</a> |{{ '%04.1f' % day.todos_sum|round(2) }}| {{ day.comment|e }}</td></tr>
 {% for task, todo in day.todos.items() | sort(attribute='1.title', reverse=True)  %}
 {% if todo.visible %}
 <tr><td class="checkbox">{% if todo.done %}✓{% else %}&nbsp;&nbsp;{% endif %}</td><td><a href="{{db.prefix}}/todo?task={{ todo.task.id_ }}&date={{ date }}">{{ todo.title }}</a></td><td>{{ todo.comment|e }}</td></tr>
@@ -63,7 +66,7 @@ todo_tmpl = """
 <tr><th>task</th><td><a href="{{db.prefix}}/task?id={{ todo.task.id_ }}">{{ todo.task.title|e }}</a></td></tr>
 <tr><th>default weight</th><td>{{ todo.default_weight }}</td></tr>
 <tr><th>day</th><td>{{ todo.day.date }}</td></tr>
-<tr><th>day weight</th><td class="input"><input type="number" name="day_weight" step=0.1 size=5 value="{{ todo.day_weight }}" /></td></tr>
+<tr><th>day weight</th><td class="input"><input type="number" name="day_weight" step=0.1 size=8 value="{{ todo.day_weight }}" /></td></tr>
 <tr><th>comment</th><td class="input"><input type="text" name="comment" value="{{todo.comment|e}}" /></td></tr>
 <tr><th>done</th><td class="input"><input type="checkbox" name="done" {% if todo.done %}checked{% endif %}/></td></tr>
 </table>
@@ -73,17 +76,17 @@ task_tmpl = """
 <input type="hidden" name="id" value="{{ task.id_ }}" />
 <table>
 <tr><th>title</th><td class="input"><input name="title" type="text" value="{{ task.title|e }}" /><details><summary>history</summary><ul>{% for k,v in task.title_history.items() | sort(attribute='0', reverse=True) %}<li>{{ k }}: {{ v|e }}{% endfor %}</ul></details></td></tr>
-<tr><th>default weight</th><td class="input"><input type="number" name="default_weight" value="{{ task.default_weight }}" step=0.1 size=5 required /><details><summary>history</summary><ul>{% for k,v in task.default_weight_history.items() | sort(attribute='0', reverse=True) %}<li>{{ k }}: {{ v|e }}{% endfor %}</ul></details></td></tr>
+<tr><th>default weight</th><td class="input"><input type="number" name="default_weight" value="{{ task.default_weight }}" step=0.1 size=8 required /><details><summary>history</summary><ul>{% for k,v in task.default_weight_history.items() | sort(attribute='0', reverse=True) %}<li>{{ k }}: {{ v|e }}{% endfor %}</ul></details></td></tr>
 <tr><th>tags</th><td class="input"><input name="tags" type="text" value="{{ task.tags_joined|e }}" ><details><summary>history</summary><ul>{% for k,v in task.tags_history.items() | sort(attribute='0', reverse=True) %}<li>{{ k }}: {{ v|e }}{% endfor %}</ul></details></td></tr>
 </table>
 <input type="submit" value="update" />
 """
 day_tmpl = """
 <p>
-<input name="hide_unchosen" type="checkbox" {% if db.hide_unchosen %}checked{% endif %} /> hide unchosen | 
-<a href="{{db.prefix}}/day?date={{prev_date}}{% if db.hide_unchosen %}&hide_unchosen=1{% endif %}">prev</a> <a href="{{db.prefix}}/day?date={{next_date}}{% if db.hide_unchosen %}&hide_unchosen=1{% endif %}">next</a> | 
+<input name="hide_unchosen" type="checkbox" {% if db.hide_unchosen %}checked{% endif %} /> hide unchosen <input name="hide_done" type="checkbox" {% if db.hide_done %}checked{% endif %} /> hide done 
+<a href="{{db.prefix}}/day?date={{prev_date}}{% if db.hide_unchosen %}&hide_unchosen=1{% endif %}{% if db.hide_done %}&hide_done=1{% endif %}">prev</a> <a href="{{db.prefix}}/day?date={{next_date}}{% if db.hide_unchosen %}&hide_unchosen=1{% endif %}{% if db.hide_done %}&hide_done=1{% endif %}">next</a> | 
 <input type="hidden" name="original_selected_date" value="{{ db.selected_date }}" />
-date: <input name="new_selected_date" value="{{ db.selected_date }}" size=8 /> |
+date: <input name="new_selected_date" value="{{ db.selected_date }}" size=10 /> |
 {{ db.selected_day.todos_sum|round(2) }} ({{ db.selected_day.todos_sum2|round(2)}}) |
 comment: <input name="day_comment" value="{{ db.selected_day.comment|e }}">
 </p>
@@ -95,9 +98,9 @@ comment: <input name="day_comment" value="{{ db.selected_day.comment|e }}">
 <tr>
 <input name="t_uuid" value="{{ uuid }}" type="hidden" >
 <td><details><summary>] <a href="{{db.prefix}}/task?id={{ uuid }}" />{{ t.current_title|e }}</a></summary>tags: {% for tag in t.tags | sort %}<a href="{{db.prefix}}/day?date={{ db.selected_date }}&t_and={{tag|e}}">{{ tag }}</a> {% endfor %}</details></td>
-<td><input name="choose" type="checkbox" value="{{ uuid }}" {% if uuid in db.selected_day.todos.keys() %}checked{% endif %} ></td>
+<td class="checkbox"><input name="choose" type="checkbox" value="{{ uuid }}" {% if uuid in db.selected_day.todos.keys() %}checked{% endif %} ></td>
 <td class="checkbox"><input name="done" type="checkbox" value="{{ uuid }}" {% if uuid in db.selected_day.todos.keys() and db.selected_day.todos[uuid].done %}checked{% endif %} ></td>
-<td class="checkbox"><input name="day_weight" type="number" step=0.1 size=5 value="{% if uuid in db.selected_day.todos.keys() and db.selected_day.todos[uuid].day_weight %}{{ db.selected_day.todos[uuid].day_weight }}{% endif %}" placeholder={{ t.current_default_weight }} ></td>
+<td class="checkbox"><input name="day_weight" type="number" step=0.1 size=8 value="{% if uuid in db.selected_day.todos.keys() and db.selected_day.todos[uuid].day_weight %}{{ db.selected_day.todos[uuid].day_weight }}{% endif %}" placeholder={{ t.current_default_weight }} ></td>
 <td type="input"><input name="todo_comment" type="text" value="{% if uuid in db.selected_day.todos.keys() %}{{ db.selected_day.todos[uuid].comment|e }}{% endif %}" ></td>
 </tr>
 {% endif %}
@@ -149,7 +152,7 @@ tasks_tmpl = """
 {% for uuid, t in db.tasks.items() | sort(attribute='1.title') %}
 {% if t.visible %}
 <tr>
-<td>{{ t.default_weight }}</a></td>
+<td class="number">{{ t.default_weight }}</a></td>
 <td><a href="{{db.prefix}}/task?id={{ uuid }}" />{{ t.title|e }}</a></td>
 <td>{% for tag in t.tags | sort %}<a href="{{db.prefix}}/tags?t_and={{tag|e}}">{{ tag }}</a> {% endfor %}</td>
 {% endif %}
@@ -344,12 +347,13 @@ class Todo:
 
 class TodoDB(PlomDB):
 
-    def __init__(self, prefix, selected_date=None, t_filter_and = None, t_filter_not = None, hide_unchosen=False):
+    def __init__(self, prefix, selected_date=None, t_filter_and = None, t_filter_not = None, hide_unchosen=False, hide_done=False):
         self.prefix = prefix
         self.selected_date = selected_date if selected_date else str(datetime.now())[:10] 
         self.t_filter_and = t_filter_and if t_filter_and else [] 
         self.t_filter_not = t_filter_not if t_filter_not else []
         self.hide_unchosen = hide_unchosen 
+        self.hide_done = hide_done 
         self.days = {}
         self.tasks = {}
         self.t_tags = set() 
@@ -363,7 +367,8 @@ class TodoDB(PlomDB):
             t = self.add_task(id_=uuid, dict_source=t_dict)
             t.visible = len([tag for tag in self.t_filter_and if not tag in t.tags]) == 0\
                     and len([tag for tag in self.t_filter_not if tag in t.tags]) == 0\
-                    and ((not self.hide_unchosen) or uuid in self.selected_day.todos)
+                    and ((not self.hide_unchosen) or uuid in self.selected_day.todos)\
+                    and ((not self.hide_done) or (uuid in self.selected_day.todos and not self.selected_day.todos[uuid].done))
             for tag in t.tags:
                 self.t_tags.add(tag)
 
@@ -438,7 +443,7 @@ class TodoDB(PlomDB):
                 days_to_show[current_date] = self.add_day()
             else:
                 days_to_show[current_date] = self.days[current_date] 
-            days_to_show[current_date].weekday = datetime.strptime(current_date, DATE_FORMAT).strftime('%A')
+            days_to_show[current_date].weekday = datetime.strptime(current_date, DATE_FORMAT).strftime('%A')[:2]
             for task_uuid, todo in days_to_show[current_date].todos.items():
                 todo.visible = self.tasks[task_uuid].visible
         return Template(form_header_tmpl + calendar_tmpl + form_footer).render(db=self, days=days_to_show, action=self.prefix+'/calendar', today=str(datetime.now())[:10], start_date=start_date_str, end_date=end_date_str)
@@ -515,7 +520,9 @@ class TodoHandler(PlomHandler):
                     db.t_filter_not += [target]
             if 'hide_unchosen' in postvars.keys():
                 db.hide_unchosen = True
-            data = [('t_and', f) for f in db.t_filter_and] + [('t_not', f) for f in db.t_filter_not] + [('hide_unchosen', int(db.hide_unchosen))]
+            if 'hide_done' in postvars.keys():
+                db.hide_done = True
+            data = [('t_and', f) for f in db.t_filter_and] + [('t_not', f) for f in db.t_filter_not] + [('hide_unchosen', int(db.hide_unchosen))] + [('hide_done', int(db.hide_done))]
 
             if parsed_url.path == prefix + '/tasks':
                 encoded_params = urlencode(data)
@@ -561,7 +568,9 @@ class TodoHandler(PlomHandler):
         t_filter_not = params.get('t_not', ['deleted'])
         hide_unchosen_params = params.get('hide_unchosen', [])
         hide_unchosen = len(hide_unchosen_params) > 0 and hide_unchosen_params[0] != '0'
-        db = TodoDB(prefix, selected_date, t_filter_and, t_filter_not, hide_unchosen)
+        hide_done_params = params.get('hide_done', [])
+        hide_done = len(hide_done_params) > 0 and hide_done_params[0] != '0'
+        db = TodoDB(prefix, selected_date, t_filter_and, t_filter_not, hide_unchosen, hide_done)
         if parsed_url.path == prefix + '/day':
             page = db.show_day()
         elif parsed_url.path == prefix + '/todo':