diff --git a/.idea/misc.xml b/.idea/misc.xml old mode 100644 new mode 100755 diff --git a/.idea/modules.xml b/.idea/modules.xml old mode 100644 new mode 100755 diff --git a/.idea/php.xml b/.idea/php.xml old mode 100644 new mode 100755 diff --git a/.idea/scopes/html.xml b/.idea/scopes/html.xml old mode 100644 new mode 100755 diff --git a/.idea/scopes/js.xml b/.idea/scopes/js.xml old mode 100644 new mode 100755 diff --git a/.idea/scopes/scss.xml b/.idea/scopes/scss.xml old mode 100644 new mode 100755 diff --git a/.idea/scopes/translator.xml b/.idea/scopes/translator.xml old mode 100644 new mode 100755 diff --git a/.idea/vcs.xml b/.idea/vcs.xml old mode 100644 new mode 100755 diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml old mode 100644 new mode 100755 diff --git a/.idea/wordRotator.iml b/.idea/wordRotator.iml old mode 100644 new mode 100755 index bcf3c2f..3a4de54 --- a/.idea/wordRotator.iml +++ b/.idea/wordRotator.iml @@ -3,7 +3,6 @@ - diff --git a/bin/build.js b/bin/build.js old mode 100644 new mode 100755 diff --git a/bin/concatTranslator.js b/bin/concatTranslator.js old mode 100644 new mode 100755 index 5669ebc..73aa6a9 --- a/bin/concatTranslator.js +++ b/bin/concatTranslator.js @@ -37,7 +37,7 @@ for (var i = 0, n = moduleDirs.length; i < n; i++) { for (var lang in translations) { - console.log(translations[lang]); + // console.log(translations[lang]); var langTranslations = JSON.stringify(translations[lang]); fs.writeFile(outputDir+"/"+lang+".json", langTranslations, err => { if (err){ diff --git a/log/error.log b/log/error.log old mode 100644 new mode 100755 index e66ccc2..28b798f --- a/log/error.log +++ b/log/error.log @@ -4,3 +4,4 @@ 2018-05-23T08:29:19+02:00 ERR (3): Unable to resolve service "Application\Model\Manager\LevelManager" to a factory; are you certain you provided it during configuration? - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/zendframework/zend-servicemanager/src/ServiceManager.php Line: 687 2018-05-23T08:29:41+02:00 ERR (3): Unable to resolve service "Application\Model\Manager\LevelManager" to a factory; are you certain you provided it during configuration? - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/zendframework/zend-servicemanager/src/ServiceManager.php Line: 687 2018-05-23T08:43:12+02:00 ERR (3): Unable to resolve service "Application\Model\Manager\LevelManager" to a factory; are you certain you provided it during configuration? - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/zendframework/zend-servicemanager/src/ServiceManager.php Line: 687 +2018-07-11T20:46:07+02:00 ERR (3): Your proxy directory "data/DoctrineORMModule/Proxy" must be writable - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php Line: 40 diff --git a/log/log.log b/log/log.log old mode 100644 new mode 100755 index e66ccc2..28b798f --- a/log/log.log +++ b/log/log.log @@ -4,3 +4,4 @@ 2018-05-23T08:29:19+02:00 ERR (3): Unable to resolve service "Application\Model\Manager\LevelManager" to a factory; are you certain you provided it during configuration? - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/zendframework/zend-servicemanager/src/ServiceManager.php Line: 687 2018-05-23T08:29:41+02:00 ERR (3): Unable to resolve service "Application\Model\Manager\LevelManager" to a factory; are you certain you provided it during configuration? - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/zendframework/zend-servicemanager/src/ServiceManager.php Line: 687 2018-05-23T08:43:12+02:00 ERR (3): Unable to resolve service "Application\Model\Manager\LevelManager" to a factory; are you certain you provided it during configuration? - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/zendframework/zend-servicemanager/src/ServiceManager.php Line: 687 +2018-07-11T20:46:07+02:00 ERR (3): Your proxy directory "data/DoctrineORMModule/Proxy" must be writable - ErrorCode: 0 File: /var/www/pwa/wordRotator/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php Line: 40 diff --git a/log/php_error.log b/log/php_error.log old mode 100644 new mode 100755 diff --git a/log/php_exceptions.log b/log/php_exceptions.log old mode 100644 new mode 100755 diff --git a/orga/database.sql b/orga/database.sql old mode 100644 new mode 100755 diff --git a/orga/deleteLevels.txt b/orga/deleteLevels.txt old mode 100644 new mode 100755 diff --git a/orga/requirements.list b/orga/requirements.list old mode 100644 new mode 100755 diff --git a/public/.htaccess b/public/.htaccess old mode 100644 new mode 100755 diff --git a/public/core/css/core.css b/public/core/css/core.css old mode 100644 new mode 100755 diff --git a/public/core/css/flashMessenger.css b/public/core/css/flashMessenger.css old mode 100644 new mode 100755 diff --git a/public/core/css/foundation.css b/public/core/css/foundation.css old mode 100644 new mode 100755 diff --git a/public/core/css/framework.css b/public/core/css/framework.css old mode 100644 new mode 100755 diff --git a/public/core/css/settingsSite.css b/public/core/css/settingsSite.css old mode 100644 new mode 100755 diff --git a/public/core/css/style.css b/public/core/css/style.css old mode 100644 new mode 100755 diff --git a/public/core/css/theme.css b/public/core/css/theme.css old mode 100644 new mode 100755 diff --git a/public/core/html/load.html b/public/core/html/load.html old mode 100644 new mode 100755 diff --git a/public/core/html/settings.html b/public/core/html/settings.html old mode 100644 new mode 100755 diff --git a/public/core/html/smartList.html b/public/core/html/smartList.html old mode 100644 new mode 100755 diff --git a/public/css/wordRotator.css b/public/css/wordRotator.css old mode 100644 new mode 100755 diff --git a/public/html/application/end.html b/public/html/application/end.html old mode 100644 new mode 100755 diff --git a/public/html/application/level.html b/public/html/application/level.html old mode 100644 new mode 100755 diff --git a/public/html/application/sync.html b/public/html/application/sync.html old mode 100644 new mode 100755 diff --git a/public/img/share.svg b/public/img/share.svg old mode 100644 new mode 100755 diff --git a/public/img/sms.svg b/public/img/sms.svg old mode 100644 new mode 100755 diff --git a/public/img/telegram.svg b/public/img/telegram.svg old mode 100644 new mode 100755 diff --git a/public/img/test.png b/public/img/test.png old mode 100644 new mode 100755 diff --git a/public/img/whatsapp.svg b/public/img/whatsapp.svg old mode 100644 new mode 100755 diff --git a/public/js/app.js b/public/js/app.js old mode 100644 new mode 100755 index e1c33a0..8dbb78b --- a/public/js/app.js +++ b/public/js/app.js @@ -2359,6 +2359,233 @@ class App { } } +class Dialog { + constructor(content, title) { + this.resolver = null; + this.content = null; + this.backgroundElement = null; + this.cancelable = true; + this.title = Helper.nonNull(title, ""); + this.translatable = true; + this.additionalClasses = ""; + this.buttons = []; + this.result = null; + + if (Helper.isNotNull(content)) { + this.setContent(content); + } + } + + setTitle(title) { + this.title = title; + return this; + } + + setTranslatable(translatable) { + this.translatable = translatable; + } + + setAdditionalClasses(classes) { + this.additionalClasses = classes; + } + + getTitle() { + return this.title; + } + + setCancelable(cancelable) { + this.cancelable = (cancelable === true); + return this; + } + + async setContent(content) { + this.contentPromise = Promise.resolve(content); + this.content = await this.contentPromise; + return this; + } + + addButton(elementOrText, listenerOrResult, shouldClose) { + shouldClose = Helper.nonNull(shouldClose, true); + + let button = null; + if (typeof elementOrText === "string") { + button = document.createElement("button"); + button.classList.add("button"); + button.classList.add("right"); + button.appendChild(Translator.makePersistentTranslation(elementOrText)); + } + else { + button = elementOrText; + } + + let self = this; + if (typeof listenerOrResult !== "function") { + let result = listenerOrResult; + listenerOrResult = function () { + self.result = result; + }; + } + + let callback = null; + if (shouldClose) { + callback = function (e) { + if (Helper.isNotNull(listenerOrResult)) { + listenerOrResult(e); + } + self.close(); + }; + } + else { + callback = listenerOrResult; + } + + if (Helper.isNotNull(callback)) { + button.addEventListener("click", callback); + } + this.buttons.push(button); + } + + async show() { + + let titleElement = document.createElement("span"); + titleElement.classList.add("title"); + if (this.translatable && this.title !== "") { + titleElement.appendChild(Translator.makePersistentTranslation(this.title)); + } + else { + titleElement.innerHTML = this.title; + } + + let titleBar = document.createElement("div"); + titleBar.appendChild(titleElement); + + let contentContainer = document.createElement("div"); + contentContainer.classList.add("content-container"); + + let modalDialog = document.createElement("div"); + modalDialog.className = this.additionalClasses; + modalDialog.classList.add("modal"); + modalDialog.appendChild(titleBar); + modalDialog.appendChild(contentContainer); + + let buttonBar = document.createElement("div"); + buttonBar.classList.add("modal-button-container"); + + for (let i = 0, n = this.buttons.length; i < n; i++) { + buttonBar.appendChild(this.buttons[i]); + } + + await this.contentPromise; + if (!(this.content instanceof Node)) { + this.content = (this.translatable) ? Translator.makePersistentTranslation(this.content) : document.createTextNode(this.content); + } + contentContainer.appendChild(this.content); + + this.backgroundElement = document.createElement("div"); + this.backgroundElement.classList.add("background"); + this.backgroundElement.appendChild(modalDialog); + + this.backgroundElement.querySelector(".modal").appendChild(buttonBar); + this.backgroundElement.style.display = "block"; + + let self = this; + if (this.cancelable) { + let closeButton = document.createElement("span"); + closeButton.classList.add("close"); + closeButton.innerHTML = "×"; + + titleBar.appendChild(closeButton); + closeButton.addEventListener("click", function () { + self.close(); + }); + window.addEventListener("click", function (e) { + if (e.target === self.backgroundElement) { + self.close(); + } + }); + } + + document.body.appendChild(this.backgroundElement); + Translator.getInstance().updateTranslations(); + + return new Promise(function (resolve) { + self.resolver = resolve; + }); + } + + close() { + if (Helper.isNotNull(this.backgroundElement)) { + this.backgroundElement.style.display = "none"; + this.backgroundElement.remove(); + this.backgroundElement = null; + } + if (Helper.isNotNull(this.resolver)) { + this.resolver(this.result); + } + } + + addDefaultButton(){ + this.addButton("confirm-button"); + } +} + +class FlashMessenger { + static deleteMessage(_idNumber, _delayInMilliSeconds) { + _delayInMilliSeconds = Helper.nonNull(_delayInMilliSeconds, 0); + setTimeout(function () { + let elem = document.getElementById("flashMessage" + _idNumber); + elem.fadeOut(.2).then(function () { + elem.remove(); + }); + }, _delayInMilliSeconds); + } + + static addMessage(messageType, messageText, timeToShow, translate){ + + let translationArgs = null; + if (Helper.isNull(messageText) || typeof messageText === "object") + { + translationArgs = messageText; + messageText = messageType; + messageType = FlashMessenger.MESSAGE_TYPE_SUCCESS; + translate = true; + } + translate = Helper.nonNull(translate, false); + + let id = FlashMessenger.messageCount; + + let wrapper = document.createElement("div"); + + let _flashMessage = document.createElement("div"); + _flashMessage.className = "flashMessage " + messageType; + _flashMessage.id = "flashMessage" + id; + _flashMessage.style.opacity = '0'; + _flashMessage.addEventListener("click", function () { + FlashMessenger.deleteMessage(id); + }); + _flashMessage.appendChild((translate) ? Translator.makePersistentTranslation(messageText, translationArgs, "span") : document.createTextNode(messageText)); + + wrapper.appendChild(_flashMessage); + document.getElementById("flashMessageContainer").appendChild(wrapper); + _flashMessage.fadeIn(); + timeToShow = Helper.nonNull(timeToShow, FlashMessenger.defaultTimeToShow); + if (timeToShow > 0) { + FlashMessenger.deleteMessage(FlashMessenger.messageCount, timeToShow); + } + FlashMessenger.messageCount++; + } +} + +FlashMessenger.messageCount = 0; +FlashMessenger.defaultTimeToShow = 3500; +FlashMessenger.LENGTH_SHORT= 1000; + +FlashMessenger.MESSAGE_TYPE_SUCCESS = 'success'; +FlashMessenger.MESSAGE_TYPE_ERROR = 'error'; +FlashMessenger.MESSAGE_TYPE_DEFAULT = 'default'; +FlashMessenger.MESSAGE_TYPE_INFO = 'info'; +FlashMessenger.MESSAGE_TYPE_WARNING = 'warning'; + class InitPromise { static addPromise(promise) @@ -2624,6 +2851,48 @@ class MyDb { }; } +class ScriptLoader { + static loadScript(scriptSrc) { + if (Helper.isNotNull(ScriptLoader.scriptPromises[scriptSrc])) { + return ScriptLoader.scriptPromises[scriptSrc]; + } + else { + let scriptPromise = new Promise(function (resolve) { + let script = document.createElement("script"); + script.src = Helper.basePath(scriptSrc); + script.onload = resolve; + + document.body.appendChild(script); + }); + ScriptLoader.scriptPromises[scriptSrc] = scriptPromise; + return scriptPromise; + } + } + static loadCss(cssFile, media){ + if (Helper.isNotNull(ScriptLoader.cssPromises[cssFile])) { + return ScriptLoader.cssPromises[cssFile]; + } + else { + media = Helper.nonNull(media, "all"); + let cssPromise = new Promise(function (resolve) { + let link = document.createElement("link"); + link.rel='stylesheet'; + link.type="text/css"; + link.href = Helper.basePath(cssFile); + link.media = media; + link.onload = resolve; + + document.head.appendChild(link); + }); + ScriptLoader.cssPromises[cssFile] = cssPromise; + return cssPromise; + } + } +} + +ScriptLoader.scriptPromises = {}; +ScriptLoader.cssPromises = {}; + class ShareButton { constructor(deviceType, icon, callback) { @@ -2761,6 +3030,26 @@ class WhatsappShareButton extends ShareButton { } } +class Fragment extends Context +{ + constructor(site, view) + { + super(view); + this.site = site; + this.active = true; + } + + getSite() + { + return this.site; + } + + isActive() + { + return this.active; + } +} + class Theme { constructor(name, className, icon) @@ -2993,58 +3282,677 @@ function applyPolyfills(){ }); } -SystemSettings.setBasePath("/pwa/wordRotator/public/"); -Translator.supportedLanguages = ["de", "en"]; -Translator.markTranslations = false; +class Constants{} +Constants.SCRIPTS = { + CKEDITOR:"version/2/ckeditor/ckeditor.js", + LIST_JS: "version/1/listjs/list.min.js" +}; -class Segment{ - constructor(element){ - this.rotation = 0; - this.element = element; - this.parent = null; +class DataManager { + static load(url, isCachable, raw) { + isCachable = Helper.nonNull(isCachable, false); + raw = Helper.nonNull(raw, false); + let fullUrl = (isCachable) ? Helper.basePath(DataManager.cachePath + url) : Helper.basePath(DataManager.dataPath + url); + return fetch(fullUrl, {"credentials": "same-origin"}).then(function (res) { + if (raw) { + return res.text(); + } + return res.json(); + }).catch(function (e) { + console.error("error", e); + if (!raw) { + return { + "success": false, + "errors": [ + "not-online" + ] + } + } + }); } - getCurrentRotations(rotations){ - return rotations; + static send(url, params) { + let fullUrl = Helper.basePath(DataManager.dataPath + url); + + if (!(params instanceof FormData)) { + let newParams = new FormData(); + for (let k in params) { + newParams.append(k, params[k]); + } + params = newParams; + } + + return fetch(fullUrl, { + "credentials": "same-origin", + "method": "POST", + "body": params + }).then(function (res) { + return res.json(); + }).catch(function (e) { + console.error("error", e); + return { + "success": false, + "errors": [ + "not-online" + ] + } + }); } - sameAs(otherSegment){ - return false; + static buildQuery(values) { + return Helper.buildQuery(values); } +} - setParent(parent) - { - this.parent = parent; - } - - getLevel() - { - if (this.parent!==null) +DataManager.dataPath = "data/"; +DataManager.cachePath = "cached/"; + +class Form { + constructor(formElem, url, method, isCachable) { + this.formElem = formElem; + this.method = Helper.nonNull(method, Helper.nonNull(formElem["method"], "POST")); + this.isCachable = (Helper.nonNull(isCachable, this.method.toLowerCase() === "get") === true); + + this.isBusy = false; + + if (typeof url === "string") { - return this.parent.getLevel(); + this.submitHandler = function(values){ + if (self.method.toLowerCase() === "get") { + return (DataManager.load(url + DataManager.buildQuery(values), self.isCachable)); + } + else { + return (DataManager.send(url, values)); + } + }; + } + else { + this.submitHandler = url; + } + + let self = this; + + this.submitCallback = null; + this.errorCallback = function (errors) { + self.setErrors(errors); + }; + + formElem.addEventListener("submit", function (e) { + e.preventDefault(); + self.doSubmit(e); + }); + + for (let i = 0, n = formElem.elements.length; i < n; i++) { + let elem = formElem.elements[i]; + elem.addEventListener("change", function () { + if (this.value.trim() !== "") { + this.classList.add("notEmpty"); + } + else { + this.classList.remove("notEmpty"); + } + this.setCustomValidity(""); + }); + elem.addEventListener("keydown", function () { + this.setCustomValidity(""); + }); } } - isSolved(){ - return (this.rotation === 0); - } - - async rotate(){ - return Promise.resolve(); - }; + onError(errorHandler, ownHandlerForOptimisticLocking){ + ownHandlerForOptimisticLocking = Helper.nonNull(ownHandlerForOptimisticLocking, true); + let callback = null; - _updateElement(){}; - - applyRotations(rotations){ - return rotations; + if (ownHandlerForOptimisticLocking){ + callback = function(errors){ + if (Array.isArray(errors) && errors.indexOf("optimistic-locking-exception") >= 0){ + let dialog = new Dialog("optimistic-locking-dialog", "optimistic-locking-dialog-title"); + dialog.addDefaultButton(); + dialog.show(); + } + else + { + errorHandler(errors); + } + }; + } + else + { + callback = errorHandler; + } + this.errorCallback = callback; } - getElement() - { - return this.element; + doSubmit() { + if (!this.isBusy) { + let self = this; + return this.submit().then(function (res) { + if (res["success"]) { + if (self.submitCallback !== null) { + return self.submitCallback(res["result"]); + } + } + else if (Helper.isNotNull(self.errorCallback)) { + return self.errorCallback(res["errors"]); + } + }); + } + } + + load(url, isCached) { + this.setValues(DataManager.load(url, isCached).then(function (values) { + if (values["success"]) { + return values["result"]; + } + return {}; + })); + return this; + } + + setValues(valuePromise) { + this.setIsBusy(true); + + let self = this; + return Promise.resolve(valuePromise).then(function (values) { + self.setIsBusy(false); + for (let k in values) { + if (Helper.isNotNull(self.formElem.elements[k])) { + self.formElem.elements[k].value = Helper.htmlspecialcharsDecode(values[k]); + if (Helper.isNotNull(values[k]) && (""+values[k]).trim() !== "") { + self.formElem.elements[k].classList.add("notEmpty"); + } + else { + self.formElem.elements[k].classList.remove("notEmpty"); + } + } + } + return self; + }); + } + + setErrors(errors) { + let hasElem = false; + let firstError = null; + + for (let k in errors) { + if (Helper.isNotNull(this.formElem.elements[k]) && this.formElem.elements[k].type !== "hidden" + && Helper.isNull(this.formElem.elements[k].readonly) && ( + Helper.isNull(this.formElem.elements[k].disabled) || !this.formElem.elements[k].disabled) + ) { + this.formElem.elements[k].setCustomValidity(Translator.translate(Helper.nonNull(errors[k], "form-default-error"))); + hasElem = true; + } + if (Helper.isNull(firstError)) { + firstError = Helper.nonNull(errors[k], "form-default-error"); + } + } + if (!hasElem && Helper.isNotNull(firstError)) { + for (let k in this.formElem.elements) { + if (this.formElem.elements[k].type !== "hidden") { + this.formElem.elements[k].setCustomValidity(Translator.translate(firstError)); + hasElem = true; + break; + } + } + } + if (hasElem) { + this.formElem.querySelector("input[type=submit]").click(); + } + } + + setIsBusy(isBusy) { + this.isBusy = isBusy; + if (this.isBusy) { + this.formElem.classList.add("sending"); + } + else { + this.formElem.classList.remove("sending"); + } + } + + submit() { + let self = this; + return new Promise(function (resolve) { + self.setIsBusy(true); + let values = new FormData(self.formElem); + resolve(self.submitHandler(values)); + }).then(function (data) { + self.setIsBusy(false); + return data; + }); + } + + onSubmit(callback) { + this.submitCallback = callback; } } +class SettingsManager { + static getInstance() { + if (SettingsManager._instance === null) { + SettingsManager._instance = new SettingsManager(); + } + return SettingsManager._instance; + } + + constructor() { + this._settings = null; + this._localStorageKey = "settings"; + } + + getSettings() { + if (Helper.isNull(this._settings)) { + this._loadSettings(); + } + return this._settings; + } + + getSetting(name, defaultValue) { + const settings = this.getSettings(); + if (Helper.isNotNull(settings[name])) { + return settings[name].value; + } + else { + return defaultValue; + } + } + + deleteSetting(name) { + this.getSettings(); + delete this._settings[name]; + this._saveSettings(); + } + + setSetting(name, value) { + this.getSettings(); + this._settings[name] = { + date: new Date().getTime(), + value: value + }; + this._saveSettings(); + } + + setSettings(settingsObject) { + this.getSettings(); + for (const k in settingsObject) { + this._settings[k] = settingsObject[k]; + } + this._saveSettings(); + } + + _loadSettings() { + this._settings = localStorage.getItem(this._localStorageKey); + if (this._settings === null) { + this._settings = {}; + } + else { + this._settings = JSON.parse(this._settings); + } + } + + _saveSettings() { + if (this._settings !== null) { + localStorage.setItem(this._localStorageKey, JSON.stringify(this._settings)); + } + } +} + +SettingsManager._instance = null; + +class SmartColumn{ + constructor(name, label, translateable){ + this._name = name; + this._label = label; + this._translateable = Helper.nonNull(translateable, true); + this._sortable = true; + + this._index = -1; + + this._clickListener = null; + } + + setClickListener(listener) + { + this._clickListener = listener; + return this; + } + + setIndex(index) + { + this._index = index; + } + + getName() + { + return this._name; + } + + getLabel() + { + return this._label; + } + + getHeadElement() + { + const headElement = document.createElement("th"); + headElement.appendChild((this._translateable)?Translator.makePersistentTranslation(this._label):document.createTextNode(this._label)); + + if (this._sortable) + { + headElement.classList.add("sort"); + headElement["dataset"]["sort"] = this._name; + } + + headElement["dataset"]["column"] = this._index; + + this._headElement = headElement; + return this._headElement; + } + + getValueName(){ + return this._name; + } + + prepareData(myData, rowData) + { + return myData; + } + + getItemElement(){ + const element = document.createElement("td"); + element.classList.add(this._name); + element["dataset"]["column"] = this._index; + + if (Helper.isNotNull(this._clickListener)) + { + element.classList.add("clickable"); + } + + return element; + } + + click(tableCell, table, event){ + if (Helper.isNotNull(this._clickListener)) + { + this._clickListener(tableCell, table, event); + } + } +} + +class ConstSmartColumn extends SmartColumn{ + constructor(name, label, translatable, valueTranslatable) { + super(name, label, translatable); + this._sortable = false; + this._valueTranslatable = Helper.nonNull(valueTranslatable, false); + } + + getValueName() { + return null; + } + + getItemElement(){ + const element = super.getItemElement(); + element.classList.remove(this._name); + element.appendChild((this._valueTranslatable)?Translator.makePersistentTranslation(this._name):document.createTextNode(this._name)); + return element; + } +} + +class DataSmartColumn extends SmartColumn{ + constructor(name, label, translateable) { + translateable = Helper.nonNull(translateable, false); + super(name, label, translateable); + } + + getHeadElement() { + return document.createTextNode(""); + } + + getValueName() { + return { + "data":[this._name] + }; + } + + getItemElement() { + return document.createTextNode(""); + } +} + +class ImgConstSmartColumn extends ConstSmartColumn{ + constructor(name, label, translateable) { + super(name, label, translateable); + this._valueTranslatable = false; + } + + getItemElement() { + const element = super.getItemElement(); + const imgElement = document.createElement("img"); + imgElement["src"] = this._name; + + element.removeAllChildren().appendChild(imgElement); + return element; + } +} + +class ListHelper { + constructor(id, options, values) { + this._tableElement = id; + this._options = Helper.nonNull(options, {}); + this._values = values; + + if (typeof this._tableElement === "string") { + this._tableElement = document.getElementById(this._tableElement); + } + + this._columns = []; + if (Array.isArray(options)) { + this._columns = options; + } + else if (Helper.isNotNull(options["columns"])) { + this._columns = options["columns"]; + } + } + + prepareData(data) { + console.log("prepareData", data); + if (Helper.isNotNull(data)) { + for (let i = 0, n = data.length; i < n; i++) { + data[i] = this.prepareDataset(data[i]); + } + } + return data; + } + + prepareDataset(dataset) { + console.log("prepareDataset", dataset); + for (let i = 0, n = this._columns.length; i < n; i++) { + if (Helper.isNotNull(dataset[this._columns[i].getName()])) { + dataset[this._columns[i].getName()] = this._columns[i].prepareData(dataset[this._columns[i].getName()], dataset); + } + } + return dataset; + } + + createTable() { + if (Helper.isNotNull(this._columns)) { + this.updateColumns(); + } + + let id = this._tableElement; + let options = this._options; + let values = this._values; + + options["item"] = Helper.nonNull(options["item"], id["id"] + "-template-item"); + options["page"] = Helper.nonNull(options["page"], 5); + options["pagination"] = Helper.nonNull(options["pagination"], { + "outerWindow": 1, + "innerWindow": 1 + }); + + let template = document.getElementById(options["item"]); + if (template) { + options["item"] = template.outerHTML; + template.remove(); + } + + values = this.prepareData(values); + + const list = new List(id, options, values); + let self = this; + id.querySelector("." + Helper.nonNull(options["listClass"], "list")).addEventListener("click", function (e) { + let columnElem = e.target.closest("td[data-column]"); + const column = parseInt(columnElem["dataset"]["column"]); + if (self._columns.length > column) { + self._columns[column].click(columnElem, list, e); + } + }); + this.list = list; + + return list; + } + + updateColumns() { + const head = document.createElement("tr"); + const item = document.createElement("tr"); + const valueNames = []; + + for (let i = 0, n = this._columns.length; i < n; i++) { + this._columns[i].setIndex(i); + + head.appendChild(this._columns[i].getHeadElement()); + item.appendChild(this._columns[i].getItemElement()); + + const valueName = this._columns[i].getValueName(); + if (Helper.isNotNull(valueName)) { + valueNames.push(valueName); + } + } + const header = this._tableElement.querySelector("thead"); + const footer = this._tableElement.querySelector("tfoot"); + + if (Helper.isNotNull(header)) { + header.removeAllChildren().appendChild(head); + } + if (Helper.isNotNull(footer)) { + footer.removeAllChildren().appendChild(Helper.cloneNode(head)); + } + + + this._options["item"] = item.outerHTML; + this._options["valueNames"] = valueNames; + } + + getList() { + return this.list; + } + + updateItem(valueName, value, newValues) { + const items = this.list.get(valueName, value); + if (Helper.isNotNull(items) && items.length >= 1) { + newValues = this.prepareDataset(newValues); + items[0].values(newValues); + } + } + + setBusy(isBusy) { + if (isBusy) { + this._tableElement.classList.add("sending"); + } + else { + this._tableElement.classList.remove("sending"); + } + } +} + +class SettingsSite extends AbstractSite$1 { + constructor(siteManager) { + super(siteManager, 'public/html/settings.html', "settings"); + for (let k in SettingsSite.settingsFragments) { + this.addSettingsFragment(k, new SettingsSite.settingsFragments[k](this)); + } + this.active = null; + } + + addSettingsFragment(name, settingsFragment) { + this.addFragment("#settings-fragments", settingsFragment); + delete this.fragments["#settings-fragments"]; + this.fragments[name] = settingsFragment; + } + + onStart() { + let res = super.onStart(); + if (Helper.isNotNull(this.active) && !this.fragments[this.active].isActive()) { + this.setActive(null); + } + + this.buildList(); + return res; + } + + setActive(name) { + if (Helper.isNotNull(this.active)) { + this.fragments[this.active].inflatePromise.then(function (view) { + view.classList.remove("active"); + }); + this.findBy("#show-fragment-" + this.active).classList.remove("active"); + } + this.active = name; + if (Helper.isNotNull(this.active)) { + this.fragments[this.active].inflatePromise.then(function (view) { + view.classList.add("active"); + }); + this.findBy("#show-fragment-" + this.active).classList.add("active"); + } + } + + buildList() { + let listNameElem = this.findBy("#settings-fragment-list"); + listNameElem.removeAllChildren(); + + let self = this; + for (let k in this.fragments) { + if (this.fragments[k].isActive()) { + + let liElement = document.createElement("li"); + liElement.id = "show-fragment-" + k; + liElement.appendChild(Translator.makePersistentTranslation(k, null, "a")); + liElement.addEventListener("click", function () { + self.setActive(k); + }); + listNameElem.appendChild(liElement); + + if (Helper.isNull(this.active)) { + this.setActive(k); + } + } + } + } + + static addSettingsFragment(name, settingsFragment) { + SettingsSite.settingsFragments[name] = settingsFragment; + } + + static setAddSettingsSite(addLink) { + SettingsSite.shouldAddSettingsSite = addLink; + } +} + +SettingsSite.settingsFragments = {}; +SettingsSite.shouldAddSettingsSite = true; + +InitPromise.addPromise(function (app) { + if (SettingsSite.shouldAddSettingsSite) { + app.addDeepLink("settings", SettingsSite.name); + + let settingsAction = new MenuAction("settings", function () { + app.startSite(SettingsSite.name); + }, MenuAction.SHOW_FOR_LARGE, 10000); + settingsAction.setIcon("img/settings.png"); + app.addDefaultAction(settingsAction); + } +}); + class ScaleHelper { scaleTo(scale, fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight) { margin = Helper.nonNull(margin, 10); @@ -3098,6 +4006,2263 @@ class ScaleHelper { } } +class Code { + constructor(args) { + if (typeof args === "string") { + args = { + "code": args + }; + } + this.args = args; + this.isCacheable = false; + } + + setIsCacheable(isCacheable) { + this.isCacheable = isCacheable; + } + + getIsCacheable() { + return this.isCacheable; + } + + activate() { + return DataManager.send("c/code", this.args); + } +} + +class CodeSite extends AbstractSite$1 { + constructor(siteManager) { + super(siteManager, "core/html/load.html", "code"); + } + + onConstruct(args) { + super.onConstruct(args); + console.log(args); + + let resPromise = Promise.resolve(); + if (Helper.isNotNull(args["code"])) { + let code = args["code"]; + let isCachable = Helper.nonNull(args["cachable"], false); + + let codeObject = new Code(code); + codeObject.setIsCacheable(isCachable); + + let self = this; + resPromise = codeObject.activate().then(function (res) { + if (!res["success"]) { + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate(res["errors"][0])); + } + else { + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate(Helper.nonNull(res["result"]["successMessage"], "code-activated"))); + } + self.finish(); + }); + } + } +} + +InitPromise.addPromise(function (app) { + app.addDeepLink("code", CodeSite); +}); + +class UserManager { + static init(app) { + UserManager.getMeUrl = null; + UserManager.userData = { + online: false, + id: null, + accesses: ["default"] + }; + UserManager.app = app; + + UserManager.fetchMePromise = new Promise(function (resolve) { + UserManager.fetchMePromiseResolver = resolve; + }); + } + + static setData(data) { + UserManager.userData = Object.assign(UserManager.userData, data); + let siteManager = UserManager.app.getSiteManager(); + + if (siteManager) + siteManager.redrawCurrentActionBar(); + } + + static fetchMe(url) { + UserManager.getMeUrl = Helper.nonNull(url, UserManager.getMeUrl); + return DataManager.load(UserManager.getMeUrl).then(function (result) { + if (result["success"]) { + UserManager.setData(result["result"]); + } + UserManager.fetchMePromiseResolver(); + }); + } + + static logOut() { + return DataManager.load("u/logout").then(function (data) { + if (data["success"]) { + UserManager.setData(data["result"]); + let siteManager = UserManager.app.getSiteManager(); + + if (siteManager) + siteManager.refreshCurrentSite(); + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("logged-out-successfully")); + } + }); + } + + static hasAccess(access) { + // console.log("Has access", access, UserManager.userData["accesses"].indexOf(access), UserManager.userData); + return (UserManager.userData["accesses"].indexOf(access) >= 0) + } + + static addCurrentUserListener(userId, listener) { + UserManager.addIsLoggedInListener(function (isLoggedIn) { + listener(isLoggedIn && UserManager.isCurrentUser(userId)); + }); + } + + static addIsLoggedInListener(listener) { + this.fetchMePromise.then(function () { + listener(UserManager.isLoggedIn()); + }); + } + + static isCurrentUser(userId) { + return UserManager.userData.id === userId; + } + + static isLoggedIn() { + return Helper.isNotNull(UserManager.userData) && Helper.isNotNull(UserManager.userData.id); + } +} + +InitPromise.addPromise(function(app){ + UserManager.init(app); + return UserManager.fetchMe("u/me").then(function(){ + UserManager.addIsLoggedInListener(function (isLoggedIn) { + if (isLoggedIn) { + const settingsManager = SettingsManager.getInstance(); + const settings = settingsManager.getSettings(); + for (let k in settings) { + settings[k]["value"] = JSON.stringify(settings[k]["value"]); + } + DataManager.send("u/syncSettings", settings).then(function(res){ + if (res["success"]) + { + for (let k in res["result"]) + { + res["result"][k]["value"] = JSON.parse(res["result"][k]["value"]); + } + settingsManager.setSettings(res["result"]); + } + }); + } + }); + }); +}); + +class UserAction extends MenuAction { + constructor(title, callback, icon, order, access) { + super(title, callback, icon, order); + this._access = Helper.nonNull(access, "default"); + } + + getVisible() { + // console.log("Action-access: ", this._access); + return (super.getVisible() && UserManager.hasAccess(this._access)); + } + + getAccess() { + return this._access; + } + + copy(instance){ + let copy = super.copy(Helper.nonNull(instance, new UserAction())); + copy._access = this._access; + return copy; + } +} + +class SystemSettings$1 { + static setBasePath(basePath) + { + SystemSettings$1._basePath = basePath; + } + static getBasePath() + { + return SystemSettings$1._basePath; + } +} +SystemSettings$1.setBasePath("/"); + +class MenuAction$1 { + constructor(title, callback, showFor, order) { + this.title = Helper$1.nonNull(title, null); + this.callback = callback; + this.showFor = Helper$1.nonNull(showFor, MenuAction$1.SHOW_FOR_MEDIUM); + this.order = Helper$1.nonNull(order, 1000); + + this._menu = null; + this._activated = true; + this._visible = true; + this.id = MenuAction$1.maxId++; + this._icon = null; + this._shouldTranslate = true; + this._copies = []; + } + + setTitle(title) + { + this.title = title; + } + + setShouldTranslate(shouldTranslate) + { + this._shouldTranslate = shouldTranslate; + } + + getTitle() + { + return this.title; + } + + getShouldTranslate() + { + return this._shouldTranslate; + } + + remove(removeCopies) { + removeCopies = Helper$1.nonNull(removeCopies, false); + if (Helper$1.isNotNull(this._menu)) { + console.log(this._menu); + this._menu.removeAction(this); + this._menu = null; + } + if (removeCopies) + { + for (let i = 0, n = this._copies.length; i < n; i++) { + this._copies[i].remove(); + } + } + } + + getMenu() { + return this._menu; + } + + setMenu(value) { + this._menu = value; + } + + getVisible() { + return this._visible; + } + + setVisible(value) { + if (value !== this._visible) { + this._visible = value; + this.redraw(); + } + } + + getActivated() { + return this._activated; + } + + getIcon() { + return this._icon; + } + + setIcon(value) { + this._icon = value; + } + + getId() + { + return this.id; + } + + redraw() { + if (Helper$1.isNotNull(this._menu)) { + this._menu.updateAction(this); + } + } + copy(instance){ + let copy = Helper$1.nonNull(instance, new MenuAction$1()); + copy.title = this.title; + copy.callback = this.callback; + copy.showFor = this.showFor; + copy.order = this.order; + + copy._activated = this._activated; + copy._visible = this._visible; + copy._icon = this._icon; + copy._shouldTranslate = this._shouldTranslate; + + copy._menu = null; + copy.id = MenuAction$1.maxId++; + this._copies.push(copy); + return copy; + } + + redrawMenu() + { + if (Helper$1.isNotNull(this._menu)) { + this._menu.redraw(); + } + } +} +MenuAction$1.maxId = 0; + +MenuAction$1.SHOW_ALWAYS = "always"; +MenuAction$1.SHOW_FOR_MEDIUM = "medium"; +MenuAction$1.SHOW_FOR_LARGE = "large"; +MenuAction$1.SHOW_NEVER = "never"; + +class OpenSubmenuAction$1 extends MenuAction$1 { + constructor(title, menu, showFor, order) { + super(title, function (action) { + action.getSubmenu().toggle(); + action.redraw(); + }, showFor, order); + + this.submenu = menu; + menu.setParentAction(this); + } + + getSubmenu() { + return this.submenu; + } + + copy(instance) { + instance = super.copy(Helper$1.nonNull(instance, new OpenSubmenuAction$1(null, this.submenu.copy()))); + return instance; + } +} + +class Menu$1 { + constructor(parentElementSelector) { + this.actions = []; + this.submenus = []; + if (typeof parentElementSelector === 'string') { + this.parentElements = document.querySelectorAll(parentElementSelector); + } + else if (Array.isArray(parentElementSelector)) { + this.parentElements = parentElementSelector; + } + else { + this.parentElements = [parentElementSelector]; + } + } + + copy(instance) + { + instance = Helper$1.nonNull(instance, new Menu$1([])); + + instance.actions = []; + for (let i = 0, n = this.actions.length; i < n; i++) { + instance.actions.push(this.actions[i].copy()); + } + + instance.submenus = []; + for (let i = 0, n = this.submenus.length; i < n; i++) { + instance.submenus.push(this.submenus[i].copy()); + } + + return instance; + } + + addAction(action) { + if (Helper$1.includesNot(this.actions, action)) { + this.actions.push(action); + this.redraw(); + action.setMenu(this); + if (action instanceof OpenSubmenuAction$1) { + this.submenus.push(action.getSubmenu()); + } + } + } + + draw() { + if (Helper$1.isNotNull(this.parentElements)) { + this.sortActions(); + + let actionElements = []; + for (let i = 0, n = this.actions.length; i < n; i++) { + let element = this.renderAction(this.actions[i]); + this.actions[i]._htmlElement = element; + actionElements.push(element); + } + for (let i = 0, n = this.parentElements.length; i < n; i++) { + this.parentElements[i].removeAllChildren(); + for (let i2 = 0, n2 = actionElements.length; i2 < n2; i2++) { + this.parentElements[i].appendChild(Helper$1.cloneNode(actionElements[i2])); + } + this.parentElements[i].onclick = this._getOnClickListener(); + } + } + } + + _getOnClickListener() { + let menu = this; + return function (event) { + let _element = event.target; + if (_element.matches('.action') || _element.matches('.action *')) { + // while (!_element.matches('.action > a')) { + // _element = _element.parentNode; + // } + _element = _element.closest(".action"); + let actionId = parseInt(_element.dataset["id"]); + for (let i = 0, n = menu.actions.length; i < n; i++) { + if (menu.actions[i].id === actionId) { + if (typeof menu.actions[i].callback === 'function' && menu.actions[i].getActivated()) { + menu.actions[i].callback(menu.actions[i], event); + } + return menu.actions[i]; + } + } + for (let i = 0, n = menu.submenus.length; i < n; i++) { + if (menu.submenus[i].click(actionId, event)) { + return menu.submenus[i]; + } + } + } + return null; + }; + } + + /** @protected */ + renderAction(action) { + let aElement = document.createElement("a"); + if (typeof action.callback === 'string') { + aElement.href = action.callback; + } + + if (Helper$1.isNotNull(action.getIcon())) { + let iconElement = document.createElement("img"); + iconElement.src = action.getIcon(); + iconElement.classList.add('action-image'); + if (action.getShouldTranslate()) + { + iconElement.dataset["translationTitle"] = action.title; + } + aElement.appendChild(iconElement); + } + let title = action.getTitle(); + if (action.getShouldTranslate()) + { + title = Translator$1.makePersistentTranslation(title); + } + else + { + title = document.createTextNode(title); + } + aElement.appendChild(title); + + return this.renderLiElement(aElement, action) + } + + /** @protected */ + renderLiElement(aElement, action) { + let liElement = document.createElement("li"); + liElement.classList.add('action'); + liElement.appendChild(aElement); + liElement.dataset["id"] = action.id; + if (Helper$1.isNotNull(action.getIcon())) { + liElement.classList.add("img"); + } + + if (!action.getVisible()) + { + liElement.classList.add("hidden"); + } + + if (action instanceof OpenSubmenuAction$1) { + action.getSubmenu().draw(); + liElement.appendChild(action.getSubmenu().getParentElement()); + liElement.classList.add("is-dropdown-submenu-parent"); + liElement.classList.add("opens-right"); + } + return liElement; + } + + /** @private */ + sortActions() { + this.actions = this.actions.sort(function (first, second) { + return first.order - second.order; + }); + } + + _getElementsForAction(action){ + let elements = []; + for (let i = 0, n = this.parentElements.length; i < n; i++) { + let elem = this.parentElements[i].querySelector("[data-id=\""+action.getId()+"\"]"); + Helper$1.isNull(elem) || elements.push(elem); + } + return elements + } + + updateAction(action) + { + let oldElements = this._getElementsForAction(action); + if (oldElements.length === 0) + { + return; + } + + let element = this.renderAction(action); + action._htmlElement = element; + + for (let i = 0, n = oldElements.length; i < n; i++) { + oldElements[i].replaceWith(Helper$1.cloneNode(element)); + } + } + + removeAction(action) + { + let index = this.actions.indexOf(action); + if (index > 0) + { + this.actions.splice(index, 1); + let oldElements = this._getElementsForAction(action); + for (let i = 0, n = oldElements.length; i < n; i++) { + oldElements[i].remove(); + } + if (action instanceof OpenSubmenuAction$1) { + let index = this.submenus.indexOf(action.getSubmenu()); + this.submenus.splice(index, 1); + } + } + } + + redraw() { + this.draw(); + } +} + +Menu$1.SHOW_ALWAYS = "always"; +Menu$1.SHOW_FOR_MEDIUM = "medium"; +Menu$1.SHOW_FOR_SMEDIUM = "smedium"; +Menu$1.SHOW_FOR_LARGE = "large"; +Menu$1.SHOW_NEVER = "never"; + +class Submenu$1 extends Menu$1 +{ + constructor() + { + let menuElement = document.createElement("ul"); + menuElement.classList.add("menu"); + menuElement.classList.add("vertical"); + menuElement.classList.add("submenu"); + menuElement.classList.add("is-dropdown-submenu"); + menuElement.classList.add("first-sub"); + super(menuElement); + + this.parentAction = null; + this.isOpen = false; + } + + + + copy(instance) + { + instance = super.copy(Helper$1.nonNull(instance, new Submenu$1())); + instance.parentElements = []; + for (let i = 0, n = this.parentElements.length; i < n; i++) { + instance.parentElements.push(Helper$1.cloneNode(this.parentElements[i])); + } + instance.parentAction = this.parentAction; + instance.isOpen = this.isOpen; + return instance; + } + + setParentAction(action) + { + this.parentAction = action; + } + + draw() + { + super.draw(); + if (Helper$1.isNotNull(this.parentElements)) + { + let self = this; + for (let i = 0, n = this.parentElements.length; i < n; i++) { + let closeListener = document.createElement("div"); + closeListener.classList.add("close-listener"); + closeListener.onclick = function(e){ + console.log(e); + self.close(); + }; + this.parentElements[i].insertBefore(closeListener, this.parentElements[i].firstElementChild); + } + } + } + + getParentElement() + { + return this.parentElements[0]; + } + + _getOnClickListener() + { + return function () {}; + } + + click(actionId, event) + { + for (let i = 0, n = this.actions.length; i < n; i++) { + if (this.actions[i].id === actionId) + { + if (typeof this.actions[i].callback === 'function' && this.actions[i].getActivated()) { + this.actions[i].callback(this.actions[i], event); + } + this.close(); + return true; + } + } + return false; + } + + toggle() + { + if (this.isOpen) + { + this.close(); + } + else + { + this.open(); + } + } + + open() + { + this.isOpen = true; + for (let i = 0, n = this.parentElements.length; i < n; i++) { + this.parentElements[i].classList.add("js-dropdown-active"); + } + if (Helper$1.isNotNull(this.parentAction)) + { + this.parentAction.redraw(); + } + } + close() + { + this.isOpen = false; + for (let i = 0, n = this.parentElements.length; i < n; i++) { + this.parentElements[i].classList.remove("js-dropdown-active"); + } + if (Helper$1.isNotNull(this.parentAction)) + { + this.parentAction.redraw(); + } + } +} + +class TranslatorDB$1 { + constructor() { + this._indexedDB = indexedDB || mozIndexedDB || webkitIndexedDB || msIndexedDB; + this._version = 3; + + let self = this; + this._dbPromise = new Promise(function (resolve, reject) { + let request = self._indexedDB.open("Translator", self._version); + request.onupgradeneeded = function (event) { + let db = event.target.result; + self._upgradeDb(db); + }; + request.onsuccess = function (event) { + let db = event.target.result; + resolve(db); + }; + request.onerror = function (event) { + reject(event); + }; + }).catch(function(e){ + console.error(e); + }); + } + + _upgradeDb(db) { + try { + db.deleteObjectStore("currentLang"); + db.deleteObjectStore("translations"); + } + catch (e) { + console.warn(e); + } + let currentLangObjectStore = db.createObjectStore("currentLang", {"keyPath": "id"}); + let translationsObjectStore = db.createObjectStore("translations", {"keyPath": ["lang","key"]}); + translationsObjectStore.createIndex("lang", "lang", {"unique": false}); + } + + setLanguage(lang) { + this._dbPromise.then(function (db) { + let transaction = TranslatorDB$1._openTransaction(["currentLang"], "readwrite", db); + let currentLangObjectStore = transaction.objectStore("currentLang"); + currentLangObjectStore.put({"id": 1, "lang": lang}); + }).catch(function(e){ + console.error(e); + }); + } + + saveTranslationsForLang(lang, translations) { + return this._dbPromise.then(function (db) { + return new Promise(function (resolve) { + let transaction = TranslatorDB$1._openTransaction(["translations"], "readwrite", db); + let translationsObjectStore = transaction.objectStore("translations"); + for (let k in translations) { + translationsObjectStore.put({"lang": lang, "key": k, "translation": translations[k]}); + } + transaction.oncomplete = function () { + resolve(); + }; + }); + }).catch(function(e){ + // console.error(e); + }); + } + + loadTranslationsForLang(lang) { + return this._dbPromise.then(function (db) { + return new Promise(function (resolve) { + let transaction = TranslatorDB$1._openTransaction(["translations"], "readonly", db); + let translationsObjectStore = transaction.objectStore("translations"); + let index = translationsObjectStore.index("lang"); + let request = index.openCursor(IDBKeyRange.only(lang)); + + let translations = {}; + request.onsuccess = function (e) { + let cursor = e.target.result; + if (cursor) { + + let translation = cursor.value; + translations[translation["key"]] = translation["translation"]; + cursor.continue(); + } + }; + transaction.oncomplete = function(){ + resolve(translations); + }; + }); + }).catch(function(e){ + console.error(e); + return {}; + }); + } + + getLanguage() { + return this._dbPromise.then(function (db) { + return new Promise(function (resolve) { + let transaction = TranslatorDB$1._openTransaction(["currentLang"], "readonly", db); + let currentLangObjectStore = transaction.objectStore("currentLang"); + let req = currentLangObjectStore.get(1); + req.onsuccess = function (e) { + let data = e.currentTarget.result; + if (data) + { + resolve(data["lang"]); + } + else + { + resolve(null); + } + }; + req.onerror = function (e) { + resolve(null); + }; + }); + }).catch(function(e){ + // console.error(e); + }); + } + + static _openTransaction(name, transactionMode, db) { + let transaction = null; + try { + transaction = db.transaction(name, transactionMode); + } + catch (e) { + console.warn(e); + transaction = db.transaction(name); + } + return transaction; + } +} + +class Translator$1 { + constructor() { + this._translations = []; + this._db = new TranslatorDB$1(); + this._currentLanguage = null; + this._supportedLanguages = Translator$1.supportedLanguages; + this._baseLanguage = Translator$1.baseLanguage; + this._languageBasePath = Translator$1.languageBasePath; + this._markUntranslatedTranslations = Translator$1.markUntranslatedTranslations; + this._markTranslations = Translator$1.markTranslations; + + let self = this; + this._initPromise = this.loadBaseLanguage().then(function () { + return self.loadUserLanguage(); + }); + } + + _loadLanguage(language) { + let self = this; + return fetch(Helper$1.basePath(this._languageBasePath + language + ".json")).then(function (result) { + return result.json(); + }).then(function (res) { + self._translations[language] = Object.assign(res, self._translations[language]); + self._db.saveTranslationsForLang(language, self._translations[language]); + }).catch(function (err) { + console.error("could not load lang " + language + " because of error: ", err); + }); + } + + loadBaseLanguage() { + let self = this; + return this._loadLanguage(this._baseLanguage).then(function () { + self._currentLanguage = self._baseLanguage; + if (typeof document !== 'undefined') { + document.getElementsByTagName("html")[0].setAttribute("lang", self._baseLanguage); + } + }); + }; + + static setLanguage(language) { + let instance = Translator$1.getInstance(); + if (instance) { + return instance.setLanguage(language); + } + } + + setLanguage(language) { + if (this._currentLanguage === language) { + this.updateTranslations(); + return Promise.resolve(); + } + + if (this._supportedLanguages.indexOf(language) === -1) { + return Promise.resolve(); + } + + this._currentLanguage = language; + if (typeof localStorage !== 'undefined') { + localStorage.setItem("language", language); + } + this._db.setLanguage(language); + + let self = this; + return this._loadLanguage(language).then(function () { + if (typeof document !== 'undefined') { + document.getElementsByTagName("html")[0].setAttribute("lang", language); + } + self.updateTranslations(); + }); + } + + static translate(key, args) { + let instance = Translator$1.getInstance(); + if (instance) { + return instance.translate(key, args); + } + return ""; + } + + translate(key, args) { + if (typeof key === 'object' && Helper$1.isNotNull(key)) { + key = this.addDynamicTranslation(key); + } + + let translation = null; + if (Helper$1.isNotNull(this._translations[this._currentLanguage]) && Helper$1.isNotNull(this._translations[this._currentLanguage][key])) { + translation = this._translations[this._currentLanguage][key]; + } + + if (Helper$1.isNull(translation)) { + if (Translator$1.logMissingTranslations) { + console.warn("missing translation for language " + this._currentLanguage + " and key " + key); + } + if (Helper$1.isNotNull(this._translations[this._baseLanguage])) { + translation = this._translations[this._baseLanguage][key]; + } + + if (Helper$1.isNull(translation)) { + if (Translator$1.logMissingTranslations) { + console.error("missing base translation for key " + key + ". FIX IT"); + } + translation = key; + } + if (this._markUntranslatedTranslations) { + translation = ">>" + translation + "<<"; + } + } + + if (this._markTranslations) { + translation = "$" + translation + "$"; + } + + if (args !== undefined) { + translation = translation.format(args); + } + + return translation; + } + + static addDynamicTranslation(trans) { + let instance = Translator$1.getInstance(); + if (instance) { + return instance.addDynamicTranslation(trans); + } + } + + addDynamicTranslation(trans) { + let key = trans["key"]; + delete trans["key"]; + for (let lang in trans) { + if (trans.hasOwnProperty(lang)) { + if (Helper$1.isNull(this._translations[lang])) { + this._translations[lang] = {}; + } + this._translations[lang][key] = trans[lang]; + } + } + return key; + } + + updateTranslations() { + if (typeof document !== 'undefined') { + let elements = document.querySelectorAll("[data-translation]"); + for (let i = 0, max = elements.length; i < max; i++) { + if (elements[i].dataset["translation"] != "") { + try { + elements[i].innerHTML = this.translate(elements[i].dataset["translation"], (elements[i].dataset["translationArgs"] !== undefined) ? JSON.parse(elements[i].dataset["translationArgs"]) : undefined); + } + catch (err) { + console.error("wrong configured translation: " + err); + } + } + for (let k in elements[i].dataset) { + if (k.startsWith("translation") && !k.endsWith("Args")) { + try { + elements[i][k.substr(11).toLowerCase()] = this.translate(elements[i].dataset[k], (elements[i].dataset[k + "Args"] !== undefined) ? JSON.parse(elements[i].dataset[k + "Args"]) : undefined); + } + catch (err) { + console.error("wrong configured translation: " + err); + } + } + } + } + } + } + + loadUserLanguage() { + let userLanguage = localStorage.getItem("language"); + if (Helper$1.isNull(userLanguage) || this._supportedLanguages.indexOf(userLanguage) === -1) { + let userLanguages = []; + if (Helper$1.isNotNull(navigator.languages)) { + userLanguages = navigator.languages.slice(0); //.slice(0) klont das Array. Behebt einen Bug in Firefox + } + + if (navigator.language !== undefined) { + userLanguages.push(navigator.language); + } + //sicherstellen, dass überhaupt eine Sprache gefunden wird + userLanguages.push(this._baseLanguage); + + if (userLanguages !== undefined) { + for (let i = 0, numLanguages = userLanguages.length; i < numLanguages; i++) { + if (this._supportedLanguages.indexOf(userLanguages[i]) !== -1) { + userLanguage = userLanguages[i]; + break; + } + } + } + } + return this.setLanguage(userLanguage.toLowerCase()) + } + + static makePersistentTranslation(key, args, tag) { + tag = Helper$1.nonNull(tag, "span"); + if (typeof key === 'object') { + key = Translator$1.addDynamicTranslation(key); + } + + if (typeof document !== 'undefined') { + let htmlElem = document.createElement(tag); + htmlElem.dataset["translation"] = key; + if (args !== undefined) { + htmlElem.dataset["translationArgs"] = JSON.stringify(args); + } + htmlElem.innerHTML = Translator$1.translate(key, args); + return htmlElem; + } + } + + static generateChangeLanguageMenuAction() { + let submenu = new Submenu$1(); + submenu.addAction(new MenuAction$1("en", function () { + Translator$1.getInstance().setLanguage("en"); + })); + submenu.addAction(new MenuAction$1("de", function () { + Translator$1.getInstance().setLanguage("de"); + })); + return new OpenSubmenuAction$1("current-lang", submenu, Menu$1.SHOW_ALWAYS) + } + + static init() { + Translator$1.instance = new Translator$1(); + // Translator.loadBaseLanguage().then(function () { + // Translator.loadUserLanguage(); + // }); + } + + static getInstance() { + return Translator$1.instance; + } +} +Translator$1.logMissingTranslations = false; + +Translator$1.instance = null; + +Translator$1.baseLanguage = "en"; +Translator$1.supportedLanguages = [ + "de", + "en" +]; +Translator$1.markUntranslatedTranslations = true; +Translator$1.markTranslations = false; +Translator$1.languageBasePath = "js/lang/"; +Translator$1.currentLanguage = null; +Translator$1.translations = {}; + +class Helper$1 { + static init() { + Helper$1.heightMmToPxFactor = null; + Helper$1.widthMmToPxFactor = null; + } + + static includesNot(array, value, fromIndex) { + return -1 === array.indexOf(value, fromIndex); + } + + static includes(array, value, fromIndex) { + return !Helper$1.includesNot(array, value, fromIndex); + } + + static isSet() { + if (arguments.length > 0) { + const object = arguments[0]; + let keys = Array.prototype.slice.call(arguments, 1); + return (Helper$1.isNotNull(object) && (keys.length === 0 || Helper$1.isSet.apply(null, [object[keys[0]]].concat(keys.slice(1))))); + } + return false; + } + + static isNull(variable) { + return (variable === null || variable === undefined); + } + + static isNotNull(variable) { + return !Helper$1.isNull(variable); + } + + static nonNull(val1, val2) { + if (Helper$1.isNotNull(val1)) { + return val1; + } + return val2; + } + + static notEmpty(value) { + return !Helper$1.empty(value); + } + + static buildQuery(values) { + let queryStrings = []; + for (let k in values) { + queryStrings.push(encodeURIComponent(k) + "=" + encodeURIComponent(values[k])); + } + return "?" + queryStrings.join("&"); + } + + static empty(value) { + return (Helper$1.isNull(value) || (typeof value === 'string' && value.trim() === "")) + } + + static inflateElementsFromString(string) { + let template = document.createElement('template'); + template.innerHTML = string; + return template.content.childNodes; + } + + static createLoadingSymbol() { + let svgNS = "http://www.w3.org/2000/svg"; + + let loader = document.createElement("div"); + loader.className = 'loader'; + + let svg = document.createElementNS(svgNS, "svg"); + svg.setAttribute('viewBox', "0 0 32 32"); + svg.setAttribute("widh", "32"); + svg.setAttribute("height", "32"); + + let circle = document.createElementNS(svgNS, "circle"); + circle.setAttribute("id", "spinner"); + circle.setAttribute("cx", "16"); + circle.setAttribute("cy", "16"); + circle.setAttribute("r", "14"); + circle.setAttribute("fill", "none"); + + svg.appendChild(circle); + loader.appendChild(svg); + + return loader; + } + + static basePath(url) { + return SystemSettings$1.getBasePath() + url; + } + + static isMobileApple() { + return navigator.userAgent.match(/iPhone|iPad|iPod/i); + } + + static isMobile() { + return (navigator.userAgent.match(/Android|BlackBerry|Opera Mini|IEMobile/i) !== null || Helper$1.isMobileApple() || (typeof window.orientation !== "undefined" || window.orientation === false || window.orientation === null)); + } + + static select(e) { + let range = document.createRange(); + range.selectNodeContents(e); + let sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } + + static format(number, leadingZeros) { + number = "" + number; + while (number.length < leadingZeros) { + number = "0" + number; + } + return number; + } + + static cloneNode(srcNode) { + let destNode = srcNode.cloneNode(true); + destNode.onclick = srcNode.onclick; + return destNode; + } + + static encodeToBase(stringToEncode, base) { + let encodedString = ""; + let charlength = Math.floor(Math.log(265) / Math.log(base)); + for (let i = 0, n = stringToEncode.length; i < n; i++) { + let value = stringToEncode.charCodeAt(i).toString(base); + let joinLength = value.length % charlength; + if (joinLength > 0) { + let joinArray = new Array(charlength + 1 - (joinLength)); //+1, da join nur zwischen elemente einfügt + value = joinArray.join("0") + value; + } + encodedString += value; + } + return encodedString; + } + + static decodeToBase(stringToDecode, base) { + let charlength = Math.floor(Math.log(265) / Math.log(base)); + let values = stringToDecode.match(new RegExp(".{1," + charlength + "}", "g")) || []; + let encodedString = ""; + for (let i = 0, n = values.length; i < n; i++) { + encodedString += String.fromCharCode(parseInt(values[i], base)); + } + return encodedString; + } + + static toggleVisibility(elem) { + if (elem.style.display === "none") { + elem.style.display = ""; + return true; + } + else { + elem.style.display = "none"; + return false; + } + } + + static print(content) { + let printContent = document.getElementById("print-content"); + if (content instanceof Element) { + printContent.removeAllChildren(); + printContent.appendChild(content); + } + else { + printContent.innerHTML = content; + } + window.print(); + } + + static strftime(sFormat, date, useUTC) { + if (!(date instanceof Date)) date = new Date(date); + useUTC = Helper$1.nonNull(useUTC, false); + let nDay = (useUTC) ? date.getUTCDay() : date.getDay(), + nDate = (useUTC) ? date.getUTCDate() : date.getDate(), + nMonth = (useUTC) ? date.getUTCMonth() : date.getMonth(), + nYear = (useUTC) ? date.getUTCFullYear() : date.getFullYear(), + nHour = (useUTC) ? date.getUTCHours() : date.getHours(), + aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], + isLeapYear = function () { + if ((nYear & 3) !== 0) return false; + return nYear % 100 !== 0 || nYear % 400 === 0; + }, + getThursday = function () { + let target = new Date(date); + target.setDate(nDate - ((nDay + 6) % 7) + 3); + return target; + }, + zeroPad = function (nNum, nPad) { + return ('' + (Math.pow(10, nPad) + nNum)).slice(1); + }; + + return sFormat.replace(/%[a-z]/gi, function (sMatch) { + return { + '%a': Translator$1.makePersistentTranslation(aDays[nDay].slice(0, 3)).outerHTML, + '%A': Translator$1.makePersistentTranslation(aDays[nDay]).outerHTML, + '%b': Translator$1.makePersistentTranslation(aMonths[nMonth].slice(0, 3)).outerHTML, + '%B': Translator$1.makePersistentTranslation(aMonths[nMonth]).outerHTML, + '%c': date.toUTCString(), + '%C': Math.floor(nYear / 100), + '%d': zeroPad(nDate, 2), + '%e': nDate, + '%f': zeroPad(date.getTime() % 1000, 4), + '%F': date.toISOString().slice(0, 10), + '%G': getThursday().getFullYear(), + '%g': ('' + getThursday().getFullYear()).slice(2), + '%H': zeroPad(nHour, 2), + '%I': zeroPad((nHour + 11) % 12 + 1, 2), + '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth > 1 && isLeapYear()) ? 1 : 0), 3), + '%k': '' + nHour, + '%l': (nHour + 11) % 12 + 1, + '%m': zeroPad(nMonth + 1, 2), + '%M': zeroPad(date.getMinutes(), 2), + '%p': (nHour < 12) ? 'AM' : 'PM', + '%P': (nHour < 12) ? 'am' : 'pm', + '%s': Math.round(date.getTime() / 1000), + '%S': zeroPad(date.getSeconds(), 2), + '%u': nDay || 7, + '%V': (function () { + let target = getThursday(), + n1stThu = target.valueOf(); + target.setMonth(0, 1); + let nJan1 = target.getDay(); + if (nJan1 !== 4) target.setMonth(0, 1 + ((4 - nJan1) + 7) % 7); + return zeroPad(1 + Math.ceil((n1stThu - target) / 604800000), 2); + })(), + '%w': '' + nDay, + '%x': date.toLocaleDateString(), + '%X': date.toLocaleTimeString(), + '%y': ('' + nYear).slice(2), + '%Y': nYear, + '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'), + '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1') + }[sMatch] || sMatch; + }); + } + + static cloneJson(obj) { + // https://stackoverflow.com/questions/4120475/how-to-create-and-clone-a-json-object/17502990#17502990 + let i; + + // basic type deep copy + if (Helper$1.isNull(obj) || typeof obj !== 'object') { + return obj + } + // array deep copy + if (obj instanceof Array) { + let cloneA = []; + for (i = 0; i < obj.length; ++i) { + cloneA[i] = Helper$1.cloneJson(obj[i]); + } + return cloneA; + } + if (obj instanceof Date) + { + return new Date(obj.getTime()); + } + // object deep copy + let cloneO = {}; + for (i in obj) { + cloneO[i] = Helper$1.cloneJson(obj[i]); + } + return cloneO; + } + + static htmlspecialcharsDecode(text) { + const map = { + '&': '&', + '&': "&", + '<': '<', + '>': '>', + '"': '"', + ''': "'", + '’': "’", + '‘': "‘", + '–': "–", + '—': "—", + '…': "…", + '”': '”' + }; + + if (Helper$1.isNotNull(text) && typeof text.replace === "function") { + return text.replace(/\&[\w\d\#]{2,5}\;/g, function (m) { + return map[m]; + }); + } + return text; + } + + static formDataFromObject(obj) { + let formData = new FormData(); + for (let k in obj) { + formData.set(k, obj[k]); + } + return formData; + } + + static scaleContentRecursive(element, content) { + + let elementStyle = window.getComputedStyle(element); + let contentStyle = window.getComputedStyle(content); + + if (contentStyle.height > elementStyle.height || contentStyle.width > elementStyle.width) { + return Helper$1.scaleDownContentRecursive(element, content); + } + } + + static scaleDownContentRecursive(element, content) { + Helper$1.convertChildrenToRelativeRecursive(element); + + let elementStyle = window.getComputedStyle(element); + let contentStyle = window.getComputedStyle(content); + + let runs = 0; + let fontSize = parseFloat(contentStyle.getPropertyValue("font-size")); + let width = contentStyle.width; + let height = contentStyle.height; + while (contentStyle.height > elementStyle.height || contentStyle.width > elementStyle.width) { + fontSize *= 0.95; + + if (height > elementStyle.height) { + height *= 0.95; + } + if (width > contentStyle.width) { + width *= 0.95; + } + content.style["font-size"] = fontSize + "px"; + content.style["max-height"] = height + "px"; + content.style["max-width"] = width + "px"; + + runs++; + if (runs > 2000) { + console.log("breaked"); + break; + } + } + Helper$1.convertToRelative(content); + + contentStyle = window.getComputedStyle(content); + content.style["font-size"] = (parseFloat(contentStyle.getPropertyValue("font-size")) / parseFloat(document.documentElement.clientHeight) * 100) + "vh"; + } + + static convertChildrenToRelativeRecursive(element) { + let children = element.childNodes; + for (let i = 0, n = children.length; i < n; i++) { + if (children[i] instanceof Element) { + Helper$1.convertToRelative(children[i]); + Helper$1.convertChildrenToRelativeRecursive(children[i]); + } + } + } + + static convertToRelative(element) { + let hasTransitionClass = (element.classList.contains("no-transtition")); + + element.classList.add("no-transition"); + + let parent = element.parentNode; + + console.log(element); + let elementStyle = window.getComputedStyle(element); + let parentStyle = window.getComputedStyle(parent); + + let fontSize = parseFloat(elementStyle.getPropertyValue("font-size")) / parseFloat(parentStyle.getPropertyValue("font-size")); + + let maxHeight = elementStyle.height; + let maxWidth = elementStyle.width; + + let pHeight = parentStyle.height; + let pWidth = parentStyle.width; + + let relativeAttributes = element.style; + relativeAttributes['max-height'] = Math.floor(maxHeight / pHeight * 100) + "%"; + relativeAttributes['margin-left'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-left')) / pWidth * 100) + "%"; + relativeAttributes['margin-right'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-right')) / pWidth * 100) + "%"; + relativeAttributes['margin-top'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-top')) / pHeight * 100) + "%"; + relativeAttributes['margin-bottom'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-bottom')) / pHeight * 100) + "%"; + relativeAttributes['max-width'] = Math.floor(maxWidth / pWidth * 100) + "%"; + relativeAttributes["font-size"] = fontSize + "em"; + // console.log(relativeAttributes); + // element.css(relativeAttributes); + + if (!hasTransitionClass) { + element.classList.remove("no-transition"); + } + } + + static isChrome() { + let isChromium = window.chrome, + winNav = window.navigator, + vendorName = winNav.vendor, + isOpera = winNav.userAgent.indexOf("OPR") > -1, + isIEedge = winNav.userAgent.indexOf("Edge") > -1, + isIOSChrome = winNav.userAgent.match("CriOS"); + + if (isIOSChrome) { + return true; + } else { + return isChromium !== null && + typeof isChromium !== "undefined" && + vendorName === "Google Inc." && + isOpera === false && + isIEedge === false; + } + } + + static getIndexedObject(array, keyValue) { + let obj = {}; + for (let i = 0, n = array.length; i < n; i++) { + obj[array[i][keyValue]] = array[i]; + } + return obj; + } + + static invertKeyValues(obj) { + let new_obj = {}; + + for (let prop in obj) { + if (obj.hasOwnProperty(prop)) { + new_obj[obj[prop]] = prop; + } + } + + return new_obj; + } + + static toArray(object) { + let res = []; + for (let k in object) { + res.push(object[k]); + } + return res; + } +} +Helper$1.init(); + +class ActionBarMenu$1 extends Menu$1 { + static init() { + function parseStyleToObject(str) { + let styleObject = {}; + + if (typeof str !== 'string') { + return styleObject; + } + + str = str.trim().slice(1, -1); // browsers re-quote string style values + + if (!str) { + return styleObject; + } + + styleObject = str.split('&').reduce(function (ret, param) { + const parts = param.replace(/\+/g, ' ').split('='); + let key = parts[0]; + let val = parts[1]; + key = decodeURIComponent(key); + + // missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + val = val === undefined ? null : decodeURIComponent(val); + + if (!ret.hasOwnProperty(key)) { + ret[key] = val; + } else if (Array.isArray(ret[key])) { + ret[key].push(val); + } else { + ret[key] = [ret[key], val]; + } + return ret; + }, {}); + + return styleObject; + } + + let cssStyle = document.getElementsByClassName('foundation-mq'); + if (cssStyle.length === 0) { + return; + } + let queries = []; + cssStyle = parseStyleToObject(window.getComputedStyle(cssStyle[0]).getPropertyValue('font-family')); + for (let key in cssStyle) { + if (cssStyle.hasOwnProperty(key)) { + queries.push({ + _name: key, + value: 'only screen and (min-width: ' + cssStyle[key] + ')' + }); + } + } + + window.addEventListener('resize', function () { + if (Helper$1.isNotNull(ActionBarMenu$1.currentMenu)) { + ActionBarMenu$1.currentMenu.updateToggleButton(); + } + }); + let responsiveMenu = document.getElementById("responsive-menu"); + document.getElementById("responsive-menu-toggle").onclick = function () { + if (window.getComputedStyle(responsiveMenu).getPropertyValue('display') === 'none') { + responsiveMenu.style.display = 'block'; + } + else if (Helper$1.isNotNull(ActionBarMenu$1.currentMenu)) { + ActionBarMenu$1.currentMenu.close(); + + } + }; + responsiveMenu.firstElementChild.addEventListener("click", function (e) { + if (e.target === responsiveMenu.firstElementChild && Helper$1.isNotNull(ActionBarMenu$1.currentMenu)) { + ActionBarMenu$1.currentMenu.close(); + + } + } + ); + ActionBarMenu$1.queries = queries; + } + + static _getCurrentSize() { + let matched; + + for (let i = 0, n = ActionBarMenu$1.queries.length; i < n; i++) { + let query = ActionBarMenu$1.queries[i]; + + if (matchMedia(query.value).matches) { + matched = query; + } + } + + if (typeof matched === 'object') { + return matched._name; + } else { + return matched; + } + } + + renderLiElement(aElement, action) { + let liElement = super.renderLiElement(aElement, action); + liElement.classList.add(action.showFor); + return liElement; + } + + static filterVisibleElements(elements) { + let visibleElements = []; + for (let i = 0, n = elements.length; i < n; i++) { + if (!elements[i].classList.contains("hidden")) { + visibleElements.push(elements[i]); + } + } + return visibleElements; + } + + updateToggleButton() { + let size = ActionBarMenu$1._getCurrentSize(); + let firstParentElement = this.parentElements[0]; + if (ActionBarMenu$1.filterVisibleElements(firstParentElement.getElementsByClassName(Menu$1.SHOW_FOR_LARGE)).length > 0 && (size === "medium" || size === "smedium" || size === "small") || + ActionBarMenu$1.filterVisibleElements(firstParentElement.getElementsByClassName(Menu$1.SHOW_FOR_MEDIUM)).length > 0 && (size === "smedium" || size === "small") || + ActionBarMenu$1.filterVisibleElements(firstParentElement.getElementsByClassName(Menu$1.SHOW_FOR_SMEDIUM)).length > 0 && (size === "small") || + ActionBarMenu$1.filterVisibleElements(firstParentElement.getElementsByClassName(Menu$1.SHOW_NEVER)).length > 0) { + document.getElementById("responsive-menu-toggle").style.display = 'block'; + } else { + document.getElementById("responsive-menu-toggle").style.display = 'none'; + if (Helper$1.isNotNull(ActionBarMenu$1.currentMenu)) { + ActionBarMenu$1.currentMenu.close(); + } + } + } + + _getOnClickListener() { + let superListener = super._getOnClickListener(); + return function (event) { + let action = superListener(event); + if (!(action instanceof OpenSubmenuAction$1) && Helper$1.isNotNull(ActionBarMenu$1.currentMenu)) { + ActionBarMenu$1.currentMenu.close(); + } + } + } + + draw(parentElement) { + let returnValue = super.draw(parentElement); + this.updateToggleButton(); + + ActionBarMenu$1.currentMenu = this; + return returnValue; + } + + close() { + document.getElementById("responsive-menu").style.display = 'none'; + for (let i = 0, n = this.submenus.length; i < n; i++) { + this.submenus[i].close(); + } + } + + + removeAction(action) { + let res = super.removeAction(action); + this.updateToggleButton(); + return res; + } +} + +ActionBarMenu$1.queries = []; +ActionBarMenu$1.currentMenu = null; +ActionBarMenu$1.init(); + +class ChainAble$1{ + constructor() + { + this.promise = Promise.resolve(); + } + + _chain(func){ + if (typeof func !== "function") + { + return this._chain(function(){ + return Promise.resolve(func); + }); + } + else + { + this.promise = this.promise.then(func); + } + return this; + } +} + +class AbstractGapiResponse$1 extends ChainAble$1{ + constructor(gameService, params) + { + super(); + this.gameService = gameService; + if (Helper$1.isNotNull(params)) + { + this.setValues(params); + } + } + setValues(params){} + load(){} +} + +class Achievement$1 extends AbstractGapiResponse$1 { + setHiddenIconUrl(hiddenIconUrl) + { + this.hiddenIconUrl = hiddenIconUrl; + } + + setValues(params) { + let self = this; + this._chain(params)._chain(function (res) { + self.achievementType = res["achievementType"]; + self.description = res["description"]; + self.experiencePoints = res["experiencePoints"]; + self.id = res["id"]; + self.initialState = res["initialState"]; + self.isRevealedIconUrlDefault = res["isRevealedIconUrlDefault"]; + self.isUnlockedIconUrlDefault = res["isUnlockedIconUrlDefault"]; + self.name = res["name"]; + self.revealedIconUrl = res["revealedIconUrl"]; + self.unlockedIconUrl = res["unlockedIconUrl"]; + + self.achievementState = res["achievementState"]; + // self.experiencePoints = res["experiencePoints"]; //oben bereits gesetzt + // self.id = res["id"]; //oben bereits gesetzt + self.lastUpdatedTimestamp = res["lastUpdatedTimestamp"]; + }); + return this.promise; + } + + show(elem) { + let self = this; + this._chain(function () { + let achievementImg = elem.querySelector(".achievement-img"); + let achievementTitle = elem.querySelector(".achievement-title"); + let achievementDescription = elem.querySelector(".achievement-description"); + let achievementLastTimestamp = elem.querySelector(".achievement-lastTimestamp"); + let achievementXp = elem.querySelector(".achievement-xp"); + + if (self.achievementState === "UNLOCKED") { + achievementImg.src = self.unlockedIconUrl; + achievementLastTimestamp.innerText = Helper$1.strftime("%d %a %Y", parseInt(self.lastUpdatedTimestamp)); + } + else if (self.achievementState === "REVEALED") { + achievementImg.src = self.revealedIconUrl; + } + else { + achievementImg.src = self.hiddenIconUrl; + achievementTitle.appendChild(Translator$1.makePersistentTranslation("achievement-hidden-title")); + achievementDescription.appendChild(Translator$1.makePersistentTranslation("achievement-hidden-description")); + return; + } + + achievementTitle.innerText = self.name; + achievementDescription.innerText = self.description; + achievementXp.innerText = self.experiencePoints+" XP"; + }); + return this.promise; + } +} + +class InitPromise$1 +{ + static addPromise(promise) + { + if (typeof promise === 'function') + { + let func = promise; + promise = InitPromise$1.mainPromise.then(function(app){ + return (func(app)); + }); + } + InitPromise$1.promises.push(promise); + } + + static resolve(app) + { + InitPromise$1.mainResolver(app); + return InitPromise$1.mainPromise.then(function(){ + return Promise.all(InitPromise$1.promises); + }); + } +} +InitPromise$1.promises = []; +InitPromise$1.mainPromise = new Promise(function(resolver){ + InitPromise$1.mainResolver = resolver; +}); + +class ShareButton$1 { + constructor(deviceType, icon, callback) + { + this._deviceType = deviceType; + this._icon = icon; + this._callback = callback; + } + + shouldShowFor(deviceType) + { + return (deviceType === (deviceType & this._deviceType)) + } + + getIcon() + { + return this._icon; + } + + getCallback() + { + return this._callback; + } +} +ShareButton$1.TYPE_DESKTOP = 1; +ShareButton$1.TYPE_MOBILE_APPLE = 2; +ShareButton$1.TYPE_MOBILE_LEFTOVER = 4; +ShareButton$1.TYPE_MOBILE = ShareButton$1.TYPE_MOBILE_APPLE+ShareButton$1.TYPE_MOBILE_LEFTOVER; +ShareButton$1.TYPE_ALL = ShareButton$1.TYPE_DESKTOP+ShareButton$1.TYPE_MOBILE; + +class ShareManager$1 { + static init() { + ShareManager$1.shareButtons = []; + } + + static addShareButton(shareButton) { + ShareManager$1.shareButtons.push(shareButton); + } + + static generateDefaultShareElement(shareUrl) + { + return ShareManager$1.generateShareElement(shareUrl, ShareManager$1.getDefaultGenerateCallback()); + } + + static generateDefaultShareElementForButtons(shareUrl, buttons) + { + return ShareManager$1.generateShareElementForButtons(shareUrl, buttons, ShareManager$1.getDefaultGenerateCallback()); + } + + static generateShareElement(shareUrl, generateCallback) { + return ShareManager$1.generateShareElementForButtons(shareUrl, ShareManager$1.shareButtons, generateCallback); + } + + static generateShareElementForButtons(shareUrl, buttons, generateCallback) + { + let shareButtonElement = document.createElement("div"); + let currentDeviceType = ShareManager$1.getCurrentDeviceType(); + for (let i = 0, n = buttons.length; i < n; i++) { + if (buttons[i].shouldShowFor(currentDeviceType)) { + let elem = generateCallback(buttons[i], shareUrl); + elem.onclick = function(event){ + buttons[i].getCallback()(shareUrl, this, event); + }; + shareButtonElement.appendChild(elem); + } + } + return shareButtonElement; + } + + static getCurrentDeviceType() { + if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) { + return ShareButton$1.TYPE_MOBILE_APPLE; + } + else if ((navigator.userAgent.match(/Android|BlackBerry|Opera Mini|IEMobile/i) !== null || (typeof window.orientation !== "undefined"))) { + return ShareButton$1.TYPE_MOBILE_LEFTOVER; + } + else { + return ShareButton$1.TYPE_DESKTOP; + } + } + + static getDefaultGenerateCallback() + { + return function(button){ + let linkElement = document.createElement("a"); + let iconElement = document.createElement("img"); + linkElement.appendChild(iconElement); + + iconElement.src = Helper$1.basePath(button.getIcon()); + iconElement.classList.add("share-icon"); + + return linkElement; + } + } +} + +ShareManager$1.init(); + +class UserSite extends AbstractSite$1{ + + constructor(siteManager, view, deepLink, access) { + super(siteManager, view, deepLink); + this._access = access; + } + + onConstruct(args) { + if (!UserManager.hasAccess(this._access)) + { + this.startSite(Achievement$1); + this.finish({ + "error":403 + }); + return; + } + return super.onConstruct(args); + } + + onStart(args) { + if (!UserManager.hasAccess(this._access)) + { + this.startSite(Achievement$1); + this.finish({ + "error":403 + }); + return; + } + return super.onStart(args); + } +} + +class LoginForm extends Form { + + constructor(formElem, url, method, isCachable) { + super(formElem, url, method, isCachable); + + let emailElem = formElem.querySelector("#email"); + let passwordElem = formElem.querySelector("#password"); + + let listener = function(){ + emailElem.setCustomValidity(""); + passwordElem.setCustomValidity(""); + }; + + emailElem.addEventListener("keydown", listener); + passwordElem.addEventListener("keydown", listener); + } +} + +class RegistrationForm extends Form { + constructor(formElem, url, method, isCachable) { + super(formElem, url, method, isCachable); + + this.pw1 = formElem.querySelector("#password1"); + this.pw2 = formElem.querySelector("#password2"); + + let self=this; + this.pw1.addEventListener("change", function(){ + self.checkPw(); + }); + this.pw2.addEventListener("change", function(){ + self.checkPw(); + }); + } + + checkPw(){ + // if (this.pw1.value !== this.pw2.value || this.pw1.value.length < 8) + // { + // + // } + } +} + +class UserFragment extends Fragment{ + + constructor(site, view, access) { + super(site, view); + this._access = access; + } + + isActive() { + return super.isActive() && UserManager.hasAccess(this._access); + } +} + +class PasswordSettingsFragment extends UserFragment{ + constructor(site) + { + super(site, "userManagement/html/fragments/passwordSettings.html", "online"); + } + onFirstStart() { + let res = super.onFirstStart(); + let form = new Form(document.getElementById("change-password-form"), "u/passwordSettings/set", "post"); + form.onSubmit(function(res){ + for (let i = 0, n = res.length; i < n; i++) + { + FlashMessenger.addMessage(res[i]); + } + form.setValues({ + "oldPassword":"", + "newPassword1":"", + "newPassword2":"" + }); + }); + return res; + } +} +InitPromise.addPromise(function(){ + SettingsSite.addSettingsFragment("password-settings", PasswordSettingsFragment); +}); + +class UserSettingsFragment extends UserFragment{ + constructor(site) + { + super(site, "userManagement/html/fragments/userSettings.html", "online"); + } + + onFirstStart() { + let res = super.onFirstStart(); + (new Form(document.getElementById("user-settings-form"), "u/userSettings/set", "post")).load('u/userSettings').onSubmit(function(res){ + for (let i = 0, n = res.length; i < n; i++) + { + FlashMessenger.addMessage(res[i]); + } + }); + return res; + } +} +InitPromise.addPromise(function(){ + SettingsSite.addSettingsFragment("user-settings", UserSettingsFragment); +}); + +class EditUserRolesSite extends UserSite { + constructor(siteManager) { + super(siteManager, 'userManagement/html/editUserRoles.html', "userRoles", "admin"); + } + + onConstruct(args) { + let res = super.onConstruct(args); + this.userId = args["id"]; + + let self = this; + return Promise.all([ + ScriptLoader.loadScript(Constants.SCRIPTS.LIST_JS), + DataManager.load("u/userRoles" + DataManager.buildQuery({"id": self.userId})).then(function (res) { + if (!res["success"]) { + FlashMessenger.addMessage(res["errors"][0]); + self.finish(); + } + else { + self.setUserRoles(res["result"]["userRoles"]); + self.setAvailableRoles(res["result"]["availableRoles"]); + self.setUsername(res["result"]["username"]); + } + }) + ]).then(function () { + return res; + }); + } + + onFirstStart() { + this.findBy("#username").innerHTML = this.username; + + const userRolesElement = this.findBy("#userRoles"); + const availableRolesElement = this.findBy("#availableRoles"); + + const imgColumnUserRoles = new ImgConstSmartColumn("img/minus.png", "", false); + const imgColumnAvailableRoles = new ImgConstSmartColumn("img/plus.png", "", false); + + const userRolesColumns = [ + new DataSmartColumn("id"), + new SmartColumn("name", "name"), + new SmartColumn("description", "description"), + imgColumnUserRoles, + ]; + + const availableRolesColumns = [ + new DataSmartColumn("id"), + new SmartColumn("name", "name"), + new SmartColumn("description", "description"), + imgColumnAvailableRoles, + ]; + + const userRolesListHelper = new ListHelper(userRolesElement, userRolesColumns, this.userRoles); + const availableRolesListHelper = new ListHelper(availableRolesElement, availableRolesColumns, this.availableRoles); + + const userRolesTable = userRolesListHelper.createTable(); + const availableRolesTable = availableRolesListHelper.createTable(); + + let self = this; + const changeRoleFunction = function (roleId, addRole) { + userRolesListHelper.setBusy(true); + availableRolesListHelper.setBusy(true); + + return DataManager.send("u/changeUserRole", { + "id": roleId, + "userId": self.userId, + "add": addRole + }).then(function (res) { + userRolesListHelper.setBusy(false); + availableRolesListHelper.setBusy(false); + + if (!res["success"]) { + FlashMessenger.addMessage(res["errors"][0]); + return res; + } + + let removingTable = null; + let addingTable = null; + if (res["result"]["hasRole"]) { + removingTable = availableRolesTable; + addingTable = userRolesTable; + } + else { + addingTable = availableRolesTable; + removingTable = userRolesTable; + } + + const rowData = removingTable.get("id", roleId); + if (rowData.length === 1) { + addingTable.add(rowData[0].values()); + removingTable.remove("id", roleId); + } + + return res; + }); + }; + + imgColumnUserRoles.setClickListener(function (cell) { + let userRoleId = cell.closest("tr")["dataset"]["id"]; + changeRoleFunction(userRoleId, false); + }); + + imgColumnAvailableRoles.setClickListener(function (cell) { + let availableRoleId = cell.closest("tr")["dataset"]["id"]; + changeRoleFunction(availableRoleId, true); + }); + + } + + setUserRoles(userRoles) { + this.userRoles = userRoles; + } + + setAvailableRoles(availableRoles) { + this.availableRoles = availableRoles; + } + + setUsername(username) { + this.username = username; + } +} + +InitPromise.addPromise(function (app) { + app.addDeepLink("userRoles", EditUserRolesSite.name); + app.addDefaultAction(new UserAction('userRoles', function(){ + app.startSite(EditUserRolesSite); + }, null, 1100, "admin")); +}); + +class ForgotPasswordSite extends UserSite{ + + constructor(siteManager) { + super(siteManager, 'userManagement/html/forgotPassword.html', "forgotPassword", "offline"); + } + + onFirstStart() { + let self = this; + (new Form(document.getElementById("forgot-password-form"), "u/newPassword", "post")).onSubmit(function(res){ + // UserManager.setData(res); + // self.startStartsite(); + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("new-password-code-send")); + self.finish(); + }); + } +} +InitPromise.addPromise(function(app){ + app.addDeepLink("forgotPassword", ForgotPasswordSite); +}); + +class LoginSite extends UserSite{ + constructor(siteManager) { + super(siteManager, 'userManagement/html/login.html', "login", "offline"); + } + + onFirstStart() { + let self = this; + (new LoginForm(document.getElementById("login-form"), "u/login", "post")).onSubmit(function(res){ + UserManager.setData(res); + self.startStartsite(); + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("login-success")); + self.finish(); + }); + + this.findBy("#forgot-password-link").addEventListener("click", function(){ + self.startSite(Achievement$1); + self.finish(); + }); + } +} +InitPromise.addPromise(function(app){ + app.addDeepLink("login", LoginSite); + app.addDefaultAction(new UserAction('login', function(){ + app.startSite(LoginSite); + }, Menu.SHOW_NEVER, 1100, "offline")); + app.addDefaultAction(new UserAction('logout', function(){ + UserManager.logOut(); + }, Menu.SHOW_NEVER, 1100, "online")); +}); + +class RegistrationSite extends UserSite { + constructor(siteManager) { + super(siteManager, 'userManagement/html/registration.html', "registration", "offline"); + } + + onFirstStart() { + (new RegistrationForm(document.getElementById("registration-form"), "u/registration", "post")).onSubmit(function(res){ + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("registration-success")); + }); + } +} + +InitPromise.addPromise(function (app) { + app.addDeepLink("registration", RegistrationSite); + app.addDefaultAction(new UserAction('registration', function(){ + app.startSite(RegistrationSite); + }, null, 1100, "offline")); +}); + +class SetNewPasswordSite extends UserSite { + constructor(siteManager) { + super(siteManager, 'userManagement/html/setNewPassword.html', "newPassword", "offline"); + } + + onConstruct(args) { + this.code = args["code"]; + return super.onConstruct(args); + } + + onFirstStart() { + let formElem = document.getElementById("new-password-form"); + document.getElementById("code").value = this.code; + + let self = this; + (new Form(formElem, "c/code", "post")).onSubmit(function(res){ + FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("password-updated")); + self.startSite(Achievement$1); + self.finish(); + }); + } +} +InitPromise.addPromise(function(app){ + app.addDeepLink("newPassword", SetNewPasswordSite); +}); + +SystemSettings.setBasePath("/pwa/wordRotator/public/"); +Translator.supportedLanguages = ["de", "en"]; +Translator.markTranslations = false; + +class Segment{ + constructor(element){ + this.rotation = 0; + this.element = element; + this.parent = null; + } + + getCurrentRotations(rotations){ + return rotations; + } + + sameAs(otherSegment){ + return false; + } + + setParent(parent) + { + this.parent = parent; + } + + getLevel() + { + if (this.parent!==null) + { + return this.parent.getLevel(); + } + } + + isSolved(){ + return (this.rotation === 0); + } + + async rotate(){ + return Promise.resolve(); + }; + + _updateElement(){}; + + applyRotations(rotations){ + return rotations; + } + + getElement() + { + return this.element; + } +} + class ParentSegment extends Segment { static initListener(){ window.addEventListener("mousedown", (e) => { @@ -3834,18 +6999,6 @@ class LevelSite extends AbstractSite$1 { } onConstruct(args) { - let a0 = -1; - let a1 = 1; - for(let i = 0; i < 10; i++) - { - let tmp = 3*a1-2*a0; - console.log("reg", i+2, tmp); - console.log("other", i+2, Math.pow(2, i+3)-3); - a0=a1; - a1=tmp; - } - - this.levelCounter = Helper.nonNull(localStorage.getItem("levelCounter"), 1); return super.onConstruct(args); } @@ -3980,153 +7133,6 @@ class LevelSite extends AbstractSite$1 { } } -class DataManager { - static load(url, isCachable, raw) { - isCachable = Helper.nonNull(isCachable, false); - raw = Helper.nonNull(raw, false); - let fullUrl = (isCachable) ? Helper.basePath(DataManager.cachePath + url) : Helper.basePath(DataManager.dataPath + url); - return fetch(fullUrl, {"credentials": "same-origin"}).then(function (res) { - if (raw) { - return res.text(); - } - return res.json(); - }).catch(function (e) { - console.error("error", e); - if (!raw) { - return { - "success": false, - "errors": [ - "not-online" - ] - } - } - }); - } - - static send(url, params) { - let fullUrl = Helper.basePath(DataManager.dataPath + url); - - if (!(params instanceof FormData)) { - let newParams = new FormData(); - for (let k in params) { - newParams.append(k, params[k]); - } - params = newParams; - } - - return fetch(fullUrl, { - "credentials": "same-origin", - "method": "POST", - "body": params - }).then(function (res) { - return res.json(); - }).catch(function (e) { - console.error("error", e); - return { - "success": false, - "errors": [ - "not-online" - ] - } - }); - } - - static buildQuery(values) { - return Helper.buildQuery(values); - } -} - -DataManager.dataPath = "data/"; -DataManager.cachePath = "cached/"; - -class SettingsSite extends AbstractSite$1 { - constructor(siteManager) { - super(siteManager, 'public/html/settings.html', "settings"); - for (let k in SettingsSite.settingsFragments) { - this.addSettingsFragment(k, new SettingsSite.settingsFragments[k](this)); - } - this.active = null; - } - - addSettingsFragment(name, settingsFragment) { - this.addFragment("#settings-fragments", settingsFragment); - delete this.fragments["#settings-fragments"]; - this.fragments[name] = settingsFragment; - } - - onStart() { - let res = super.onStart(); - if (Helper.isNotNull(this.active) && !this.fragments[this.active].isActive()) { - this.setActive(null); - } - - this.buildList(); - return res; - } - - setActive(name) { - if (Helper.isNotNull(this.active)) { - this.fragments[this.active].inflatePromise.then(function (view) { - view.classList.remove("active"); - }); - this.findBy("#show-fragment-" + this.active).classList.remove("active"); - } - this.active = name; - if (Helper.isNotNull(this.active)) { - this.fragments[this.active].inflatePromise.then(function (view) { - view.classList.add("active"); - }); - this.findBy("#show-fragment-" + this.active).classList.add("active"); - } - } - - buildList() { - let listNameElem = this.findBy("#settings-fragment-list"); - listNameElem.removeAllChildren(); - - let self = this; - for (let k in this.fragments) { - if (this.fragments[k].isActive()) { - - let liElement = document.createElement("li"); - liElement.id = "show-fragment-" + k; - liElement.appendChild(Translator.makePersistentTranslation(k, null, "a")); - liElement.addEventListener("click", function () { - self.setActive(k); - }); - listNameElem.appendChild(liElement); - - if (Helper.isNull(this.active)) { - this.setActive(k); - } - } - } - } - - static addSettingsFragment(name, settingsFragment) { - SettingsSite.settingsFragments[name] = settingsFragment; - } - - static setAddSettingsSite(addLink) { - SettingsSite.shouldAddSettingsSite = addLink; - } -} - -SettingsSite.settingsFragments = {}; -SettingsSite.shouldAddSettingsSite = true; - -InitPromise.addPromise(function (app) { - if (SettingsSite.shouldAddSettingsSite) { - app.addDeepLink("settings", SettingsSite.name); - - let settingsAction = new MenuAction("settings", function () { - app.startSite(SettingsSite.name); - }, MenuAction.SHOW_FOR_LARGE, 10000); - settingsAction.setIcon("img/settings.png"); - app.addDefaultAction(settingsAction); - } -}); - class SynchronizeSite extends AbstractSite$1 { constructor(siteManager) { @@ -4199,13 +7205,13 @@ let app = new App(); app.setAddThemeAction(true); app.addDefaultAction(Translator.generateChangeLanguageMenuAction()); -//bridge für Android -// window["ThemeManager"] = ThemeManager; -// window["ThemeManager"]["addChangeListener"] = ThemeManager.addChangeListener; -// window["app"] = app; -// window["app"]["refreshCurrentSite"] = app.refreshCurrentSite; -// window["Translator"] = Translator; -// window["Translator"]["setLanguage"] = Translator.setLanguage; +// bridge für Android +window["ThemeManager"] = ThemeManager; +window["ThemeManager"]["addChangeListener"] = ThemeManager.addChangeListener; +window["app"] = app; +window["app"]["refreshCurrentSite"] = app.refreshCurrentSite; +window["Translator"] = Translator; +window["Translator"]["setLanguage"] = Translator.setLanguage; InitPromise.resolve(app).then(function(){ app.start(SynchronizeSite); diff --git a/public/js/lang/de.json b/public/js/lang/de.json old mode 100644 new mode 100755 diff --git a/public/js/lang/en.json b/public/js/lang/en.json old mode 100644 new mode 100755 diff --git a/public/js/manifest.json b/public/js/manifest.json old mode 100644 new mode 100755 diff --git a/public/pwaAssets/css/pwaAssets.css b/public/pwaAssets/css/pwaAssets.css old mode 100644 new mode 100755 diff --git a/public/pwaAssets/html/fragment/tabbedFragment.html b/public/pwaAssets/html/fragment/tabbedFragment.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/403.html b/public/userManagement/html/403.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/editUserRoles.html b/public/userManagement/html/editUserRoles.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/forgotPassword.html b/public/userManagement/html/forgotPassword.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/fragments/passwordSettings.html b/public/userManagement/html/fragments/passwordSettings.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/fragments/userSettings.html b/public/userManagement/html/fragments/userSettings.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/login.html b/public/userManagement/html/login.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/registration.html b/public/userManagement/html/registration.html old mode 100644 new mode 100755 diff --git a/public/userManagement/html/setNewPassword.html b/public/userManagement/html/setNewPassword.html old mode 100644 new mode 100755 diff --git a/public/version/1/listjs/list.min.js b/public/version/1/listjs/list.min.js old mode 100644 new mode 100755 diff --git a/rollup.config.js b/rollup.config.js old mode 100644 new mode 100755 diff --git a/src/js/init.js b/src/js/init.js old mode 100644 new mode 100755 index da95231..107000f --- a/src/js/init.js +++ b/src/js/init.js @@ -8,6 +8,13 @@ import { Translator, WhatsappShareButton } from "./lib/pwa-lib"; + +import "./lib/pwa-lib" +import "./lib/pwa-core" +import "./lib/pwa-assets" +import "./lib/pwa-code-management" +import "./lib/pwa-user-management" + import './settings' // import {ClockSite} from "../module/Application/pwa/js/site/ClockSite"; import {LevelSite} from "../module/Application/pwa/js/site/LevelSite"; @@ -31,13 +38,13 @@ let app = new App(); app.setAddThemeAction(true); app.addDefaultAction(Translator.generateChangeLanguageMenuAction()); -//bridge für Android -// window["ThemeManager"] = ThemeManager; -// window["ThemeManager"]["addChangeListener"] = ThemeManager.addChangeListener; -// window["app"] = app; -// window["app"]["refreshCurrentSite"] = app.refreshCurrentSite; -// window["Translator"] = Translator; -// window["Translator"]["setLanguage"] = Translator.setLanguage; +// bridge für Android +window["ThemeManager"] = ThemeManager; +window["ThemeManager"]["addChangeListener"] = ThemeManager.addChangeListener; +window["app"] = app; +window["app"]["refreshCurrentSite"] = app.refreshCurrentSite; +window["Translator"] = Translator; +window["Translator"]["setLanguage"] = Translator.setLanguage; InitPromise.resolve(app).then(function(){ app.start(SynchronizeSite); diff --git a/src/js/lib/pwa-assets.js b/src/js/lib/pwa-assets.js old mode 100644 new mode 100755 diff --git a/src/js/lib/pwa-code-management.js b/src/js/lib/pwa-code-management.js old mode 100644 new mode 100755 index dd52ccb..9904525 --- a/src/js/lib/pwa-code-management.js +++ b/src/js/lib/pwa-code-management.js @@ -2,30 +2,25 @@ import { DataManager } from './pwa-core.js'; import { AbstractSite, FlashMessenger, Helper, InitPromise, Translator } from './pwa-lib.js'; class Code { - constructor(args) - { - if (typeof args === "string") - { + constructor(args) { + if (typeof args === "string") { args = { - "code":args + "code": args }; } this.args = args; this.isCacheable = false; } - setIsCacheable(isCacheable) - { + setIsCacheable(isCacheable) { this.isCacheable = isCacheable; } - getIsCacheable() - { + getIsCacheable() { return this.isCacheable; } - activate() - { + activate() { return DataManager.send("c/code", this.args); } } @@ -62,7 +57,7 @@ class CodeSite extends AbstractSite { } InitPromise.addPromise(function (app) { - app.addDeepLink("code", CodeSite.name); + app.addDeepLink("code", CodeSite); }); export { Code, CodeSite }; diff --git a/src/js/lib/pwa-core.js b/src/js/lib/pwa-core.js old mode 100644 new mode 100755 diff --git a/src/js/lib/pwa-cronjob.js b/src/js/lib/pwa-cronjob.js old mode 100644 new mode 100755 diff --git a/src/js/lib/pwa-lib.js b/src/js/lib/pwa-lib.js old mode 100644 new mode 100755 diff --git a/src/js/lib/pwa-user-management.js b/src/js/lib/pwa-user-management.js old mode 100644 new mode 100755 index 8f4a990..8150353 --- a/src/js/lib/pwa-user-management.js +++ b/src/js/lib/pwa-user-management.js @@ -1801,7 +1801,7 @@ class UserSite extends AbstractSite$1{ onConstruct(args) { if (!UserManager.hasAccess(this._access)) { - this.startSite(Achievement.name); + this.startSite(Achievement); this.finish({ "error":403 }); @@ -1813,7 +1813,7 @@ class UserSite extends AbstractSite$1{ onStart(args) { if (!UserManager.hasAccess(this._access)) { - this.startSite(Achievement.name); + this.startSite(Achievement); this.finish({ "error":403 }); @@ -2082,7 +2082,7 @@ class EditUserRolesSite extends UserSite { InitPromise.addPromise(function (app) { app.addDeepLink("userRoles", EditUserRolesSite.name); app.addDefaultAction(new UserAction('userRoles', function(){ - app.startSite(EditUserRolesSite.name); + app.startSite(EditUserRolesSite); }, null, 1100, "admin")); }); @@ -2121,7 +2121,7 @@ class LoginSite extends UserSite{ }); this.findBy("#forgot-password-link").addEventListener("click", function(){ - self.startSite(Achievement.name); + self.startSite(Achievement); self.finish(); }); } @@ -2129,7 +2129,7 @@ class LoginSite extends UserSite{ InitPromise.addPromise(function(app){ app.addDeepLink("login", LoginSite); app.addDefaultAction(new UserAction('login', function(){ - app.startSite(LoginSite.name); + app.startSite(LoginSite); }, Menu.SHOW_NEVER, 1100, "offline")); app.addDefaultAction(new UserAction('logout', function(){ UserManager.logOut(); @@ -2157,7 +2157,7 @@ class RegistrationSite extends UserSite { InitPromise.addPromise(function (app) { app.addDeepLink("registration", RegistrationSite); app.addDefaultAction(new UserAction('registration', function(){ - app.startSite(RegistrationSite.name); + app.startSite(RegistrationSite); }, null, 1100, "offline")); }); @@ -2178,7 +2178,7 @@ class SetNewPasswordSite extends UserSite { let self = this; (new Form(formElem, "c/code", "post")).onSubmit(function(res){ FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("password-updated")); - self.startSite(Achievement.name); + self.startSite(Achievement); self.finish(); }); } diff --git a/src/module/Application/config/routes/routes.sync.php b/src/module/Application/config/routes/routes.sync.php old mode 100644 new mode 100755 index acfbc2d..2526cc6 --- a/src/module/Application/config/routes/routes.sync.php +++ b/src/module/Application/config/routes/routes.sync.php @@ -16,17 +16,17 @@ return array( 'route' => '/wordRotator', ], 'child_routes' => [ -// 'words' => [ -// 'type' => Segment::class, -// 'options' => [ -// 'route' => '/words', -// 'defaults' => [ -// 'controller' => SyncController::class, -// 'action' => 'getWords', -// 'resource' => 'default', -// ] -// ], -// ], + 'words' => [ + 'type' => Segment::class, + 'options' => [ + 'route' => '/words', + 'defaults' => [ + 'controller' => SyncController::class, + 'action' => 'getWords', + 'resource' => 'default', + ] + ], + ], 'levels' => [ 'type' => Segment::class, 'options' => [ @@ -38,28 +38,28 @@ return array( ] ], ], -// 'getAuthToken' => [ -// 'type' => Segment::class, -// 'options' => [ -// 'route' => '/token', -// 'defaults' => [ -// 'controller' => SyncController::class, -// 'action' => 'getAuthToken', -// 'resource' => 'default', -// ] -// ], -// ], -// 'rate' => [ -// 'type' => Segment::class, -// 'options' => [ -// 'route' => '/rate', -// 'defaults' => [ -// 'controller' => SyncController::class, -// 'action' => 'rate', -// 'resource' => 'default', -// ] -// ], -// ], + 'getAuthToken' => [ + 'type' => Segment::class, + 'options' => [ + 'route' => '/token', + 'defaults' => [ + 'controller' => SyncController::class, + 'action' => 'getAuthToken', + 'resource' => 'default', + ] + ], + ], + 'rate' => [ + 'type' => Segment::class, + 'options' => [ + 'route' => '/rate', + 'defaults' => [ + 'controller' => SyncController::class, + 'action' => 'rate', + 'resource' => 'default', + ] + ], + ], ], ], ], diff --git a/src/module/Application/pwa/html/application/end.html b/src/module/Application/pwa/html/application/end.html old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/html/application/level.html b/src/module/Application/pwa/html/application/level.html old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/html/application/sync.html b/src/module/Application/pwa/html/application/sync.html old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/WordRotatorDb.js b/src/module/Application/pwa/js/WordRotatorDb.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/site/EndSite.js b/src/module/Application/pwa/js/site/EndSite.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/site/LevelSite.js b/src/module/Application/pwa/js/site/LevelSite.js old mode 100644 new mode 100755 index f1e6593..5bad7ff --- a/src/module/Application/pwa/js/site/LevelSite.js +++ b/src/module/Application/pwa/js/site/LevelSite.js @@ -25,18 +25,6 @@ export class LevelSite extends AbstractSite { } onConstruct(args) { - let a0 = -1; - let a1 = 1; - for(let i = 0; i < 10; i++) - { - let tmp = 3*a1-2*a0; - console.log("reg", i+2, tmp); - console.log("other", i+2, Math.pow(2, i+3)-3); - a0=a1; - a1=tmp; - } - - this.levelCounter = Helper.nonNull(localStorage.getItem("levelCounter"), 1); return super.onConstruct(args); } diff --git a/src/module/Application/pwa/js/site/SynchronizeSite.js b/src/module/Application/pwa/js/site/SynchronizeSite.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/FourWordsLevel.js b/src/module/Application/pwa/js/wordrotator/Level/FourWordsLevel.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/FourWordsLevel12.js b/src/module/Application/pwa/js/wordrotator/Level/FourWordsLevel12.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/FourWordsLevel8.js b/src/module/Application/pwa/js/wordrotator/Level/FourWordsLevel8.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/Level.js b/src/module/Application/pwa/js/wordrotator/Level/Level.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/LevelHelper.js b/src/module/Application/pwa/js/wordrotator/Level/LevelHelper.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/RowLevel.js b/src/module/Application/pwa/js/wordrotator/Level/RowLevel.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/RowLevel10.js b/src/module/Application/pwa/js/wordrotator/Level/RowLevel10.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/RowLevel8.js b/src/module/Application/pwa/js/wordrotator/Level/RowLevel8.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/SimpleLevel.js b/src/module/Application/pwa/js/wordrotator/Level/SimpleLevel.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/SixWordsRowLevel.js b/src/module/Application/pwa/js/wordrotator/Level/SixWordsRowLevel.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/SixWordsRowLevel12.js b/src/module/Application/pwa/js/wordrotator/Level/SixWordsRowLevel12.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Level/SixWordsRowLevel8.js b/src/module/Application/pwa/js/wordrotator/Level/SixWordsRowLevel8.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Segment/LeafSegment.js b/src/module/Application/pwa/js/wordrotator/Segment/LeafSegment.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Segment/ParentSegment.js b/src/module/Application/pwa/js/wordrotator/Segment/ParentSegment.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Segment/RowSegment.js b/src/module/Application/pwa/js/wordrotator/Segment/RowSegment.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Segment/Segment.js b/src/module/Application/pwa/js/wordrotator/Segment/Segment.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Segment/TemplateContainer.js b/src/module/Application/pwa/js/wordrotator/Segment/TemplateContainer.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/js/wordrotator/Segment/TriangleSegment.js b/src/module/Application/pwa/js/wordrotator/Segment/TriangleSegment.js old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/translations/de.json b/src/module/Application/pwa/translations/de.json old mode 100644 new mode 100755 diff --git a/src/module/Application/pwa/translations/en.json b/src/module/Application/pwa/translations/en.json old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Controller/SyncController.php b/src/module/Application/src/Controller/SyncController.php old mode 100644 new mode 100755 index 9e4dc97..3db032c --- a/src/module/Application/src/Controller/SyncController.php +++ b/src/module/Application/src/Controller/SyncController.php @@ -28,79 +28,79 @@ class SyncController extends JsonController const MAX_RATINGS_PER_LEVEL = 2; -// public function getAuthTokenAction() -// { -// if (!$this->getRequest()->isPost()) { -// return $this->triggerDispatchError(404); -// } -// -// /** @var AuthTokenManager $authTokenManager */ -// $authTokenManager = $this->get(AuthTokenManager::class); -// -// $token = new AuthToken(); -// $name = $this->getRequest()->getPost("name"); -// if (trim($name) == "") { -// return $this->triggerDispatchError(400); -// } -// $token->setName($name); -// $token->setToken($authTokenManager->generateNewAuthToken()); -// $authTokenManager->save($token); -// -// $this->layout("layout/ajaxData"); -// $viewModel = new ViewModel(); -// $viewModel->setTemplate("ajax/json"); -// $viewModel->setVariable("json", [ -// "result" => true, -// "data" => [ -// "authToken" => $token->getToken(), -// ], -// ]); -// return $viewModel; -// } + public function getAuthTokenAction() + { + if (!$this->getRequest()->isPost()) { + return $this->triggerDispatchError(404); + } -// public function getWordsAction() -// { -// $request = $this->getRequest(); -// if (!$request->isPost()) { -// return $this->triggerDispatchError(); -// } -// -// $this->getEventManager()->trigger(Module::EVENT_LOG, null, array( -// "message" => "Synchronized Words: " . $request->toString(), -// "level" => Logger::INFO -// )); -// -// $currentRun = (int)$request->getPost("currentRun", null); -// $dateLastSync = $request->getPost("dateLastSync", null); -// if ($dateLastSync != null) { -// try { -// $dateLastSync = \DateTime::createFromFormat(self::DATETIME_SYNC_FORMAT, $dateLastSync); -// } catch (\Throwable $t) { -// $dateLastSync = null; -// } -// } -// -// /** @var WordManager $wordManager */ -// $wordManager = $this->get(WordManager::class); -// $newDate = new \DateTime(); -// $words = $wordManager->wordsToArray($wordManager->findNewerThan($dateLastSync, $currentRun)); -// $numberWordsToSync = $wordManager->countNewerThan($dateLastSync); -// -// $this->layout("layout/ajaxData"); -// $viewModel = new ViewModel(); -// $viewModel->setTemplate("ajax/json"); -// $viewModel->setVariable("json", [ -// "result" => true, -// "data" => [ -// "countWords" => $numberWordsToSync, -// "currentSyncDate" => $newDate->format(self::DATETIME_SYNC_FORMAT), -// "currentRun" => $currentRun, -// "maxRuns" => ceil($numberWordsToSync / SyncController::SYNC_MAX_WORDS), -// "words" => $words, -// ], -// ]); -// return $viewModel; -// } + /** @var AuthTokenManager $authTokenManager */ + $authTokenManager = $this->get(AuthTokenManager::class); + + $token = new AuthToken(); + $name = $this->getRequest()->getPost("name"); + if (trim($name) == "") { + return $this->triggerDispatchError(400); + } + $token->setName($name); + $token->setToken($authTokenManager->generateNewAuthToken()); + $authTokenManager->save($token); + + $this->layout("layout/ajaxData"); + $viewModel = new ViewModel(); + $viewModel->setTemplate("ajax/json"); + $viewModel->setVariable("json", [ + "result" => true, + "data" => [ + "authToken" => $token->getToken(), + ], + ]); + return $viewModel; + } + + public function getWordsAction() + { + $request = $this->getRequest(); + if (!$request->isPost()) { + return $this->triggerDispatchError(); + } + + $this->getEventManager()->trigger(Module::EVENT_LOG, null, array( + "message" => "Synchronized Words: " . $request->toString(), + "level" => Logger::INFO + )); + + $currentRun = (int)$request->getPost("currentRun", null); + $dateLastSync = $request->getPost("dateLastSync", null); + if ($dateLastSync != null) { + try { + $dateLastSync = \DateTime::createFromFormat(self::DATETIME_SYNC_FORMAT, $dateLastSync); + } catch (\Throwable $t) { + $dateLastSync = null; + } + } + + /** @var WordManager $wordManager */ + $wordManager = $this->get(WordManager::class); + $newDate = new \DateTime(); + $words = $wordManager->wordsToArray($wordManager->findNewerThan($dateLastSync, $currentRun)); + $numberWordsToSync = $wordManager->countNewerThan($dateLastSync); + + $this->layout("layout/ajaxData"); + $viewModel = new ViewModel(); + $viewModel->setTemplate("ajax/json"); + $viewModel->setVariable("json", [ + "result" => true, + "data" => [ + "countWords" => $numberWordsToSync, + "currentSyncDate" => $newDate->format(self::DATETIME_SYNC_FORMAT), + "currentRun" => $currentRun, + "maxRuns" => ceil($numberWordsToSync / SyncController::SYNC_MAX_WORDS), + "words" => $words, + ], + ]); + return $viewModel; + } public function getLevelsAction() { @@ -129,91 +129,91 @@ class SyncController extends JsonController ]; } -// public function rateAction() -// { -// $request = $this->getRequest(); -// if (!$request->isPost()) { -// return $this->triggerDispatchError(404); -// } -// -// $this->getEventManager()->trigger(Module::EVENT_LOG, null, array( -// "message" => "Synchronized Level: " . $request->toString(), -// "level" => Logger::INFO -// )); -// -// /** @var AuthTokenManager $authTokenManager */ -// $authTokenManager = $this->get(AuthTokenManager::class); -// $authToken = $authTokenManager->findOneByToken($request->getPost("authToken")); -// -// if ($authToken == null) { -// return $this->triggerDispatchError(403); -// } -// -// /** @var RatingManager $ratingManager */ -// $ratingManager = $this->get(RatingManager::class); -// -// /** @var LevelManager $levelManager */ -// $levelManager = $this->get(LevelManager::class); -// $levelsArray = json_decode($request->getPost("levels"), true); -// -// $levels = []; -// foreach ($levelsArray as $levelArray) { -// $levelManager->beginTransaction(); -// -// $words = json_encode($levelArray["words"]); -// $rotations = json_encode($levelArray["rotations"]); -// $level = $levelManager->findOneBy([ -// "words" => $words, -// "positions" => $rotations, -// "renderer" => $levelArray["rendererType"], -// "lang" => $levelArray["language"], -// ]); -// if ($level == null) { -// $level = new Level(); -// $level->setDeleted(false); -// $level->setWords($words); -// $level->setPositions($rotations); -// $level->setRenderer($levelArray["rendererType"]); -// $level->setLang($levelArray["language"]); -// $level->setLastUpdated(new \DateTime()); -// $level->setDeleted(false); -// $level->setDifficulty($levelArray["difficulty"]); + public function rateAction() + { + $request = $this->getRequest(); + if (!$request->isPost()) { + return $this->triggerDispatchError(404); + } + + $this->getEventManager()->trigger(Module::EVENT_LOG, null, array( + "message" => "Synchronized Level: " . $request->toString(), + "level" => Logger::INFO + )); + + /** @var AuthTokenManager $authTokenManager */ + $authTokenManager = $this->get(AuthTokenManager::class); + $authToken = $authTokenManager->findOneByToken($request->getPost("authToken")); + + if ($authToken == null) { + return $this->triggerDispatchError(403); + } + + /** @var RatingManager $ratingManager */ + $ratingManager = $this->get(RatingManager::class); + + /** @var LevelManager $levelManager */ + $levelManager = $this->get(LevelManager::class); + $levelsArray = json_decode($request->getPost("levels"), true); + + $levels = []; + foreach ($levelsArray as $levelArray) { + $levelManager->beginTransaction(); + + $words = json_encode($levelArray["words"]); + $rotations = json_encode($levelArray["rotations"]); + $level = $levelManager->findOneBy([ + "words" => $words, + "positions" => $rotations, + "renderer" => $levelArray["rendererType"], + "lang" => $levelArray["language"], + ]); + if ($level == null) { + $level = new Level(); + $level->setDeleted(false); + $level->setWords($words); + $level->setPositions($rotations); + $level->setRenderer($levelArray["rendererType"]); + $level->setLang($levelArray["language"]); + $level->setLastUpdated(new \DateTime()); + $level->setDeleted(false); + $level->setDifficulty($levelArray["difficulty"]); + $levelManager->save($level); + } + $rating = $ratingManager->findOneBy([ + "level" => $level, + "authToken" => $authToken, + ]); + + if ($rating == null) { + $rating = new Rating(); + $rating->setAuthToken($authToken); + $rating->setLevel($level); + $level->getRatings()->add($rating); + } + + $ratingScore = $levelArray["rating"]; + $rating->setRating($ratingScore); + + if ($level->getRatings()->count() >= self::MAX_RATINGS_PER_LEVEL || $ratingScore < 0) { + $level->setDeleted(true); + $level->setLastUpdated(new \DateTime()); // $levelManager->save($level); -// } -// $rating = $ratingManager->findOneBy([ -// "level" => $level, -// "authToken" => $authToken, -// ]); -// -// if ($rating == null) { -// $rating = new Rating(); -// $rating->setAuthToken($authToken); -// $rating->setLevel($level); -// $level->getRatings()->add($rating); -// } -// -// $ratingScore = $levelArray["rating"]; -// $rating->setRating($ratingScore); -// -// if ($level->getRatings()->count() >= self::MAX_RATINGS_PER_LEVEL || $ratingScore < 0) { -// $level->setDeleted(true); -// $level->setLastUpdated(new \DateTime()); -//// $levelManager->save($level); -// } -// -// $ratingManager->save($rating); -// $levelManager->endTransaction(); -// $levels[] = $level; -// } -// $this->layout("layout/ajaxData"); -// $viewModel = new ViewModel(); -// $viewModel->setTemplate("ajax/json"); -// $viewModel->setVariable("json", [ -// "result" => true, -// "data" => [ -// "levels" => $levelManager->levelsToArray($levels), -// ], -// ]); -// return $viewModel; -// } + } + + $ratingManager->save($rating); + $levelManager->endTransaction(); + $levels[] = $level; + } + $this->layout("layout/ajaxData"); + $viewModel = new ViewModel(); + $viewModel->setTemplate("ajax/json"); + $viewModel->setVariable("json", [ + "result" => true, + "data" => [ + "levels" => $levelManager->levelsToArray($levels), + ], + ]); + return $viewModel; + } } \ No newline at end of file diff --git a/src/module/Application/src/Model/AuthToken.php b/src/module/Application/src/Model/AuthToken.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Level.php b/src/module/Application/src/Model/Level.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Manager/AuthTokenManager.php b/src/module/Application/src/Model/Manager/AuthTokenManager.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Manager/LevelManager.php b/src/module/Application/src/Model/Manager/LevelManager.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Manager/RatingManager.php b/src/module/Application/src/Model/Manager/RatingManager.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Manager/WordManager.php b/src/module/Application/src/Model/Manager/WordManager.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Rating.php b/src/module/Application/src/Model/Rating.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Repository/AuthTokenRepository.php b/src/module/Application/src/Model/Repository/AuthTokenRepository.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Repository/LevelRepository.php b/src/module/Application/src/Model/Repository/LevelRepository.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Repository/RatingRepository.php b/src/module/Application/src/Model/Repository/RatingRepository.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Repository/WordRepository.php b/src/module/Application/src/Model/Repository/WordRepository.php old mode 100644 new mode 100755 diff --git a/src/module/Application/src/Model/Word.php b/src/module/Application/src/Model/Word.php old mode 100644 new mode 100755 diff --git a/src/scss/_editStory.scss b/src/scss/_editStory.scss old mode 100644 new mode 100755 diff --git a/src/scss/wordRotator.scss b/src/scss/wordRotator.scss old mode 100644 new mode 100755 diff --git a/webpack.config.js b/webpack.config.js old mode 100644 new mode 100755