initial commit

This commit is contained in:
silas
2018-05-15 17:30:16 +02:00
commit 1efcd2526b
105 changed files with 18204 additions and 0 deletions

44
src/js/init.js Normal file
View File

@@ -0,0 +1,44 @@
import {
App, applyPolyfills,
InitPromise,
ShareManager,
SmsShareButton, TelegramShareButton,
Theme,
ThemeManager,
Translator,
WhatsappShareButton
} from "./lib/pwa-lib";
import './settings'
import {ClockSite} from "../module/Application/pwa/js/site/ClockSite";
applyPolyfills();
ThemeManager.addTheme(new Theme('red', ''));
ThemeManager.addTheme(new Theme("blue", "blue"));
ThemeManager.addTheme(new Theme("black", "black"));
ThemeManager.addTheme(new Theme("green", "green"));
ThemeManager.addTheme(new Theme("pink", "pink"));
ShareManager.addShareButton(new WhatsappShareButton('img/whatsapp.svg'));
ShareManager.addShareButton(new SmsShareButton('img/sms.svg'));
ShareManager.addShareButton(new TelegramShareButton('img/telegram.svg'));
// ShareManager.addShareButton(new CopyShareButton('img/copy.svg'));
let app = new App();
// app.addDeepLink("policy", PrivatePolicySite.name);
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;
InitPromise.resolve(app).then(function(){
app.start(ClockSite);
Translator.setLanguage("de");
});

68
src/js/lib/pwa-assets.js Normal file
View File

@@ -0,0 +1,68 @@
import { Fragment, Helper, Translator } from './pwa-lib.js';
class TabbedFragment extends Fragment {
constructor(site) {
super(site, 'pwaAssets/html/fragment/tabbedFragment.html');
this.fragments = {};
this.tabHeadingTemplate = null;
this.tabHeadingContainer = null;
this.tabContainer = null;
this.tabKeys = [];
this.currentTabIndex = 0;
}
onFirstStart() {
super.onFirstStart();
this.tabContainer = this.findBy(".tab-container");
this.showTab(0);
}
addFragment(name, fragment, translationArgs, isTranslatable) {
isTranslatable = Helper.nonNull(isTranslatable, true);
if (translationArgs === false) {
isTranslatable = false;
}
this.fragments[name] = fragment;
const tabIndex = this.tabKeys.length;
this.tabKeys.push(name);
const _self = this;
this.inflatePromise = this.inflatePromise.then(function (siteContent) {
if (Helper.isNull(_self.tabHeadingTemplate)) {
_self.tabHeadingTemplate = siteContent.querySelector(".tab-header-template");
}
const newTabHeader = Helper.cloneNode(_self.tabHeadingTemplate);
newTabHeader.classList.add("tab-" + tabIndex);
newTabHeader.querySelector(".tab-name").appendChild((isTranslatable) ? Translator.makePersistentTranslation(name, translationArgs) : document.createTextNode(name));
newTabHeader.addEventListener("click", function(){
_self.showTab(tabIndex);
});
if (Helper.isNull(_self.tabHeadingContainer)) {
_self.tabHeadingContainer = siteContent.querySelector(".tab-header-container");
}
_self.tabHeadingContainer.appendChild(newTabHeader);
return siteContent;
});
}
showTab(index) {
if (index >= 0 && index < this.tabKeys.length) {
this.findBy(".tab-" + this.currentTabIndex).classList.remove("active");
this.findBy(".tab-" + index).classList.add("active");
this.tabContainer.removeAllChildren().appendChild(Helper.createLoadingSymbol());
this.currentTabIndex = index;
const _self = this;
this.fragments[this.tabKeys[index]].inflatePromise.then(tabView => {
if (_self.currentTabIndex === index) {
_self.tabContainer.removeAllChildren().appendChild(tabView);
}
});
}
}
}
export { TabbedFragment };

View File

@@ -0,0 +1,68 @@
import { DataManager } from './pwa-core.js';
import { AbstractSite, FlashMessenger, Helper, InitPromise, Translator } from './pwa-lib.js';
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 {
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.name);
});
export { Code, CodeSite };

