I have mainly cosmetics comments, please take them as that.
On Tue, Aug 18, 2020 at 09:19:22PM +0200, Michal Sojka wrote:
Compared to the previous version of the patch, now the main logic resides in templates/user.html. I think that this way it is a bit easier to understand what's going on.
The stuff in main.js related to eventName variable needs to be updated or cleaned up. I think I didn't get how it was supposed to work in the previous version of the patch.
app.py | 14 ++++++++-- coffee_db.py | 23 +++++++++++++++++ templates/main.js | 31 ++++++++++++++++++++++- templates/user.html | 62 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 3 deletions(-)
diff --git a/app.py b/app.py index 75b93d7..faeb82b 100644 --- a/app.py +++ b/app.py @@ -113,11 +113,14 @@ def user(): counts=counts, identifiers=db.list_user_identifiers(uid), iid=session["iid"],
stamp=time.time()
stamp=time.time(),
# TODO: Replace stamp parameter with proper cache control HTTP # headers in responselast_events=db.last_events() )
- return render_template('user.html', stamp=time.time())
- return render_template('user.html', stamp=time.time(),
last_events=db.last_events(),
)
@app.route('/user/rename') @@ -262,6 +265,13 @@ def coffee_add(): db.add_coffee(session["iid"], json["flavor"], json["time"]) return redirect(url_for('user'))
+@app.route("/event/add", methods=["POST"])
POST always create new object by (REST) convention. Therefore, sending POST to endpoint "/event" is clearer.
+def event_add():
- if request.method == "POST":
I think (but not sure) that this is unnecessary due to that only POST method is allowed (`methods=["POST"]`).
json = request.json
print("User '%(uid)s' registered event %(event_name)s at %(time)s" % json)
db.add_event(json["uid"], json["event_name"], json["time"])
- return redirect(url_for('user'))
# TODO: Remove me - unused @app.route("/coffee/count") diff --git a/coffee_db.py b/coffee_db.py index 25551f9..24d6e39 100644 --- a/coffee_db.py +++ b/coffee_db.py @@ -99,6 +99,16 @@ def add_coffee(uid, flavor, time=None): c.execute("insert or ignore into coffees (id, flavor, time) values (?,?,?)", (uid, flavor, time)) close_db(conn)
+def add_event(uid, event_name, time):
- conn, c = open_db()
- c.execute("""insert into events (user_id, event_type, time)
values (?, (SELECT id FROM event_types WHERE name = ?), ?)""",
(uid, event_name, time))
- close_db(conn)
Different number of blank lines between functions looks ugly.
def flavors(): conn, c = open_db() res = list(c.execute("select distinct name, ord from flavors")) @@ -193,3 +203,16 @@ def drink_count(uid=None, start=None, stop=None): "left join identifiers ids on co.id = ids.id where " + " and ".join(clauses) + " group by fl.type " "order by fl.ord asc", args))
+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"""))
- close_db(conn)
- return res
diff --git a/templates/main.js b/templates/main.js index 417dc40..0483423 100644 --- a/templates/main.js +++ b/templates/main.js @@ -29,6 +29,9 @@ function replayOfflineQueue() { }
var flavorChosen; +var eventName; // TODO... +var eventStatus; +var eventAction;
// Central function to update UI elements. To ensure that the UI is // consistent, other code should only change state variables and then @@ -48,8 +51,14 @@ function updateUI()
if (id_user !== undefined) { document.getElementById("nextStep").innerHTML = "Now select a beverage on the coffee machineā¦";
} else {
} else if (flavorChosen !== undefined) { document.getElementById("nextStep").innerHTML = "Enjoy your " + flavorChosen + "!";
// clean the coffee machine makes it cleaned
// ^ Action ^ Name ^ Status
} else if (eventStatus !== undefined && eventStatus !== "") {
document.getElementById("nextStep").innerHTML = "You have " + eventStatus + " the " + eventName + ". Thanks!";
} else {
document.getElementById("nextStep").innerHTML = "Event '" + eventAction + "' reported for the " + eventName + ". Thanks!"; } if (timeToLogout !== undefined)
@@ -171,6 +180,7 @@ function logout() { id_user = undefined; timeToLogout = undefined; identifier_registration = false;
- window.scrollTo(0, 0); // Scroll up
}
function countingTimeLogout(count_time) @@ -212,6 +222,25 @@ function addCoffee(flavor, time = new Date()) { } }
+function addEvent(event_name, time = new Date()) {
- var data = JSON.stringify({
time: time.toISOString(),
event_name: event_name,
uid: id_user
- });
- if (id_user) {
ajax("POST", "event/add", data, "user");
See POST event route comment.
id_user = undefined;
eventName = name; // TODO...
eventStatus = status;
eventAction = action;
countingTimeLogout(10); //mean 10 seconds
window.scrollTo(0, 0); // Scroll up
- }
+}
function addIdentifier_start() { identifier_registration = true; document.getElementById("addIdentifier").disabled = true; diff --git a/templates/user.html b/templates/user.html index 5ad7b90..ed0156d 100644 --- a/templates/user.html +++ b/templates/user.html @@ -1,3 +1,26 @@ +<style> +.events {
- margin: 0.8em;
- margin-bottom: 1.5em;
- padding: 2px;
- border-spacing: 2em 0;
- text-align: center;
+}
+.events-list {
- border: 1px solid black;
- padding: 0.5em;
- display: inline-block;
- vertical-align: top;
+}
+.events-list h4 {
- margin: 0.5ex;
- margin-bottom: 1ex;
- border-bottom: 1px dashed black;
+} +</style>
{% if name %} <form style="position: absolute; right: 15%; width: 15%; height: 15%;"> <button type="button" id="logout_button" onclick="logout()" style="width: 100%; height: 100%;">logout</button> @@ -77,3 +100,42 @@ <img src="{{ url_for('coffee_graph_history', _external=True, stamp=stamp) }}"> <img src="{{ url_for('coffee_graph_flavors', _external=True, stamp=stamp, days=7) }}"> {% endif %}
<br />
<form>
<h3>{{ "Record event" if name else "Events" }}:</h3>
{% macro event_box(title, events) -%}
<div class="events-list">
<h4>{{title}}</h4>
{% set verb = {
"COFFEE_MACHINE_CLEANED": "cleaned",
"COFFEE_PACK_OPENED": "opened",
"COFFEE_PACK_LAST_OPENED": "last opened",
"MILK_CONTAINER_CLEANED": "cleaned",
"MILK_CONTAINER_PILL_CLEANED": "pill cleaned",
}
%}
{% if name %} {# User logged in - show action buttons #}
{% for event in events %}
<input type="button" value="{{ verb[event] }}"
onclick="addEvent('{{ event }}')" />
({{ last_events[event] | humanize if event in last_events else "never" }})
<br />
{% endfor %}
{% else %} {# Nobody logged in - show last times #}
{# Calculate maximum timestamp of all relevant events #}
{% set when = last_events.items() | selectattr(0, 'in', events) | map(attribute=1) | max | humanize %}
{% if when %}
{{ verb[events[0]] }} {{ when }}
{% else %}
never {{ verb[events[0]] }}
{% endif %}
{% endif %}
</div>
{%- endmacro %}
<div class="events">
{{ event_box('Coffee machine', ['COFFEE_MACHINE_CLEANED'] ) }}
{{ event_box('Coffee pack', ['COFFEE_PACK_OPENED', 'COFFEE_PACK_LAST_OPENED'] ) }}
{{ event_box('Milk container', ['MILK_CONTAINER_CLEANED', 'MILK_CONTAINER_PILL_CLEANED'] ) }}
</div>
</form>
-- 2.28.0.rc2
Coffee mailing list Coffee@rtime.felk.cvut.cz https://rtime.felk.cvut.cz/mailman/listinfo/coffee