diff options
-rw-r--r-- | css/bubbles.css | 94 | ||||
-rw-r--r-- | css/styles.css | 20 | ||||
-rw-r--r-- | img/avatars/asijanec.png | bin | 389 -> 82 bytes | |||
-rw-r--r-- | js/chats.js | 373 | ||||
-rw-r--r-- | js/gsec.js | 18 | ||||
-rw-r--r-- | js/lang/bundle.js | 26 | ||||
-rw-r--r-- | js/messaging.js | 2 | ||||
-rw-r--r-- | js/setup-storage.js | 3 | ||||
-rw-r--r-- | pages/about.html | 1 | ||||
-rw-r--r-- | pages/absences.html | 1 | ||||
-rw-r--r-- | pages/chats.html | 104 | ||||
-rw-r--r-- | pages/grades.html | 3 | ||||
-rw-r--r-- | pages/gradings.html | 3 | ||||
-rw-r--r-- | pages/meals.html | 3 | ||||
-rw-r--r-- | pages/messaging.html | 5 | ||||
-rw-r--r-- | pages/settings.html | 3 | ||||
-rw-r--r-- | pages/teachers.html | 3 | ||||
-rw-r--r-- | pages/timetable.html | 3 | ||||
-rw-r--r-- | sw.js | 8 |
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 Binary files differindex 34d0e3e..ccae7d0 100644 --- a/img/avatars/asijanec.png +++ b/img/avatars/asijanec.png 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); + } + } +} @@ -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 « 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> » <x-su>chat</x-su></span> + <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> @@ -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 |