summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--css/bubbles.css94
-rw-r--r--css/styles.css20
-rw-r--r--img/avatars/asijanec.pngbin389 -> 82 bytes
-rw-r--r--js/chats.js373
-rw-r--r--js/gsec.js18
-rw-r--r--js/lang/bundle.js26
-rw-r--r--js/messaging.js2
-rw-r--r--js/setup-storage.js3
-rw-r--r--pages/about.html1
-rw-r--r--pages/absences.html1
-rw-r--r--pages/chats.html104
-rw-r--r--pages/grades.html3
-rw-r--r--pages/gradings.html3
-rw-r--r--pages/meals.html3
-rw-r--r--pages/messaging.html5
-rw-r--r--pages/settings.html3
-rw-r--r--pages/teachers.html3
-rw-r--r--pages/timetable.html3
-rw-r--r--sw.js8
19 files changed, 647 insertions, 26 deletions
diff --git a/css/bubbles.css b/css/bubbles.css
new file mode 100644
index 0000000..8a19ff1
--- /dev/null
+++ b/css/bubbles.css
@@ -0,0 +1,94 @@
+/* obviously stolen, source https://codepen.io/swards/pen/gxQmbj */
+.chat {
+ width: 100%;
+ border-left: solid 1px #EEE;
+ border-right: solid 1px #EEE;
+ /* border-bottom: solid 1px #EEE; */
+ display: flex;
+ flex-direction: column;
+ padding: 10px;
+}
+
+.messages {
+ margin-top: 30px;
+ display: flex;
+ flex-direction: column;
+}
+
+.message {
+ border-radius: 20px;
+ padding: 8px 15px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ display: inline-block;
+}
+
+.yours {
+ align-items: flex-start;
+}
+
+.yours .message {
+ margin-right: 25%;
+ background-color: #eee;
+ position: relative;
+}
+
+.yours .message.last:before {
+ content: "";
+ position: absolute;
+ z-index: 0;
+ bottom: 0;
+ left: -7px;
+ height: 20px;
+ width: 20px;
+ background: #eee;
+ border-bottom-right-radius: 15px;
+}
+.yours .message.last:after {
+ content: "";
+ position: absolute;
+ z-index: 1;
+ bottom: 0;
+ left: -10px;
+ width: 10px;
+ height: 20px;
+ background: white;
+ border-bottom-right-radius: 10px;
+}
+
+.mine {
+ align-items: flex-end;
+}
+
+.mine .message {
+ color: white;
+ margin-left: 25%;
+ background: linear-gradient(to bottom, var(--color-primary) 0%, var(--color-secondary) 100%);
+ background-attachment: fixed;
+ position: relative;
+}
+
+.mine .message.last:before {
+ content: "";
+ position: absolute;
+ z-index: 0;
+ bottom: 0;
+ right: -8px;
+ height: 20px;
+ width: 20px;
+ background: linear-gradient(to bottom, var(--color-primary) 0%, var(--color-secondary) 100%);
+ background-attachment: fixed;
+ border-bottom-left-radius: 15px;
+}
+
+.mine .message.last:after {
+ content: "";
+ position: absolute;
+ z-index: 1;
+ bottom: 0;
+ right: -10px;
+ width: 10px;
+ height: 20px;
+ background: white;
+ border-bottom-left-radius: 10px;
+} \ No newline at end of file
diff --git a/css/styles.css b/css/styles.css
index 8ad12a0..a06c906 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -28,8 +28,12 @@ body {
}
nav {
- background: var(--color-primary);
- border-bottom: 10px solid var(--color-accent);
+ background: var(--color-primary);
+ border-bottom: 10px solid var(--color-accent);
+ position: sticky;
+ left: 0;
+ top: 0;
+ z-index: 69; /* choose a number, any number */
}
.hidden {
@@ -147,4 +151,14 @@ a.collection-item {
.input-field textarea:not([readonly]):focus {
border-bottom: 1px solid var(--color-primary) !important;
box-shadow: 0 1px 0 0 var(--color-primary) !important;
-} \ No newline at end of file
+}
+
+.chat-sticky-input {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ background-color: white;
+ text-align: center;
+ z-index: 60;
+}
diff --git a/img/avatars/asijanec.png b/img/avatars/asijanec.png
index 34d0e3e..ccae7d0 100644
--- a/img/avatars/asijanec.png
+++ b/img/avatars/asijanec.png
Binary files differ
diff --git a/js/chats.js b/js/chats.js
new file mode 100644
index 0000000..73dc791
--- /dev/null
+++ b/js/chats.js
@@ -0,0 +1,373 @@
+const API_ENDPOINT = "https://gimb.tk/test.php";
+const DIRECTORY_URL = "/directory.json";
+// "Global" object for name directory
+var directory = null;
+var currentlyChattingWith = null; // msgid
+var sogovornik = null; // name
+var firstPageOfMessages = null; // so we can test if new messages ever arrive
+
+async function checkLogin() {
+ localforage.getItem("logged_in").then(function (value) {
+ // This code runs once the value has been loaded
+ // from the offline store.
+ if (value !== true) {
+ window.location.replace("/index.html");
+ }
+ }).catch(function (err) {
+ // This code runs if there were any errors
+ console.log(err);
+ });
+}
+function getKeyByValue(object, value) {
+ return Object.keys(object).find(key => object[key] === value);
+}
+// -----------HTML HELPERS-----------
+function htmlEncode(value) {
+ // Create a in-memory element, set its inner text (which is automatically encoded)
+ // Then grab the encoded contents back out. The element never exists on the DOM.
+ return $("<textarea/>").text(value).html();
+}
+
+function htmlDecode(value) {
+ return $("<textarea/>").html(value).text();
+}
+// ---------------------------------
+
+// Try to fetch name:id directory
+function loadDirectory() {
+ $.ajax({
+ url: DIRECTORY_URL,
+ crossDomain: true,
+
+ dataType: "json",
+ cache: false,
+ type: "GET",
+
+ success: (data) => {
+ // If we were able to retrieve it, update the saved directory
+ localforage.setItem("directory", data);
+ directory = data;
+ // Populate autocomplete
+ populateAutocomplete();
+ },
+
+ error: () => {
+ // Otherwise, try to retrieve stored directory
+ localforage.getItem("directory").then((stored_directory) => {
+ if (stored_directory === null) {
+ // If unable, set directory to null (so other functions know that we don't have it)
+ UIAlert( D("nameDirectoryNotSet"), "loadDirectory(): stored_directory === null" );
+ directory = null;
+ // Disable send button
+ document.getElementById("msg-send").disabled = true;
+ } else {
+ directory = stored_directory;
+ // Populate autocomplete
+ populateAutocomplete();
+ }
+ });
+ }
+ });
+}
+
+function populateAutocomplete() {
+ let elems = document.querySelectorAll('.autocomplete-fullname');
+ // če se uporablja globalna var directory, ki je shranjena kot objekt (vedno shranjen kot reference), bo pri let x=y x le pointer na object y
+ // in se bo spremenil z spremembo "originala". spodnja stvar itak ni preveč efficent, loop čez vseh 7000 ljudi bi lahko delal težave...
+ // kakšen Object.keys bi bila boljša varianta ampak raje napišem tale komentar... idk, to se mi je zdelo uporabno ampak sedaj obžalujem
+ // samo guglal sem "copying an object js"
+ let autocomplete_entries = Object.assign({}, directory);
+ for (let variableKey in autocomplete_entries) {
+ autocomplete_entries[variableKey] = null;
+ }
+ M.Autocomplete.init(elems, {
+ data: autocomplete_entries,
+ onAutocomplete: validateName,
+ minLength: 0
+ });
+ if(window.location.hash.length > 1) {
+ document.getElementById("full-name").value = decodeURIComponent(window.location.hash.substring(1));
+ } else {
+ document.getElementById("full-name").value = getUrlParameter("m");
+ }
+ M.updateTextFields();
+ validateName();
+}
+
+// Function to toggle loading bar
+function setLoading(state) {
+ if (state) {
+ $("#loading-bar").removeClass("hidden");
+ } else {
+ $("#loading-bar").addClass("hidden");
+ }
+}
+async function sendMessage(recipient_number = null, body = null) {
+ if(recipient_number == null || recipient_number == undefined) {
+ recipient_number = directory[sogovornik];
+ }
+ if(body == null || body == undefined) {
+ body = document.getElementById("msg-body").value;
+ }
+ if(body.length > 180) {
+ throw new RangeError("sendMessage(): message is longer than 180 characters.");
+ }
+ let promises_to_run = [
+ localforage.getItem("username").then((value) => {
+ username = value;
+ }),
+ localforage.getItem("password").then((value) => {
+ password = value;
+ }),
+ ];
+ setLoading(true);
+ Promise.all(promises_to_run).then(() => {
+ try {
+ let gsecInstance = new gsec();
+ gsecInstance.login(username, password).then( () => {
+ gsecInstance.sendMessage(recipient_number, "beziapp-ctlmsg-chat-"+body, "BežiApp chat: "+body).then( (value) => {
+ addMessage(0, body);
+ setLoading(false);
+ }).catch( (err) => {
+ gsecErrorHandlerUI(err);
+ setLoading(false);
+ });
+ });
+ } catch (err) {
+ gsecErrorHandlerUI(err);
+ setLoading(false);
+ }
+ });
+}
+function addMessage(whom, body, datePlacement = 0, messageDate = null) { // datePlacement: 0=append bubble to end, 1=append bubble to start.
+ if(whom == 0) {
+ var whos = "mine";
+ } else {
+ var whos = "yours";
+ }
+ var timestamp = Date.now();
+ if(messageDate instanceof Date) { timestamp = messageDate.getTime(); }
+ if(typeof messageDate == "number") { timestamp = messageDate; }
+ var chatarea = document.getElementsByClassName("chat")[0];
+ var alreadyMessages = chatarea.querySelectorAll(".message");
+ var textnode = document.createTextNode(body);
+ var bubblenode = document.createElement("div");
+ bubblenode.setAttribute("data-date", timestamp);
+ bubblenode.appendChild(textnode);
+ if(chatarea.childElementCount == 0) {
+ bubblenode.className = "message last";
+ var messagesnest = document.createElement("div");
+ var istaoseba = false;
+ } else {
+ if(datePlacement == 0 || timestamp > Number(alreadyMessages[alreadyMessages.length - 1].getAttribute("data-date"))) {
+ datePlacement = 0;
+ console.log(alreadyMessages[0].getAttribute("data-date"));
+ bubblenode.className = "message last";
+ if(chatarea.children.item(chatarea.children.length - 1).classList.contains(whos)) { // ista oseba
+ var istaoseba = true;
+ var messagesnest = chatarea.children.item(chatarea.children.length - 1);
+ messagesnest.children.item(messagesnest.children.length - 1).classList.remove("last");
+ } else {
+ var istaoseba = false;
+ var messagesnest = document.createElement("div");
+ }
+ } else if (datePlacement == 1 || timestamp < Number(alreadyMessages[0].getAttribute("data-date"))) {
+ datePlacement = 1;
+ console.log(alreadyMessages[0].getAttribute("data-date"));
+ if(chatarea.children.item(0).classList.contains(whos)) { // ista oseba
+ bubblenode.className = "message";
+ var istaoseba = true;
+ var messagesnest = chatarea.children.item(0);
+ } else {
+ bubblenode.className = "message last";
+ var istaoseba = false;
+ var messagesnest = document.createElement("div");
+ }
+ } else { // auto place (slower, so 0 or 1 are options
+ console.log("if3");
+ for(var iter = 0; iter < alreadyMessages.length - 2; iter++) { // (-2 zato, ker potem iter+1 ne obstaja pri zadnjem elementu)
+ if (
+ Number(alreadyMessages[iter].getAttribute("data-date")) < timstamp
+ && Number(alreadyMessages[iter+1].getAttribute("data-date")) > timestamp
+ ) {
+ var zgornjiIsti = alreadyMessages[iter].parentElement.classList.contains(whos);
+ var spodnjiIsti = alreadyMessages[iter+1].parentElement.classList.contains(whos);
+ console.log([zgornjiIsti, spodnjiIsti]);
+ if(zgornjiIsti && spodnjiIsti) {
+ var messagesnest = alreadyMessages[iter].parentElement;
+ bubblenode.className = "message";
+ messagesnest.insertBefore(bubblenode, alreadyMessages[iter+1]);
+ return;
+ }
+ if(zgornjiIsti && !spodnjiIsti) {
+ var messagesnest = alreadyMessages[iter].parentElement;
+ bubblenode.className = "message last";
+ messagesnest.children.item(messagesnest.childElementCount - 1).classList.remove("last");
+ messagesnest.appendChild(bubblenode);
+ return;
+ }
+ if(!zgornjiIsti && spodnjiIsti) {
+ var messagesnest = alreadyMessages[iter+1].parentElement;
+ bubblenode.className = "message";
+ messagesnest.insertBefore(bubblenode, alreadyMessages[iter+1]);
+ return;
+ }
+ throw new RangeError("This should not happen!");
+ }
+ }
+ throw new RangeError("This should not happen!1");
+ }
+ }
+ // autodetect date is not present here anymore
+ messagesnest.className = whos+" messages";
+ if(datePlacement == 0) {
+ messagesnest.appendChild(bubblenode);
+ } else {
+ messagesnest.prepend(bubblenode);
+ }
+ if(!istaoseba) {
+ if(datePlacement == 0) {
+ chatarea.appendChild(messagesnest);
+ } else{
+ chatarea.prepend(messagesnest);
+ }
+ }
+}
+async function validateName() {
+ if (directory !== null) {
+ document.getElementById("full-name").disabled = false;
+ if ($("#full-name").val() in directory) {
+ $("#full-name").addClass("valid");
+ $("#full-name").removeClass("invalid");
+ document.getElementById("chat-recipient-select-btn").disabled = false;
+ document.getElementById("msg-body").disabled = false;
+ } else {
+ $("#full-name").addClass("invalid");
+ $("#full-name").removeClass("valid");
+ document.getElementById("chat-recipient-select-btn").disabled = true;
+ document.getElementById("msg-body").disabled = true;
+ document.getElementById("msg-body").value = "";
+ }
+ } else {
+ document.getElementById("chat-recipient-select-btn").disabled = true;
+ document.getElementById("full-name").value = D("nameDirectoryNotSet");
+ document.getElementById("full-name").disabled = true;
+ document.getElementById("msg-body").value = "";
+ }
+}
+
+async function clearMessages() {
+ var chatarea = document.getElementsByClassName("chat")[0];
+ chatarea.innerHTML = "";
+}
+
+function getUrlParameter(sParam) {
+ const url_params = new URLSearchParams(window.location.search);
+ const found_param = url_params.get(sParam);
+ return found_param;
+}
+
+document.addEventListener("DOMContentLoaded", () => {
+ checkLogin();
+ loadDirectory();
+ updateSendButton();
+ var receivedmessages = null;
+ M.updateTextFields();
+ // Setup side menu
+ const menus = document.querySelectorAll(".side-menu");
+ M.Sidenav.init(menus, { edge: "right", draggable: true });
+ let elems = document.querySelectorAll('.modal');
+ let instances = M.Modal.init(elems, {});
+ // Setup side modal
+ const modals = document.querySelectorAll('.side-modal');
+ M.Sidenav.init(modals, { edge: 'left', draggable: false });
+ prepareAndStartFetchingMessages(); // just opens modal, as there is no recipient selected
+
+});
+
+async function updateSendButton() {
+ if(document.getElementById("msg-body").value.length == 0) {
+ document.getElementById("msg-send").disabled = true;
+ } else {
+ document.getElementById("msg-send").disabled = false;
+ }
+}
+
+async function setRecipient(name = null) {
+ if(name == null || name == false || name == undefined) {
+ name = document.getElementById("full-name").value;
+ } else if (typeof name != "number") {
+ throw new TypeError('Hello from setRecipient(): name can only be string or null!');
+ }
+
+ if(Object.keys(directory).includes(name)) {} else {
+ UIAlert(D("recipientNotInDirectory"));
+ throw new RangeError("Hello from setRecipient(): name is not in directory");
+ }
+ var modal = document.querySelectorAll('#directory-side-menu')[0];
+ var modalInstance = M.Sidenav.getInstance(modal);
+ modalInstance.close();
+ document.getElementsByClassName("msg-chattingWith")[0].innerHTML = name;
+ sogovornik = name;
+ currentlyChattingWith = directory[name];
+ document.getElementById("chat-mustSelectRecipient").hidden=true;
+ updateSendButton();
+ clearMessages(); // <-- do when recipient selected
+ prepareAndStartFetchingMessages(); // <-- same
+}
+
+async function prepareAndStartFetchingMessages() {
+ if(currentlyChattingWith === 0 || (currentlyChattingWith >= 1 && currentlyChattingWith < 69420)) {
+ document.getElementById("msg-body").disabled = false;
+ await clearMessages();
+ startFetchingMessages();
+ } else {
+ var modal = document.querySelectorAll('#directory-side-menu')[0];
+ var modalInstance = M.Sidenav.getInstance(modal);
+ modalInstance.open();
+ }
+}
+
+async function startFetchingMessages() {
+ let promises_to_run = [
+ localforage.getItem("username").then((value) => {
+ username = value;
+ }),
+ localforage.getItem("password").then((value) => {
+ password = value;
+ }),
+ ];
+ setLoading(true);
+ await Promise.all(promises_to_run);
+ try {
+ let gsecInstance = new gsec();
+ await gsecInstance.login(username, password);
+ for (var category = 0; category <= 1; category++) {
+ let lastpage = await gsecInstance.fetchMessagesLastPageNumber(category);
+ startLoadingMessagesForCategory(gsecInstance, category, lastpage);
+ }
+ } catch (err) {
+ gsecErrorHandlerUI(err);
+ setLoading(false);
+ }
+}
+
+async function startLoadingMessagesForCategory(gsecInstance, category, lastpage) {
+ for(var page = 1; page <= lastpage; page++) {
+ var gsecMsgList = await gsecInstance.fetchMessagesList(category, page);
+ if(category == 0) {
+ whom = 1;
+ } else {
+ whom = 0;
+ }
+ renderMessages(gsecMsgList, whom, 1);
+ }
+}
+
+async function renderMessages(gsecMsgList, whom, order = 1) { // order: 1=newest>olest 0=oldest>newest 2=autodetect (todo-not implemented)
+ for(const message of gsecMsgList) { // whom: 0=me 1=you
+ if(message.subject.substring(0, 20) == "beziapp-ctlmsg-chat-") {
+ addMessage(whom, message.subject.substring(20), 2, message.date.getTime);
+ }
+ }
+}
diff --git a/js/gsec.js b/js/gsec.js
index 7bfad46..e1c2ffc 100644
--- a/js/gsec.js
+++ b/js/gsec.js
@@ -430,7 +430,7 @@ class gsec {
});
});
}
- fetchMessagesList(category = GSEC_MSGTYPE_RECEIVED, pageNumber = 1, outputResponse = false) {
+ fetchMessagesList(category = GSEC_MSGTYPE_RECEIVED, pageNumber = 1, outputResponse = false) { // outputResponse je probably za debug
var msgCategory = GSEC_MSGTYPES[category];
var messages = [];
var requestURi = GSE_URL+"Page_Gim/Uporabnik/Sporocila.aspx";
@@ -447,12 +447,20 @@ class gsec {
for(const messageElement of messageElements) {
let msgId = messageElement.getElementsByTagName("input")[0].value;
var date = messageElement.getElementsByClassName("msgSubDate")[0].innerHTML.split(" ")[0].split(".");
- if(date[2].length < 1) {
- let today = new Date();
+ var today = new Date();
+ if(date[2] == undefined || date[2].length < 1) {
date[2] = today.getFullYear();
}
+ if(date[1] == undefined || date[1].length < 1) {
+ date[1] = today.getMonth()+1;
+ date[0] = today.getDate();
+ }
var tume = messageElement.getElementsByClassName("msgSubDate")[0].innerHTML.split(" ")[1];
- var dateObj = new Date(Date.parse(date[2]+"-"+date[1]+"-"+date[0]+" "+tume)); // "tume"!
+ if (tume == undefined || tume == null) { // js nism kriv za to pizdraijo; gimsis je.
+ tume = messageElement.getElementsByClassName("msgSubDate")[0].innerHTML;
+ }
+ var dateStringToParse = date[2]+"-"+date[1]+"-"+date[0]+" "+tume;
+ var dateObj = new Date(Date.parse(dateStringToParse)); // "tume"!
var person = messageElement.getElementsByClassName("msgDir")[0].innerHTML;
var subject = messageElement.getElementsByClassName("msgSubject")[0].innerHTML;
messages.push({"date": dateObj, "sender": person, "subject": subject, "msgId": msgId});
@@ -482,4 +490,4 @@ class gsec {
});
});
}
-}
+} \ No newline at end of file
diff --git a/js/lang/bundle.js b/js/lang/bundle.js
index 8f540b9..58757ed 100644
--- a/js/lang/bundle.js
+++ b/js/lang/bundle.js
@@ -109,6 +109,7 @@ var langstrings = {
en: {
miscTranslationLanguage: "English",
miscTranslationAuthors: "Rok Štular",
+ "": "",
// date
monday: "monday",
tuesday: "tuesday",
@@ -199,7 +200,7 @@ var langstrings = {
thisMessageWasEncrypted: "this message was encrypted by BežiApp",
enterPassword: "enter password",
decrypt: "decrypt",
- nameDirecroryNotSet: "name directory not set, sending unavailable",
+ nameDirectoryNotSet: "name directory not set, sending unavailable",
errorFetchingMessages: "error fetching messages",
unableToReceiveTheMessage: "unable to receive the message",
unableToDeleteTheMessage: "unable to delete the message",
@@ -208,6 +209,15 @@ var langstrings = {
imageAddedAsAnAttachment: "image added as an attachment",
unableToReadDirectory: "unable to read directory of people",
messageCouldNotBeSent: "message could to be sent",
+ // chats
+ chat: "chat",
+ chattingWith: "chatting with",
+ noMessages: "no messages",
+ stillLoading: "loading is still in progress",
+ directory: "directory",
+ select: "select",
+ mustSelectRecipient: "you have to select a recipient before chatting. Open directory on the left side by clicking on the top left addressbook button and select a recipient in order to start chatting with them",
+ recipientNotInDirectory: "recipient is not in directory.",
// meals
loginToLopolis: "login to Lopolis",
loginToLopolisNote: "it seems like you're not currently logged in to eRestavracija, so this form has been presented to you. You have a different username and password combination used for applying and opting out of of menus. In order to use this feature, you have to log in with your Lopolis account.",
@@ -277,6 +287,7 @@ var langstrings = {
sl: {
miscTranslationLanguage: "slovenščina",
miscTranslationAuthors: "Anton Luka Šijanec",
+ "": "",
// date
monday: "ponedeljek",
tuesday: "torek",
@@ -367,7 +378,7 @@ var langstrings = {
thisMessageWasEncrypted: "to sporočilo je šifriral BežiApp",
enterPassword: "vnesite geslo",
decrypt: "odšifriraj",
- nameDirecroryNotSet: "imenik ni nastavljen, pošiljanje ni mogoče",
+ nameDirectoryNotSet: "imenik ni nastavljen, pošiljanje ni mogoče",
errorFetchingMessages: "sporočil ni bilo mogoče prenesti",
unableToReceiveTheMessage: "sporočila ni bilo mogoče prenesti",
unableToDeleteTheMessage: "sporočila ni bilo mogoče izbrisati",
@@ -376,6 +387,15 @@ var langstrings = {
imageAddedAsAnAttachment: "slika dodana kot priloga",
unableToReadDirectory: "imenika ni bilo mogoče prebrati",
messageCouldNotBeSent: "sporočila ni bilo mogoče poslati",
+ // chats
+ chat: "klepet",
+ chattingWith: "klepet z osebo",
+ noMessages: "ni sporočil",
+ stillLoading: "nalaganje še poteka",
+ directory: "imenik",
+ select: "izberi",
+ mustSelectRecipient: "pred klepetom morate izbrati sogovornika. Odprite imenik (meni na levi strani) s pritiskom na gumb \"imenik\" zgoraj desno in izberite sogovornika.",
+ recipientNotInDirectory: "izbrane osebe ni v imeniku",
// meals
loginToLopolis: "prijava v Lopolis",
loginToLopolisNote: "izgleda, da niste prijavljeni v eRestavracijo, zato se vam je prikazal prijavni obrazec. Za uporavljanje s prehrano se uporablja druga kombinacija uporabniškega imena in gesla, zato se prijavite s svojimi Lopolis prijavnimi podatki za nadaljevanje.",
@@ -441,4 +461,4 @@ var langstrings = {
gsecErrLogin: "napaka avtentikacije na GimSISu (napačno geslo?), poskusite se odjaviti",
gsecErrOther: "neznana napaka GimSISa, poskusite se odjaviti"
}
-}
+} \ No newline at end of file
diff --git a/js/messaging.js b/js/messaging.js
index 9ec9410..2b5c065 100644
--- a/js/messaging.js
+++ b/js/messaging.js
@@ -434,4 +434,4 @@ document.addEventListener("DOMContentLoaded", () => {
const menus = document.querySelectorAll(".side-menu");
M.Sidenav.init(menus, { edge: "right", draggable: true });
-});
+}); \ No newline at end of file
diff --git a/js/setup-storage.js b/js/setup-storage.js
index 0fe26d2..0fe3fef 100644
--- a/js/setup-storage.js
+++ b/js/setup-storage.js
@@ -16,7 +16,7 @@ async function setupStorage(force = false) {
localforage.setItem("absences", {}),
localforage.setItem("messages", {}),
localforage.setItem("directory", {}),
- localforage.setItem("meals", {})
+ localforage.setItem("meals", {})
];
if(logged_in && force == false) { // torej, če je že bila prijava narejena, ne posodobi backwards-compatible vrednosti (username, password,...)
await Promise.all(promises_update);
@@ -33,4 +33,3 @@ async function setupStorage(force = false) {
console.log("[setupStorage] user not logged in: set up whole database");
}
}
-
diff --git a/pages/about.html b/pages/about.html
index 22997b2..1da0e03 100644
--- a/pages/about.html
+++ b/pages/about.html
@@ -51,6 +51,7 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
<li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
diff --git a/pages/absences.html b/pages/absences.html
index a25d128..d0acee6 100644
--- a/pages/absences.html
+++ b/pages/absences.html
@@ -54,6 +54,7 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
<li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
diff --git a/pages/chats.html b/pages/chats.html
new file mode 100644
index 0000000..fc35048
--- /dev/null
+++ b/pages/chats.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <meta name="google" content="notranslate">
+ <title>Chats &laquo; BežiApp</title>
+ <!-- Materialize -->
+ <link type="text/css" href="/css/materialize.min.css" rel="stylesheet">
+ <link href="/css/materialicons.css" rel="stylesheet">
+ <script type="text/javascript" src="/js/lib/materialize.min.js"></script>
+ <script src="/js/lib/jquery.min.js"></script>
+ <script type="text/javascript" src="/js/lib/localforage.min.js"></script>
+ <link type="text/css" href="/css/styles.css" rel="stylesheet">
+ <link type="text/css" href="/css/bubbles.css" rel="stylesheet">
+ <script type="text/javascript" src="/js/gsec.js" ></script>
+ <script type="text/javascript" src="/js/chats.js"></script>
+ <link rel="manifest" href="/manifest.json">
+ <script src="/js/app.js"></script>
+ <script src="/js/lang/bundle.js"></script>
+ <script src="/js/lib/xss.js"></script>
+ <script src="/js/lib/sjcl.js"></script>
+ <link rel="shortcut icon" type="image/png" href="/favicon.png" />
+ <!-- iOS support -->
+ <link rel="apple-touch-icon" href="/img/icons/icon_96.png">
+ <link rel="apple-touch-icon" href="/img/icons/icon_512.png">
+ <meta name="apple-mobile-web-app-status-bar" content="#004d32">
+ </head>
+ <body>
+ <nav class="z-depth-0" id="navigation-main">
+ <div class="nav-wrapper container">
+ <span class="left white-text directory-opener">
+ <i class="material-icons sidenav-trigger" data-target="directory-side-menu">contacts</i>
+ </span>
+ <!-- | <x-su>chattingWith</x-su> --> <!-- too much for smaller devices -->
+ <span class="msg-chattingWith"><b>Beži</b><span>App</span> &raquo; <x-su>chat</x-su></span> &nbsp;
+ <span class="right white-text">
+ <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i>
+ </span>
+ </div>
+ <div id="loading-bar" class="progress hidden">
+ <div class="indeterminate"></div>
+ </div>
+ </nav>
+ <ul id="side-menu" class="sidenav side-menu">
+ <li><a class="subheader"><h4><b>Beži</b>App</h4></a></li>
+ <li><a href="/pages/timetable.html" class="waves-effect"><i class="material-icons">view_module</i><x-su>timetable</x-su></a></li>
+ <li><a href="/pages/gradings.html" class="waves-effect"><i class="material-icons">event</i><x-su>gradings</x-su></a></li>
+ <li><a href="/pages/grades.html" class="waves-effect"><i class="material-icons">receipt</i><x-su>grades</x-su></a></li>
+ <li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
+ <li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
+ <li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><div class="divider"></div></li>
+ <li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
+ <li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
+ <li><a href="/pages/settings.html" class="waves-effect"><i class="material-icons">settings</i><x-su>settings</x-su></a></li>
+ </ul>
+ <ul id="directory-side-menu" class="sidenav side-modal">
+ <br>
+ <li><a class="header"><h5><x-su>directory</x-su></h5></a></li>
+ <li>
+ <div class="container">
+ <div class="row">
+ <div class="input-field">
+ <i class="material-icons prefix">account_circle</i>
+ <input oninput="validateName();" id="full-name" type="text" class="autocomplete-fullname validate">
+ <label for="full-name"><x-su>recipient</x-su></label>
+ </div>
+ </div>
+ <div class="row">
+ <button id="chat-recipient-select-btn" onclick="setRecipient()" class="btn waves-effect">
+ <x-su>select</x-su>
+ </button>
+ </div>
+ </div>
+ </li>
+ </ul>
+ <div class="container">
+ <h6 id="chat-mustSelectRecipient"><x-du>mustSelectRecipient</x-du></h6>
+ <div style="text-align:center" class="msg-messagesPlaceholder">
+ <br />
+ <x-du class="msg-messagesPlaceholderText"></x-du> <!-- stillLoading / noMessages -->
+ </div>
+ <div class="chat"></div> <!-- <div data-remark="a child, so chatarea.children does not scare of losing all of her kids"></div> -->
+ <div class="chat-sticky-input">
+ <div class="row">
+ <div class="input-field col s10">
+ <i class="material-icons prefix">mode_edit</i>
+ <textarea maxlength="180" disabled="disabled" oninput="updateSendButton();" id="msg-body" class="materialize-textarea"></textarea>
+ <label for="msg-body"><x-su>messageBody</x-su></label>
+ </div>
+ <div class="input-field col s2">
+ <button class="btn waves-effect waves-light" onclick="sendMessage();" id="msg-send" type="button" disabled="disabled" name="action">
+ <i class="material-icons">send</i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/pages/grades.html b/pages/grades.html
index 878ccd2..0c7e161 100644
--- a/pages/grades.html
+++ b/pages/grades.html
@@ -54,7 +54,8 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
- <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
diff --git a/pages/gradings.html b/pages/gradings.html
index d18670e..72a809a 100644
--- a/pages/gradings.html
+++ b/pages/gradings.html
@@ -61,7 +61,8 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
- <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
diff --git a/pages/meals.html b/pages/meals.html
index 0aae59e..00d150c 100644
--- a/pages/meals.html
+++ b/pages/meals.html
@@ -54,7 +54,8 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
- <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
diff --git a/pages/messaging.html b/pages/messaging.html
index 99f12db..6fbf2db 100644
--- a/pages/messaging.html
+++ b/pages/messaging.html
@@ -52,6 +52,7 @@
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
@@ -138,9 +139,5 @@
</div>
</p>
</div>
-
-
-
</body>
-
</html>
diff --git a/pages/settings.html b/pages/settings.html
index 9d8aaa6..9cde7ac 100644
--- a/pages/settings.html
+++ b/pages/settings.html
@@ -51,7 +51,8 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
- <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
diff --git a/pages/teachers.html b/pages/teachers.html
index e68f512..55a9a92 100644
--- a/pages/teachers.html
+++ b/pages/teachers.html
@@ -54,7 +54,8 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
- <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
diff --git a/pages/timetable.html b/pages/timetable.html
index 3bdb4fa..b7ce913 100644
--- a/pages/timetable.html
+++ b/pages/timetable.html
@@ -63,7 +63,8 @@
<li><a href="/pages/teachers.html" class="waves-effect"><i class="material-icons">supervisor_account</i><x-su>teachers</x-su></a></li>
<li><a href="/pages/absences.html" class="waves-effect"><i class="material-icons">query_builder</i><x-su>absences</x-su></a></li>
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
- <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
+ <li><a href="/pages/chats.html" class="waves-effect"><i class="material-icons">chat</i><x-su>chat</x-su></a></li>
+ <li><a href="/pages/meals.html" class="waves-effect"><i class="material-icons">fastfood</i><x-su>meals</x-su></a></li>
<li><div class="divider"></div></li>
<li><a href="/pages/about.html" class="waves-effect"><i class="material-icons">info</i><x-su>about</x-su></a></li>
<li><a href="/logout.html" class="waves-effect"><i class="material-icons">exit_to_app</i><x-su>logout</x-su></a></li>
diff --git a/sw.js b/sw.js
index f217f03..2e75d02 100644
--- a/sw.js
+++ b/sw.js
@@ -77,7 +77,11 @@ const assets = [
"/index.html",
"/login.html",
"/logout.html",
- "/favicon.png"
+ "/favicon.png",
+
+ "/pages/chats.html",
+ "/js/chats.js",
+ "/css/bubbles.css"
];
importScripts("/js/lib/localforage.min.js");
@@ -137,4 +141,4 @@ self.addEventListener("fetch", (evt) => {
evt.respondWith(caches.match(evt.request).then((cache_res) => {
return cache_res || fetch(evt.request);
}))
-});
+}); \ No newline at end of file