798
src/js/lib/pwa-core.js Normal file
View File

@@ -0,0 +1,798 @@
import { MenuAction, Helper, Dialog, Translator, Fragment, AbstractSite, InitPromise } from './pwa-lib.js';
class ConditionAction extends MenuAction
{
constructor(title, callback, condition, showFor, order) {
super(title, callback, showFor, order);
this.condition = condition;
}
getVisible() {
return (super.getVisible() && this.condition(this));
}
}
class Constants{}
Constants.SCRIPTS = {
CKEDITOR:"version/2/ckeditor/ckeditor.js",
LIST_JS: "version/1/listjs/list.min.js"
};
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 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")
{
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("");
});
}
}
onError(errorHandler, ownHandlerForOptimisticLocking){
ownHandlerForOptimisticLocking = Helper.nonNull(ownHandlerForOptimisticLocking, true);
let callback = null;
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;
}
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 LocalStorageSettingsFragment extends Fragment {
onFirstStart() {
let res = super.onFirstStart();
let settings = this.findBy(".setting", true);
const settingsManager = SettingsManager.getInstance();
for (let i = 0, n = settings.length; i < n; i++) {
let setting = settings[i];
const name = setting.name;
let value = settingsManager.getSetting(name);
let isCheckable = false;
if (setting instanceof HTMLInputElement && (setting.type === 'checkbox' || setting.type === 'radio')) {
isCheckable = true;
}
if (Helper.isNull(value) && Helper.isNotNull(settings[i]["dataset"]["default"])) {
value = setting["dataset"]["default"];
if (Helper.isNotNull(setting["dataset"]["defaultTranslateable"])) {
setting["dataset"]["translation"] = "";
setting["dataset"]["translationValue"] = value;
value = Translator.translate(value);
}
}
if (Helper.isNotNull(value)) {
if (isCheckable) {
setting.checked = (value === setting.value);
}
else {
setting.value = value;
}
if (value !== "") {
setting.classList.add("notEmpty");
}
}
setting.addEventListener("change", function () {
let value = this.value;
if (isCheckable) {
if (this.checked)
{
settingsManager.setSetting(name, value);
}
else
{
settingsManager.setSetting(name, null);
}
}
else {
settingsManager.setSetting(name, value);
}
delete setting["dataset"]["translationValue"];
delete setting["dataset"]["translation"];
});
}
return res;
}
}
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 ImgSmartColumn extends SmartColumn{
getValueName() {
return {
"name":this._name,
"attr":"src"
};
}
getItemElement() {
const element = super.getItemElement();
element.classList.remove(this._name);
const imgElement = document.createElement("img");
imgElement.classList.add(this._name);
element.appendChild(imgElement);
return element;
}
}
class AliasImgSmartColumn extends ImgSmartColumn{
constructor(name, label, translatable, aliases) {
if (typeof translatable === 'object' && Helper.isNull(aliases))
{
aliases = translatable;
translatable = null;
}
super(name, label, translatable);
this.aliases = aliases;
this.reverseAliases = Helper.invertKeyValues(aliases);
}
prepareData(myData)
{
if (Helper.isNotNull(this.aliases[myData]))
{
return this.aliases[myData];
}
return myData;
}
getAlias(value)
{
if (Helper.isNotNull(this.reverseAliases[value]))
{
return this.reverseAliases[value];
}
return null;
}
}
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 {
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);
}
});
export { ConditionAction, Constants, DataManager, Form, LocalStorageSettingsFragment, SettingsManager, AliasImgSmartColumn, ConstSmartColumn, DataSmartColumn, ImgConstSmartColumn, ImgSmartColumn, ListHelper, SmartColumn, SettingsSite };

View File

@@ -0,0 +1 @@

4293
src/js/lib/pwa-lib.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

7
src/js/settings.js Executable file
View File

@@ -0,0 +1,7 @@
import {SystemSettings, Translator} from "./lib/pwa-lib";
SystemSettings.setBasePath("/pwa/stories/public/");
Translator.supportedLanguages = ["de", "en"];
Translator.markTranslations = false;
const TRACKING_ID = '';