From 616c225661687b05ab82160f5b7d6dcb4d39b8e6 Mon Sep 17 00:00:00 2001 From: sijanec Date: Wed, 23 Sep 2020 18:37:16 +0200 Subject: fixed meals layout - fullcalendar -- do not merge! todo: fix sidenav in meals --- assets/css/styles.css | 14 +- assets/js/gradings.js | 318 +++++++++---------- assets/js/lang/bundle.js | 8 +- assets/js/meals.js | 710 +++++++++++++++++++++--------------------- assets/pages-src/gradings.bvr | 143 ++++----- assets/pages-src/meals.bvr | 262 +++++++++------- 6 files changed, 767 insertions(+), 688 deletions(-) (limited to 'assets') diff --git a/assets/css/styles.css b/assets/css/styles.css index 0e11125..a363449 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -428,4 +428,16 @@ h1, h2, h3, h4, h5, h6 { ol { color: var(--color-text) !important; -} \ No newline at end of file +} + +/* meals: */ + +.selected-meal { + color: green !important; + font-weight: bold !important; +} + +.to-be-selected-meal { + color: brown !important; + font-weight: italic !important; +} diff --git a/assets/js/gradings.js b/assets/js/gradings.js index 4730248..92e696d 100644 --- a/assets/js/gradings.js +++ b/assets/js/gradings.js @@ -2,197 +2,197 @@ var calendar_obj = null; var gradings; async function checkLogin() { - localforage.getItem("logged_in").then((value) => { - // This code runs once the value has been loaded - // from the offline store. - if (value !== true) { - window.location.replace("/index.html"); - } - }).catch((err) => { - // This code runs if there were any errors - console.log(err); - }); + localforage.getItem("logged_in").then((value) => { + // This code runs once the value has been loaded + // from the offline store. + if (value !== true) { + window.location.replace("/index.html"); + } + }).catch((err) => { + // This code runs if there were any errors + console.log(err); + }); } // Set loading bar visibility function setLoading(state) { - if (state) { - $("#loading-bar").removeClass("hidden"); - } else { - $("#loading-bar").addClass("hidden"); - } + if (state) { + $("#loading-bar").removeClass("hidden"); + } else { + $("#loading-bar").addClass("hidden"); + } } // GET COLOR FROM STRING function hashCode(str) { // java String#hashCode - var hash = 0; - for (var i = 0; i < str.length; i++) { - hash = str.charCodeAt(i) + ((hash << 5) - hash); - } - return hash; + var hash = 0; + for (var i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + return hash; } function intToRGB(i) { - var c = (i & 0x00FFFFFF) - .toString(16) - .toUpperCase(); + var c = (i & 0x00FFFFFF) + .toString(16) + .toUpperCase(); - return "00000".substring(0, 6 - c.length) + c; + return "00000".substring(0, 6 - c.length) + c; } // http://www.w3.org/TR/AERT#color-contrast function getForegroundFromBackground(background_color) { - let color_hex = background_color.replace("#", ""); - let rgb = [ - parseInt(color_hex.substring(0, 2), 16), - parseInt(color_hex.substring(2, 4), 16), - parseInt(color_hex.substring(4, 6), 16) - ]; - let o = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) / 1000); - if (o > 180) { - return "#000000"; - } else { - return "#ffffff"; - } + let color_hex = background_color.replace("#", ""); + let rgb = [ + parseInt(color_hex.substring(0, 2), 16), + parseInt(color_hex.substring(2, 4), 16), + parseInt(color_hex.substring(4, 6), 16) + ]; + let o = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) / 1000); + if (o > 180) { + return "#000000"; + } else { + return "#ffffff"; + } } function getHexColorFromString(str) { - return "#" + intToRGB(hashCode(str)); + return "#" + intToRGB(hashCode(str)); } // -------------------------------------------------- function getDateString() { - let date = new Date(); + 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 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; + let date_string = year_str + "-" + month_str + "-" + day_str; + return date_string; } async function loadGradings(force_refresh = false) { - setLoading(true); - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - localforage.getItem("gradings").then((value) => { - gradings = value; - }) - ]; - await Promise.all(promises_to_run); - if (gradings == null || gradings == [] || gradings == -1 || force_refresh) { - try { - let gsecInstance = new gsec(); - await gsecInstance.login(username, password); - gsecInstance.fetchGradings().then( (value) => { - gradings = value; - localforage.setItem("gradings", value).then(() => { - displayData(); - setLoading(false); - }); - setLoading(false); - }).catch( (err) => { - gsecErrorHandlerUI(err); - setLoading(false); - }); - } catch (err) { - gsecErrorHandlerUI(err); - setLoading(false); - } - } else { - displayData(); - setLoading(false); - } + setLoading(true); + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + localforage.getItem("gradings").then((value) => { + gradings = value; + }) + ]; + await Promise.all(promises_to_run); + if (gradings == null || gradings == [] || gradings == -1 || force_refresh) { + try { + let gsecInstance = new gsec(); + await gsecInstance.login(username, password); + gsecInstance.fetchGradings().then((value) => { + gradings = value; + localforage.setItem("gradings", value).then(() => { + displayData(); + setLoading(false); + }); + setLoading(false); + }).catch((err) => { + gsecErrorHandlerUI(err); + setLoading(false); + }); + } catch (err) { + gsecErrorHandlerUI(err); + setLoading(false); + } + } else { + displayData(); + setLoading(false); + } } function displayData() { - let transformed_gradings = []; - gradings.forEach((element, index) => { - let bg_color = getHexColorFromString(element["acronym"]); - let fg_color = getForegroundFromBackground(bg_color); - let grading_object = { - start: element["date"].toISOString().substring(0, 10), // če se da direktno date object, se doda še 1a zraven (prefixa tajtlu) (verjetno 1am ura) - title: element["acronym"], - id: index.toString(), - backgroundColor: bg_color, - textColor: fg_color - }; - transformed_gradings.push(grading_object); - }); - calendar_obj.removeAllEvents(); - calendar_obj.addEventSource(transformed_gradings); + let transformed_gradings = []; + gradings.forEach((element, index) => { + let bg_color = getHexColorFromString(element["acronym"]); + let fg_color = getForegroundFromBackground(bg_color); + let grading_object = { + start: element["date"].toISOString().substring(0, 10), // če se da direktno date object, se doda še 1a zraven (prefixa tajtlu) (verjetno 1am ura) + title: element["acronym"], + id: index.toString(), + backgroundColor: bg_color, + textColor: fg_color + }; + transformed_gradings.push(grading_object); + }); + calendar_obj.removeAllEvents(); + calendar_obj.addEventSource(transformed_gradings); } async function validateInputs() { - if ($("#input-grading-name").val() != null && $("#input-grading-name").val().length > 0) { - $("#btn-add-grading").removeAttr("disabled"); - $("#input-grading-name").addClass("valid"); - $("#input-grading-name").removeClass("invalid"); - } else { - $("#btn-add-grading").attr("disabled", "disabled"); - $("#input-grading-name").addClass("invalid"); - $("#input-grading-name").removeClass("valid"); - } + if ($("#input-grading-name").val() != null && $("#input-grading-name").val().length > 0) { + $("#btn-add-grading").removeAttr("disabled"); + $("#input-grading-name").addClass("valid"); + $("#input-grading-name").removeClass("invalid"); + } else { + $("#btn-add-grading").attr("disabled", "disabled"); + $("#input-grading-name").addClass("invalid"); + $("#input-grading-name").removeClass("valid"); + } } function gradingClickHandler(eventClickInfo) { - let grading_id = parseInt(eventClickInfo.event.id); - let grading_subject = gradings[grading_id]["subject"]; - let grading_date_obj = gradings[grading_id]["date"]; - let grading_date = dateString.longFormatted(grading_date_obj); - let grading_description = gradings[grading_id]["description"]; - $("#grading-subject").text(grading_subject); - $("#grading-date").text(grading_date); - $("#grading-description").text(grading_description); - const modal = document.querySelectorAll(".side-modal")[0]; - M.Sidenav.getInstance(modal).open(); + let grading_id = parseInt(eventClickInfo.event.id); + let grading_subject = gradings[grading_id]["subject"]; + let grading_date_obj = gradings[grading_id]["date"]; + let grading_date = dateString.longFormatted(grading_date_obj); + let grading_description = gradings[grading_id]["description"]; + $("#grading-subject").text(grading_subject); + $("#grading-date").text(grading_date); + $("#grading-description").text(grading_description); + const modal = document.querySelectorAll(".side-modal")[0]; + M.Sidenav.getInstance(modal).open(); } function setupPickers() { - // Setup pickers, todo (adding an event), to be stored in messages - var date_object = new Date(); - let elems = document.querySelectorAll('#datepicker-add'); - let options = { - autoClose: true, - format: "dd.mm.yyyy", - defaultDate: date_object, - setDefaultDate: true, - firstDay: 1 - } - instances = M.Datepicker.init(elems, options); + // Setup pickers, todo (adding an event), to be stored in messages + var date_object = new Date(); + let elems = document.querySelectorAll('#datepicker-add'); + let options = { + autoClose: true, + format: "dd.mm.yyyy", + defaultDate: date_object, + setDefaultDate: true, + firstDay: 1 + } + instances = M.Datepicker.init(elems, options); } document.addEventListener("DOMContentLoaded", () => { - checkLogin(); - // Calendar setup - var calendarEl = document.getElementById("calendar"); - calendar_obj = new FullCalendar.Calendar(calendarEl, { - firstDay: 1, - plugins: ["dayGrid"], - defaultDate: getDateString(), - navLinks: false, - editable: false, - events: [], - eventClick: gradingClickHandler, - height: "parent" - }); - calendar_obj.render(); - - // Modal for adding gradings - - // setupPickers(); // todo (adding an event), to be stored in messages - // // Setup modals + checkLogin(); + // Calendar setup + var calendarEl = document.getElementById("calendar"); + calendar_obj = new FullCalendar.Calendar(calendarEl, { + firstDay: 1, + plugins: ["dayGrid"], + defaultDate: getDateString(), + navLinks: false, + editable: false, + events: [], + eventClick: gradingClickHandler, + height: "parent" + }); + calendar_obj.render(); + + // Modal for adding gradings + + // setupPickers(); // todo (adding an event), to be stored in messages + // // Setup modals // const modal_elems = document.querySelectorAll('.modal'); // const modal_options = { // onOpenStart: () => { $("#fab-new").hide() }, @@ -202,15 +202,21 @@ document.addEventListener("DOMContentLoaded", () => { // M.Modal.init(modal_elems, modal_options); - loadGradings(true); - // Setup refresh handler - $("#refresh-icon").click(() => { - loadGradings(true); - }); - // Setup side menu - const menus = document.querySelectorAll(".side-menu"); - M.Sidenav.init(menus, { edge: "right", draggable: true }); - // Setup side modal - const modals = document.querySelectorAll('.side-modal'); - M.Sidenav.init(modals, { edge: 'left', draggable: false }); + loadGradings(true); + // Setup refresh handler + $("#refresh-icon").click(() => { + loadGradings(true); + }); + // Setup side menu + const menus = document.querySelectorAll(".side-menu"); + M.Sidenav.init(menus, { + edge: "right", + draggable: true + }); + // Setup side modal + const modals = document.querySelectorAll('.side-modal'); + M.Sidenav.init(modals, { + edge: 'left', + draggable: false + }); }); diff --git a/assets/js/lang/bundle.js b/assets/js/lang/bundle.js index 10cfd20..4e15832 100644 --- a/assets/js/lang/bundle.js +++ b/assets/js/lang/bundle.js @@ -241,7 +241,7 @@ var langstrings = { 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: "if a meal is not present in the meals collapsible field, this does not necessarily mean it does not exist. Meals that haven't been altered by you and are unchangable (read-only) are not shown for clarity.", + 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", @@ -252,6 +252,7 @@ var langstrings = { errorSettingMeals: "error setting meals", mealSet: "meal set! Reload meals to be sure", selected: "selected", + meal: "meal", // about version: "version", authors: "authors", @@ -439,7 +440,7 @@ var langstrings = { 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: ", // meals - loginError: "napaka pri prijavi", + 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", @@ -448,7 +449,7 @@ var langstrings = { 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: "če nek dan manjka med meniji, to verjetno pomeni, da ni več spremenljiv in zanj niste ročno spremenili menija", + 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", @@ -459,6 +460,7 @@ var langstrings = { errorSettingMeals: "napaka pri nastavljanju menijev", mealSet: "obrok nastavljen! osvežite obroke in se prepričajte sami", selected: "izbrano", + meal: "obrok", // about version: "različica", authors: "avtorji", diff --git a/assets/js/meals.js b/assets/js/meals.js index 891feae..bf9a48e 100644 --- a/assets/js/meals.js +++ b/assets/js/meals.js @@ -1,394 +1,410 @@ const API_ENDPOINT = "https://lopolis-api.gimb.tk/"; +var meals_calendar_obj = null; +var meals_data_global = {}; + +function getDateString() { // ne mene gledat, ne vem, kaj je to. + 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); - }); + 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"); - } + 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); // 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); - } - }); + 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); // 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); + } + }); } 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); - } - - passtocallback.data = allmeals; - passtocallback.token = dataauth.token; - let toBePassed = [passtocallback].concat(callbackparams); - callback(...toBePassed); + 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); + } + + passtocallback.data = allmeals; + passtocallback.token = dataauth.token; + let toBePassed = [passtocallback].concat(callbackparams); + callback(...toBePassed); } async function loadMeals() { - getToken(getMenus, [displayMeals, []]); + getToken(getMenus, [displayMeals, []]); } function displayMeals(meals) { - // console.log(JSON.stringify(meals)); // debug // dela! - - let root_element = document.getElementById("meals-collapsible"); - for (const [date, mealzz] of Object.entries(meals.data)) { - let unabletochoosequestionmark = ""; - let readonly = mealzz.readonly; - var datum = new Date(date); - - // Create root element for a date entry - let subject_entry = document.createElement("li"); - - // Create subject collapsible header - let subject_header = document.createElement("div"); - subject_header.classList.add("collapsible-header"); - subject_header.classList.add("collapsible-header-root"); - - // Create header text element - let subject_header_text = document.createElement("span"); - - if(mealzz.readonly) { - unabletochoosequestionmark = `*${S("readOnly")}*`; - } - - // Use ES6 templates - subject_header_text = `${dateString.day(datum.getDay())}, ${datum.getDate()}. ${dateString.month(datum.getMonth())} ${datum.getFullYear()} (${mealzz.meal} @ ${mealzz.location}) ${unabletochoosequestionmark}`; - - // Create collection for displaying individuals meals - let subject_body = document.createElement("div"); - subject_body.className = "collapsible-body"; - let subject_body_root = document.createElement("ul"); - subject_body_root.className = "collection"; - - for(const [dindex, dmil] of Object.entries(mealzz.menu_options)) { - // Create element for individual meal - let meal_node = document.createElement("li"); - meal_node.className = "collection-item"; - meal_node.classList.add("collection-item") - meal_node.classList.add("meal-node"); - meal_node.dataset["index"] = dindex; - - if (!readonly) { - meal_node.onclick = () => { - setMenu(date, dmil.value); - } - } - - let meal_node_div = document.createElement("div"); - // Node for left text - let meal_lefttext = document.createElement("span"); - // Node for the right text - let meal_righttext = document.createElement("div"); - meal_righttext.className = "secondary-content"; - // Apply different style, if the meal is selected - if (dmil.selected) { - // Text - meal_lefttext.innerHTML = `${dmil.text}`; - // Number - meal_righttext.innerText = S("selected"); - } else { - // Text - meal_lefttext.innerText = dmil.text; - // Number - meal_righttext.innerText = ""; - } - meal_node_div.appendChild(meal_lefttext); - meal_node_div.appendChild(meal_righttext); - meal_node.appendChild(meal_node_div); - subject_body_root.appendChild(meal_node); - } - var subject_header_text_span = document.createElement("span"); - subject_header_text_span.innerText = subject_header_text; - subject_header.appendChild(subject_header_text_span); - subject_body.append(subject_body_root); - subject_entry.append(subject_header); - subject_entry.append(subject_body); - root_element.append(subject_entry); - } - $("#meals-collapsible").append(root_element); - // refreshClickHandlers(); + // console.log(JSON.stringify(meals)); // debug // dela! + 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"); // 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"), + 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; } function clearMeals() { - const table = document.getElementById("meals-collapsible"); - while (table.firstChild) { - table.removeChild(table.firstChild); - } + meals_calendar_obj.removeAllEvents(); } function refreshMeals() { - clearMeals(); - loadMeals(); + clearMeals(); + loadMeals(); } function lopolisLogout() { - localforage.setItem("logged_in_lopolis", false); - $("#meals-collapsible").html(""); - checkLogin(); + 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); - } - }); + 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; - } - - 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"); - } - }); + 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)) { + // 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 choice = {}; + choice[date] = menu; + getToken(getMenus, [setMenus, choice]); } function setupEventListeners() { - $("#meals-login").click(() => { - lopolisLogin(); - }); + $("#meals-login").click(() => { + lopolisLogin(); + }); + + $("#meals-logout").click(() => { + lopolisLogout(); + }); +} - $("#meals-logout").click(() => { - lopolisLogout(); - }); +var mealClickHandler = (eventClickInfo) => { + // console.log("meal clicked!"); // debug + 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)) { // če je beljiv + 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("a"); + menu_option_a_el.innerText = option_object.text; + // console.log(JSON.stringify(meal_object)); // debug + if (option_object.selected != null) { + if(option_object.selected) { + // console.log("selected"); // debug + // + menu_option_a_el.className = "selected-meal"; + } + } + menu_option_a_el.style = "waves-effect"; + 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_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(); } // Initialization code document.addEventListener("DOMContentLoaded", async () => { - checkLogin(); - - setupEventListeners(); - - let coll_elem = document.querySelectorAll('.collapsible'); - M.Collapsible.init(coll_elem, {}); - - // Setup refresh handler - $("#refresh-icon").click(function () { - refreshMeals(); - }); - - let elems = document.querySelectorAll('.modal'); - M.Modal.init(elems, {}); - // Setup side menu - const menus = document.querySelectorAll('.side-menu'); - M.Sidenav.init(menus, { edge: 'right', draggable: true }); - - // Setup side modal - const modals = document.querySelectorAll('.side-modal'); - M.Sidenav.init(modals, { edge: 'left', draggable: false }); - - 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(); + 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(); + + // Setup refresh handler + $("#refresh-icon").click(function() { + refreshMeals(); + }); + + // Setup side menu + const menus = document.querySelectorAll('.side-menu'); + M.Sidenav.init(menus, { + edge: 'right', + draggable: true + }); + + // Setup side modal + const modals = document.querySelectorAll('.side-modal'); + M.Sidenav.init(modals, { + edge: 'left', + draggable: false + }); + + // ne vem, kaj je to spodaj ˇˇˇ + 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(); }); diff --git a/assets/pages-src/gradings.bvr b/assets/pages-src/gradings.bvr index 20a2d39..9a18dae 100644 --- a/assets/pages-src/gradings.bvr +++ b/assets/pages-src/gradings.bvr @@ -1,89 +1,90 @@ <@?i global@> - - - - - - - - Gradings « BežiApp + + - - - - + + + + + + Gradings « BežiApp - - + + + + - - - - - - + + - - - + + + + + + - - - - - + + + - - - - - + + + + + - - + + + + + + + + <@?i navigation@> - + -
-
-
-
+
+
+
+
- - + - <@?i grading-add-modal@> + <@?i grading-add-modal@> - + - + \ No newline at end of file diff --git a/assets/pages-src/meals.bvr b/assets/pages-src/meals.bvr index 0621766..cdfd7d1 100644 --- a/assets/pages-src/meals.bvr +++ b/assets/pages-src/meals.bvr @@ -1,116 +1,158 @@ <@?i global@> - - - - - - - - Meals « BežiApp + + - - - - + + + + + + Meals « BežiApp - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + <@?i navigation@> -
- - - + +
+ + + - + -- cgit v1.2.3