var flask = "{{ url_for('hello', _external=True) }}"
-var updateRemote = undefined;
-var loggedIn = false;
+// State variables
+
+var updateRemote = undefined; // defined iff remote server accessible
+var timeToLogout = undefined; // defined during logout countdown
+var logoutTimer;
+var reloadTimer = undefined;
+var id_user; // ID of the user who is to be accounted for the next coffee
+var identifier_registration = false; // true if identifier is supposed to be registered for user
+var eventMsg = undefined; // Feedback message about the last event performed by the user
console.log("hello from flask");
//sendJSON("{\"type\":\"empty\"}");
document.getElementById(id).innerHTML = msg;
}
-function loadLocalStorage() {
+function replayOfflineQueue() {
if (localStorage) {
- if (localStorage.length) {
- for (var i = 0; i < localStorage.length; i++) {
- var value = localStorage.getItem(localStorage.key(i));
- try {
- updateRemote(value);
- } catch (err) {
- console.log("no json: " + value)
- }
- }
- localStorage.clear();
+ let queue = JSON.parse(localStorage.getItem("offlineQueue")) || [];
+ if (Array.isArray(queue)) {
+ queue.forEach(function (entry) {
+ updateRemote(entry.data, new Date(entry.time));
+ });
+ localStorage.removeItem("offlineQueue");
}
}
}
var flavorChosen;
-function countingTimeLogout(count_time){
- document.getElementById("logout_button").value = 'Logout in \n(' + count_time + ' second)';
- if (count_time == 0){
- timer = setTimeout(logout, 100);
- return;
- }
- setTimeout(function() { countingTimeLogout(count_time -1); }, 1000);
-}
-
-function updateNextStep()
+// Central function to update UI elements. To ensure that the UI is
+// consistent, other code should only change state variables and then
+// call this function. This function updates the UI to match the state.
+function updateUI()
{
- if (loggedIn) {
- document.getElementById("nextStep").innerHTML = "Now select a beverage on the coffee machineā¦";
- } else {
- if (flavorChosen !== undefined) {
- document.getElementById("nextStep").innerHTML = "Enjoy your " + flavorChosen + "!";
- flavorChosen=undefined;
- countingTimeLogout(10); //mean 10 seconds
+ try {
+ let offline = updateRemote === undefined;
+
+ document.getElementById("local").style.display = !offline ? "none" : "block";
+ document.getElementById("remote").style.display = offline ? "none" : "block";
+
+ if (offline) {
+ showOfflineQueue();
+ return;
+ }
+
+ if (eventMsg !== undefined) {
+ update("eventMsg", eventMsg);
+ eventMsg = undefined;
+ }
+ if (id_user !== undefined) {
+ document.getElementById("nextStep").innerHTML = "Now select a beverage on the coffee machineā¦";
+ } else if (flavorChosen !== undefined) {
+ document.getElementById("nextStep").innerHTML = "Enjoy your " + flavorChosen + "!";
}
+
+ if (timeToLogout !== undefined)
+ document.getElementById("logout_button").innerHTML = '<br>logout<br>(' + timeToLogout + ' s)';
+ }
+ catch (err) {
+ console.log("updateUI error: ", err);
}
}
-function hiddenUpdateRemote(json) {
+function hiddenUpdateRemote(json, time = new Date()) {
var msg = JSON.parse(json);
- //update("json", "json: " + JSON.stringify(msg))
-
switch(msg.type) {
case "empty":
- //update("json","");
break;
case "rfid":
- /*update("json",
- "uid: " + msg.uid + "<br>" +
- "card type: " + msg.card_type + "<br>" +
- "uid size: " + msg.size + " bytes<br>" +
- "sak: " + msg.sak
- );*/
- login(msg.uid);
+ if (identifier_registration) {
+ ajax("POST", "user/identifier/add", JSON.stringify({ id: msg.uid }), "content");
+
+ addIdentifier_finish();
+ } else {
+ login(msg.uid);
+ }
break;
case "keys":
- //update("json", "key: " + msg.key);
- if (loggedIn) {
+ if (!identifier_registration) {
var flavor = getFlavor(msg.key);
if (flavor !== "") {
- addCoffee(flavor);
+ addCoffee(flavor, time);
+ } else if (msg.key == "A") {
+ // When pressing 'Menu' key, logout to not count
+ // subsequent keys as coffee orders.
+ logout();
}
}
break;
- case "fuck":
+ case "ajax_failure":
ajax(msg.method, msg.route, msg.data, msg.id);
break;
}
+
sendLog(json);
}
function loadRemote(string) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200) {
- update("remote", this.responseText);
- updateRemote = hiddenUpdateRemote;
- loadLocalStorage();
- if (loggedIn) {
- document.getElementById("local").style.display = "none";
+ if (this.readyState == 4) {
+ if (this.status == 200) {
+ update("remote", this.responseText);
+ updateRemote = hiddenUpdateRemote;
+ replayOfflineQueue();
+ updateUI();
+ clearTimeout(reloadTimer);
+ if (id_user)
+ logout();
+ else
+ ajax("GET", "home", "", "content"); // Load home screen on first load or reload
+ } else {
+ // Cancel current timer for the case when loadRemote()
+ // was called multiple times (e.g. multiple ajax()
+ // calls failed simultaneously).
+ clearTimeout(reloadTimer);
+ reloadTimer = setTimeout(loadRemote, 1000);
}
}
};
if (this.readyState == 4) {
if (this.status == 200) {
update(id, this.responseText);
- updateNextStep();
+ updateUI();
} else {
updateRemote = undefined;
- update("remote", "<center>Server offline...</center>");
- document.getElementById("local").style.display = "block";
+ updateUI();
+ loadRemote(); // Try to contact the server periodically
+
if (localStorage) {
- var now = Date.now();
- var fuck = JSON.stringify({
- type: "fuck",
+ var ajax_failure = JSON.stringify({
+ type: "ajax_failure",
method: method,
route: route,
data: data,
id: id
});
- localStorage.setItem(now, fuck);
- console.log(now + ": " + fuck);
+ let queue = JSON.parse(localStorage.getItem("offlineQueue")) || [];
+ queue.push({ time: Date.now(), data: ajax_failure });
+ try {
+ localStorage.setItem("offlineQueue", JSON.stringify(queue));
+ }
+ catch (err) {
+ console.log(err);
+ }
}
}
}
function login(id) {
- ajax("POST", "login", id, "user");
- loggedIn = true;
- document.getElementById("local").style.display = "none";
+ ajax("POST", "login", id, "content");
+ id_user = id;
+ countingTimeLogout(120);
}
function logout() {
sendReset();
- ajax("GET", "logout", "", "user");
- loggedIn = false;
- document.getElementById("local").style.display = "block";
+ ajax("GET", "logout", "", "content");
+ id_user = undefined;
+ timeToLogout = undefined;
+ identifier_registration = false;
+ window.scrollTo(0, 0); // Scroll up
+}
+
+function countingTimeLogout(count_time)
+{
+ clearTimeout(logoutTimer);
+ timeToLogout = count_time;
+ updateUI();
+ if (count_time == 0) {
+ logout();
+ } else {
+ logoutTimer = setTimeout(function() { countingTimeLogout(count_time - 1); }, 1000);
+ }
}
function renameUser() {
- ajax("GET", "user/rename?name=" + document.getElementById("username").value, "", "user");
+ ajax("GET", "user/rename?name=" + document.getElementById("username").value, "", "content");
}
function getFlavor(letter) {
}
}
-function addCoffee(flavor) {
+function addCoffee(flavor, time = new Date()) {
var data = JSON.stringify({
- time: new Date().toISOString(),
+ time: time.toISOString(),
flavor: flavor
});
- if (loggedIn) {
- ajax("POST", "coffee/add", data, "user");
+ if (id_user) {
+ ajax("POST", "coffee/add", data, "content");
flavorChosen = flavor;
- loggedIn = false;
+ id_user = undefined;
+ countingTimeLogout(10); //mean 10 seconds
+ }
+}
+
+
+function addEvent(event_name, action_msg, time = new Date()) {
+ var data = JSON.stringify({
+ time: time.toISOString(),
+ event_name: event_name,
+ uid: id_user
+ });
+ if (id_user) {
+ eventMsg = "You have " + action_msg + ". Thanks!"
+ ajax("POST", "event", data, "content");
+ window.scrollTo(0, 0); // Scroll up
}
}
+
+function addIdentifier_start() {
+ identifier_registration = true;
+ document.getElementById("addIdentifier").disabled = true;
+ document.getElementById("labelIdentifier").style.visibility = "visible";
+ document.getElementById("abortIdentifier").disabled = false;
+}
+
+function addIdentifier_finish() {
+ identifier_registration = false;
+ document.getElementById("addIdentifier").disabled = false;
+ document.getElementById("labelIdentifier").style.visibility = "hidden";
+ document.getElementById("abortIdentifier").disabled = true;
+}
+
+function disableIdentifier(id) {
+ ajax("POST", "user/identifier/disable", JSON.stringify({ id: id }), "content");
+}
+
+function renameIdentifier(i) {
+ var data = JSON.stringify({
+ id: document.getElementById("identifier_" + i).innerText,
+ name: document.getElementById("identifier_name_" + i).value
+ });
+
+ ajax("POST", "user/identifier/rename", data, "content");
+}
+
function sendLog(json) {
ajax("POST", "log", json, "log");
}
+
+function tellCoffeebot(what)
+{
+ ajax("POST", "tellCoffeebot", JSON.stringify({text: what}), "log");
+}