An ADHD-friendly regular task tracker
Revision | 608c9ce918c08fb0b6e57405287e44d6033ba512 (tree) |
---|---|
Time | 2024-03-09 14:44:57 |
Author | Corbin <cds@corb...> |
Commiter | Corbin |
Start building a Web frontend.
@@ -0,0 +1,41 @@ | ||
1 | +#!/usr/bin/env python3 | |
2 | + | |
3 | +from datetime import datetime, timedelta | |
4 | +import html | |
5 | +import sqlite3 | |
6 | + | |
7 | +from flask import Flask | |
8 | + | |
9 | +# XXX Flask multithreading -> need to reconnect per-thread | |
10 | +# XXX I think there's an extension that solves this? | |
11 | +def cursor(): return sqlite3.connect("every.db").cursor() | |
12 | + | |
13 | +app = Flask("every-card") | |
14 | + | |
15 | +@app.route("/") | |
16 | +def root(): return "Working on it..." | |
17 | + | |
18 | +SHOW_QUERY = """ | |
19 | +select label, description, unixepoch() - updated_at, unixepoch() - updated_at + consequences_after_s from tasks | |
20 | +where updated_at + available_every_s <= unixepoch() and wheel = ? | |
21 | +order by updated_at + consequences_after_s | |
22 | +""" | |
23 | + | |
24 | +def roundUp(delta): | |
25 | + print("rounding up", delta) | |
26 | + # return timedelta(seconds=delta).days + 1 | |
27 | + return timedelta(seconds=delta) | |
28 | +def roundDown(delta): | |
29 | + print("rounding down", delta) | |
30 | + # return timedelta(seconds=delta).days - 1 | |
31 | + return timedelta(seconds=delta) | |
32 | + | |
33 | +@app.route("/show/<wheel>") | |
34 | +def show(wheel): | |
35 | + l = "".join("<li>{1} ({0}): Last done {2} days ago, needs to be done within the next {3} days</li>".format( | |
36 | + html.escape(row[0]), html.escape(row[1]), | |
37 | + roundUp(row[2]), roundDown(row[3])) | |
38 | + for row in cursor().execute(SHOW_QUERY, (wheel,))) | |
39 | + return "<!DOCTYPE html><h1>Tasks for {0}</h1><ol>{1}</ol>".format(wheel, l) | |
40 | + | |
41 | +app.run(debug=True, host="0.0.0.0", port=1312) |
@@ -36,7 +36,7 @@ def add(wheel, label, description, available_every, consequences_after): | ||
36 | 36 | conn.commit() |
37 | 37 | print("Added new task!") |
38 | 38 | |
39 | -show_query = """ | |
39 | +SHOW_QUERY = """ | |
40 | 40 | select label, description from tasks |
41 | 41 | where updated_at + available_every_s <= unixepoch() |
42 | 42 | and wheel = ? |
@@ -46,7 +46,7 @@ order by updated_at + consequences_after_s | ||
46 | 46 | @cli.command() |
47 | 47 | @click.argument("wheel") |
48 | 48 | def show(wheel): |
49 | - for row in c.execute(show_query, (wheel,)): | |
49 | + for row in c.execute(SHOW_QUERY, (wheel,)): | |
50 | 50 | print("Task:", row[1], "(" + row[0] + ")") |
51 | 51 | |
52 | 52 | updated_at_query = """ |
@@ -56,17 +56,18 @@ where wheel=? and label=? | ||
56 | 56 | |
57 | 57 | @cli.command() |
58 | 58 | @click.argument("wheel") |
59 | -@click.argument("label") | |
60 | -def do(wheel, label): | |
61 | - t = c.execute(updated_at_query, (wheel, label)).fetchone() | |
62 | - if not t: | |
63 | - print("No such task") | |
64 | - return | |
65 | - updated_at = t[0] | |
66 | - print("Task last updated:", datetime.fromtimestamp(updated_at)) | |
67 | - c.execute("update tasks set updated_at=? where wheel=? and label=?", | |
68 | - (time.time(), wheel, label)) | |
69 | - conn.commit() | |
59 | +@click.argument("labels", nargs=-1) | |
60 | +def do(wheel, labels): | |
61 | + for label in labels: | |
62 | + t = c.execute(updated_at_query, (wheel, label)).fetchone() | |
63 | + if not t: | |
64 | + print("No such task") | |
65 | + continue | |
66 | + updated_at = t[0] | |
67 | + print("Task last updated:", datetime.fromtimestamp(updated_at)) | |
68 | + c.execute("update tasks set updated_at=? where wheel=? and label=?", | |
69 | + (time.time(), wheel, label)) | |
70 | + conn.commit() | |
70 | 71 | print("Task done! Nice!") |
71 | 72 | |
72 | 73 | cli() |
@@ -11,7 +11,7 @@ | ||
11 | 11 | let |
12 | 12 | pkgs = import nixpkgs { inherit system; }; |
13 | 13 | py = pkgs.python311.withPackages (ps: [ |
14 | - ps.click | |
14 | + ps.click ps.flask | |
15 | 15 | ]); |
16 | 16 | every = pkgs.stdenv.mkDerivation { |
17 | 17 | name = "every"; |
@@ -21,7 +21,9 @@ | ||
21 | 21 | installPhase = '' |
22 | 22 | mkdir -p $out/bin/ |
23 | 23 | cp every.py $out/bin/every |
24 | - patchShebangs $out/bin/every | |
24 | + cp every-card.py $out/bin/every-card | |
25 | + chmod +x $out/bin/* | |
26 | + patchShebangs $out/bin/every{,-card} | |
25 | 27 | ''; |
26 | 28 | }; |
27 | 29 | in { |
@@ -30,7 +32,6 @@ | ||
30 | 32 | packages = [ |
31 | 33 | py |
32 | 34 | pkgs.sqlite pkgs.rlwrap |
33 | - every | |
34 | 35 | ]; |
35 | 36 | }; |
36 | 37 | }); |
@@ -0,0 +1,3 @@ | ||
1 | +It's easy for me to do things every day, at a fixed time, in a rhythm. It's | |
2 | +much harder to remember to do things which only occur every few days, or every | |
3 | +quarter, or every few years. |