Barevné události a další drobné změny

--- app.py | 15 +++++++++------ templates/user.html | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app.py b/app.py index 9c6f6d1..ee95747 100644 --- a/app.py +++ b/app.py @@ -25,11 +25,14 @@ app.secret_key = b'_5#y2L"F4Q8z\n\xec]/' # Inspired by https://shubhamjain.co/til/how-to-render-human-readable-time-in-jinja/, # updated to our needs -def humanize_ts(time): - """ - Convert date in ISO format to relative, human readable string - like 'an hour ago', 'Yesterday', '3 months ago', - 'just now', etc +def humanize_ts(time, max_interval="years"): + """Convert date/time in ISO format to relative, human readable string. + + Example return values: 'an hour ago', 'Yesterday', '3 months ago', + 'just now', etc. + + When optional max_interval is set to "days", the return value will + report at most the number of days ago, not week, months or years. """ if jinja2.is_undefined(time): return time @@ -58,7 +61,7 @@ def humanize_ts(time): return str(int(second_diff / 3600)) + " hours ago" if day_diff == 1: return "Yesterday" - if day_diff < 7: + if day_diff < 7 or max_interval == "days": return str(day_diff) + " days ago" if day_diff < 31: return str(int(day_diff / 7)) + " weeks ago" diff --git a/templates/user.html b/templates/user.html index 0d382bf..a757cb8 100644 --- a/templates/user.html +++ b/templates/user.html @@ -109,13 +109,13 @@ <div class="btnline"> <input type="button" value="{{ verb[event]|first }}" onclick="addEvent('{{ event }}', '{{ verb[events[0]]|last }} the {{ title }}')" /> - ({{ last_events[event] | humanize if event in last_events else "never" }}) + ({{ last_events[event] | humanize(max_interval="days") if event in last_events else "never" }}) </div> {%- endfor -%} {%- else -%} {# Nobody logged in - show overview with summary times #} {# Calculate maximum timestamp of all relevant events #} {%- set when = last_events.items() | selectattr(0, 'in', - events) | map(attribute=1) | max | humanize -%} + events) | map(attribute=1) | max | humanize(max_interval="days") -%} {%- if when -%} {{ verb[events[0]]|last }} {{ when }} {%- else -%} -- 2.28.0.rc2

