From 3a3246dfecab404df90513989bf84a270e17d1f1 Mon Sep 17 00:00:00 2001 From: sijanec Date: Sat, 26 Sep 2020 21:42:10 +0200 Subject: DNM: started lopolisc/untested, added server nginx conf fileas --- assets/js/lopolisc.js | 271 +++++++++++++++++++++++++++++++++++++++++++++ assets/pages-src/meals.bvr | 2 + 2 files changed, 273 insertions(+) create mode 100644 assets/js/lopolisc.js (limited to 'assets') diff --git a/assets/js/lopolisc.js b/assets/js/lopolisc.js new file mode 100644 index 0000000..1f5291a --- /dev/null +++ b/assets/js/lopolisc.js @@ -0,0 +1,271 @@ +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_NET_POSTBACK_POST = "LOPOLISC NETWORK ERROR (ajax error) in postback POST" +const LOPOLISC_ERR_LOGIN = "LOPOLISC LOGIN ERROR"; +const LOPOLISC_ERR_CHECKOUTS = "LOPOLISC CHECKOUTS ERROR" +const LOPOLISC_SIGNATURE = "lopolisc.js neuradni API - antonsijanec.eu" + +class lopolisc { + + constructor() { + } + + parseAndPost(inputHTML, params, 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 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 + } + } + + 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", + 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); + }); + }, + error: () => { + reject(new Error(LOPOLISC_ERR_NET_POSTBACK_GET)); + } + }); + }); + } + + login(usernameToLogin, passwordToLogin) { + return new Promise((resolve, reject) => { + var dataToSend = { + "Uporabnik": usernameToLogin, + "Geslo": passwordToLogin + }; + this.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 = new Date()) { + return new Promise((resolve) => { + var dataToSend = { + "MesecModel.Mesec": String(date_object.getMonth()), + "MesecModel.Leto": String(date_object.getFullYear()), + "Ukaz": "" + }; + this.postback(LOPOLIS_URL+"/Prehrana/Odjava", dataToSend, "form1", 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")) { + checkouts[element.getElementsByTagName("input")[2].value] = { + checked: 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.getElementByTagName("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, + element.getElementByTagName("input")[2].name: // date + String(element.getElementByTagName("input")[2].value), + element.getElementByTagName("input")[3].name: // prijava id + String(elememt.getElementByTagName("input")[3].value), + element.getElementByTagName("input")[4].name: // readonly + String(element.getElementByTagName("input")[4].value) + } + } + resolve(checkouts); + }); + }); + } + + setCheckouts(odjava_objects) { + return new Promise((resolve) => { + var dataToSend = { "Ukaz": "Shrani" }; + for (const odjava_object of 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 odjava_object of odjava_objects) { + if (!(parsed.getElementById("OdjavaItems_"+odjava_object.index+"__CheckOut".checked == odjava_object.checked)) { + reject(LOPOLISC_ERR_CHECKOUTS); + } + } + resolve(true); + }); + }); + } + + fetchMeals(date_object = new Date()) {//todo: fetchAllMeals naslednja 2 meseca + return new Promise((resolve) => { + var meals = {}; + var dataToSend = { + "Ukaz": "", + "MesecModel.Mesec": String(date_object.getMonth()), + "MesecModel.Leto": String(date_object.getFullYear()) + } + this.postback(LOPOLIS_URL+"/Prehrana/Prednarocanje", {}, null, true). + 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 (option of element.getElementsByTagName("select")[0].options) { + if (option.value.length > 0 || 1==1) { // tudi prazno opcijo pustimo + menuoptions.push({ + value: option.value, + text: option.innerText, + selected: option.selected + }); + } + if (option.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 + } + meals[element.getElementsByTagName("input")[0].value] = { // trying + 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.getElementByTagName("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, + element.getElementByTagName("input")[0].name: // date + String(element.getElementByTagName("input")[0].value), + element.getElementByTagName("input")[1].name: // prijava id + String(elememt.getElementByTagName("input")[1].value), + element.getElementByTagName("input")[2].name: // readonly + String(element.getElementByTagName("input")[2].value) + } + } + resolve(meals); + }); + }); + } + + setMeals(meal_objects) { + return new Promise((resolve) => { + var dataToSend = { "Ukaz": "Shrani" }; + for (const meal_object of meal_objects) { + for (const [meal, 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["+odjava_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 odjava_object of odjava_objects) { + if (!(parsed.getElementById("PrednarocanjeItems_"+odjava_object.index+"__CheckOut".checked == odjava_object.checked)) { + reject(LOPOLISC_ERR_CHECKOUTS); + } + } + resolve(true); + }); + }); + } +} diff --git a/assets/pages-src/meals.bvr b/assets/pages-src/meals.bvr index c0d655b..d98ed56 100644 --- a/assets/pages-src/meals.bvr +++ b/assets/pages-src/meals.bvr @@ -43,6 +43,8 @@ + + -- cgit v1.2.3