
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 | 15 +++++++++-- coffee_db.py | 23 +++++++++++++++++ templates/main.js | 31 ++++++++++++++++++++++- templates/user.html | 62 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 0e0564a..14a2684 100644 --- a/app.py +++ b/app.py @@ -115,11 +115,14 @@ def user(): counts=counts, identifiers=db.list_user_identifiers(uid), iid=session["iid"], - stamp=time.time() + stamp=time.time(), + last_events=db.last_events() ) # TODO: Replace stamp parameter with proper cache control HTTP # headers in response - 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') @@ -265,6 +268,14 @@ def coffee_add(): return redirect(url_for('user')) +@app.route("/event", methods=["POST"]) +def event_add(): + 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") def coffee_count(): diff --git a/coffee_db.py b/coffee_db.py index 25551f9..5a9206f 100644 --- a/coffee_db.py +++ b/coffee_db.py @@ -99,6 +99,15 @@ 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) + + def flavors(): conn, c = open_db() res = list(c.execute("select distinct name, ord from flavors")) @@ -193,3 +202,17 @@ 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..ac1fc7b 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", data, "user"); + 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