summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--assets/js/app.js.bvr1
-rw-r--r--assets/js/lang/bundle.js29
-rw-r--r--assets/js/lopolisc.js433
-rw-r--r--assets/js/meals.js311
-rw-r--r--assets/pages-src/changelog.bvr13
-rw-r--r--assets/pages-src/meals.bvr20
-rw-r--r--assets/pages-src/misc/grading-add-modal.bvr1
-rw-r--r--assets/pages-src/misc/matomo.bvr52
-rw-r--r--assets/pages-src/misc/msg-compose-modal.bvr1
-rw-r--r--assets/pages-src/misc/navigation.bvr4
-rw-r--r--assets/root/sw.js.bvr1
-rwxr-xr-xdist/cache_name.txt2
-rwxr-xr-xdist/js/app.js57
-rwxr-xr-xdist/js/lang/bundle.js6
-rwxr-xr-xdist/js/lopolisc.js52
-rwxr-xr-xdist/js/meals.js35
-rwxr-xr-xdist/pages/about.html10
-rwxr-xr-xdist/pages/absences.html6
-rwxr-xr-xdist/pages/changelog.html13
-rwxr-xr-xdist/pages/chats.html6
-rwxr-xr-xdist/pages/grades.html6
-rwxr-xr-xdist/pages/gradings.html9
-rwxr-xr-xdist/pages/jitsi.html6
-rwxr-xr-xdist/pages/meals.html26
-rwxr-xr-xdist/pages/messaging.html9
-rwxr-xr-xdist/pages/settings.html6
-rwxr-xr-xdist/pages/teachers.html6
-rwxr-xr-xdist/pages/timetable.html6
-rwxr-xr-xdist/sw.js5
-rw-r--r--global.bvr2
-rw-r--r--server/proxy/apache.conf99
-rw-r--r--server/proxy/lopolis.conf55
-rw-r--r--server/proxy/nginx.conf133
-rw-r--r--server/proxy/zgimsis.conf51
34 files changed, 901 insertions, 571 deletions
diff --git a/assets/js/app.js.bvr b/assets/js/app.js.bvr
index 5441c59..a96ea88 100644
--- a/assets/js/app.js.bvr
+++ b/assets/js/app.js.bvr
@@ -1,4 +1,5 @@
<@?i global@>
+// @begin=html@
const app_version = "<@?g app_version@>";
const previous_commit = "<@?g latest_commit@>";
const BEZIAPP_UPDATE_INTERVAL = 300; // update vsakih 300 sekund
diff --git a/assets/js/lang/bundle.js b/assets/js/lang/bundle.js
index 4e15832..bd0335c 100644
--- a/assets/js/lang/bundle.js
+++ b/assets/js/lang/bundle.js
@@ -18,9 +18,6 @@ async function refreshLangDOM() {
localforage.getItem("chosenLang").then( (value) => {
chosenLang = value;
})
- // localforage.getItem("chosenCapitalize").then( (value) => { // poor unused code
- // chosenCapitalize = value;
- // })
];
await Promise.all(promises_to_runn);
// this could be done nicer. p. s.: lahko bi se uporablil x-s in x-S za razločitev med capitalize in !capitalize queryselectorall ni case sensitive za imena elementov
@@ -58,16 +55,18 @@ async function setLangConfigAndReload() {
window.location.reload();
}
window.addEventListener("DOMContentLoaded", () => {
- localforage.getItem("chosenLang").then( (value) => {
- if(value == null) {
- setLangConfigAndReload();
- } else {
- chosenLang = value;
- }
- });
- refreshLangDOM();
+ find_chosen_lang();
});
+async function find_chosen_lang() {
+ let value = await localforage.getItem("chosenLang");
+ if(value == null) {
+ setLangConfigAndReload();
+ } else {
+ chosenLang = value;
+ }
+ refreshLangDOM();
+}
const capitalize = (s) => {
if (typeof s !== 'string') return ''
@@ -253,6 +252,10 @@ var langstrings = {
mealSet: "meal set! Reload meals to be sure",
selected: "selected",
meal: "meal",
+ checkedOut: "checked out",
+ checkedIn: "checked in",
+ successfulCheckingInOut: "successfully checked in/out",
+ errorCheckingInOut: "failed to check in/out",
// about
version: "version",
authors: "authors",
@@ -461,6 +464,10 @@ var langstrings = {
mealSet: "obrok nastavljen! osvežite obroke in se prepričajte sami",
selected: "izbrano",
meal: "obrok",
+ checkedOut: "odjavljen",
+ checkedIn: "prijavljen",
+ errorCheckingInOut: "prijava/odjava na obrok NI uspela",
+ successfulCheckingInOut: "prijava/odjava na obrok je uspela",
// about
version: "različica",
authors: "avtorji",
diff --git a/assets/js/lopolisc.js b/assets/js/lopolisc.js
new file mode 100644
index 0000000..dfd9ff6
--- /dev/null
+++ b/assets/js/lopolisc.js
@@ -0,0 +1,433 @@
+function getStringBetween(string, start, end) {
+ return string.split(start).pop().split(end)[0];
+}
+
+const LOPOLIS_URL = "https://lopolis.gimb.tk/";
+const LOPOLISC_ERR_NET = "LOPOLSIC NETWORK ERROR (ajax error)";
+const LOPOLISC_ERR_NET_POSTBACK_GET = "LOPOLISC NETWORK ERROR (ajax error) "+
+ "in postback GET";
+const LOPOLISC_ERR_LOGIN = "LOPOLISC LOGIN ERROR";
+const LOPOLISC_ERR_NET_POSTBACK_POST = "LOPOLISC NETWORK ERROR (ajax error) "+
+ "in postback POST";
+const LOPOLISC_ERR_NET_POSTBACK_POST_IN_POSTBACK = "LOPOLISC NETWORK ERROR $$$";
+const LOPOLISC_ERR_NOTAPPLIED = "LOPOLISC DATA NOT APPLIED ERROR";
+const LOPOLISC_SIGNATURE = "lopolisc.js neuradni API - anton<at>sijanec.eu";
+const LOPOLISC_ERR_OUT_OF_RETRIES = "LOPOLISC ERROR NI VEČ POSKUSOV!";
+class lopolisc {
+
+ constructor() {
+ }
+
+ parseAndPost(inputHTML, userParams, formId = null, useDiffAction = null) {
+ return new Promise((resolve, reject) => {
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(inputHTML, "text/html");
+
+ var form;
+ if (formId == null) {
+ form = parsed.getElementsByTagName("form")[0];
+ } else {
+ form = parsed.getElementById(formId);
+ }
+
+ var params = {};
+ var otherParams = $(form).serializeArray();
+ for (const input of otherParams) {
+ if (!(input.name in params)) {
+ params[input.name] = input.value; // so we don't overwrite existing values
+ }
+ }
+
+ for (const [key, value] of Object.entries(userParams)) { // neki me je
+ params[key] = value; // zajebaval, pa sem tkole naredu - še enkrat
+ } // prepišemo vse, kar je v params, z uporabniškimi parametri
+ // POPRAVEK PO 2 min debugganja: ne, nič ni bilo narobe, pozabil sem
+ // passat dataToSend v postback(), passal sem {} :facepalm: </notetoself>
+ var action;
+ if (useDiffAction == null || useDiffAction == false) {
+ action = new URL($(form).attr("action"), LOPOLIS_URL); // absolute == relative + base
+ } else {
+ action = useDiffAction;
+ }
+
+ params["programska-oprema"] = LOPOLISC_SIGNATURE;
+ $.ajax({
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true,
+ url: action,
+ cache: false,
+ type: "POST",
+ data: params,
+ dataType: "text",
+ maxRetries: 3,
+ success: (postData, textStatus, xhr) => {
+ resolve({data: postData, textStatus: textStatus, code: xhr.status});
+ },
+ error: () => {
+ reject(new Error(LOPOLISC_ERR_NET_POSTBACK_POST));
+ }
+ });
+ });
+ }
+
+ postback(getUrl, params = {}, formId = null, useDiffAction = null) {
+ return new Promise( (resolve, reject) => {
+ $.ajax({
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true,
+ url: getUrl,
+ cache: false,
+ type: "GET",
+ dataType: "html",
+ success: (data) => {
+ if (useDiffAction === true) {
+ useDiffAction = getUrl;
+ }
+ this.parseAndPost(data, params, formId, useDiffAction)
+ .then((value) => {
+ resolve(value);
+ }).catch((e)=>{
+ reject(new Error(LOPOLISC_ERR_NET_POSTBACK_POST_IN_POSTBACK));
+ });
+ },
+ error: () => {
+ reject(new Error(LOPOLISC_ERR_NET_POSTBACK_GET));
+ }
+ });
+ });
+ }
+
+ getUserData() {
+ return new Promise((resolve, reject)=>{
+ $.ajax({
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true,
+ url: LOPOLIS_URL+"?MeniID=2",
+ cache: false,
+ type: "GET",
+ dataType: "html",
+ success: (data) => {
+ if (data.includes("Dostop ni dovoljen")) {
+ // console.log(data);
+ resolve(false);
+ return;
+ }
+ let parser = new DOMParser();
+ let p = parser.parseFromString(data, "text/html");
+ let uporabnik = {
+ u: p.getElementsByClassName("obrazecPovdarjen")[0].innerText.trim(),
+ n: p.getElementsByClassName("obrazecPovdarjen")[1].innerText.trim(),
+ e: p.getElementById("Email").value
+ }
+ resolve(uporabnik);
+ },
+ error: () => {
+ reject(new Error(LOPOLISC_ERR_NET));
+ }
+ });
+ });
+ }
+
+ logout() { // you can get pretty race conditiony if you use this wrong! // nah
+ return new Promise((resolve, reject)=>{
+ this.postback(LOPOLIS_URL + "Uporab/Prijava", {}, null, false).then((response) => { // če je true, bo URL, če je false, bo action
+ resolve(true); // don't bother checking cookies...
+ });
+ });
+ }
+
+ login(usernameToLogin, passwordToLogin) {
+ return new Promise(async function(resolve, reject) {
+ let l = new lopolisc();
+ var uporabnik = await l.getUserData();
+ if (uporabnik != false) {
+ if (uporabnik.u = usernameToLogin) {
+ resolve(true);
+ return;
+ } else {
+ await this.logout();
+ }
+ }
+ var dataToSend = {
+ "Uporabnik": usernameToLogin,
+ "Geslo": passwordToLogin,
+ "OsveziURL": "https://pornhub.com/\"; lopolis=\"boljsi od easistenta",
+ };
+ l.postback(LOPOLIS_URL + "Uporab/Prijava", dataToSend, null, true).then((response) => { // če je true, bo URL, če je false, bo action
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(response.data, "text/html");
+ if (parsed.getElementById("divPrijavaOsvezi") != null) {
+ resolve(true);
+ }
+ reject(new Error(LOPOLISC_ERR_LOGIN));
+ });
+ });
+ }
+
+ fetchCheckouts(date_object = null) {
+ if (date_object == null) {
+ date_object = new Date();
+ }
+ return new Promise((resolve, reject) => {
+ var dataToSend = {
+ "MesecModel.Mesec": String(date_object.getMonth()+1),
+ "MesecModel.Leto": String(date_object.getFullYear()),
+ "Ukaz": ""
+ };
+ this.postback(LOPOLIS_URL+"Prehrana/Odjava", dataToSend, null, true).then((response) => {
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(response.data, "text/html");
+ let checkouts = {};
+ for (const element of parsed.getElementsByTagName("tbody")[0].
+ getElementsByTagName("tr")) {
+ let date_idx = element.getElementsByTagName("input")[2].value;
+ checkouts[date_idx] = {
+ checked/*out*/: element.getElementsByTagName("input")[0].checked,
+ readonly: element.getElementsByTagName("input")[0].disabled,
+ // spodaj spremenljivke, ki so potrebne za submit (ne-API)
+ index: Number(getStringBetween( // string, start, end
+ element.getElementsByTagName("input")[0].name, "[", "]"
+ )),
+ "OsebaModel.ddlOseba":
+ parsed.getElementsByTagName("option")[0].value,
+ "OsebaModel.OsebaID":
+ parsed.getElementById("OsebaModel_OsebaID").value,
+ "OsebaModel.OsebaTipID":
+ parsed.getElementById("OsebaModel_OsebaTipID").value,
+ "OsebaModel.UstanovaID":
+ parsed.getElementById("OsebaModel_UstanovaID").value,
+ "MesecModel.Mesec": parsed.getElementById("MesecModel_Mesec").value,
+ "MesecModel.Leto": parsed.getElementById("MesecModel_Leto").value
+ }
+ checkouts[date_idx][element.getElementsByTagName("input")[2].name] =
+ String(element.getElementsByTagName("input")[2].value);
+ checkouts[date_idx][element.getElementsByTagName("input")[3].name] =
+ String(element.getElementsByTagName("input")[3].value);
+ checkouts[date_idx][element.getElementsByTagName("input")[4].name] =
+ String(element.getElementsByTagName("input")[4].value);
+ }
+ resolve(checkouts);
+ });
+ });
+ }
+
+ fetchAllMeals(koliko = 3) { // "vsi" pomeni nas. n mes. (vklj. s tem me.)
+ return new Promise (async function(resolve, reject) {
+ let date = new Date();
+ let podatki = {};
+ while (koliko-- > 0) {
+ let l = new lopolisc(); // this zajebava, sorry; seja je itak na
+ let resp = await l.fetchMeals(date); // browserju, ne na objectu.
+ podatki = {...podatki, ...resp};
+ date.setMonth(date.getMonth()+1); // ja, popravi se letnica!
+ }
+ resolve(podatki);
+ });
+ }
+
+
+ fetchAllCheckouts(koliko = 3) { // "vsi" pomeni nas. n mes. (vklj. s tem me.)
+ return new Promise (async function(resolve, reject) {
+ let date = new Date();
+ let podatki = {};
+ while (koliko-- > 0) {
+ let l = new lopolisc(); // this zajebava, sorry; seja je itak na
+ let resp = await l.fetchCheckouts(date); // browserju, ne na objectu.
+ podatki = {...podatki, ...resp};
+ date.setMonth(date.getMonth()+1); // ja, popravi se letnica!
+ }
+ resolve(podatki);
+ });
+ }
+
+ setCheckouts(odjava_objects) {
+ let odjava_objects_sorted = {};
+ for (const [odjava_da, odjava_ob] of Object.entries(odjava_objects)) {
+ let yearmonth_combo = odjava_da.substring(0,7);
+ if (odjava_objects_sorted[yearmonth_combo] == undefined) {
+ odjava_objects_sorted[yearmonth_combo] = {};
+ }
+ odjava_objects_sorted[yearmonth_combo][odjava_da] = odjava_ob;
+ }
+ if (Object.entries(odjava_objects_sorted).length < 1) {
+ return false;
+ } else if (Object.entries(odjava_objects_sorted).length > 1) {
+ var response;
+ for (const [ym_combo, odj_ob] of Object.entries(odjava_objects_sorted)) {
+ response = this.setCheckouts(odj_ob);
+ }
+ return response; // napake so itak exceptioni, promisov ne potrebujemo!
+ } // else: samo en mesec podatkov imamo, let's go!
+ return new Promise((resolve, reject) => {
+ var dataToSend = { "Ukaz": "Shrani" };
+ for (const [odjava_da, odjava_object] of Object.entries(odjava_objects)) {
+ for (const [index, property] of Object.entries(odjava_object)) {
+ dataToSend[index] = property;
+ }
+ dataToSend["OdjavaItems["+odjava_object.index+"].CheckOut"] =
+ String(odjava_object.checked);
+ } // now we have some excess values, who cares (index, readonly, checked)
+ this.postback(LOPOLIS_URL+"Prehrana/Odjava", dataToSend, null, true).
+ then( (response) => {
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(response.data, "text/html");
+ for (const [od_date, odjava_object] of Object.entries(odjava_objects)) {
+ if (!(parsed.getElementById("OdjavaItems_"+odjava_object.index+"__CheckOut").checked == odjava_object.checked)) {
+ reject(LOPOLISC_ERR_NOTAPPLIED);
+ }
+ }
+ resolve(true);
+ });
+ });
+ }
+
+ fetchMeals(date_object = null, retried = 3) { // retried je interni parameter
+ if (date_object == null) {
+ date_object = new Date();
+ }
+ return new Promise((resolve, reject) => {
+ var meals = {};
+ var dataToSend = {
+ "Ukaz": "",
+ "MesecModel.Mesec": String(date_object.getMonth()+1),
+ "API-METODA": "fetchMeals",
+ "MesecModel.Leto": String(date_object.getFullYear())
+ }
+ this.postback(LOPOLIS_URL+"?MeniID=78",dataToSend,"form1",false).
+ then((response) => {
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(response.data, "text/html");
+ for (const element of parsed.getElementsByTagName("tbody")[0].
+ getElementsByTagName("tr")) {
+ let menuoptions = [];
+ let is_any_selected = false;
+ for (const opt of element.getElementsByTagName("select")[0].options) {
+ if (opt.value.length > 0 || 1==1) { // tudi prazno opcijo pustimo
+ menuoptions.push({
+ value: opt.value,
+ text: opt.innerText,
+ selected: opt.selected
+ });
+ }
+ if (opt.selected) {
+ is_any_selected = true;
+ }
+ }
+ if (!is_any_selected) {
+ menuoptions[0].selected = true; // !!! KAJ GRE LAHKO NAROBE:
+ // * če je readonly je itak en izbran
+ // * če je en izbran je itak en izbran
+ // * če noben ni izbran in je readonly se izbere prazna - okej
+ // * če noben ni izbran in je readonly se izbere prazna - okej
+ // prazna (index 0) defaulta na meni 1 (index 1) ampak ne bom tvegal
+ }
+ let date_idx = element.getElementsByTagName("input")[0].value;
+ meals[date_idx] = { // trying to keep same api as rstular's lopolisapi
+ meal: element.getElementsByTagName("td")[1].innerText.trim(),
+ "menu-type": element.getElementsByTagName("td")[2].innerText.trim(),
+ location: element.getElementsByTagName("td")[3].innerText.trim(),
+ readonly: element.getElementsByTagName("select")[0].disabled,
+ menu_options: menuoptions,
+ // properties below are "private" and non-API (undocumented even)
+ index: Number(getStringBetween( // string, start, end
+ element.getElementsByTagName("input")[0].name, "[", "]"
+ )),
+ "OsebaModel.ddlOseba":
+ parsed.getElementsByTagName("option")[0].value,
+ "OsebaModel.OsebaID":
+ parsed.getElementById("OsebaModel_OsebaID").value,
+ "OsebaModel.OsebaTipID":
+ parsed.getElementById("OsebaModel_OsebaTipID").value,
+ "OsebaModel.UstanovaID":
+ parsed.getElementById("OsebaModel_UstanovaID").value,
+ "MesecModel.Mesec": parsed.getElementById("MesecModel_Mesec").value,
+ "MesecModel.Leto": parsed.getElementById("MesecModel_Leto").value
+ }
+ meals[date_idx][element.getElementsByTagName("input")[0].name] =
+ String(element.getElementsByTagName("input")[0].value); // date
+ meals[date_idx][element.getElementsByTagName("input")[1].name] =
+ String(element.getElementsByTagName("input")[1].value); // prijOID?
+ meals[date_idx][element.getElementsByTagName("input")[2].name] =
+ String(element.getElementsByTagName("input")[2].value); // readonly
+ }
+ resolve(meals);
+ }).catch((err)=>{
+ if (retried <= 0) {
+ reject(new Error(LOPOLISC_ERR_OUT_OF_RETRIES));
+ } else {
+ resolve(this.fetchMeals(date_object, retried-1)); // retry
+ }
+ });
+ });
+ }
+
+ setMeals(meal_objects) {
+ let meal_objects_sorted = {};
+ for (const [meal_da, meal_ob] of Object.entries(meal_objects)) {
+ let yearmonth_combo = meal_da.substring(0,7);
+ if (meal_objects_sorted[yearmonth_combo] == undefined) {
+ meal_objects_sorted[yearmonth_combo] = {};
+ }
+ meal_objects_sorted[yearmonth_combo][meal_da] = meal_ob;
+ }
+ if (Object.entries(meal_objects_sorted).length < 1) { // ni podatkov sploh
+ return false;
+ } else if (Object.entries(meal_objects_sorted).length > 1) {
+ var response;
+ for (const [ym_combo, meal_ob] of Object.entries(meal_objects_sorted)) {
+ response = this.setMeals(meal_ob);
+ }
+ return response; // itak ne uporabljamo response ampak try{}catch{} except
+ } // else: samo en mesec podatkov imamo, let's go!
+
+ return new Promise((resolve, reject) => {
+ var dataToSend = { "Ukaz": "Shrani" };
+ for (const [meal_date, meal_object] of Object.entries(meal_objects)) {
+ for (const [index, property] of Object.entries(meal_object)) {
+ dataToSend[index] = String(property);
+ }
+ for (const menu_option of meal_object.menu_options) {
+ if (menu_option.selected) {
+ dataToSend["PrednarocanjeItems["+meal_object.index+
+ "].MeniIDSkupinaID"] = menu_option.value;
+ }
+ }
+ } // excess values: meal, menu-type, location, readonly, menu_options
+ this.postback(LOPOLIS_URL+"Prehrana/Prednarocanje",dataToSend,null,true).
+ then( (response) => {
+ let parser = new DOMParser();
+ let parsed = parser.parseFromString(response.data, "text/html");
+ for (const [meal_date, meal_object] of Object.entries(meal_objects)) {
+ let selected_value;
+ for (const menu_option of meal_object.menu_options) {
+ if (menu_option.selected) {
+ selected_value = menu_option.value;
+ }
+ }
+ if (!(parsed.getElementById("PrednarocanjeItems_"+meal_object.index+"__MeniIDSkupinaID").selectedOptions[0].value == selected_value)) {
+ reject(LOPOLISC_ERR_NOTAPPLIED);
+ }
+ }
+ resolve(true);
+ });
+ });
+ }
+
+ chooseMenu(meal_object, meal_index) {
+ for (const menu_option of meal_object.menu_options) {
+ menu_option.selected = false;
+ }
+ meal_object.menu_options[meal_index].selected = true;
+ return;
+ }
+
+}
+
+// Edited with \ / o _ _ this script is I /\/\ 2020
+// Improved & free \/ I I I I vim-powered my editor \__/ -- sijanec
diff --git a/assets/js/meals.js b/assets/js/meals.js
index 15accdb..1cf1977 100644
--- a/assets/js/meals.js
+++ b/assets/js/meals.js
@@ -1,8 +1,8 @@
-const API_ENDPOINT = "https://lopolis-api.gimb.tk/";
+const API_ENDPOINT = "https://lopolis-api.gimb.tk/"; // unused!
var meals_calendar_obj = null;
var meals_data_global = {};
-
+var checkouts_data_global = {};
function getDateString() { // ne mene gledat, ne vem, kaj je to.
let date = new Date();
@@ -50,105 +50,49 @@ async function getToken(callback, callbackparams = []) {
})
];
await Promise.all(promises_to_run);
-
- $.ajax({
- url: API_ENDPOINT + "gettoken",
- crossDomain: true,
- contentType: "application/json",
- data: JSON.stringify({
- "username": username,
- "password": password
- }),
-
- dataType: "json",
- cache: false,
- type: "POST",
-
- success: (dataauth) => {
- if (dataauth == null || dataauth.error == true) {
- UIAlert(D("authenticationError"), "getToken(): response error or null");
- localforage.setItem("logged_in_lopolis", false).then(function() {
- checkLogin();
- });
- } else if (dataauth.error == false) {
- let empty = {};
- empty.token = dataauth.data;
- let argumentsToCallback = [empty].concat(callbackparams);
- callback(...argumentsToCallback); // poslje token v {token: xxx}
- } else {
- UIAlert(D("authenticationError"), "getToken(): invalid response, no condition met");
- }
- setLoading(false);
- },
- error: () => {
- UIAlert(D("lopolisAPIConnectionError"), "getToken(): AJAX error");
- setLoading(false);
- }
- });
+ try {
+ var lopolisClient = new lopolisc();
+ var response = await lopolisClient.login(username, password);
+ // če response ni true bo itak exception
+ } catch (e) {
+ console.log(e);
+ UIAlert(D("authenticationError"), "getToken(): invalid response, no condition met");
+ await localforage.setItem("logged_in_lopolis", false);
+ return false;
+ }
+ await localforage.setItem("logged_in_lopolis", true);
+ let empty = {};
+ empty.token = {}; // tokenov NI VEČ! old code pa to
+ let argumentsToCallback = [empty].concat(callbackparams);
+ callback(...argumentsToCallback); // poslje token v {token: xxx}
}
async function getMenus(dataauth, callback, callbackparams = []) {
setLoading(true);
- let current_date = new Date();
- // naloži za dva meseca vnaprej (če so zadnji dnevi v mesecu)
- let mealsgathered = {};
- let promises_to_wait_for = [];
- for (let iteration = 1; iteration <= 2; iteration++) {
-
- promises_to_wait_for[iteration] = $.ajax({
- url: API_ENDPOINT + "getmenus",
- crossDomain: true,
- contentType: "application/json",
- data: JSON.stringify({
- "month": current_date.getMonth() + iteration,
- "year": current_date.getFullYear()
- }),
-
- headers: {
- "Authorization": `Bearer ${dataauth.token}`
- },
-
- dataType: "json",
- cache: false,
- type: "POST",
-
- success: (meals) => {
- if (meals == null || meals.error == true) {
- UIAlert(D("errorGettingMenus"), "getMenus(): response error or null");
- setLoading(false);
- localforage.setItem("logged_in_lopolis", false).then(() => {
- checkLogin();
- });
- } else if (meals.error == false) {
- setLoading(false);
- mealsgathered[iteration] = meals;
- } else {
- setLoading(false);
- UIAlert(D("errorUnexpectedResponse"), "getMenus(): invalid response, no condition met");
- }
- },
-
- error: () => {
- setLoading(false);
- UIAlert(D("lopolisAPIConnectionError"), "getMenus(): AJAX error");
- }
- });
- }
-
- await Promise.all(promises_to_wait_for); // javascript is ducking amazing
-
- let allmeals = {};
let passtocallback = {};
-
- for (const [index, monthmeals] of Object.entries(mealsgathered)) { // although this is not very javascripty
- allmeals = mergeDeep(allmeals, monthmeals.data);
+ let allmeals, allcheckouts;
+ let tries = 3;
+ while (true) {
+ try {
+ let lopolisClient = new lopolisc();
+ allmeals = await lopolisClient.fetchAllMeals();
+ allcheckouts = await lopolisClient.fetchAllCheckouts();
+ } catch (e) {
+ console.log(e);
+ UIAlert(D("lopolisAPIConnectionError"), "getMenus(): AJAX error");
+ if (tries-- < 0) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+ break;
}
-
- passtocallback.data = allmeals;
- passtocallback.token = dataauth.token;
+ passtocallback.data = allmeals; // kot po starem apiju so meniji še vedno tu!!
+ passtocallback.checkouts = allcheckouts;
+ passtocallback.token = "tokens-not-used-anymore";
let toBePassed = [passtocallback].concat(callbackparams);
callback(...toBePassed);
-
}
async function loadMeals() {
@@ -158,6 +102,7 @@ async function loadMeals() {
function displayMeals(meals) {
// console.log(JSON.stringify(meals)); // debug // dela!
meals_data_global = meals.data;
+ checkouts_data_global = meals.checkouts;
let transformed_meals = [];
for (const [date, mealzz] of Object.entries(meals.data)) {
let bg_color = "#877F02"; let fg_color = "#FFFFFF";
@@ -165,7 +110,7 @@ function displayMeals(meals) {
let meal_date = new Date(date+"+00:00"); // idk u figure it out. timezones
let meal_object = {
start: meal_date.toISOString().substring(0,10), // zakaj? poglej gradings.js - NUJNO! poglej, če so timezoni v redu! da slučajno ne preskakuje na naslednji dan!
- title: S("meal"),
+ title: mealzz.meal,
id: date,
allDay: true,
backgroundColor: bg_color,
@@ -175,6 +120,7 @@ function displayMeals(meals) {
}
meals_calendar_obj.removeAllEvents();
meals_calendar_obj.addEventSource(transformed_meals);
+ setLoading(false);
return;
}
@@ -188,117 +134,35 @@ function refreshMeals() {
}
function lopolisLogout() {
- localforage.setItem("logged_in_lopolis", false);
- $("#meals-collapsible").html("");
- checkLogin();
+ localforage.setItem("logged_in_lopolis", false).then(()=>{
+ clearMeals();
+ checkLogin();
+ });
}
async function lopolisLogin() {
setLoading(true);
var usernameEl = $("#meals-username");
var passwordEl = $("#meals-password");
- $.ajax({
- url: API_ENDPOINT + "gettoken",
- crossDomain: true,
- contentType: "application/json",
- data: JSON.stringify({
- "username": usernameEl.val(),
- "password": passwordEl.val()
- }),
-
- dataType: "json",
- cache: false,
- type: "POST",
-
- success: async function(data) {
- if (data == null) {
- UIAlert(S("requestForAuthenticationFailed"), "lopolisLogin(): date is is null");
- setLoading(false);
- usernameEl.val("");
- passwordEl.val("");
- } else if (data.error == true) {
- UIAlert(S("loginFailed"), "lopolisLogin(): login failed. data.error is true");
- usernameEl.val("");
- passwordEl.val("");
- setLoading(false);
- } else {
- let promises_to_run = [
- localforage.setItem("logged_in_lopolis", true),
- localforage.setItem("lopolis_username", usernameEl.val()),
- localforage.setItem("lopolis_password", passwordEl.val())
- ];
- await Promise.all(promises_to_run);
- checkLogin();
- UIAlert("Credential match!");
- }
- },
-
- error: () => {
- UIAlert(D("loginError"), "lopolisLogin(): ajax.error");
- setLoading(false);
- }
- });
-}
-
-async function setMenus(currentmeals = 69, toBeSentChoices) { // currentmeals je getMenus response in vsebuje tudi token.
-
- if (currentmeals === 69) {
- getToken(getMenus, [setMenus, toBeSentChoices]);
- return;
+ try {
+ let l = new lopolisc();
+ await l.login(usernameEl.val(), passwordEl.val());
+ } catch (e) {
+ UIAlert(D("loginError"), "lopolisLogin(): ajax.error");
+ setLoading(false);
+ return false;
}
-
- for (const [mealzzdate, mealzz] of Object.entries(currentmeals.data)) {
- if (mealzzdate in toBeSentChoices === false) {
- for (const [mealid, mealdata] of Object.entries(mealzz.menu_options)) {
- // console.log(mealdata);
- if (mealdata.selected == true || mealzz.readonly == true) {
- toBeSentChoices[mealzzdate] = mealdata.value;
- break;
- }
- }
- }
- }
-
- setLoading(true);
-
- $.ajax({
- url: API_ENDPOINT + "setmenus",
- crossDomain: true,
- contentType: "application/json",
- data: JSON.stringify({
- "choices": toBeSentChoices
- }),
- headers: {
- "Authorization": "Bearer " + currentmeals.token
- },
- dataType: "json",
- cache: false,
- type: "POST",
-
- success: (response) => {
- if (response === null || response.error == true) {
- UIAlert(D("errorSettingMeals"), "setMenus(): response error or null");
- } else if (response.error == false) {
- UIAlert(D("mealSet"), "setMenus(): meni nastavljen");
- } else {
- UIAlert(D("errorUnexpectedResponse"), "setMenus(): invalid response, no condition met");
- }
- setLoading(false);
- },
-
- error: () => {
- setLoading(false);
- UIAlert(D("lopolisAPIConnectionError"), "setMenus(): AJAX error");
- }
- });
-}
-async function setMenu(date, menu) {
- let choice = {};
- choice[date] = menu;
- getToken(getMenus, [setMenus, choice]);
+ let promises_to_run = [
+ localforage.setItem("logged_in_lopolis", true),
+ localforage.setItem("lopolis_username", usernameEl.val()),
+ localforage.setItem("lopolis_password", passwordEl.val())
+ ];
+ await Promise.all(promises_to_run);
+ checkLogin();
+ UIAlert("Credential match!");
+ return true;
}
-
function setupEventListeners() {
$("#meals-login").click(() => {
lopolisLogin();
@@ -310,9 +174,39 @@ function setupEventListeners() {
}
var mealClickHandler = (eventClickInfo) => {
- // console.log("meal clicked!"); // debug
let meal_date = eventClickInfo.event.id;
let meal_object = meals_data_global[meal_date];
+
+ /// ˇˇˇ checkouts
+ $("#checkout_label").show(); let can_do_checkout = true;
+ let checkout_object;
+ try {
+ checkout_object = checkouts_data_global[meal_date];
+ } catch (e) {
+ $("#checkout_label").hide(); let can_do_checkout = false;
+ }
+ if (checkout_object == undefined || checkout_object == null) {
+ can_do_checkout = false;
+ }
+ console.log(checkout_object);
+ if (can_do_checkout) { let cc = $("#checkout_checkbox");
+ cc[0].checked/*in*/ = !(checkout_object.checked/*out*/);
+ cc.off();
+ cc.on("change", ()=>{
+ let l = new lopolisc();
+ checkouts_data_global[meal_date].checked/*out*/ = !(cc[0].checked/*in*/);
+ setLoading(true);
+ l.setCheckouts(checkouts_data_global).then(()=>{ // update server checkots
+ UIAlert(D("successfulCheckingInOut"), "successfulcheckinginout");
+ setLoading(false);
+ }).catch(()=>{
+ UIAlert(D("errorCheckingInOut"), "errorcheckinginout");
+ setLoading(false);
+ });
+ });
+ cc.prop("disabled", checkout_object.readonly);
+ }
+ /// ^^^ checkouts
$("#meal-type").text(meal_object.meal);
let meal_date_obj = new Date(meal_date);
$("#meal-date").text(dateString.longFormatted(meal_date_obj));
@@ -326,12 +220,9 @@ var mealClickHandler = (eventClickInfo) => {
let menu_option_li_el = document.createElement("li");
let menu_option_a_el = document.createElement("button");
menu_option_a_el.innerText = option_object.text;
- // console.log(JSON.stringify(meal_object)); // debug
let classlist = "";
if (option_object.selected != null) {
if(option_object.selected) {
- // console.log("selected"); // debug
- //
classlist = "color: green; font-weight: bold";
}
}
@@ -339,13 +230,25 @@ var mealClickHandler = (eventClickInfo) => {
menu_option_a_el.style = "color: var(--color-text); background-color: rgba(0,0,0,0); line-height: 1.2; height:auto; "+classlist+" !important";
menu_option_a_el.id = "menu_index_"+option_index;
if(!(meal_object.readonly)) {
- menu_option_a_el.onclick = () => {
- setMenu(meal_date, option_object.value);
+ menu_option_a_el.disabled = false;
+ menu_option_a_el.onclick = () => {
+ setLoading(true);
+ let l = new lopolisc();
+ l.chooseMenu(meals_data_global[meal_date], option_index);
+ l.setMeals(meals_data_global).then(()=>{
+ UIAlert(D("mealSet"), "meal set!");
+ setLoading(false);
+ }).catch(()=>{
+ UIAlert(D("errorSettingMeals"), "error setting meals");
+ setLoading(false);
+ });
menu_option_a_el.className = "to-be-selected-meal";
let sidenav_element = document.getElementById("meal-info");
let sidenav_instance = M.Sidenav.getInstance(sidenav_element);
sidenav_instance.close();
};
+ } else {
+ menu_option_a_el.disabled = true;
}
menu_option_li_el.appendChild(menu_option_a_el);
document.getElementById("meal-options").appendChild(menu_option_li_el);
@@ -357,6 +260,7 @@ var mealClickHandler = (eventClickInfo) => {
// Initialization code
document.addEventListener("DOMContentLoaded", async () => {
+ await find_chosen_lang();
checkLogin();
var calendarEl = document.getElementById("meals-calendar");
@@ -377,6 +281,7 @@ document.addEventListener("DOMContentLoaded", async () => {
// Setup refresh handler
$("#refresh-icon").click(function() {
+ setLoading(true);
refreshMeals();
});
@@ -408,5 +313,5 @@ document.addEventListener("DOMContentLoaded", async () => {
format: "dddd, dd. mmmm yyyy"
});
- refreshMeals();
+ // refreshMeals(); // checklogin already does this
});
diff --git a/assets/pages-src/changelog.bvr b/assets/pages-src/changelog.bvr
index 56b883c..e112765 100644
--- a/assets/pages-src/changelog.bvr
+++ b/assets/pages-src/changelog.bvr
@@ -53,6 +53,18 @@
</h3>
<ul class="collapsible">
<li>
+
+ <div class="collapsible-header">Version 1.0.16-beta</div>
+ <div class="collapsible-body">
+ <ul class="collection">
+ <li class="collection-item">Fixed meals</li>
+ <li class="collection-item">Removed LopolisAPI, created
+ lopolisc.js</li>
+ <li class="collection-item">Removed GimB Meet</li>
+ <li class="collection-item">Added checkout option to meals</li>
+ </ul>
+ </div>
+
<div class="collapsible-header">Version 1.0.15-beta</div>
<div class="collapsible-body">
<ul class="collection">
@@ -60,7 +72,6 @@
</ul>
</div>
-
<div class="collapsible-header">Version 1.0.14-beta</div>
<div class="collapsible-body">
<ul class="collection">
diff --git a/assets/pages-src/meals.bvr b/assets/pages-src/meals.bvr
index c0d655b..2fd4840 100644
--- a/assets/pages-src/meals.bvr
+++ b/assets/pages-src/meals.bvr
@@ -17,20 +17,18 @@
<script src="/js/lib/jquery.min.js"></script>
<!-- localForage -->
<script type="text/javascript" src="/js/lib/localforage.min.js"></script>
+ <!-- i18n bundle -->
+ <script src="/js/lang/bundle.js"></script>
<!-- mergedeep.js -->
<script type="text/javascript" src="/js/lib/mergedeep.js"></script>
<!-- stylesheet for custom styles -->
<link type="text/css" href="/css/styles.css" rel="stylesheet">
- <!-- page-specific javascript code -->
- <script type="text/javascript" src="/js/meals.js"></script>
<!-- PWA manifest -->
<link rel="manifest" href="/manifest.json">
<!-- app global code -->
<script src="/js/app.js"></script>
<!-- code for custom theme switcher -->
<script src="/js/lib/themes.js"></script>
- <!-- i18n bundle -->
- <script src="/js/lang/bundle.js"></script>
<!-- favicon -->
<link rel="shortcut icon" type="image/png" href="/favicon.png" />
<!-- iOS support -->
@@ -43,6 +41,10 @@
<link href="/css/fullcalendar/custom.css" rel="stylesheet" />
<script src="/js/lib/fullcalendar/core/main.min.js"></script>
<script src="/js/lib/fullcalendar/daygrid/main.min.js"></script>
+ <!-- lopolis client API library - unofficial by sijanec -->
+ <script src="/js/lopolisc.js"></script>
+ <!-- page-specific javascript code -->
+ <script type="text/javascript" src="/js/meals.js"></script>
</head>
<body>
@@ -81,6 +83,16 @@
<x-du>readOnly</x-du>
</a>
</li>
+ <li>
+ <div class=switch style=margin-left:0.7cm>
+ <label id=checkbox_label style>
+ <x-su>checkedOut</x-su>
+ <input id=checkout_checkbox type=checkbox>
+ <span class=lever></span>
+ <x-su>checkedIn</x-su>
+ </label>
+ </div>
+ </li>
<div class=divider></div>
<li id=meal-options>
diff --git a/assets/pages-src/misc/grading-add-modal.bvr b/assets/pages-src/misc/grading-add-modal.bvr
index 0b7189d..6017189 100644
--- a/assets/pages-src/misc/grading-add-modal.bvr
+++ b/assets/pages-src/misc/grading-add-modal.bvr
@@ -1,3 +1,4 @@
+<!-- @begin=html@ -->
<!-- Modal Structure -->
<div id="beziapp-add-grading" class="modal modal-fixed-footer">
diff --git a/assets/pages-src/misc/matomo.bvr b/assets/pages-src/misc/matomo.bvr
index d57beb0..614e210 100644
--- a/assets/pages-src/misc/matomo.bvr
+++ b/assets/pages-src/misc/matomo.bvr
@@ -28,42 +28,32 @@ let promises_to_run_app = [
Promise.all(promises_to_run_app).then(() => {
-if (BEZIAPP_USERNAME == null || BEZIAPP_USERNAME == "") {
- var username_report = "neprijavljen.uporabnik";
-} else {
- var username_report = BEZIAPP_USERNAME;
-}
-if (BEZIAPP_LOPOLIS_USERNAME == null || BEZIAPP_LOPOLIS_USERNAME == "") {
- var lopolis_username_report = "NEPRIJAVLJENUPORABNIK";
-} else {
- var lopolis_username_report = BEZIAPP_LOPOLIS_USERNAME;
-}
-if (BEZIAPP_LANGUAGE == null || BEZIAPP_LANGUAGE == "") {
- var language_report = "unspecified_language";
-} else {
- var language_report = BEZIAPP_LANGUAGE
-}
-if (BEZIAPP_THEME == null || BEZIAPP_THEME == "") {
- var theme_report = "unspecified_theme";
-} else {
- var theme_report = BEZIAPP_THEME;
-}
-if (BEZIAPP_ERRORREPORTING == null || BEZIAPP_ERRORREPORTING == "") {
- var errorreporting_report = "unspecified-errorreporting";
-} else {
- var errorreporting_report = BEZIAPP_ERRORREPORTING;
-}
-
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setDoNotTrack", true]);
- _paq.push(['setUserId', username_report]);
+
+ if (BEZIAPP_USERNAME == null || BEZIAPP_USERNAME == "") {
+ } else {
+ _paq.push(['setUserId', BEZIAPP_USERNAME]);
+ }
+ if (BEZIAPP_LOPOLIS_USERNAME == null || BEZIAPP_LOPOLIS_USERNAME == "") {
+ } else {
+ _paq.push(['setCustomVariable', 1, 'lopolis-username', BEZIAPP_LOPOLIS_USERNAME, 'visit']);
+ }
+ if (BEZIAPP_LANGUAGE == null || BEZIAPP_LANGUAGE == "") {
+ } else {
+ _paq.push(['setCustomVariable', 2, 'language', BEZIAPP_LANGUAGE, 'visit']);
+ }
+ if (BEZIAPP_THEME == null || BEZIAPP_THEME == "") {
+ } else {
+ _paq.push(['setCustomVariable', 3, 'theme', BEZIAPP_THEME, 'visit']);
+ }
+ if (BEZIAPP_ERRORREPORTING == null || BEZIAPP_ERRORREPORTING == "") {
+ } else {
+ _paq.push(['setCustomVariable', 4, 'errorreporting', BEZIAPP_ERRORREPORTING, 'visit']);
+ }
_paq.push(['enableHeartBeatTimer', 30]);
- _paq.push(['setCustomVariable', 1, 'lopolis-username', lopolis_username_report, 'visit']);
- _paq.push(['setCustomVariable', 2, 'language', language_report, 'visit']);
- _paq.push(['setCustomVariable', 3, 'theme', theme_report, 'visit']);
- _paq.push(['setCustomVariable', 4, 'errorreporting', errorreporting_report, 'visit']);
_paq.push(['setCustomVariable', 5, 'domain', window.location.host, 'visit']);
_paq.push(['trackPageView']);
_paq.push(['trackAllContentImpressions']);
diff --git a/assets/pages-src/misc/msg-compose-modal.bvr b/assets/pages-src/misc/msg-compose-modal.bvr
index 48afaaf..ac91b83 100644
--- a/assets/pages-src/misc/msg-compose-modal.bvr
+++ b/assets/pages-src/misc/msg-compose-modal.bvr
@@ -1,3 +1,4 @@
+<!-- @begin=html@ -->
<!-- Modal Structure -->
<div id="beziapp-new-message" class="modal modal-fixed-footer">
diff --git a/assets/pages-src/misc/navigation.bvr b/assets/pages-src/misc/navigation.bvr
index 2f0da71..3b5b1a5 100644
--- a/assets/pages-src/misc/navigation.bvr
+++ b/assets/pages-src/misc/navigation.bvr
@@ -1,3 +1,4 @@
+<!-- @begin=html@ -->
<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -8,7 +9,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/assets/root/sw.js.bvr b/assets/root/sw.js.bvr
index 45ac9dd..5f0979f 100644
--- a/assets/root/sw.js.bvr
+++ b/assets/root/sw.js.bvr
@@ -1,4 +1,5 @@
<@?i global@>
+// @begin=js@
// Change version to cause cache refresh
const static_cache_name = "site-static-<@?g app_version@>-<@?u 0 7 ?g latest_commit@>";
// commit before the latest is <@?g latest_commit@>
diff --git a/dist/cache_name.txt b/dist/cache_name.txt
index 0d968c3..5d3eada 100755
--- a/dist/cache_name.txt
+++ b/dist/cache_name.txt
@@ -2,4 +2,4 @@
-///site-static-1.0.15.0-beta-a0a53be|||
+///site-static-1.0.16.0-beta-f54120a|||
diff --git a/dist/js/app.js b/dist/js/app.js
index 783361e..fe857c9 100755
--- a/dist/js/app.js
+++ b/dist/js/app.js
@@ -2,8 +2,9 @@
-const app_version = "1.0.15.0-beta";
-const previous_commit = "a0a53bec5f61439dece140798235114a0164e26d";
+// @begin=html@
+const app_version = "1.0.16.0-beta";
+const previous_commit = "f54120aa036215dee0f02ff2c1a9ce20def75006";
const BEZIAPP_UPDATE_INTERVAL = 300; // update vsakih 300 sekund
if ("serviceWorker" in navigator) {
@@ -156,42 +157,32 @@ let promises_to_run_app = [
Promise.all(promises_to_run_app).then(() => {
-if (BEZIAPP_USERNAME == null || BEZIAPP_USERNAME == "") {
- var username_report = "neprijavljen.uporabnik";
-} else {
- var username_report = BEZIAPP_USERNAME;
-}
-if (BEZIAPP_LOPOLIS_USERNAME == null || BEZIAPP_LOPOLIS_USERNAME == "") {
- var lopolis_username_report = "NEPRIJAVLJENUPORABNIK";
-} else {
- var lopolis_username_report = BEZIAPP_LOPOLIS_USERNAME;
-}
-if (BEZIAPP_LANGUAGE == null || BEZIAPP_LANGUAGE == "") {
- var language_report = "unspecified_language";
-} else {
- var language_report = BEZIAPP_LANGUAGE
-}
-if (BEZIAPP_THEME == null || BEZIAPP_THEME == "") {
- var theme_report = "unspecified_theme";
-} else {
- var theme_report = BEZIAPP_THEME;
-}
-if (BEZIAPP_ERRORREPORTING == null || BEZIAPP_ERRORREPORTING == "") {
- var errorreporting_report = "unspecified-errorreporting";
-} else {
- var errorreporting_report = BEZIAPP_ERRORREPORTING;
-}
-
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setDoNotTrack", true]);
- _paq.push(['setUserId', username_report]);
+
+ if (BEZIAPP_USERNAME == null || BEZIAPP_USERNAME == "") {
+ } else {
+ _paq.push(['setUserId', BEZIAPP_USERNAME]);
+ }
+ if (BEZIAPP_LOPOLIS_USERNAME == null || BEZIAPP_LOPOLIS_USERNAME == "") {
+ } else {
+ _paq.push(['setCustomVariable', 1, 'lopolis-username', BEZIAPP_LOPOLIS_USERNAME, 'visit']);
+ }
+ if (BEZIAPP_LANGUAGE == null || BEZIAPP_LANGUAGE == "") {
+ } else {
+ _paq.push(['setCustomVariable', 2, 'language', BEZIAPP_LANGUAGE, 'visit']);
+ }
+ if (BEZIAPP_THEME == null || BEZIAPP_THEME == "") {
+ } else {
+ _paq.push(['setCustomVariable', 3, 'theme', BEZIAPP_THEME, 'visit']);
+ }
+ if (BEZIAPP_ERRORREPORTING == null || BEZIAPP_ERRORREPORTING == "") {
+ } else {
+ _paq.push(['setCustomVariable', 4, 'errorreporting', BEZIAPP_ERRORREPORTING, 'visit']);
+ }
_paq.push(['enableHeartBeatTimer', 30]);
- _paq.push(['setCustomVariable', 1, 'lopolis-username', lopolis_username_report, 'visit']);
- _paq.push(['setCustomVariable', 2, 'language', language_report, 'visit']);
- _paq.push(['setCustomVariable', 3, 'theme', theme_report, 'visit']);
- _paq.push(['setCustomVariable', 4, 'errorreporting', errorreporting_report, 'visit']);
_paq.push(['setCustomVariable', 5, 'domain', window.location.host, 'visit']);
_paq.push(['trackPageView']);
_paq.push(['trackAllContentImpressions']);
diff --git a/dist/js/lang/bundle.js b/dist/js/lang/bundle.js
index 7c0a4af..eecd450 100755
--- a/dist/js/lang/bundle.js
+++ b/dist/js/lang/bundle.js
@@ -4,7 +4,9 @@ let stringContainersd=document.querySelectorAll("x-dl:not(.langFinished)");for(i
let stringContainersS=document.querySelectorAll("x-su:not(.langFinished)");for(i=0;i<stringContainersS.length;i++){stringContainersS[i].innerHTML=S(stringContainersS[i].innerHTML);stringContainersS[i].classList.add("langFinished");stringContainersS[i].hidden=false;}
let stringContainersD=document.querySelectorAll("x-du:not(.langFinished)");for(i=0;i<stringContainersD.length;i++){stringContainersD[i].innerHTML=D(stringContainersD[i].innerHTML);stringContainersD[i].classList.add("langFinished");stringContainersD[i].hidden=false;}}
async function setLangConfigAndReload(){let promises_to_run=[localforage.setItem("chosenLang","en")];await Promise.all(promises_to_run);window.location.reload();}
-window.addEventListener("DOMContentLoaded",()=>{localforage.getItem("chosenLang").then((value)=>{if(value==null){setLangConfigAndReload();}else{chosenLang=value;}});refreshLangDOM();});const capitalize=(s)=>{if(typeof s!=='string')return''
+window.addEventListener("DOMContentLoaded",()=>{find_chosen_lang();});async function find_chosen_lang(){let value=await localforage.getItem("chosenLang");if(value==null){setLangConfigAndReload();}else{chosenLang=value;}
+refreshLangDOM();}
+const capitalize=(s)=>{if(typeof s!=='string')return''
return s.charAt(0).toUpperCase()+s.slice(1)}
var s=function(whatString){return getLang.s(whatString);};var d=function(whatString){return getLang.d(whatString);};var S=function(whatString){return getLang.S(whatString);};var D=function(whatString){return getLang.D(whatString);};var getLang={s:function(whatString){return langstrings[chosenLang][whatString];},S:function(whatString){return capitalize(langstrings[chosenLang][whatString]);},d:function(whatString){if(langstrings[chosenLang][whatString].slice(-1)!="."){return langstrings[chosenLang][whatString]+".";}else{return langstrings[chosenLang][whatString];}},D:function(whatString){if(langstrings[chosenLang][whatString].slice(-1)!="."){return capitalize(langstrings[chosenLang][whatString]+".");}else{return capitalize(langstrings[chosenLang][whatString]);}},}
-var langstrings={en:{miscTranslationLanguage:"English",miscTranslationAuthors:"Rok Štular","":"",monday:"monday",tuesday:"tuesday",wednesday:"wednesday",thursday:"thursday",friday:"friday",saturday:"saturday",sunday:"sunday",am:"am",pm:"pm",january:"january",february:"february",march:"march",april:"april",may:"may",june:"june",july:"july",august:"august",september:"september",october:"october",november:"november",december:"december",username:"username",password:"password",signIn:"sign in",bySigningInYouAgreeTo:"by signing in, you agree to",theToS:"the terms and conditions",and:"and",thePrivacyPolicy:"the privacy policy",loginFailed:"login failed",browserNotSupported:"bežiapp won't work on your device, unless you update your Internet browser",timetable:"timetable",gradings:"gradings",grades:"grades",teachers:"teachers",absences:"absences",messaging:"messaging",meals:"meals",about:"about",logout:"logout",settings:"settings",noPeriods:"no periods in selected week",date:"date",description:"description",add:"add",requestFailed:"request failed",addGrading:"add grading",noInternetConnection:"no internet connection",temporary:"temporary",useOnlyPermanentGrades:"use only permanent grades",useOnlyPermanentGradesNote1:"if checked, only permanent grades will be used in the average grade calculation",useOnlyPermanentGradesNote2:"if left unchecked, the calculation will include every available grade",type:"type",term:"term",teacher:"teacher",zakljucneGradess:"grades in red are final grades that appear on your end-of-year certificate and are decided by your teacher. They are not averages like grades in black. Should you have any questions or complaints about them, contact your teacher",name:"name",schoolSubject:"subject",tpMeetings:"TP meetings",from:"from",to:"to",cancel:"cancel",ok:"ok",noAbsences:"no absences in the chosen time period",lesson:"lesson",notProcessed:"not processed",authorizedAbsence:"authorized",unauthorizedAbsence:"unauthorized",doesNotCount:"does not count",loadingMessages:"Loading messages...",sendAMessage:"send a message",send:"send",recipient:"recipient",messageSubject:"subject",messageBody:"message body",removeImages:"remove images",note:"note",largeImagesNote:"GimB servers don't like large messages, so only very small images may be attached or your message will not be delivered",attachedImages:"attached images",encryptMessage:"Encrypt message",passwordForE2EE:"password for encrypting the message",messages:"messages",received:"received",sent:"sent",deleted:"deleted",messageStorageUsed:"message storage used in this folder",maxMessagesNote:"you can only have 120 messages per message folder, older messages will not be shown. Remember to delete read and sent messages regulary to avoid any issues.",loadMessageBody:"load message body",thisMessageWasEncrypted:"this message was encrypted",enterPassword:"enter password",decrypt:"decrypt",nameDirectoryNotSet:"name directory not set, sending unavailable",errorFetchingMessages:"error fetching messages",unableToReceiveTheMessage:"unable to receive the message",unableToDeleteTheMessage:"unable to delete the message",messageWasProbablySent:"message was probably sent, check the Sent folder to be sure",errorSendingMessage:"error sending message",imageAddedAsAnAttachment:"image added as an attachment",unableToReadDirectory:"unable to read directory of people",messageCouldNotBeSent:"message could to be sent",incorrectPassword:"incorrect password",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.",chatExternalInfo:"you have just received a chat. Chats are not supported by GimSIS, so you must reply by changing the subject to something else. Chat body: ",loginError:"login error",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.",logInToLopolis:"log in to Lopolis",logOutFromLopolis:"log out from Lopolis",readOnly:"read only",usage:"usage",mealsUsageNote:"click on a date to open the collapsible menu with choices and click on a specific meal to select it. Reload the meals when you're done and check the entries.",lunchesNote:"app was not tested with lunches in mind. Meals probably won't work with lunches and having a lunch subscription may even break its functionality.",mealNotShownNote:"editable meals are highlighted in gold, read-only meals are highlighted in grey and cannot be changed. Meals that provide no options for menus are not shown for clarity, same applies for days where there are no meals",mealsContributeNote:"you are welcome to contribute to the LopolisAPI project and add features, such as checkouts.",authenticationError:"authentication error",lopolisAPIConnectionError:"LopolisAPI server connection error",errorGettingMenus:"error getting menus",errorUnexpectedResponse:"error: unexpected response",requestForAuthenticationFailed:"request for authentication failed",credentialsMatch:"credentials match",errorSettingMeals:"error setting meals",mealSet:"meal set! Reload meals to be sure",selected:"selected",meal:"meal",version:"version",authors:"authors",translatorsForThisLanguage:"translators for this language",whatIsNew:"what's new",whatsNew:"what's new",reportABug:"report a bug",sendASuggestion:"send a suggestion",instagram:"instagram",changelog:"changelog",termsOfUse:"terms of use",termsOfUseDescription:"as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App",termsOfUseHarass:"to abuse, harass, threaten, impersonate or intimidate any person",termsOfUsePost:"to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person",termsOfUseCommunicate:"to communicate with the App developers or other users in abusive or offensive manner",termsOfUsePurpose:"for any purpose that is not permitted under the laws of the jurisdiction where you use the App",termsOfUseExploit:"to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user",termsOfUseSpam:"to create or transmit unwanted “spam” to any person or any URL",termsOfUseModify:"you may also not reverse engineer, modify or redistribute the app without written consent from the developers",terminationOfServices:"termination of services",terminationOfServicesDescriptions:"the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons",terminationOfServicesBreaching:"breaching the Terms of Service",terminationOfServicesRequest:"receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App",limitationOfLiability:"limitation of Liability",limitationOfLiabilityContent:"the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.",tosAreEffectiveAsOf:"the Terms of Service are effective as of",privacyImportant:"your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.",privacyOnlyAskedWhen:"we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.",privacyDataCollection:"we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.",privacySharingData:"we don’t share any personally identifying information publicly or with third-parties, except when required to by law",privacyExternalSites:"our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.",privacyRefuse:"you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.",privacyAcceptWithUse:"your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.",privacyEffectiveAsOf:"this policy is effective as of",language:"language",selectLanguage:"select desired language",languageSet:"language set, open another page for the changes to take effect",theme:"theme",themeLight:"light theme (default)",themeDark:"dark theme",themeNight:"night theme",selectTheme:"select a theme",triggerWarning:"the following switch enables additional settings, which some people may: disagree with, find annoying, be offended by them. By enabling the switch, you agree that you won't be triggered by any of the additional options and will not asociate any of the authors and/or their personal beliefs and opinions with additional options.",triggerAgreement:"i agree with terms and conditions stated above",triggerWarningSet:"additional settings toggled",additionalOptions:"additional settings",themeSet:"theme set, open another page for the changes to take effect",errorReportingSet:"error reporting preference set",errorReporting:"error reporting",on:"on",off:"off",selectErrorReporting:"should error reports be submitted to the developers?",gsecErrNet:"GimSIS connection error",gsecErrLogin:"GimSIS login error (bad password?), try logging out",gsecErrOther:"GimSIS unknown error, try logging out",videoconferences:"GimB meet"},sl:{miscTranslationLanguage:"slovenščina",miscTranslationAuthors:"Anton Luka Šijanec","":"",monday:"ponedeljek",tuesday:"torek",wednesday:"sreda",thursday:"četrtek",friday:"petek",saturday:"sobota",sunday:"nedelja",am:"dop.",pm:"pop.",january:"januar",february:"februar",march:"marec",april:"april",may:"maj",june:"junij",july:"julij",august:"avgust",september:"september",october:"oktober",november:"november",december:"december",username:"uporabniško ime",password:"geslo",signIn:"prijava",bySigningInYouAgreeTo:"s prijavo se strinjate s",theToS:"pogoji uporabe (v angleščini)",and:"in",thePrivacyPolicy:"politika zasebnosti (v angleščini)",loginFailed:"prijava je spodletela",browserNotSupported:"BežiApp ne bo deloval na vaši napravi, če ne posodobite vašega Internetnega brskalnika",noPeriods:"ni ur v izbranem tednu",timetable:"urnik",gradings:"ocenjevanja",grades:"ocene",teachers:"profesorji",absences:"izostanki",messaging:"sporočanje",meals:"obroki",about:"o",logout:"odjava",settings:"nastavitve",date:"datum",description:"opis",add:"dodaj",requestFailed:"zahteva spodletela",addGrading:"dodaj ocenjevanje",noInternetConnection:"ni povezave s spletom",temporary:"začasno",useOnlyPermanentGrades:"uporabi le stalne ocene",useOnlyPermanentGradesNote1:"če je označeno, bodo za izračun povprečja uporabljene le stalne ocene",useOnlyPermanentGradesNote2:"če pa je polje neoznačeno, pa se ob izračunu povprečne ocene upoštevajo vse ocene",type:"tip",term:"rok",teacher:"profesor",zakljucneGradess:"zaključne ocene, ki bodo na spričevalu, so označene z rdečo, povprečja ocen pa so v črni barvi. V kolikor imate kakršnekoli pritožbe ali vprašanja glede zaključnih ocen, povprašajte profesorja",name:"ime",schoolSubject:"predmet",tpMeetings:"govorilne ure",from:"od",to:"do",cancel:"prekliči",ok:"v redu",noAbsences:"ni izostankov v izbranem časovnem obdobju",lesson:"ura",notProcessed:"ni obdelano",authorizedAbsence:"opravičeno",unauthorizedAbsence:"neopravičeno",doesNotCount:"ne šteje",loadingMessages:"Nalagam sporočila...",sendAMessage:"pošlji sporočilo",send:"pošlji",recipient:"prejemnik",messageSubject:"zadeva",messageBody:"telo",removeImages:"odstrani slike",note:"opomba",largeImagesNote:"GimB strežniki ne marajo velikih sporočil, zato lahko pošiljate le zelo majhne slike, v nasprotnem primeru sporočilo ne bo dostavljeno",attachedImages:"pripete slike",encryptMessage:"Šifriraj sporočilo",passwordForE2EE:"geslo za šifriranje sporočila",messages:"sporočila",received:"prejeta",sent:"poslana",deleted:"izbrisana",messageStorageUsed:"zasedenost shrambe sporočil v tej mapi",maxMessagesNote:"v vsaki mapi imate lahko največ 120 sporočil. Starejša sporočila ne bodo prikazana. Redno brišite sporočila, da se izognete morebitnim težavam.",loadMessageBody:"naloži telo sporočila",thisMessageWasEncrypted:"to sporočilo je šifrirano",enterPassword:"vnesite geslo",decrypt:"dešifriraj",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",messageWasProbablySent:"sporočilo je bilo verjetno poslano, prepričajte se in preverite mapo s poslanimi sporočili",errorSendingMessage:"sporočila ni bilo mogoče poslati",imageAddedAsAnAttachment:"slika dodana kot priloga",unableToReadDirectory:"imenika ni bilo mogoče prebrati",messageCouldNotBeSent:"sporočila ni bilo mogoče poslati",incorrectPassword:"nepravilno geslo",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",chatExternalInfo:"dobili ste kratko sporočilo v standardu, ki ga GimSIS ne podpira. Pri odgovarjanju spremenite zadevo. Vsebina sporočila: ",loginError:"napaka pri prijavi",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.",logInToLopolis:"prijava v Lopolis",logOutFromLopolis:"odjava iz Lopolisa",readOnly:"samo za branje",usage:"uporaba",mealsUsageNote:"kliknite na datum za prikaz menijev, nato pa si enega izberite s klikom na ime menija. Po nastavitvi menijev ponovno naložite menije in se prepričajte o pravilnih nastavitvah.",lunchesNote:"aplikacija ni testirana za naročanje na kosila, zato verjetno to ne deluje. Če ste naročeni na kosila lahko naročanje na menije sploh ne deluje ali pa deluje narobe.",mealNotShownNote:"obroki, označeni z zlato so nastavljivi, tisti, označeni s sivo, niso, če pa pri kakšnem dnevu obroka ni, pa pomeni, da ga ni moč nastaviti ali pa da ne obrok ne obstaja",mealsContributeNote:"vabimo vas k urejanju LopolisAPI programa za upravljanje z meniji.",authenticationError:"napaka avtentikacije",lopolisAPIConnectionError:"napaka povezave na LopolisAPI strežnik",errorGettingMenus:"napaka branja menijev",errorUnexpectedResponse:"napaka: nepričakovan odgovor",requestForAuthenticationFailed:"zahteva za avtentikacijo ni uspela",credentialsMatch:"prijavni podatki so pravilni",errorSettingMeals:"napaka pri nastavljanju menijev",mealSet:"obrok nastavljen! osvežite obroke in se prepričajte sami",selected:"izbrano",meal:"obrok",version:"različica",authors:"avtorji",translatorsForThisLanguage:"prevajalci izbranega jezika",whatIsNew:"kaj je novega",whatsNew:"kaj je novega",reportABug:"prijavite napako",sendASuggestion:"pošljite pripombo/predlog/pohvalo/pritožbo",instagram:"instagram",changelog:"dnevnik sprememb",termsOfUse:"terms of use",termsOfUseDescription:"as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App",termsOfUseHarass:"to abuse, harass, threaten, impersonate or intimidate any person",termsOfUsePost:"to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person",termsOfUseCommunicate:"to communicate with the App developers or other users in abusive or offensive manner",termsOfUsePurpose:"for any purpose that is not permitted under the laws of the jurisdiction where you use the App",termsOfUseExploit:"to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user",termsOfUseSpam:"to create or transmit unwanted “spam” to any person or any URL",termsOfUseModify:"you may also not reverse engineer, modify or redistribute the app without written consent from the developers",terminationOfServices:"termination of services",terminationOfServicesDescriptions:"the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons",terminationOfServicesBreaching:"breaching the Terms of Service",terminationOfServicesRequest:"receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App",limitationOfLiability:"limitation of Liability",limitationOfLiabilityContent:"the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.",tosAreEffectiveAsOf:"the Terms of Service are effective as of",privacyImportant:"your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.",privacyOnlyAskedWhen:"we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.",privacyDataCollection:"we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.",privacySharingData:"we don’t share any personally identifying information publicly or with third-parties, except when required to by law",privacyExternalSites:"our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.",privacyRefuse:"you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.",privacyAcceptWithUse:"your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.",privacyEffectiveAsOf:"this policy is effective as of",language:"jezik",selectLanguage:"izberite željen jezik",languageSet:"jezik nastavljen, odprite neko drugo stran da se pokažejo spremembe",theme:"izgled",themeLight:"svetel izgled (privzeto)",themeDark:"temen izgled",themeNight:"nočni izgled",themeSet:"izgled nastavljen, odprite neko drugo stran da se spremembe uveljavijo",selectTheme:"izberite željen izgled",errorReportingSet:"nastavitev pošiljanja napak izbrana",errorReporting:"pošiljanje napak",on:"vklopljeno",off:"izklopljeno",selectErrorReporting:"ali naj so napake v aplikaciji posredovane razvijalcem?",triggerWarning:"spodnji gumb omogoči dodatne možnosti, ki lahko razburijo/vznevoljijo nekatere uporabnike. Če omogočite stikalo, se strinjate, da avtorjev in/ali njihovih osebnih prepričanj ne boste povezovali s katerokoli od dodatnih omogočenih možnosti",triggerAgreement:"strinjam se z zgoraj navedenimi pogoji",triggerWarningSet:"spremenili ste stanje dodatnih nastavitev",additionalOptions:"dodatne nastavitve",gsecErrNet:"napaka povezave na GimSIS",gsecErrLogin:"prijava v GimSIS ni uspela (napačno geslo?), poskusite se odjaviti",gsecErrOther:"neznana napaka GimSISa, poskusite se odjaviti",videoconferences:"GimB konference"}} \ No newline at end of file
+var langstrings={en:{miscTranslationLanguage:"English",miscTranslationAuthors:"Rok Štular","":"",monday:"monday",tuesday:"tuesday",wednesday:"wednesday",thursday:"thursday",friday:"friday",saturday:"saturday",sunday:"sunday",am:"am",pm:"pm",january:"january",february:"february",march:"march",april:"april",may:"may",june:"june",july:"july",august:"august",september:"september",october:"october",november:"november",december:"december",username:"username",password:"password",signIn:"sign in",bySigningInYouAgreeTo:"by signing in, you agree to",theToS:"the terms and conditions",and:"and",thePrivacyPolicy:"the privacy policy",loginFailed:"login failed",browserNotSupported:"bežiapp won't work on your device, unless you update your Internet browser",timetable:"timetable",gradings:"gradings",grades:"grades",teachers:"teachers",absences:"absences",messaging:"messaging",meals:"meals",about:"about",logout:"logout",settings:"settings",noPeriods:"no periods in selected week",date:"date",description:"description",add:"add",requestFailed:"request failed",addGrading:"add grading",noInternetConnection:"no internet connection",temporary:"temporary",useOnlyPermanentGrades:"use only permanent grades",useOnlyPermanentGradesNote1:"if checked, only permanent grades will be used in the average grade calculation",useOnlyPermanentGradesNote2:"if left unchecked, the calculation will include every available grade",type:"type",term:"term",teacher:"teacher",zakljucneGradess:"grades in red are final grades that appear on your end-of-year certificate and are decided by your teacher. They are not averages like grades in black. Should you have any questions or complaints about them, contact your teacher",name:"name",schoolSubject:"subject",tpMeetings:"TP meetings",from:"from",to:"to",cancel:"cancel",ok:"ok",noAbsences:"no absences in the chosen time period",lesson:"lesson",notProcessed:"not processed",authorizedAbsence:"authorized",unauthorizedAbsence:"unauthorized",doesNotCount:"does not count",loadingMessages:"Loading messages...",sendAMessage:"send a message",send:"send",recipient:"recipient",messageSubject:"subject",messageBody:"message body",removeImages:"remove images",note:"note",largeImagesNote:"GimB servers don't like large messages, so only very small images may be attached or your message will not be delivered",attachedImages:"attached images",encryptMessage:"Encrypt message",passwordForE2EE:"password for encrypting the message",messages:"messages",received:"received",sent:"sent",deleted:"deleted",messageStorageUsed:"message storage used in this folder",maxMessagesNote:"you can only have 120 messages per message folder, older messages will not be shown. Remember to delete read and sent messages regulary to avoid any issues.",loadMessageBody:"load message body",thisMessageWasEncrypted:"this message was encrypted",enterPassword:"enter password",decrypt:"decrypt",nameDirectoryNotSet:"name directory not set, sending unavailable",errorFetchingMessages:"error fetching messages",unableToReceiveTheMessage:"unable to receive the message",unableToDeleteTheMessage:"unable to delete the message",messageWasProbablySent:"message was probably sent, check the Sent folder to be sure",errorSendingMessage:"error sending message",imageAddedAsAnAttachment:"image added as an attachment",unableToReadDirectory:"unable to read directory of people",messageCouldNotBeSent:"message could to be sent",incorrectPassword:"incorrect password",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.",chatExternalInfo:"you have just received a chat. Chats are not supported by GimSIS, so you must reply by changing the subject to something else. Chat body: ",loginError:"login error",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.",logInToLopolis:"log in to Lopolis",logOutFromLopolis:"log out from Lopolis",readOnly:"read only",usage:"usage",mealsUsageNote:"click on a date to open the collapsible menu with choices and click on a specific meal to select it. Reload the meals when you're done and check the entries.",lunchesNote:"app was not tested with lunches in mind. Meals probably won't work with lunches and having a lunch subscription may even break its functionality.",mealNotShownNote:"editable meals are highlighted in gold, read-only meals are highlighted in grey and cannot be changed. Meals that provide no options for menus are not shown for clarity, same applies for days where there are no meals",mealsContributeNote:"you are welcome to contribute to the LopolisAPI project and add features, such as checkouts.",authenticationError:"authentication error",lopolisAPIConnectionError:"LopolisAPI server connection error",errorGettingMenus:"error getting menus",errorUnexpectedResponse:"error: unexpected response",requestForAuthenticationFailed:"request for authentication failed",credentialsMatch:"credentials match",errorSettingMeals:"error setting meals",mealSet:"meal set! Reload meals to be sure",selected:"selected",meal:"meal",checkedOut:"checked out",checkedIn:"checked in",successfulCheckingInOut:"successfully checked in/out",errorCheckingInOut:"failed to check in/out",version:"version",authors:"authors",translatorsForThisLanguage:"translators for this language",whatIsNew:"what's new",whatsNew:"what's new",reportABug:"report a bug",sendASuggestion:"send a suggestion",instagram:"instagram",changelog:"changelog",termsOfUse:"terms of use",termsOfUseDescription:"as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App",termsOfUseHarass:"to abuse, harass, threaten, impersonate or intimidate any person",termsOfUsePost:"to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person",termsOfUseCommunicate:"to communicate with the App developers or other users in abusive or offensive manner",termsOfUsePurpose:"for any purpose that is not permitted under the laws of the jurisdiction where you use the App",termsOfUseExploit:"to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user",termsOfUseSpam:"to create or transmit unwanted “spam” to any person or any URL",termsOfUseModify:"you may also not reverse engineer, modify or redistribute the app without written consent from the developers",terminationOfServices:"termination of services",terminationOfServicesDescriptions:"the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons",terminationOfServicesBreaching:"breaching the Terms of Service",terminationOfServicesRequest:"receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App",limitationOfLiability:"limitation of Liability",limitationOfLiabilityContent:"the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.",tosAreEffectiveAsOf:"the Terms of Service are effective as of",privacyImportant:"your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.",privacyOnlyAskedWhen:"we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.",privacyDataCollection:"we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.",privacySharingData:"we don’t share any personally identifying information publicly or with third-parties, except when required to by law",privacyExternalSites:"our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.",privacyRefuse:"you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.",privacyAcceptWithUse:"your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.",privacyEffectiveAsOf:"this policy is effective as of",language:"language",selectLanguage:"select desired language",languageSet:"language set, open another page for the changes to take effect",theme:"theme",themeLight:"light theme (default)",themeDark:"dark theme",themeNight:"night theme",selectTheme:"select a theme",triggerWarning:"the following switch enables additional settings, which some people may: disagree with, find annoying, be offended by them. By enabling the switch, you agree that you won't be triggered by any of the additional options and will not asociate any of the authors and/or their personal beliefs and opinions with additional options.",triggerAgreement:"i agree with terms and conditions stated above",triggerWarningSet:"additional settings toggled",additionalOptions:"additional settings",themeSet:"theme set, open another page for the changes to take effect",errorReportingSet:"error reporting preference set",errorReporting:"error reporting",on:"on",off:"off",selectErrorReporting:"should error reports be submitted to the developers?",gsecErrNet:"GimSIS connection error",gsecErrLogin:"GimSIS login error (bad password?), try logging out",gsecErrOther:"GimSIS unknown error, try logging out",videoconferences:"GimB meet"},sl:{miscTranslationLanguage:"slovenščina",miscTranslationAuthors:"Anton Luka Šijanec","":"",monday:"ponedeljek",tuesday:"torek",wednesday:"sreda",thursday:"četrtek",friday:"petek",saturday:"sobota",sunday:"nedelja",am:"dop.",pm:"pop.",january:"januar",february:"februar",march:"marec",april:"april",may:"maj",june:"junij",july:"julij",august:"avgust",september:"september",october:"oktober",november:"november",december:"december",username:"uporabniško ime",password:"geslo",signIn:"prijava",bySigningInYouAgreeTo:"s prijavo se strinjate s",theToS:"pogoji uporabe (v angleščini)",and:"in",thePrivacyPolicy:"politika zasebnosti (v angleščini)",loginFailed:"prijava je spodletela",browserNotSupported:"BežiApp ne bo deloval na vaši napravi, če ne posodobite vašega Internetnega brskalnika",noPeriods:"ni ur v izbranem tednu",timetable:"urnik",gradings:"ocenjevanja",grades:"ocene",teachers:"profesorji",absences:"izostanki",messaging:"sporočanje",meals:"obroki",about:"o",logout:"odjava",settings:"nastavitve",date:"datum",description:"opis",add:"dodaj",requestFailed:"zahteva spodletela",addGrading:"dodaj ocenjevanje",noInternetConnection:"ni povezave s spletom",temporary:"začasno",useOnlyPermanentGrades:"uporabi le stalne ocene",useOnlyPermanentGradesNote1:"če je označeno, bodo za izračun povprečja uporabljene le stalne ocene",useOnlyPermanentGradesNote2:"če pa je polje neoznačeno, pa se ob izračunu povprečne ocene upoštevajo vse ocene",type:"tip",term:"rok",teacher:"profesor",zakljucneGradess:"zaključne ocene, ki bodo na spričevalu, so označene z rdečo, povprečja ocen pa so v črni barvi. V kolikor imate kakršnekoli pritožbe ali vprašanja glede zaključnih ocen, povprašajte profesorja",name:"ime",schoolSubject:"predmet",tpMeetings:"govorilne ure",from:"od",to:"do",cancel:"prekliči",ok:"v redu",noAbsences:"ni izostankov v izbranem časovnem obdobju",lesson:"ura",notProcessed:"ni obdelano",authorizedAbsence:"opravičeno",unauthorizedAbsence:"neopravičeno",doesNotCount:"ne šteje",loadingMessages:"Nalagam sporočila...",sendAMessage:"pošlji sporočilo",send:"pošlji",recipient:"prejemnik",messageSubject:"zadeva",messageBody:"telo",removeImages:"odstrani slike",note:"opomba",largeImagesNote:"GimB strežniki ne marajo velikih sporočil, zato lahko pošiljate le zelo majhne slike, v nasprotnem primeru sporočilo ne bo dostavljeno",attachedImages:"pripete slike",encryptMessage:"Šifriraj sporočilo",passwordForE2EE:"geslo za šifriranje sporočila",messages:"sporočila",received:"prejeta",sent:"poslana",deleted:"izbrisana",messageStorageUsed:"zasedenost shrambe sporočil v tej mapi",maxMessagesNote:"v vsaki mapi imate lahko največ 120 sporočil. Starejša sporočila ne bodo prikazana. Redno brišite sporočila, da se izognete morebitnim težavam.",loadMessageBody:"naloži telo sporočila",thisMessageWasEncrypted:"to sporočilo je šifrirano",enterPassword:"vnesite geslo",decrypt:"dešifriraj",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",messageWasProbablySent:"sporočilo je bilo verjetno poslano, prepričajte se in preverite mapo s poslanimi sporočili",errorSendingMessage:"sporočila ni bilo mogoče poslati",imageAddedAsAnAttachment:"slika dodana kot priloga",unableToReadDirectory:"imenika ni bilo mogoče prebrati",messageCouldNotBeSent:"sporočila ni bilo mogoče poslati",incorrectPassword:"nepravilno geslo",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",chatExternalInfo:"dobili ste kratko sporočilo v standardu, ki ga GimSIS ne podpira. Pri odgovarjanju spremenite zadevo. Vsebina sporočila: ",loginError:"napaka pri prijavi",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.",logInToLopolis:"prijava v Lopolis",logOutFromLopolis:"odjava iz Lopolisa",readOnly:"samo za branje",usage:"uporaba",mealsUsageNote:"kliknite na datum za prikaz menijev, nato pa si enega izberite s klikom na ime menija. Po nastavitvi menijev ponovno naložite menije in se prepričajte o pravilnih nastavitvah.",lunchesNote:"aplikacija ni testirana za naročanje na kosila, zato verjetno to ne deluje. Če ste naročeni na kosila lahko naročanje na menije sploh ne deluje ali pa deluje narobe.",mealNotShownNote:"obroki, označeni z zlato so nastavljivi, tisti, označeni s sivo, niso, če pa pri kakšnem dnevu obroka ni, pa pomeni, da ga ni moč nastaviti ali pa da ne obrok ne obstaja",mealsContributeNote:"vabimo vas k urejanju LopolisAPI programa za upravljanje z meniji.",authenticationError:"napaka avtentikacije",lopolisAPIConnectionError:"napaka povezave na LopolisAPI strežnik",errorGettingMenus:"napaka branja menijev",errorUnexpectedResponse:"napaka: nepričakovan odgovor",requestForAuthenticationFailed:"zahteva za avtentikacijo ni uspela",credentialsMatch:"prijavni podatki so pravilni",errorSettingMeals:"napaka pri nastavljanju menijev",mealSet:"obrok nastavljen! osvežite obroke in se prepričajte sami",selected:"izbrano",meal:"obrok",checkedOut:"odjavljen",checkedIn:"prijavljen",errorCheckingInOut:"prijava/odjava na obrok NI uspela",successfulCheckingInOut:"prijava/odjava na obrok je uspela",version:"različica",authors:"avtorji",translatorsForThisLanguage:"prevajalci izbranega jezika",whatIsNew:"kaj je novega",whatsNew:"kaj je novega",reportABug:"prijavite napako",sendASuggestion:"pošljite pripombo/predlog/pohvalo/pritožbo",instagram:"instagram",changelog:"dnevnik sprememb",termsOfUse:"terms of use",termsOfUseDescription:"as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App",termsOfUseHarass:"to abuse, harass, threaten, impersonate or intimidate any person",termsOfUsePost:"to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person",termsOfUseCommunicate:"to communicate with the App developers or other users in abusive or offensive manner",termsOfUsePurpose:"for any purpose that is not permitted under the laws of the jurisdiction where you use the App",termsOfUseExploit:"to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user",termsOfUseSpam:"to create or transmit unwanted “spam” to any person or any URL",termsOfUseModify:"you may also not reverse engineer, modify or redistribute the app without written consent from the developers",terminationOfServices:"termination of services",terminationOfServicesDescriptions:"the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons",terminationOfServicesBreaching:"breaching the Terms of Service",terminationOfServicesRequest:"receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App",limitationOfLiability:"limitation of Liability",limitationOfLiabilityContent:"the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.",tosAreEffectiveAsOf:"the Terms of Service are effective as of",privacyImportant:"your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.",privacyOnlyAskedWhen:"we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.",privacyDataCollection:"we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.",privacySharingData:"we don’t share any personally identifying information publicly or with third-parties, except when required to by law",privacyExternalSites:"our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.",privacyRefuse:"you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.",privacyAcceptWithUse:"your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.",privacyEffectiveAsOf:"this policy is effective as of",language:"jezik",selectLanguage:"izberite željen jezik",languageSet:"jezik nastavljen, odprite neko drugo stran da se pokažejo spremembe",theme:"izgled",themeLight:"svetel izgled (privzeto)",themeDark:"temen izgled",themeNight:"nočni izgled",themeSet:"izgled nastavljen, odprite neko drugo stran da se spremembe uveljavijo",selectTheme:"izberite željen izgled",errorReportingSet:"nastavitev pošiljanja napak izbrana",errorReporting:"pošiljanje napak",on:"vklopljeno",off:"izklopljeno",selectErrorReporting:"ali naj so napake v aplikaciji posredovane razvijalcem?",triggerWarning:"spodnji gumb omogoči dodatne možnosti, ki lahko razburijo/vznevoljijo nekatere uporabnike. Če omogočite stikalo, se strinjate, da avtorjev in/ali njihovih osebnih prepričanj ne boste povezovali s katerokoli od dodatnih omogočenih možnosti",triggerAgreement:"strinjam se z zgoraj navedenimi pogoji",triggerWarningSet:"spremenili ste stanje dodatnih nastavitev",additionalOptions:"dodatne nastavitve",gsecErrNet:"napaka povezave na GimSIS",gsecErrLogin:"prijava v GimSIS ni uspela (napačno geslo?), poskusite se odjaviti",gsecErrOther:"neznana napaka GimSISa, poskusite se odjaviti",videoconferences:"GimB konference"}} \ No newline at end of file
diff --git a/dist/js/lopolisc.js b/dist/js/lopolisc.js
new file mode 100755
index 0000000..32c3f82
--- /dev/null
+++ b/dist/js/lopolisc.js
@@ -0,0 +1,52 @@
+
+function getStringBetween(string,start,end){return string.split(start).pop().split(end)[0];}
+const LOPOLIS_URL="https://lopolis.gimb.tk/";const LOPOLISC_ERR_NET="LOPOLSIC NETWORK ERROR (ajax error)";const LOPOLISC_ERR_NET_POSTBACK_GET="LOPOLISC NETWORK ERROR (ajax error) "+"in postback GET";const LOPOLISC_ERR_LOGIN="LOPOLISC LOGIN ERROR";const LOPOLISC_ERR_NET_POSTBACK_POST="LOPOLISC NETWORK ERROR (ajax error) "+"in postback POST";const LOPOLISC_ERR_NET_POSTBACK_POST_IN_POSTBACK="LOPOLISC NETWORK ERROR $$$";const LOPOLISC_ERR_NOTAPPLIED="LOPOLISC DATA NOT APPLIED ERROR";const LOPOLISC_SIGNATURE="lopolisc.js neuradni API - anton<at>sijanec.eu";const LOPOLISC_ERR_OUT_OF_RETRIES="LOPOLISC ERROR NI VEČ POSKUSOV!";class lopolisc{constructor(){}
+parseAndPost(inputHTML,userParams,formId=null,useDiffAction=null){return new Promise((resolve,reject)=>{let parser=new DOMParser();let parsed=parser.parseFromString(inputHTML,"text/html");var form;if(formId==null){form=parsed.getElementsByTagName("form")[0];}else{form=parsed.getElementById(formId);}
+var params={};var otherParams=$(form).serializeArray();for(const input of otherParams){if(!(input.name in params)){params[input.name]=input.value;}}
+for(const[key,value]of Object.entries(userParams)){params[key]=value;}
+var action;if(useDiffAction==null||useDiffAction==false){action=new URL($(form).attr("action"),LOPOLIS_URL);}else{action=useDiffAction;}
+params["programska-oprema"]=LOPOLISC_SIGNATURE;$.ajax({xhrFields:{withCredentials:true},crossDomain:true,url:action,cache:false,type:"POST",data:params,dataType:"text",maxRetries:3,success:(postData,textStatus,xhr)=>{resolve({data:postData,textStatus:textStatus,code:xhr.status});},error:()=>{reject(new Error(LOPOLISC_ERR_NET_POSTBACK_POST));}});});}
+postback(getUrl,params={},formId=null,useDiffAction=null){return new Promise((resolve,reject)=>{$.ajax({xhrFields:{withCredentials:true},crossDomain:true,url:getUrl,cache:false,type:"GET",dataType:"html",success:(data)=>{if(useDiffAction===true){useDiffAction=getUrl;}
+this.parseAndPost(data,params,formId,useDiffAction).then((value)=>{resolve(value);}).catch((e)=>{reject(new Error(LOPOLISC_ERR_NET_POSTBACK_POST_IN_POSTBACK));});},error:()=>{reject(new Error(LOPOLISC_ERR_NET_POSTBACK_GET));}});});}
+getUserData(){return new Promise((resolve,reject)=>{$.ajax({xhrFields:{withCredentials:true},crossDomain:true,url:LOPOLIS_URL+"?MeniID=2",cache:false,type:"GET",dataType:"html",success:(data)=>{if(data.includes("Dostop ni dovoljen")){resolve(false);return;}
+let parser=new DOMParser();let p=parser.parseFromString(data,"text/html");let uporabnik={u:p.getElementsByClassName("obrazecPovdarjen")[0].innerText.trim(),n:p.getElementsByClassName("obrazecPovdarjen")[1].innerText.trim(),e:p.getElementById("Email").value}
+resolve(uporabnik);},error:()=>{reject(new Error(LOPOLISC_ERR_NET));}});});}
+logout(){return new Promise((resolve,reject)=>{this.postback(LOPOLIS_URL+"Uporab/Prijava",{},null,false).then((response)=>{resolve(true);});});}
+login(usernameToLogin,passwordToLogin){return new Promise(async function(resolve,reject){let l=new lopolisc();var uporabnik=await l.getUserData();if(uporabnik!=false){if(uporabnik.u=usernameToLogin){resolve(true);return;}else{await this.logout();}}
+var dataToSend={"Uporabnik":usernameToLogin,"Geslo":passwordToLogin,"OsveziURL":"https://pornhub.com/\"; lopolis=\"boljsi od easistenta",};l.postback(LOPOLIS_URL+"Uporab/Prijava",dataToSend,null,true).then((response)=>{let parser=new DOMParser();let parsed=parser.parseFromString(response.data,"text/html");if(parsed.getElementById("divPrijavaOsvezi")!=null){resolve(true);}
+reject(new Error(LOPOLISC_ERR_LOGIN));});});}
+fetchCheckouts(date_object=null){if(date_object==null){date_object=new Date();}
+return new Promise((resolve,reject)=>{var dataToSend={"MesecModel.Mesec":String(date_object.getMonth()+1),"MesecModel.Leto":String(date_object.getFullYear()),"Ukaz":""};this.postback(LOPOLIS_URL+"Prehrana/Odjava",dataToSend,null,true).then((response)=>{let parser=new DOMParser();let parsed=parser.parseFromString(response.data,"text/html");let checkouts={};for(const element of parsed.getElementsByTagName("tbody")[0].getElementsByTagName("tr")){let date_idx=element.getElementsByTagName("input")[2].value;checkouts[date_idx]={checked:element.getElementsByTagName("input")[0].checked,readonly:element.getElementsByTagName("input")[0].disabled,index:Number(getStringBetween(element.getElementsByTagName("input")[0].name,"[","]")),"OsebaModel.ddlOseba":parsed.getElementsByTagName("option")[0].value,"OsebaModel.OsebaID":parsed.getElementById("OsebaModel_OsebaID").value,"OsebaModel.OsebaTipID":parsed.getElementById("OsebaModel_OsebaTipID").value,"OsebaModel.UstanovaID":parsed.getElementById("OsebaModel_UstanovaID").value,"MesecModel.Mesec":parsed.getElementById("MesecModel_Mesec").value,"MesecModel.Leto":parsed.getElementById("MesecModel_Leto").value}
+checkouts[date_idx][element.getElementsByTagName("input")[2].name]=String(element.getElementsByTagName("input")[2].value);checkouts[date_idx][element.getElementsByTagName("input")[3].name]=String(element.getElementsByTagName("input")[3].value);checkouts[date_idx][element.getElementsByTagName("input")[4].name]=String(element.getElementsByTagName("input")[4].value);}
+resolve(checkouts);});});}
+fetchAllMeals(koliko=3){return new Promise(async function(resolve,reject){let date=new Date();let podatki={};while(koliko-->0){let l=new lopolisc();let resp=await l.fetchMeals(date);podatki={...podatki,...resp};date.setMonth(date.getMonth()+1);}
+resolve(podatki);});}
+fetchAllCheckouts(koliko=3){return new Promise(async function(resolve,reject){let date=new Date();let podatki={};while(koliko-->0){let l=new lopolisc();let resp=await l.fetchCheckouts(date);podatki={...podatki,...resp};date.setMonth(date.getMonth()+1);}
+resolve(podatki);});}
+setCheckouts(odjava_objects){let odjava_objects_sorted={};for(const[odjava_da,odjava_ob]of Object.entries(odjava_objects)){let yearmonth_combo=odjava_da.substring(0,7);if(odjava_objects_sorted[yearmonth_combo]==undefined){odjava_objects_sorted[yearmonth_combo]={};}
+odjava_objects_sorted[yearmonth_combo][odjava_da]=odjava_ob;}
+if(Object.entries(odjava_objects_sorted).length<1){return false;}else if(Object.entries(odjava_objects_sorted).length>1){var response;for(const[ym_combo,odj_ob]of Object.entries(odjava_objects_sorted)){response=this.setCheckouts(odj_ob);}
+return response;}
+return new Promise((resolve,reject)=>{var dataToSend={"Ukaz":"Shrani"};for(const[odjava_da,odjava_object]of Object.entries(odjava_objects)){for(const[index,property]of Object.entries(odjava_object)){dataToSend[index]=property;}
+dataToSend["OdjavaItems["+odjava_object.index+"].CheckOut"]=String(odjava_object.checked);}
+this.postback(LOPOLIS_URL+"Prehrana/Odjava",dataToSend,null,true).then((response)=>{let parser=new DOMParser();let parsed=parser.parseFromString(response.data,"text/html");for(const[od_date,odjava_object]of Object.entries(odjava_objects)){if(!(parsed.getElementById("OdjavaItems_"+odjava_object.index+"__CheckOut").checked==odjava_object.checked)){reject(LOPOLISC_ERR_NOTAPPLIED);}}
+resolve(true);});});}
+fetchMeals(date_object=null,retried=3){if(date_object==null){date_object=new Date();}
+return new Promise((resolve,reject)=>{var meals={};var dataToSend={"Ukaz":"","MesecModel.Mesec":String(date_object.getMonth()+1),"API-METODA":"fetchMeals","MesecModel.Leto":String(date_object.getFullYear())}
+this.postback(LOPOLIS_URL+"?MeniID=78",dataToSend,"form1",false).then((response)=>{let parser=new DOMParser();let parsed=parser.parseFromString(response.data,"text/html");for(const element of parsed.getElementsByTagName("tbody")[0].getElementsByTagName("tr")){let menuoptions=[];let is_any_selected=false;for(const opt of element.getElementsByTagName("select")[0].options){if(opt.value.length>0||1==1){menuoptions.push({value:opt.value,text:opt.innerText,selected:opt.selected});}
+if(opt.selected){is_any_selected=true;}}
+if(!is_any_selected){menuoptions[0].selected=true;}
+let date_idx=element.getElementsByTagName("input")[0].value;meals[date_idx]={meal:element.getElementsByTagName("td")[1].innerText.trim(),"menu-type":element.getElementsByTagName("td")[2].innerText.trim(),location:element.getElementsByTagName("td")[3].innerText.trim(),readonly:element.getElementsByTagName("select")[0].disabled,menu_options:menuoptions,index:Number(getStringBetween(element.getElementsByTagName("input")[0].name,"[","]")),"OsebaModel.ddlOseba":parsed.getElementsByTagName("option")[0].value,"OsebaModel.OsebaID":parsed.getElementById("OsebaModel_OsebaID").value,"OsebaModel.OsebaTipID":parsed.getElementById("OsebaModel_OsebaTipID").value,"OsebaModel.UstanovaID":parsed.getElementById("OsebaModel_UstanovaID").value,"MesecModel.Mesec":parsed.getElementById("MesecModel_Mesec").value,"MesecModel.Leto":parsed.getElementById("MesecModel_Leto").value}
+meals[date_idx][element.getElementsByTagName("input")[0].name]=String(element.getElementsByTagName("input")[0].value);meals[date_idx][element.getElementsByTagName("input")[1].name]=String(element.getElementsByTagName("input")[1].value);meals[date_idx][element.getElementsByTagName("input")[2].name]=String(element.getElementsByTagName("input")[2].value);}
+resolve(meals);}).catch((err)=>{if(retried<=0){reject(new Error(LOPOLISC_ERR_OUT_OF_RETRIES));}else{resolve(this.fetchMeals(date_object,retried-1));}});});}
+setMeals(meal_objects){let meal_objects_sorted={};for(const[meal_da,meal_ob]of Object.entries(meal_objects)){let yearmonth_combo=meal_da.substring(0,7);if(meal_objects_sorted[yearmonth_combo]==undefined){meal_objects_sorted[yearmonth_combo]={};}
+meal_objects_sorted[yearmonth_combo][meal_da]=meal_ob;}
+if(Object.entries(meal_objects_sorted).length<1){return false;}else if(Object.entries(meal_objects_sorted).length>1){var response;for(const[ym_combo,meal_ob]of Object.entries(meal_objects_sorted)){response=this.setMeals(meal_ob);}
+return response;}
+return new Promise((resolve,reject)=>{var dataToSend={"Ukaz":"Shrani"};for(const[meal_date,meal_object]of Object.entries(meal_objects)){for(const[index,property]of Object.entries(meal_object)){dataToSend[index]=String(property);}
+for(const menu_option of meal_object.menu_options){if(menu_option.selected){dataToSend["PrednarocanjeItems["+meal_object.index+"].MeniIDSkupinaID"]=menu_option.value;}}}
+this.postback(LOPOLIS_URL+"Prehrana/Prednarocanje",dataToSend,null,true).then((response)=>{let parser=new DOMParser();let parsed=parser.parseFromString(response.data,"text/html");for(const[meal_date,meal_object]of Object.entries(meal_objects)){let selected_value;for(const menu_option of meal_object.menu_options){if(menu_option.selected){selected_value=menu_option.value;}}
+if(!(parsed.getElementById("PrednarocanjeItems_"+meal_object.index+"__MeniIDSkupinaID").selectedOptions[0].value==selected_value)){reject(LOPOLISC_ERR_NOTAPPLIED);}}
+resolve(true);});});}
+chooseMenu(meal_object,meal_index){for(const menu_option of meal_object.menu_options){menu_option.selected=false;}
+meal_object.menu_options[meal_index].selected=true;return;}} \ No newline at end of file
diff --git a/dist/js/meals.js b/dist/js/meals.js
index adaf275..fa25e40 100755
--- a/dist/js/meals.js
+++ b/dist/js/meals.js
@@ -1,30 +1,29 @@
-const API_ENDPOINT="https://lopolis-api.gimb.tk/";var meals_calendar_obj=null;var meals_data_global={};function getDateString(){let date=new Date();let year_str=date.getFullYear();let month_str=date.getMonth()+1
+const API_ENDPOINT="https://lopolis-api.gimb.tk/";var meals_calendar_obj=null;var meals_data_global={};var checkouts_data_global={};function getDateString(){let date=new Date();let year_str=date.getFullYear();let month_str=date.getMonth()+1
month_str=month_str.toString().padStart(2,"0");let day_str=date.getDate();day_str=day_str.toString().padStart(2,"0");let date_string=year_str+"-"+month_str+"-"+day_str;return date_string;}
async function checkLogin(){localforage.getItem("logged_in_lopolis").then((value)=>{if(value!=true){$("#meals-container").hide();$("#meals-login-container").show();}else{$("#meals-container").show();$("#meals-login-container").hide();loadMeals();}}).catch((err)=>{console.log(err);});}
function setLoading(state){if(state){$("#loading-bar").removeClass("hidden");}else{$("#loading-bar").addClass("hidden");}}
-async function getToken(callback,callbackparams=[]){setLoading(true);let promises_to_run=[localforage.getItem("lopolis_username").then((value)=>{username=value;}),localforage.getItem("lopolis_password").then((value)=>{password=value;})];await Promise.all(promises_to_run);$.ajax({url:API_ENDPOINT+"gettoken",crossDomain:true,contentType:"application/json",data:JSON.stringify({"username":username,"password":password}),dataType:"json",cache:false,type:"POST",success:(dataauth)=>{if(dataauth==null||dataauth.error==true){UIAlert(D("authenticationError"),"getToken(): response error or null");localforage.setItem("logged_in_lopolis",false).then(function(){checkLogin();});}else if(dataauth.error==false){let empty={};empty.token=dataauth.data;let argumentsToCallback=[empty].concat(callbackparams);callback(...argumentsToCallback);}else{UIAlert(D("authenticationError"),"getToken(): invalid response, no condition met");}
-setLoading(false);},error:()=>{UIAlert(D("lopolisAPIConnectionError"),"getToken(): AJAX error");setLoading(false);}});}
-async function getMenus(dataauth,callback,callbackparams=[]){setLoading(true);let current_date=new Date();let mealsgathered={};let promises_to_wait_for=[];for(let iteration=1;iteration<=2;iteration++){promises_to_wait_for[iteration]=$.ajax({url:API_ENDPOINT+"getmenus",crossDomain:true,contentType:"application/json",data:JSON.stringify({"month":current_date.getMonth()+iteration,"year":current_date.getFullYear()}),headers:{"Authorization":`Bearer ${dataauth.token}`},dataType:"json",cache:false,type:"POST",success:(meals)=>{if(meals==null||meals.error==true){UIAlert(D("errorGettingMenus"),"getMenus(): response error or null");setLoading(false);localforage.setItem("logged_in_lopolis",false).then(()=>{checkLogin();});}else if(meals.error==false){setLoading(false);mealsgathered[iteration]=meals;}else{setLoading(false);UIAlert(D("errorUnexpectedResponse"),"getMenus(): invalid response, no condition met");}},error:()=>{setLoading(false);UIAlert(D("lopolisAPIConnectionError"),"getMenus(): AJAX error");}});}
-await Promise.all(promises_to_wait_for);let allmeals={};let passtocallback={};for(const[index,monthmeals]of Object.entries(mealsgathered)){allmeals=mergeDeep(allmeals,monthmeals.data);}
-passtocallback.data=allmeals;passtocallback.token=dataauth.token;let toBePassed=[passtocallback].concat(callbackparams);callback(...toBePassed);}
+async function getToken(callback,callbackparams=[]){setLoading(true);let promises_to_run=[localforage.getItem("lopolis_username").then((value)=>{username=value;}),localforage.getItem("lopolis_password").then((value)=>{password=value;})];await Promise.all(promises_to_run);try{var lopolisClient=new lopolisc();var response=await lopolisClient.login(username,password);}catch(e){console.log(e);UIAlert(D("authenticationError"),"getToken(): invalid response, no condition met");await localforage.setItem("logged_in_lopolis",false);return false;}
+await localforage.setItem("logged_in_lopolis",true);let empty={};empty.token={};let argumentsToCallback=[empty].concat(callbackparams);callback(...argumentsToCallback);}
+async function getMenus(dataauth,callback,callbackparams=[]){setLoading(true);let passtocallback={};let allmeals,allcheckouts;let tries=3;while(true){try{let lopolisClient=new lopolisc();allmeals=await lopolisClient.fetchAllMeals();allcheckouts=await lopolisClient.fetchAllCheckouts();}catch(e){console.log(e);UIAlert(D("lopolisAPIConnectionError"),"getMenus(): AJAX error");if(tries--<0){return false;}else{continue;}}
+break;}
+passtocallback.data=allmeals;passtocallback.checkouts=allcheckouts;passtocallback.token="tokens-not-used-anymore";let toBePassed=[passtocallback].concat(callbackparams);callback(...toBePassed);}
async function loadMeals(){getToken(getMenus,[displayMeals,[]]);}
-function displayMeals(meals){meals_data_global=meals.data;let transformed_meals=[];for(const[date,mealzz]of Object.entries(meals.data)){let bg_color="#877F02";let fg_color="#FFFFFF";if(mealzz.readonly)bg_color="#8d9288";let meal_date=new Date(date+"+00:00");let meal_object={start:meal_date.toISOString().substring(0,10),title:S("meal"),id:date,allDay:true,backgroundColor:bg_color,textColor:fg_color}
+function displayMeals(meals){meals_data_global=meals.data;checkouts_data_global=meals.checkouts;let transformed_meals=[];for(const[date,mealzz]of Object.entries(meals.data)){let bg_color="#877F02";let fg_color="#FFFFFF";if(mealzz.readonly)bg_color="#8d9288";let meal_date=new Date(date+"+00:00");let meal_object={start:meal_date.toISOString().substring(0,10),title:mealzz.meal,id:date,allDay:true,backgroundColor:bg_color,textColor:fg_color}
transformed_meals.push(meal_object);}
-meals_calendar_obj.removeAllEvents();meals_calendar_obj.addEventSource(transformed_meals);return;}
+meals_calendar_obj.removeAllEvents();meals_calendar_obj.addEventSource(transformed_meals);setLoading(false);return;}
function clearMeals(){meals_calendar_obj.removeAllEvents();}
function refreshMeals(){clearMeals();loadMeals();}
-function lopolisLogout(){localforage.setItem("logged_in_lopolis",false);$("#meals-collapsible").html("");checkLogin();}
-async function lopolisLogin(){setLoading(true);var usernameEl=$("#meals-username");var passwordEl=$("#meals-password");$.ajax({url:API_ENDPOINT+"gettoken",crossDomain:true,contentType:"application/json",data:JSON.stringify({"username":usernameEl.val(),"password":passwordEl.val()}),dataType:"json",cache:false,type:"POST",success:async function(data){if(data==null){UIAlert(S("requestForAuthenticationFailed"),"lopolisLogin(): date is is null");setLoading(false);usernameEl.val("");passwordEl.val("");}else if(data.error==true){UIAlert(S("loginFailed"),"lopolisLogin(): login failed. data.error is true");usernameEl.val("");passwordEl.val("");setLoading(false);}else{let promises_to_run=[localforage.setItem("logged_in_lopolis",true),localforage.setItem("lopolis_username",usernameEl.val()),localforage.setItem("lopolis_password",passwordEl.val())];await Promise.all(promises_to_run);checkLogin();UIAlert("Credential match!");}},error:()=>{UIAlert(D("loginError"),"lopolisLogin(): ajax.error");setLoading(false);}});}
-async function setMenus(currentmeals=69,toBeSentChoices){if(currentmeals===69){getToken(getMenus,[setMenus,toBeSentChoices]);return;}
-for(const[mealzzdate,mealzz]of Object.entries(currentmeals.data)){if(mealzzdate in toBeSentChoices===false){for(const[mealid,mealdata]of Object.entries(mealzz.menu_options)){if(mealdata.selected==true||mealzz.readonly==true){toBeSentChoices[mealzzdate]=mealdata.value;break;}}}}
-setLoading(true);$.ajax({url:API_ENDPOINT+"setmenus",crossDomain:true,contentType:"application/json",data:JSON.stringify({"choices":toBeSentChoices}),headers:{"Authorization":"Bearer "+currentmeals.token},dataType:"json",cache:false,type:"POST",success:(response)=>{if(response===null||response.error==true){UIAlert(D("errorSettingMeals"),"setMenus(): response error or null");}else if(response.error==false){UIAlert(D("mealSet"),"setMenus(): meni nastavljen");}else{UIAlert(D("errorUnexpectedResponse"),"setMenus(): invalid response, no condition met");}
-setLoading(false);},error:()=>{setLoading(false);UIAlert(D("lopolisAPIConnectionError"),"setMenus(): AJAX error");}});}
-async function setMenu(date,menu){let choice={};choice[date]=menu;getToken(getMenus,[setMenus,choice]);}
+function lopolisLogout(){localforage.setItem("logged_in_lopolis",false).then(()=>{clearMeals();checkLogin();});}
+async function lopolisLogin(){setLoading(true);var usernameEl=$("#meals-username");var passwordEl=$("#meals-password");try{let l=new lopolisc();await l.login(usernameEl.val(),passwordEl.val());}catch(e){UIAlert(D("loginError"),"lopolisLogin(): ajax.error");setLoading(false);return false;}
+let promises_to_run=[localforage.setItem("logged_in_lopolis",true),localforage.setItem("lopolis_username",usernameEl.val()),localforage.setItem("lopolis_password",passwordEl.val())];await Promise.all(promises_to_run);checkLogin();UIAlert("Credential match!");return true;}
function setupEventListeners(){$("#meals-login").click(()=>{lopolisLogin();});$("#meals-logout").click(()=>{lopolisLogout();});}
-var mealClickHandler=(eventClickInfo)=>{let meal_date=eventClickInfo.event.id;let meal_object=meals_data_global[meal_date];$("#meal-type").text(meal_object.meal);let meal_date_obj=new Date(meal_date);$("#meal-date").text(dateString.longFormatted(meal_date_obj));if(!(meal_object.readonly)){document.getElementById("meal-readonly").style.display="none";}else{document.getElementById("meal-readonly").style.display="block";}
+var mealClickHandler=(eventClickInfo)=>{let meal_date=eventClickInfo.event.id;let meal_object=meals_data_global[meal_date];$("#checkout_label").show();let can_do_checkout=true;let checkout_object;try{checkout_object=checkouts_data_global[meal_date];}catch(e){$("#checkout_label").hide();let can_do_checkout=false;}
+if(checkout_object==undefined||checkout_object==null){can_do_checkout=false;}
+console.log(checkout_object);if(can_do_checkout){let cc=$("#checkout_checkbox");cc[0].checked=!(checkout_object.checked);cc.off();cc.on("change",()=>{let l=new lopolisc();checkouts_data_global[meal_date].checked=!(cc[0].checked);setLoading(true);l.setCheckouts(checkouts_data_global).then(()=>{UIAlert(D("successfulCheckingInOut"),"successfulcheckinginout");setLoading(false);}).catch(()=>{UIAlert(D("errorCheckingInOut"),"errorcheckinginout");setLoading(false);});});cc.prop("disabled",checkout_object.readonly);}
+$("#meal-type").text(meal_object.meal);let meal_date_obj=new Date(meal_date);$("#meal-date").text(dateString.longFormatted(meal_date_obj));if(!(meal_object.readonly)){document.getElementById("meal-readonly").style.display="none";}else{document.getElementById("meal-readonly").style.display="block";}
document.getElementById("meal-options").innerHTML="";for(const[option_index,option_object]of Object.entries(meal_object.menu_options)){let menu_option_li_el=document.createElement("li");let menu_option_a_el=document.createElement("button");menu_option_a_el.innerText=option_object.text;let classlist="";if(option_object.selected!=null){if(option_object.selected){classlist="color: green; font-weight: bold";}}
-menu_option_a_el.classList="waves-effect waves-light btn-large";menu_option_a_el.style="color: var(--color-text); background-color: rgba(0,0,0,0); line-height: 1.2; height:auto; "+classlist+" !important";menu_option_a_el.id="menu_index_"+option_index;if(!(meal_object.readonly)){menu_option_a_el.onclick=()=>{setMenu(meal_date,option_object.value);menu_option_a_el.className="to-be-selected-meal";let sidenav_element=document.getElementById("meal-info");let sidenav_instance=M.Sidenav.getInstance(sidenav_element);sidenav_instance.close();};}
+menu_option_a_el.classList="waves-effect waves-light btn-large";menu_option_a_el.style="color: var(--color-text); background-color: rgba(0,0,0,0); line-height: 1.2; height:auto; "+classlist+" !important";menu_option_a_el.id="menu_index_"+option_index;if(!(meal_object.readonly)){menu_option_a_el.disabled=false;menu_option_a_el.onclick=()=>{setLoading(true);let l=new lopolisc();l.chooseMenu(meals_data_global[meal_date],option_index);l.setMeals(meals_data_global).then(()=>{UIAlert(D("mealSet"),"meal set!");setLoading(false);}).catch(()=>{UIAlert(D("errorSettingMeals"),"error setting meals");setLoading(false);});menu_option_a_el.className="to-be-selected-meal";let sidenav_element=document.getElementById("meal-info");let sidenav_instance=M.Sidenav.getInstance(sidenav_element);sidenav_instance.close();};}else{menu_option_a_el.disabled=true;}
menu_option_li_el.appendChild(menu_option_a_el);document.getElementById("meal-options").appendChild(menu_option_li_el);}
let sidenav_element=document.getElementById("meal-info");let sidenav_instance=M.Sidenav.getInstance(sidenav_element);sidenav_instance.open();}
-document.addEventListener("DOMContentLoaded",async()=>{checkLogin();var calendarEl=document.getElementById("meals-calendar");meals_calendar_obj=new FullCalendar.Calendar(calendarEl,{firstDay:1,plugins:["dayGrid"],defaultDate:getDateString(),navLinks:false,editable:false,events:[],eventClick:mealClickHandler,height:"parent"});meals_calendar_obj.render();setupEventListeners();$("#refresh-icon").click(function(){refreshMeals();});const menus=document.querySelectorAll('.side-menu');M.Sidenav.init(menus,{edge:'right',draggable:true});const modals=document.querySelectorAll('.side-modal');M.Sidenav.init(modals,{edge:'left',draggable:false});document.getElementsByClassName("fc-today-button")[0].style="display:none !important";var elemsx=document.querySelectorAll('select');M.FormSelect.init(elemsx);var datepickerelems=document.querySelectorAll('.datepicker');var today=new Date();M.Datepicker.init(datepickerelems,{firstDay:1,minDate:today,showDaysInNextAndPreviousMonths:true,showClearBtn:true,format:"dddd, dd. mmmm yyyy"});refreshMeals();}); \ No newline at end of file
+document.addEventListener("DOMContentLoaded",async()=>{await find_chosen_lang();checkLogin();var calendarEl=document.getElementById("meals-calendar");meals_calendar_obj=new FullCalendar.Calendar(calendarEl,{firstDay:1,plugins:["dayGrid"],defaultDate:getDateString(),navLinks:false,editable:false,events:[],eventClick:mealClickHandler,height:"parent"});meals_calendar_obj.render();setupEventListeners();$("#refresh-icon").click(function(){setLoading(true);refreshMeals();});const menus=document.querySelectorAll('.side-menu');M.Sidenav.init(menus,{edge:'right',draggable:true});const modals=document.querySelectorAll('.side-modal');M.Sidenav.init(modals,{edge:'left',draggable:false});document.getElementsByClassName("fc-today-button")[0].style="display:none !important";var elemsx=document.querySelectorAll('select');M.FormSelect.init(elemsx);var datepickerelems=document.querySelectorAll('.datepicker');var today=new Date();M.Datepicker.init(datepickerelems,{firstDay:1,minDate:today,showDaysInNextAndPreviousMonths:true,showClearBtn:true,format:"dddd, dd. mmmm yyyy"});}); \ No newline at end of file
diff --git a/dist/pages/about.html b/dist/pages/about.html
index b501109..2959511 100755
--- a/dist/pages/about.html
+++ b/dist/pages/about.html
@@ -49,7 +49,8 @@
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -59,7 +60,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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>
@@ -76,7 +78,7 @@
<!-- One day in the future we may have sw cache version covered by this as well -->
<h5 class="subheader">
<x-su>version</x-su>
- 1.0.15.0-beta
+ 1.0.16.0-beta
</h5>
</div>
</div>
@@ -160,7 +162,7 @@
<div class="row">
<p>
<small>
- ^HEAD a0a53bec5f61439dece140798235114a0164e26d
+ ^HEAD f54120aa036215dee0f02ff2c1a9ce20def75006
</small>
</p>
</div>
diff --git a/dist/pages/absences.html b/dist/pages/absences.html
index d50e546..cd03b3f 100755
--- a/dist/pages/absences.html
+++ b/dist/pages/absences.html
@@ -50,7 +50,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -60,7 +61,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/pages/changelog.html b/dist/pages/changelog.html
index 9f8cbab..9902ec8 100755
--- a/dist/pages/changelog.html
+++ b/dist/pages/changelog.html
@@ -56,6 +56,18 @@
</h3>
<ul class="collapsible">
<li>
+
+ <div class="collapsible-header">Version 1.0.16-beta</div>
+ <div class="collapsible-body">
+ <ul class="collection">
+ <li class="collection-item">Fixed meals</li>
+ <li class="collection-item">Removed LopolisAPI, created
+ lopolisc.js</li>
+ <li class="collection-item">Removed GimB Meet</li>
+ <li class="collection-item">Added checkout option to meals</li>
+ </ul>
+ </div>
+
<div class="collapsible-header">Version 1.0.15-beta</div>
<div class="collapsible-body">
<ul class="collection">
@@ -63,7 +75,6 @@
</ul>
</div>
-
<div class="collapsible-header">Version 1.0.14-beta</div>
<div class="collapsible-body">
<ul class="collection">
diff --git a/dist/pages/chats.html b/dist/pages/chats.html
index e1cb37c..d842531 100755
--- a/dist/pages/chats.html
+++ b/dist/pages/chats.html
@@ -56,7 +56,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -66,7 +67,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/pages/grades.html b/dist/pages/grades.html
index 0a8e5ec..c2c083a 100755
--- a/dist/pages/grades.html
+++ b/dist/pages/grades.html
@@ -50,7 +50,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -60,7 +61,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/pages/gradings.html b/dist/pages/gradings.html
index c2c9d7b..d20020b 100755
--- a/dist/pages/gradings.html
+++ b/dist/pages/gradings.html
@@ -58,7 +58,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -68,7 +69,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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>
@@ -103,7 +105,8 @@
<i class="large material-icons">add</i>
</a>
</div> -->
- <!-- Modal Structure -->
+ <!-- @begin=html@ -->
+ <!-- Modal Structure -->
<div id="beziapp-add-grading" class="modal modal-fixed-footer">
<div class="modal-content">
diff --git a/dist/pages/jitsi.html b/dist/pages/jitsi.html
index 678ad9d..343302d 100755
--- a/dist/pages/jitsi.html
+++ b/dist/pages/jitsi.html
@@ -47,7 +47,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -57,7 +58,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/pages/meals.html b/dist/pages/meals.html
index 56e0af3..26e79f6 100755
--- a/dist/pages/meals.html
+++ b/dist/pages/meals.html
@@ -20,20 +20,18 @@
<script src="/js/lib/jquery.min.js"></script>
<!-- localForage -->
<script type="text/javascript" src="/js/lib/localforage.min.js"></script>
+ <!-- i18n bundle -->
+ <script src="/js/lang/bundle.js"></script>
<!-- mergedeep.js -->
<script type="text/javascript" src="/js/lib/mergedeep.js"></script>
<!-- stylesheet for custom styles -->
<link type="text/css" href="/css/styles.css" rel="stylesheet">
- <!-- page-specific javascript code -->
- <script type="text/javascript" src="/js/meals.js"></script>
<!-- PWA manifest -->
<link rel="manifest" href="/manifest.json">
<!-- app global code -->
<script src="/js/app.js"></script>
<!-- code for custom theme switcher -->
<script src="/js/lib/themes.js"></script>
- <!-- i18n bundle -->
- <script src="/js/lang/bundle.js"></script>
<!-- favicon -->
<link rel="shortcut icon" type="image/png" href="/favicon.png" />
<!-- iOS support -->
@@ -46,6 +44,10 @@
<link href="/css/fullcalendar/custom.css" rel="stylesheet" />
<script src="/js/lib/fullcalendar/core/main.min.js"></script>
<script src="/js/lib/fullcalendar/daygrid/main.min.js"></script>
+ <!-- lopolis client API library - unofficial by sijanec -->
+ <script src="/js/lopolisc.js"></script>
+ <!-- page-specific javascript code -->
+ <script type="text/javascript" src="/js/meals.js"></script>
</head>
<body>
@@ -63,7 +65,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -73,7 +76,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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>
@@ -101,6 +105,16 @@
<x-du>readOnly</x-du>
</a>
</li>
+ <li>
+ <div class=switch style=margin-left:0.7cm>
+ <label id=checkbox_label style>
+ <x-su>checkedOut</x-su>
+ <input id=checkout_checkbox type=checkbox>
+ <span class=lever></span>
+ <x-su>checkedIn</x-su>
+ </label>
+ </div>
+ </li>
<div class=divider></div>
<li id=meal-options>
diff --git a/dist/pages/messaging.html b/dist/pages/messaging.html
index 5c9fb32..5acb6f6 100755
--- a/dist/pages/messaging.html
+++ b/dist/pages/messaging.html
@@ -52,7 +52,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -62,7 +63,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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>
@@ -107,7 +109,8 @@
<i class="large material-icons">mode_edit</i>
</a>
</div>
- <!-- Modal Structure -->
+ <!-- @begin=html@ -->
+ <!-- Modal Structure -->
<div id="beziapp-new-message" class="modal modal-fixed-footer">
<div class="modal-content">
diff --git a/dist/pages/settings.html b/dist/pages/settings.html
index 5e96b77..43e6376 100755
--- a/dist/pages/settings.html
+++ b/dist/pages/settings.html
@@ -47,7 +47,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -57,7 +58,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/pages/teachers.html b/dist/pages/teachers.html
index b346762..0c1e9cb 100755
--- a/dist/pages/teachers.html
+++ b/dist/pages/teachers.html
@@ -50,7 +50,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -60,7 +61,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/pages/timetable.html b/dist/pages/timetable.html
index efc6e35..f4b6220 100755
--- a/dist/pages/timetable.html
+++ b/dist/pages/timetable.html
@@ -59,7 +59,8 @@
<div class="indeterminate"></div>
</div>
</nav>
- <ul id="side-menu" class="sidenav side-menu">
+ <!-- @begin=html@ -->
+<ul id="side-menu" class="sidenav side-menu">
<li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><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>
@@ -69,7 +70,8 @@
<li><a href="/pages/messaging.html" class="waves-effect"><i class="material-icons">message</i><x-su>messaging</x-su></a></li>
<!-- chats not done yet, expecting merge so removing from navigation panel --sijanec -->
<!-- <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/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li>
+ <!-- <li><a href="/pages/jitsi.html" class="waves-effect"><i class="material-icons">video_call</i><x-su>videoconferences</x-su></a></li> -->
+ <!-- jitsi got reverted to jitsi from gimb meet so it's sucky to show this -->
<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/dist/sw.js b/dist/sw.js
index dcf9d10..1b83714 100755
--- a/dist/sw.js
+++ b/dist/sw.js
@@ -2,9 +2,10 @@
+// @begin=js@
// Change version to cause cache refresh
-const static_cache_name = "site-static-1.0.15.0-beta-a0a53be";
-// commit before the latest is a0a53bec5f61439dece140798235114a0164e26d
+const static_cache_name = "site-static-1.0.16.0-beta-f54120a";
+// commit before the latest is f54120aa036215dee0f02ff2c1a9ce20def75006
// Got them with find . -not -path '*/\.*' | sed "s/.*/\"&\",/" | grep -v sw.js
// sw.js NE SME BITI CACHAN, ker vsebuje verzijo!
diff --git a/global.bvr b/global.bvr
index 74d6617..8001baa 100644
--- a/global.bvr
+++ b/global.bvr
@@ -1,3 +1,3 @@
<@?s bvr_include_path assets/pages-src/ assets/pages-src/misc/@>
<@?s latest_commit ?u 0 -1 ?i .git/refs/heads/dev@>
-<@?s app_version 1.0.15.0-beta@>
+<@?s app_version 1.0.16.0-beta@>
diff --git a/server/proxy/apache.conf b/server/proxy/apache.conf
deleted file mode 100644
index e0c49a5..0000000
--- a/server/proxy/apache.conf
+++ /dev/null
@@ -1,99 +0,0 @@
-<VirtualHost *:27443>
- SSLEngine On
- SSLCertificateFile /etc/ssl/sslforfree/sg.crt
- SSLCertificateKeyFile /etc/ssl/sslforfree/sg.key
- SSLProxyEngine On
- SSLProxyCheckPeerCN Off
- SSLProxyCheckPeerName Off
- # The ServerName directive sets the request scheme, hostname and port that
- # the server uses to identify itself. This is used when creating
- # redirection URLs. In the context of virtual hosts, the ServerName
- # specifies what hostname must appear in the request's Host: header to
- # match this virtual host. For the default virtual host (this file) this
- # value is not decisive as it is used as a last resort host regardless.
- # However, you must set it for any further virtual host explicitly.
- #ServerName www.example.com
-
- #ServerAdmin webmaster@localhost
- #DocumentRoot /var/www/apache2
-
- # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
- # error, crit, alert, emerg.
- # It is also possible to configure the loglevel for particular
- # modules, e.g.
- #LogLevel info ssl:warn
-
- ErrorLog ${APACHE_LOG_DIR}/error.log
- CustomLog ${APACHE_LOG_DIR}/access.log combined
-
- # For most configuration files from conf-available/, which are
- # enabled or disabled at a global level, it is possible to
- # include a line for only one particular virtual host. For example the
- # following line enables the CGI configuration for this host only
- # after it has been globally disabled with "a2disconf".
- #Include conf-available/serve-cgi-bin.conf
-
- RequestHeader unset Accept-Encoding
- ProxyPreserveHost Off
- ProxyPass "/" "https://zgimsis.gimb.org:443/"
- ProxyPassReverse "/" "https://zgimsis.gimb.org:443/"
- AddOutputFilterByType SUBSTITUTE text/html
- Substitute "s|zgimsis.gimb.org|zgimsis.gimb.tk:27443|i"
- Substitute "s/window.location.replace/console.log/i"
- DumpIOInput Off
- DumpIOOutput On
- LogLevel dumpio:trace7
- LogLevel debug
-
-</VirtualHost>
-<VirtualHost *:2780>
-# ServerName cargova.xn--pga.ga
-# SSLEngine On
-# SSLCertificateFile /etc/ssl/sslforfree/sg.crt
-# SSLCertificateKeyFile /etc/ssl/sslforfree/sg.key
- SSLProxyEngine On
- SSLProxyCheckPeerCN Off
- SSLProxyCheckPeerName Off
- # The ServerName directive sets the request scheme, hostname and port that
- # the server uses to identify itself. This is used when creating
- # redirection URLs. In the context of virtual hosts, the ServerName
- # specifies what hostname must appear in the request's Host: header to
- # match this virtual host. For the default virtual host (this file) this
- # value is not decisive as it is used as a last resort host regardless.
- # However, you must set it for any further virtual host explicitly.
- #ServerName www.example.com
-
- #ServerAdmin webmaster@localhost
- #DocumentRoot /var/www/apache2
-
- # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
- # error, crit, alert, emerg.
- # It is also possible to configure the loglevel for particular
- # modules, e.g.
- #LogLevel info ssl:warn
-
- ErrorLog ${APACHE_LOG_DIR}/error.log
- CustomLog ${APACHE_LOG_DIR}/access.log combined
-
- # For most configuration files from conf-available/, which are
- # enabled or disabled at a global level, it is possible to
- # include a line for only one particular virtual host. For example the
- # following line enables the CGI configuration for this host only
- # after it has been globally disabled with "a2disconf".
- #Include conf-available/serve-cgi-bin.conf
-
- RequestHeader unset Accept-Encoding
- ProxyPreserveHost Off
- ProxyPass "/" "https://zgimsis.gimb.org:443/"
- ProxyPassReverse "/" "https://zgimsis.gimb.org:443/"
- AddOutputFilterByType SUBSTITUTE text/html
- Substitute "s/zgimsis.gimb.org/zgimsis.gimb.tk:2780/i"
- Substitute "s/window.location.replace/console.log/i"
- DumpIOInput Off
- DumpIOOutput On
- LogLevel dumpio:trace7
- LogLevel debug
-
-</VirtualHost>
-
-# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/server/proxy/lopolis.conf b/server/proxy/lopolis.conf
new file mode 100644
index 0000000..66f2d94
--- /dev/null
+++ b/server/proxy/lopolis.conf
@@ -0,0 +1,55 @@
+# /etc/nginx/sites-enabled/lopolis
+server {
+ listen 0.0.0.0:80;
+ listen [::]:80;
+ server_name .lopolis.gimb.tk;
+ return 301 https://lopolis.gimb.tk/;
+}
+server {
+ listen 0.0.0.0:443 http2 ssl;
+ listen [::]:443 http2 ssl;
+ ssl_certificate /etc/ssl/sslforfree/gimb.tk.crtca;
+ ssl_certificate_key /etc/ssl/sslforfree/gimb.tk.key;
+ server_name .lopolis.gimb.tk;
+ location / {
+ if ($http_origin ~ \.?gimb\.tk$) {
+ set $cors 'true';
+ set $both_conditions "P";
+ add_header "x-debug-http-origin-check" "passed";
+ }
+ if ($http_origin ~ \.?beziapp\.github\.io$) {
+ set $cors 'true';
+ set $both_conditions "P";
+ add_header "x-debug-http-origin-check" "passed";
+ }
+ if ($cors = 'true') {
+ add_header "Access-Control-Allow-Origin" $http_origin always;
+ add_header "Access-Control-Allow-Credentials" "true" always;
+ add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
+ add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ }
+ if ($request_method = 'OPTIONS') {
+ set $both_conditions "${both_conditions}D";
+ }
+ if ($both_conditions = PD) {
+ add_header "Access-Control-Allow-Origin" $http_origin always;
+ add_header "Access-Control-Allow-Credentials" "true" always;
+ add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
+ add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ add_header 'Access-Control-Max-Age' -1;
+ add_header 'Content-Type' 'text/plain charset=UTF-8';
+ add_header 'Content-Length' 0;
+ return 204;
+ }
+ access_log /var/log/nginx/lopolis/access.log postdata;
+ proxy_set_header Host www.lopolis.si;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_redirect off;
+ proxy_ssl_server_name on;
+ proxy_pass https://www.lopolis.si;
+ # try_files $uri $uri/ =404;
+ }
+}
+
diff --git a/server/proxy/nginx.conf b/server/proxy/nginx.conf
deleted file mode 100644
index 222b8d2..0000000
--- a/server/proxy/nginx.conf
+++ /dev/null
@@ -1,133 +0,0 @@
-#server {
-# server_name _;
-# listen 80 default_server;
-# # listen 443 default_server;
-# listen [::]:80 default_server;
-# # listen [::]:443 default_server;
-# return 444;
-#}
-server {
- listen 93.103.156.37:80;
- listen [::]:80;
- server_name .g.gimb.tk .gimsis.gimb.tk .zgimsis.gimb.tk .gimsisext.gimb.tk .gse.gimb.tk;
- return 301 https://zgimsis.gimb.tk$request_uri;
- port_in_redirect off;
- server_name_in_redirect off;
-}
-server {
- listen 93.103.156.37:443 ssl http2;
- listen [::]:443 ssl http2;
- ssl_certificate /etc/ssl/sslforfree/sg.crt;
- ssl_certificate_key /etc/ssl/sslforfree/sg.key;
- ssl_session_cache builtin:1000 shared:SSL:10m;
- ssl_prefer_server_ciphers on;
- add_header Strict-Transport-Security "max-age=604800";
- #root /var/www/html;
- index index.php index.html index.htm index.nginx-debian.html;
- server_name .g.gimb.tk .gimsis.gimb.tk .zgimsis.gimb.tk .gimsisext.gimb.tk .gse.gimb.tk;
- location /gse/ {
- #try_files $uri $uri/ =404;
- proxy_pass https://localhost:27443;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- set $cors '';
- set $both_conditions "";
- add_header "x-debug-location-gse" "triggered";
- if ($http_origin ~ \.?gimb\.tk$) {
- set $cors 'true';
- set $both_conditions "P";
- add_header "x-debug-http-origin-check" "passed";
- }
- if ($cors = 'true') {
- add_header "Access-Control-Allow-Origin" $http_origin always;
- add_header "Access-Control-Allow-Credentials" "true" always;
- add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
- add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
- add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
- }
- if ($request_method = 'OPTIONS') {
- set $both_conditions "${both_conditions}D";
- }
- if ($both_conditions = PD) {
- add_header "Access-Control-Allow-Origin" $http_origin always;
- add_header "Access-Control-Allow-Credentials" "true" always;
- add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
- add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
- add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
- add_header 'Access-Control-Max-Age' -1;
- add_header 'Content-Type' 'text/plain charset=UTF-8';
- add_header 'Content-Length' 0;
- return 204;
- }
- }
- location / {
- set $cors '';
- if ($http_origin ~ \.?gimb\.tk$) {
- set $cors 'true';
- }
- if ($cors = 'true') {
- add_header "Access-Control-Allow-Origin" $http_origin always;
- add_header "Access-Control-Allow-Credentials" "true" always;
- add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
- add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
- add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
- }
- if ($request_method = 'OPTIONS') {
- add_header 'Access-Control-Max-Age' 300;
- add_header 'Content-Type' 'text/plain charset=UTF-8';
- add_header 'Content-Length' 0;
- return 204;
- }
- return 301 https://zgimsis.gimb.tk/gse/;
- }
- #location ~ \.php$ {
- # include snippets/fastcgi-php.conf;
- # fastcgi_pass unix:/run/php/php7.3-fpm.sock;
- #}
- location ~ /\.ht {
- deny all;
- }
- port_in_redirect off;
- server_name_in_redirect off;
-}
-server {
- listen 93.103.156.37:80;
- listen [::]:80;
- server_name .la.gimb.tk .lopolisapi.gimb.tk .lopolis-api.gimb.tk;
- return 301 https://lopolis-api.gimb.tk$request_uri;
- port_in_redirect off;
- server_name_in_redirect off;
-}
-server {
- listen 93.103.156.37:443 ssl http2;
- listen [::]:443 ssl http2;
- ssl_certificate /etc/ssl/sslforfree/sg.crt;
- ssl_certificate_key /etc/ssl/sslforfree/sg.key;
- ssl_session_cache builtin:1000 shared:SSL:10m;
- ssl_prefer_server_ciphers on;
- add_header Strict-Transport-Security "max-age=604800";
- #root /var/www/html;
- index index.php index.html index.htm index.nginx-debian.html;
- server_name .la.gimb.tk .lopolisapi.gimb.tk .lopolis-api.gimb.tk;
- location / {
- #try_files $uri $uri/ =404;
- proxy_pass http://localhost:44625;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- }
- #location / {
-# return 301 https://zgimsis.gimb.tk/gse/;
-# }
- #location ~ \.php$ {
- # include snippets/fastcgi-php.conf;
- # fastcgi_pass unix:/run/php/php7.3-fpm.sock;
- #}
- location ~ /\.ht {
- deny all;
- }
- add_header X-This-Is-Definetley-Not-Flask I-Really-Care-If-Someone-DoSes-This-/s;
- add_header X-I-Mean-If-Someone-Wants-To-DoS-Me They-Have-The-Power-To-Do-It;
- add_header X-Although-It-Is-Illegal-And-I Will-Report-You-To-SiCert-And-They-Will-Bit-Your-Ass;
- port_in_redirect off;
- server_name_in_redirect off;
-}
diff --git a/server/proxy/zgimsis.conf b/server/proxy/zgimsis.conf
new file mode 100644
index 0000000..72a5974
--- /dev/null
+++ b/server/proxy/zgimsis.conf
@@ -0,0 +1,51 @@
+# /etc/nginx/sites-enabled/zgimsis
+server {
+ listen 0.0.0.0:80;
+ listen [::]:80;
+ server_name .zgimsis.gimb.tk;
+ return 301 https://zgimsis.gimb.tk/gse/;
+}
+server {
+ listen 0.0.0.0:443 http2 ssl;
+ listen [::]:443 http2 ssl;
+ ssl_certificate /etc/ssl/sslforfree/gimb.tk.crtca;
+ ssl_certificate_key /etc/ssl/sslforfree/gimb.tk.key;
+ server_name .zgimsis.gimb.tk;
+ location / {
+ if ($http_origin ~ \.?gimb\.tk$) {
+ set $cors 'true';
+ set $both_conditions "P";
+ add_header "x-debug-http-origin-check" "passed";
+ }
+ if ($http_origin ~ \.?beziapp\.github\.io$) {
+ set $cors 'true';
+ set $both_conditions "P";
+ add_header "x-debug-http-origin-check" "passed";
+ }
+ if ($cors = 'true') {
+ add_header "Access-Control-Allow-Origin" $http_origin always;
+ add_header "Access-Control-Allow-Credentials" "true" always;
+ add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
+ add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ }
+ if ($request_method = 'OPTIONS') {
+ set $both_conditions "${both_conditions}D";
+ }
+ if ($both_conditions = PD) {
+ add_header "Access-Control-Allow-Origin" $http_origin always;
+ add_header "Access-Control-Allow-Credentials" "true" always;
+ add_header "Access-Control-Allow-Methods" "GET, POST, PATCH, PUT, DELETE, OPTIONS" always;
+ add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ add_header 'Access-Control-Expose-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,Authorization' always;
+ add_header 'Access-Control-Max-Age' -1;
+ add_header 'Content-Type' 'text/plain charset=UTF-8';
+ add_header 'Content-Length' 0;
+ return 204;
+ }
+ access_log /var/log/nginx/zgimsis/access.log postdata;
+ proxy_pass https://zgimsis.gimb.org/;
+ # try_files $uri $uri/ =404;
+ }
+}
+