This simplifies date-related filters - humanize_ts in this commit, date_filter in the next commit. --- app.py | 5 +---- coffee_db.py | 14 +++++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app.py b/app.py index ee95747..1a3c79f 100644 --- a/app.py +++ b/app.py @@ -36,10 +36,7 @@ def humanize_ts(time, max_interval="years"): """ if jinja2.is_undefined(time): return time - now = datetime.now(timezone.utc) - if time[-1] == 'Z': # Convert Zulu time zone to datetime compatible format - time = time[0:-1] + '+00:00' - diff = now - datetime.fromisoformat(time) + diff = datetime.now(timezone.utc) - time second_diff = diff.seconds day_diff = diff.days diff --git a/coffee_db.py b/coffee_db.py index 7fddd8e..810ed8e 100644 --- a/coffee_db.py +++ b/coffee_db.py @@ -1,5 +1,6 @@ import sqlite3 import os +from datetime import datetime dbdir = os.path.dirname(__file__) dbdef = os.path.join(dbdir, "coffee_db.sql") @@ -219,14 +220,21 @@ def drink_count(uid=None, start=None, stop=None): + " and ".join(clauses) + " group by fl.type " "order by fl.ord asc", args)) +def sqlite_timestring_to_datetime(timestring): + if timestring[-1] == 'Z': # Convert Zulu time zone to datetime compatible format + timestring = timestring[0:-1] + '+00:00' + return datetime.fromisoformat(timestring) def last_events(): """Return mapping with event names as keys and SQLite time string of the last event as values. """ conn, c = open_db() - res = dict(c.execute("""select name, MAX(time) - from events as e left join event_types as et on e.event_type = et.id - group by name""")) + res = {} + for name, time in c.execute("""select name, MAX(time) + from events as e left join event_types as et on e.event_type = et.id + group by name"""): + res[name] = sqlite_timestring_to_datetime(time) + close_db(conn) return res -- 2.28.0.rc2

--- app.py | 11 +++++++++++ templates/user.html | 24 +++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/app.py b/app.py index 1a3c79f..7504ab1 100644 --- a/app.py +++ b/app.py @@ -70,6 +70,17 @@ def humanize_ts(time, max_interval="years"): app.jinja_env.filters['humanize'] = humanize_ts +def days_filter(time, max_interval="years"): + """Return the number of days elapsed since time.""" + if jinja2.is_undefined(time): + return time + diff = datetime.now(timezone.utc) - time + return diff.days + + +app.jinja_env.filters['days'] = days_filter + + @app.route('/') def hello(): if "uid" in session: diff --git a/templates/user.html b/templates/user.html index a757cb8..cca3ef8 100644 --- a/templates/user.html +++ b/templates/user.html @@ -1,4 +1,14 @@ <style> + +.warning { + background-color: navajowhite; +} + +.bad { + background-color: orangered; + color: white; +} + .events { margin: 0.8em; margin-bottom: 1.5em; @@ -92,8 +102,11 @@ {##########} <br /> <form> - {%- macro event_box(title, events) -%} - <div class="events-box"> + {%- macro event_box(title, events, warn_days=999, bad_days=9999) -%} + {# Calculate maximum timestamp of all relevant events #} + {%- set when = last_events.items() | selectattr(0, 'in', events) | map(attribute=1) | max -%} + {%- set days = when | days | default(0) -%} + <div class="events-box{% if days >= bad_days %} bad {% elif days >= warn_days %} warning{% endif %}"> <h4>{{title | capitalize}}</h4> {#- The first item in the list is used as button label, last item in the overview -#} {%- set verb = { @@ -113,11 +126,8 @@ </div> {%- endfor -%} {%- else -%} {# Nobody logged in - show overview with summary times #} - {# Calculate maximum timestamp of all relevant events #} - {%- set when = last_events.items() | selectattr(0, 'in', - events) | map(attribute=1) | max | humanize(max_interval="days") -%} {%- if when -%} - {{ verb[events[0]]|last }} {{ when }} + {{ verb[events[0]]|last }} {{ when | humanize(max_interval="days") }} {%- else -%} never {{ verb[events[0]]|last }} {%- endif -%} @@ -127,7 +137,7 @@ <div class="events"> <h3>{{ ("Record<br />event" if name else "Events") | safe }}:</h3> {{ event_box('coffee machine', ['COFFEE_MACHINE_CLEANED'] ) }} - {{ event_box('milk container', ['MILK_CONTAINER_CLEANED', 'MILK_CONTAINER_CLEANED_WITH_TABLET'] ) }} + {{ event_box('milk container', ['MILK_CONTAINER_CLEANED', 'MILK_CONTAINER_CLEANED_WITH_TABLET'], warn_days=4, bad_days=7) }} {{ event_box('coffee pack', ['COFFEE_PACK_OPENED'] ) }} </div> -- 2.28.0.rc2

Napíšu to do jednoho, ať neposílám dva maily. :) - U funkce days_filter(time, max_interval="years") se ten druhý parameter vůbec nepoužívá? - U funkce humanize_ts(…) [z 2/4] se mi moc nelíbí ten parametr 'max_interval'. Chápu, že ses chtěl vyhnout 'only_days=0/1', ale teď je tam něco, co vlastně funguje jen "trochu" -- když je tam ='days' dělá to něco, když je tam cokoliv jiného je to jak předtím. (Ale samozřejmě mám pochopení pro to, že jiné možnosti moc nepoužijeme :)) J. Cituji Michal Sojka <michal.sojka@cvut.cz>:
--- app.py | 11 +++++++++++ templates/user.html | 24 +++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/app.py b/app.py index 1a3c79f..7504ab1 100644 --- a/app.py +++ b/app.py @@ -70,6 +70,17 @@ def humanize_ts(time, max_interval="years"): app.jinja_env.filters['humanize'] = humanize_ts
+def days_filter(time, max_interval="years"): + """Return the number of days elapsed since time.""" + if jinja2.is_undefined(time): + return time + diff = datetime.now(timezone.utc) - time + return diff.days + + +app.jinja_env.filters['days'] = days_filter + + @app.route('/') def hello(): if "uid" in session: diff --git a/templates/user.html b/templates/user.html index a757cb8..cca3ef8 100644 --- a/templates/user.html +++ b/templates/user.html @@ -1,4 +1,14 @@ <style> + +.warning { + background-color: navajowhite; +} + +.bad { + background-color: orangered; + color: white; +} + .events { margin: 0.8em; margin-bottom: 1.5em; @@ -92,8 +102,11 @@ {##########} <br /> <form> - {%- macro event_box(title, events) -%} - <div class="events-box"> + {%- macro event_box(title, events, warn_days=999, bad_days=9999) -%} + {# Calculate maximum timestamp of all relevant events #} + {%- set when = last_events.items() | selectattr(0, 'in', events) | map(attribute=1) | max -%} + {%- set days = when | days | default(0) -%} + <div class="events-box{% if days >= bad_days %} bad {% elif days >= warn_days %} warning{% endif %}"> <h4>{{title | capitalize}}</h4> {#- The first item in the list is used as button label, last item in the overview -#} {%- set verb = { @@ -113,11 +126,8 @@ </div> {%- endfor -%} {%- else -%} {# Nobody logged in - show overview with summary times #} - {# Calculate maximum timestamp of all relevant events #} - {%- set when = last_events.items() | selectattr(0, 'in', - events) | map(attribute=1) | max | humanize(max_interval="days") -%} {%- if when -%} - {{ verb[events[0]]|last }} {{ when }} + {{ verb[events[0]]|last }} {{ when | humanize(max_interval="days") }} {%- else -%} never {{ verb[events[0]]|last }} {%- endif -%} @@ -127,7 +137,7 @@ <div class="events"> <h3>{{ ("Record<br />event" if name else "Events") | safe }}:</h3> {{ event_box('coffee machine', ['COFFEE_MACHINE_CLEANED'] ) }} - {{ event_box('milk container', ['MILK_CONTAINER_CLEANED', 'MILK_CONTAINER_CLEANED_WITH_TABLET'] ) }} + {{ event_box('milk container', ['MILK_CONTAINER_CLEANED', 'MILK_CONTAINER_CLEANED_WITH_TABLET'], warn_days=4, bad_days=7) }} {{ event_box('coffee pack', ['COFFEE_PACK_OPENED'] ) }} </div> -- 2.28.0.rc2
_______________________________________________ Coffee mailing list Coffee@rtime.felk.cvut.cz https://rtime.felk.cvut.cz/mailman/listinfo/coffee

On Fri, Aug 21 2020, klapajar@fel.cvut.cz wrote:
Napíšu to do jednoho, ať neposílám dva maily. :)
- U funkce days_filter(time, max_interval="years") se ten druhý parameter vůbec nepoužívá?
Jo, to máš pravdu (copy&paste).
- U funkce humanize_ts(…) [z 2/4] se mi moc nelíbí ten parametr 'max_interval'. Chápu, že ses chtěl vyhnout 'only_days=0/1', ale teď je tam něco, co vlastně funguje jen "trochu" -- když je tam ='days' dělá to něco, když je tam cokoliv jiného je to jak předtím. (Ale samozřejmě mám pochopení pro to, že jiné možnosti moc nepoužijeme :))
Dobře, přidám tam kontrolu, aby když tam bude něco neočekávaného, aby to vyhodilo výjimku. Díky -M.

--- app.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app.py b/app.py index 7504ab1..cbdb9e9 100644 --- a/app.py +++ b/app.py @@ -287,14 +287,6 @@ def event_add(): return redirect(url_for('user')) -# TODO: Remove me - unused -@app.route("/coffee/count") -def coffee_count(): - start = request.args.get("start") - stop = request.args.get("stop") - return str(dict(db.drink_count(session.get("uid"), start, stop)).get("coffee", 0)) - - @app.route('/js') def js(): response = make_response(render_template('main.js')) -- 2.28.0.rc2
participants (2)
-
klapajar@fel.cvut.cz
-
Michal Sojka