initial commit
This commit is contained in:
44
src/js/init.js
Normal file
44
src/js/init.js
Normal 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
68
src/js/lib/pwa-assets.js
Normal 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 };
|
||||
68
src/js/lib/pwa-code-management.js
Normal file
68
src/js/lib/pwa-code-management.js
Normal 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
798
src/js/lib/pwa-core.js
Normal 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 };
|
||||
1
src/js/lib/pwa-cronjob.js
Normal file
1
src/js/lib/pwa-cronjob.js
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
4293
src/js/lib/pwa-lib.js
Normal file
4293
src/js/lib/pwa-lib.js
Normal file
File diff suppressed because it is too large
Load Diff
2190
src/js/lib/pwa-user-management.js
Normal file
2190
src/js/lib/pwa-user-management.js
Normal file
File diff suppressed because it is too large
Load Diff
7
src/js/settings.js
Executable file
7
src/js/settings.js
Executable 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 = '';
|
||||
16
src/module/Application/config/controller.config.php
Executable file
16
src/module/Application/config/controller.config.php
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Application;
|
||||
|
||||
use Ainias\Core\Factory\Controller\ServiceActionControllerFactory;
|
||||
use Application\Controller\AuthorController;
|
||||
use Application\Controller\PwaController;
|
||||
use Application\Controller\StoryController;
|
||||
|
||||
return array(
|
||||
'controllers' => [
|
||||
'factories' => [
|
||||
Controller\IndexController::class => ServiceActionControllerFactory::class,
|
||||
],
|
||||
],
|
||||
);
|
||||
23
src/module/Application/config/doctrine.config.php
Executable file
23
src/module/Application/config/doctrine.config.php
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Application;
|
||||
|
||||
use Ainias\Core\Connections\MyConnection;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
|
||||
return array(
|
||||
'doctrine' => array(
|
||||
'driver' => array(
|
||||
'orm_default' => array(
|
||||
'drivers' => array(
|
||||
__NAMESPACE__.'\Model' => 'entities_default',
|
||||
),
|
||||
),
|
||||
'entities_default' => array(
|
||||
'paths' => array(
|
||||
__DIR__ . '/../src/Model',
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
16
src/module/Application/config/factories.config.php
Executable file
16
src/module/Application/config/factories.config.php
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace Application;
|
||||
|
||||
use Ainias\Core\Factory\Model\Manager\DefaultManagerFactory;
|
||||
|
||||
return array(
|
||||
'service_manager' => array(
|
||||
'abstract_factories' => array(
|
||||
),
|
||||
'aliases' => array(
|
||||
'translator' => 'MvcTranslator',
|
||||
),
|
||||
'factories' => array(
|
||||
),
|
||||
),
|
||||
);
|
||||
25
src/module/Application/config/manager.config.php
Executable file
25
src/module/Application/config/manager.config.php
Executable file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace Application;
|
||||
|
||||
use Zend\ServiceManager\Factory\InvokableFactory;
|
||||
|
||||
return array(
|
||||
'view_helpers' => array(
|
||||
'factories' => array(
|
||||
),
|
||||
'aliases' => [
|
||||
],
|
||||
'invokables' => [
|
||||
]
|
||||
),
|
||||
'translator' => array(
|
||||
'locale' => 'en_US',
|
||||
'translation_file_patterns' => array(
|
||||
array(
|
||||
'type' => 'gettext',
|
||||
'base_dir' => __DIR__ . '/../language',
|
||||
'pattern' => '%s.mo',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
7
src/module/Application/config/navigation.config.php
Executable file
7
src/module/Application/config/navigation.config.php
Executable file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
'navigation' => [
|
||||
'left' => [
|
||||
],
|
||||
],
|
||||
];
|
||||
7
src/module/Application/config/routes.config.php
Executable file
7
src/module/Application/config/routes.config.php
Executable file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
$config = array();
|
||||
foreach (glob(__DIR__ . '/routes/routes.*.php') as $filename) {
|
||||
$config = array_merge_recursive($config, include($filename));
|
||||
}
|
||||
return $config;
|
||||
27
src/module/Application/config/routes/routes.index.php
Executable file
27
src/module/Application/config/routes/routes.index.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Application;
|
||||
|
||||
use Zend\Router\Http\Segment;
|
||||
|
||||
return array(
|
||||
'router' => [
|
||||
'routes' => [
|
||||
'data' => [
|
||||
'child_routes' => [
|
||||
'clock' => [
|
||||
'type' => Segment::class,
|
||||
'options' => [
|
||||
'route' => '/clock',
|
||||
'defaults' => [
|
||||
'controller' => Controller\IndexController::class,
|
||||
'action' => 'clock',
|
||||
'resource' => 'default',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
);
|
||||
35
src/module/Application/pwa/html/application/chat.html
Normal file
35
src/module/Application/pwa/html/application/chat.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<div class='max-height'>
|
||||
<span id='chat-title' class='chat'>
|
||||
<span class='chat-img-container'><img class='chat-img'></span>
|
||||
<span class='chat-name'></span>
|
||||
</span>
|
||||
<div id='date-template'>
|
||||
<div class='date'></div>
|
||||
</div>
|
||||
|
||||
<div id='message-template' class='fill-me vertical message'>
|
||||
<div class='author-image-container'><img class='author-image'></div>
|
||||
<div class='grow'>
|
||||
<div class='bubble'>
|
||||
<div class='author'></div>
|
||||
<div class='message-text'></div>
|
||||
<div class='time'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='fill-me max-height'>
|
||||
<div class='grow' id='message-container'></div>
|
||||
<div>
|
||||
<div id='send-container' class='fill-me vertical'>
|
||||
<div class = 'answer-button-container'>
|
||||
<button id='previous-button' class='answer-button'><</button>
|
||||
</div>
|
||||
<div class='grow' id='answer'></div>
|
||||
<div class = 'answer-button-container'>
|
||||
<button id='next-button' class='answer-button'>></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
4
src/module/Application/pwa/html/application/clock.html
Normal file
4
src/module/Application/pwa/html/application/clock.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<div class = 'row'>
|
||||
<div class = 'small-12 smedium-6 columns' data-translation="current-time">Current time:</div>
|
||||
<div class = 'small-12 smedium-6 columns' id = 'current-time'>???</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<div id = 'tabs'></div>
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
<div>
|
||||
<div id='author-template' class='author-entry fill-me vertical'>
|
||||
<div class='author-image-container'><img class='author-image'></div>
|
||||
<div class='author-name grow'></div>
|
||||
<!--<div>-->
|
||||
<div class='user-flag'>1</div>
|
||||
<!--</div>-->
|
||||
</div>
|
||||
<div id='author-list'></div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div>
|
||||
chats
|
||||
</div>
|
||||
@@ -0,0 +1,76 @@
|
||||
<div class='max-height fill-me'>
|
||||
<div class='row max-width grow flex-center'>
|
||||
<div class='columns small-centered small-12 smedium-9 medium-11 large-7'>
|
||||
<h3 data-translation="ask-settings"></h3>
|
||||
<label class='row'>
|
||||
<span class='columns small-6' data-translation="ignore-card-always"></span>
|
||||
<span class='columns small-6'><input type="checkbox" class='setting' name='ignore-card-always'
|
||||
value='true'></span>
|
||||
</label>
|
||||
|
||||
<h5 data-translation="settings-ignore-buttons-heading"></h5>
|
||||
<p data-translation="settings-ignore-buttons-explanation"></p>
|
||||
|
||||
<div class='row'>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="text" class='setting' required name="ignore-button-1-text"
|
||||
data-default="ignore-card-1" data-default-translateable="1">
|
||||
<span data-translation="settings-ignore-button-1-text"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="number" class='setting' required name="ignore-button-1-time" data-default="120">
|
||||
<span data-translation="settings-ignore-button-1-time"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="text" class='setting' required name="ignore-button-2-text"
|
||||
data-default="ignore-card-2" data-default-translateable="1">
|
||||
<span data-translation="settings-ignore-button-2-text"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="number" class='setting' required name="ignore-button-2-time" data-default="1440">
|
||||
<span data-translation="settings-ignore-button-2-time"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="text" class='setting' required name="ignore-button-3-text"
|
||||
data-default="ignore-card-3" data-default-translateable="1">
|
||||
<span data-translation="settings-ignore-button-3-text"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="number" class='setting' required name="ignore-button-3-time" data-default="7200">
|
||||
<span data-translation="settings-ignore-button-3-time"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="text" class='setting' required name="ignore-button-4-text" data-default="ignore-card-4"
|
||||
data-default-translateable="1">
|
||||
<span data-translation="settings-ignore-button-4-text"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="columns small-12 smedium-6">
|
||||
<label>
|
||||
<input type="number" class='setting' required name="ignore-button-4-time" data-default="525600">
|
||||
<span data-translation="settings-ignore-button-4-time"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
<div>
|
||||
<div id='chat-template' class='chat overview fill-me vertical'>
|
||||
<div class = 'chat-img-container'><img class='chat-img'></div>
|
||||
<div class='grow'>
|
||||
<div class = 'fill-me vertical'>
|
||||
<div class='chat-name grow'></div>
|
||||
<div class = 'unread-message-counter'></div>
|
||||
</div>
|
||||
<div class = 'fill-me vertical'>
|
||||
<div class='chat-last-message grow'></div>
|
||||
<div class = 'chat-last-message-timestamp'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='chat-container'>
|
||||
</div>
|
||||
</div>
|
||||
21
src/module/Application/pwa/js/site/ClockSite.js
Normal file
21
src/module/Application/pwa/js/site/ClockSite.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import {DataManager} from "../../../../../js/lib/pwa-core";
|
||||
import {AbstractSite} from "../../../../../js/lib/pwa-lib";
|
||||
|
||||
export class ClockSite extends AbstractSite
|
||||
{
|
||||
constructor(siteManager) {
|
||||
super(siteManager, "html/application/clock.html");
|
||||
}
|
||||
|
||||
|
||||
onConstruct(args) {
|
||||
this.setTitle("clock");
|
||||
return super.onConstruct(args);
|
||||
}
|
||||
|
||||
onFirstStart(){
|
||||
DataManager.load("clock").then(function(data){
|
||||
document.getElementById("current-time").innerText = data.result.date;
|
||||
});
|
||||
}
|
||||
}
|
||||
6
src/module/Application/pwa/translations/de.json
Normal file
6
src/module/Application/pwa/translations/de.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"is-writing":"{0} schreibt...",
|
||||
"restart":"Story neustarten...",
|
||||
"should-restart-title":"Wirklich neustarten?",
|
||||
"should-restart-question":"Willst du wirklich neu starten? Dein bisheriger Fortschritt geht dabei verloren!"
|
||||
}
|
||||
3
src/module/Application/pwa/translations/en.json
Normal file
3
src/module/Application/pwa/translations/en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"is-writing":"{0} is writing..."
|
||||
}
|
||||
18
src/module/Application/src/Controller/IndexController.php
Executable file
18
src/module/Application/src/Controller/IndexController.php
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
|
||||
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
namespace Application\Controller;
|
||||
|
||||
use Ainias\Core\Controller\JsonController;
|
||||
|
||||
class IndexController extends JsonController
|
||||
{
|
||||
public function clockAction()
|
||||
{
|
||||
return ["date" => (new \DateTime())->format("H:i:s, Y-m-d")];
|
||||
}
|
||||
}
|
||||
143
src/module/Application/src/Module.php
Executable file
143
src/module/Application/src/Module.php
Executable file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
|
||||
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
namespace Application;
|
||||
|
||||
use Ainias\Core\Connections\MyConnection;
|
||||
use Ainias\Core\Model\Doctrine\DatabaseListener;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Zend\EventManager\Event;
|
||||
use Zend\Http\Request;
|
||||
use Zend\Http\Response;
|
||||
use Zend\Log\Filter\Priority;
|
||||
use Zend\Log\Logger;
|
||||
use Zend\Log\Writer\ChromePhp;
|
||||
use Zend\Log\Writer\Stream;
|
||||
use Zend\Mvc\Controller\AbstractActionController;
|
||||
use Zend\Mvc\ModuleRouteListener;
|
||||
use Zend\Mvc\MvcEvent;
|
||||
use Zend\Router\Http\TreeRouteStack;
|
||||
use Zend\Session\Container;
|
||||
use Zend\Session\SessionManager;
|
||||
use Zend\View\Model\ViewModel;
|
||||
|
||||
class Module
|
||||
{
|
||||
const VERSION = '3.0.0dev';
|
||||
const LOG_DIR = __DIR__ . "/../../../../log";
|
||||
const EVENT_LOG = "log";
|
||||
|
||||
public function onBootstrap(MvcEvent $e)
|
||||
{
|
||||
$eventManager = $e->getApplication()->getEventManager();
|
||||
$moduleRouteListener = new ModuleRouteListener();
|
||||
$moduleRouteListener->attach($eventManager);
|
||||
$request = $e->getRequest();
|
||||
|
||||
$logPath = realpath(self::LOG_DIR);
|
||||
$logger = new Logger();
|
||||
$catchAllWriter = new Stream($logPath . "/log.log");
|
||||
$logger->addWriter($catchAllWriter);
|
||||
$errorWriter = new Stream($logPath . "/error.log");
|
||||
$errorWriter->addFilter(new Priority(Logger::ERR));
|
||||
$logger->addWriter($errorWriter);
|
||||
$errorLogger = new Logger();
|
||||
$phpErrorWriter = new Stream($logPath . "/php_error.log");
|
||||
$errorLogger->addWriter($catchAllWriter);
|
||||
$errorLogger->addWriter($phpErrorWriter);
|
||||
Logger::registerErrorHandler($errorLogger);
|
||||
Logger::registerFatalErrorShutdownFunction($errorLogger);
|
||||
|
||||
$exceptionLogger = new Logger();
|
||||
$exceptionWriter = new Stream($logPath . "/php_exceptions.log");
|
||||
$exceptionLogger->addWriter($catchAllWriter);
|
||||
$exceptionLogger->addWriter($exceptionWriter);
|
||||
Logger::registerExceptionHandler($exceptionLogger);
|
||||
|
||||
if (($request instanceof Request)) {
|
||||
$chromePhp = new ChromePhp();
|
||||
$errorLogger->addWriter($chromePhp);
|
||||
$exceptionLogger->addWriter($chromePhp);
|
||||
}
|
||||
|
||||
$eventManager->getSharedManager()->attach('*', self::EVENT_LOG, function (Event $e) use ($logger) {
|
||||
$params = $e->getParams();
|
||||
|
||||
if (isset($params["message"])) {
|
||||
if (isset($params["level"]) && ($params["level"] == Logger::ALERT || $params["level"] == Logger::CRIT || $params["level"] == Logger::DEBUG || $params["level"] == Logger::EMERG || $params["level"] == Logger::ERR || $params["level"] == Logger::INFO || $params["level"] == Logger::NOTICE)) {
|
||||
$logLevel = $params["level"];
|
||||
} else {
|
||||
$logLevel = Logger::INFO;
|
||||
}
|
||||
$logger->log($logLevel, $params["message"]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function getConfig()
|
||||
{
|
||||
$config = array();
|
||||
foreach (glob(__DIR__ . '/../config/*.config.php') as $filename) {
|
||||
$config = array_merge_recursive($config, include($filename));
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
// public function getServiceConfig()
|
||||
// {
|
||||
// return [
|
||||
// 'factories' => [
|
||||
// SessionManager::class => function ($container) {
|
||||
// $config = $container->get('config');
|
||||
// if (!isset($config['session'])) {
|
||||
// $sessionManager = new SessionManager();
|
||||
// Container::setDefaultManager($sessionManager);
|
||||
// return $sessionManager;
|
||||
// }
|
||||
//
|
||||
// $session = $config['session'];
|
||||
//
|
||||
// $sessionConfig = null;
|
||||
// if (isset($session['config'])) {
|
||||
// $class = isset($session['config']['class'])
|
||||
// ? $session['config']['class']
|
||||
// : SessionConfig::class;
|
||||
//
|
||||
// $options = isset($session['config']['options'])
|
||||
// ? $session['config']['options']
|
||||
// : [];
|
||||
//
|
||||
// $sessionConfig = new $class();
|
||||
// $sessionConfig->setOptions($options);
|
||||
// }
|
||||
//
|
||||
// $sessionStorage = null;
|
||||
// if (isset($session['storage'])) {
|
||||
// $class = $session['storage'];
|
||||
// $sessionStorage = new $class();
|
||||
// }
|
||||
//
|
||||
// $sessionSaveHandler = null;
|
||||
// if (isset($session['save_handler'])) {
|
||||
// // class should be fetched from service manager
|
||||
// // since it will require constructor arguments
|
||||
// $sessionSaveHandler = $container->get($session['save_handler']);
|
||||
// }
|
||||
//
|
||||
// $sessionManager = new SessionManager(
|
||||
// $sessionConfig,
|
||||
// $sessionStorage,
|
||||
// $sessionSaveHandler
|
||||
// );
|
||||
//
|
||||
// Container::setDefaultManager($sessionManager);
|
||||
// return $sessionManager;
|
||||
// },
|
||||
// ],
|
||||
// ];
|
||||
// }
|
||||
}
|
||||
208
src/scss/_actionBar.scss
Executable file
208
src/scss/_actionBar.scss
Executable file
@@ -0,0 +1,208 @@
|
||||
@import "../../node_modules/foundation-sites/scss/foundation";
|
||||
|
||||
#action-bar {
|
||||
.close-listener {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
z-index: 9000;
|
||||
}
|
||||
#responsive-menu {
|
||||
.top-bar-right {
|
||||
position: relative;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
.top-bar-right {
|
||||
width: auto;
|
||||
|
||||
.menu {
|
||||
&.action-bar {
|
||||
a {
|
||||
img + span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.action {
|
||||
position: relative;
|
||||
z-index: 9000;
|
||||
&.is-dropdown-submenu-parent{
|
||||
z-index: 9001;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
@include breakpoint(small down) {
|
||||
&.smedium {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@include breakpoint(smedium down) {
|
||||
li {
|
||||
display: table-cell;
|
||||
}
|
||||
&.medium {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@include breakpoint(medium down) {
|
||||
&.large {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.never {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
display: inline-block;
|
||||
//float: right;
|
||||
position: absolute;
|
||||
z-index: 9000;
|
||||
border: 1px solid rgb(202, 202, 202);
|
||||
padding: 0.2rem;
|
||||
transform: translateX(-100%);
|
||||
text-align: left;
|
||||
|
||||
.action {
|
||||
&.is-dropdown-submenu-parent {
|
||||
z-index: 9001;
|
||||
ul.is-dropdown-submenu {
|
||||
top: auto;
|
||||
> li.action, > .close-listener {
|
||||
z-index: 9001;
|
||||
}
|
||||
}
|
||||
> a:after {
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 6px inset;
|
||||
content: "";
|
||||
border-bottom-width: 0;
|
||||
border-top-style: solid;
|
||||
border-color: #ffffff transparent transparent;
|
||||
right: 5px;
|
||||
left: auto;
|
||||
margin-top: -3px;
|
||||
}
|
||||
}
|
||||
a {
|
||||
white-space: nowrap;
|
||||
img {
|
||||
display: none;
|
||||
+ span {
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include breakpoint(medium) {
|
||||
&.medium {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@include breakpoint(smedium) {
|
||||
&.smedium {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@include breakpoint(large) {
|
||||
&.large {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(small down) {
|
||||
&.smedium {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@include breakpoint(smedium down) {
|
||||
&.medium {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@include breakpoint(medium down) {
|
||||
&.large {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&.never {
|
||||
display: block;
|
||||
}
|
||||
&.always {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.action {
|
||||
z-index: 100;
|
||||
@include breakpoint(smedium down) {
|
||||
a {
|
||||
width: 100%;
|
||||
//text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(smedium down) {
|
||||
a {
|
||||
padding-left: 0.68rem;
|
||||
}
|
||||
}
|
||||
@include breakpoint(small down) {
|
||||
a {
|
||||
padding-left: 0.236rem;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.is-dropdown-submenu-parent) {
|
||||
@include breakpoint(smedium down) {
|
||||
a {
|
||||
padding-right: 0.68rem;
|
||||
}
|
||||
}
|
||||
@include breakpoint(small down) {
|
||||
a {
|
||||
padding-right: 0.236rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.img a {
|
||||
padding-top: 0;
|
||||
//padding-bottom: 0;
|
||||
img {
|
||||
vertical-align: inherit;
|
||||
max-height: 1.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
> li > ul.is-dropdown-submenu {
|
||||
min-width: 0;
|
||||
.action {
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
> li.opens-right > ul.is-dropdown-submenu {
|
||||
right: auto;
|
||||
left: auto;
|
||||
a {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown.menu > li.is-dropdown-submenu-parent > a:after {
|
||||
border-color: #ffffff transparent transparent;
|
||||
}
|
||||
19
src/scss/_editStory.scss
Normal file
19
src/scss/_editStory.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
#author-list {
|
||||
.author-entry {
|
||||
border-bottom: 1px solid $borderColor;
|
||||
.author-image-container {
|
||||
.author-image {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.user-flag{
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.isUser{
|
||||
.user-flag{
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
621
src/scss/_foundationSettings.scss
Executable file
621
src/scss/_foundationSettings.scss
Executable file
@@ -0,0 +1,621 @@
|
||||
// Foundation for Sites Settings
|
||||
// -----------------------------
|
||||
//
|
||||
// Table of Contents:
|
||||
//
|
||||
// 1. Global
|
||||
// 2. Breakpoints
|
||||
// 3. The Grid
|
||||
// 4. Base Typography
|
||||
// 5. Typography Helpers
|
||||
// 6. Abide
|
||||
// 7. Accordion
|
||||
// 8. Accordion Menu
|
||||
// 9. Badge
|
||||
// 10. Breadcrumbs
|
||||
// 11. Button
|
||||
// 12. Button Group
|
||||
// 13. Callout
|
||||
// 14. Card
|
||||
// 15. Close Button
|
||||
// 16. Drilldown
|
||||
// 17. Dropdown
|
||||
// 18. Dropdown Menu
|
||||
// 19. Forms
|
||||
// 20. Label
|
||||
// 21. Media Object
|
||||
// 22. Menu
|
||||
// 23. Meter
|
||||
// 24. Off-canvas
|
||||
// 25. Orbit
|
||||
// 26. Pagination
|
||||
// 27. Progress Bar
|
||||
// 28. Responsive Embed
|
||||
// 29. Reveal
|
||||
// 30. Slider
|
||||
// 31. Switch
|
||||
// 32. Table
|
||||
// 33. Tabs
|
||||
// 34. Thumbnail
|
||||
// 35. Title Bar
|
||||
// 36. Tooltip
|
||||
// 37. Top Bar
|
||||
|
||||
@import '../../node_modules/foundation-sites/scss/util/util';
|
||||
|
||||
// 1. Global
|
||||
// ---------
|
||||
|
||||
$global-font-size: 100%;
|
||||
$global-width: rem-calc(1200);
|
||||
$global-lineheight: 1.5;
|
||||
$foundation-palette: (
|
||||
primary: #1779ba,
|
||||
secondary: #767676,
|
||||
success: #3adb76,
|
||||
warning: #ffae00,
|
||||
alert: #cc4b37,
|
||||
);
|
||||
$light-gray: #e6e6e6;
|
||||
$medium-gray: #cacaca;
|
||||
$dark-gray: #8a8a8a;
|
||||
$black: #0a0a0a;
|
||||
$white: #fefefe;
|
||||
$body-background: $white;
|
||||
$body-font-color: $black;
|
||||
$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
|
||||
$body-antialiased: true;
|
||||
$global-margin: 1rem;
|
||||
$global-padding: 1rem;
|
||||
$global-weight-normal: normal;
|
||||
$global-weight-bold: bold;
|
||||
$global-radius: 0;
|
||||
$global-text-direction: ltr;
|
||||
$global-flexbox: false;
|
||||
$print-transparent-backgrounds: true;
|
||||
|
||||
@include add-foundation-colors;
|
||||
|
||||
// 2. Breakpoints
|
||||
// --------------
|
||||
|
||||
$breakpoints: (
|
||||
small:0px,
|
||||
smedium: 400px,
|
||||
medium: 640px,
|
||||
large: 1024px,
|
||||
xlarge: 1200px,
|
||||
xxlarge: 1440px,
|
||||
);
|
||||
$print-breakpoint: large;
|
||||
$breakpoint-classes: (small medium large);
|
||||
|
||||
// 3. The Grid
|
||||
// -----------
|
||||
|
||||
$grid-row-width: $global-width;
|
||||
$grid-column-count: 12;
|
||||
$grid-column-gutter: (
|
||||
small: 20px,
|
||||
medium: 30px,
|
||||
);
|
||||
$grid-column-align-edge: true;
|
||||
$block-grid-max: 8;
|
||||
|
||||
// 4. Base Typography
|
||||
// ------------------
|
||||
|
||||
$header-font-family: $body-font-family;
|
||||
$header-font-weight: $global-weight-normal;
|
||||
$header-font-style: normal;
|
||||
$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
|
||||
$header-color: inherit;
|
||||
$header-lineheight: 1.4;
|
||||
$header-margin-bottom: 0.5rem;
|
||||
$header-styles: (
|
||||
small: (
|
||||
'h1': ('font-size': 24),
|
||||
'h2': ('font-size': 20),
|
||||
'h3': ('font-size': 19),
|
||||
'h4': ('font-size': 18),
|
||||
'h5': ('font-size': 17),
|
||||
'h6': ('font-size': 16),
|
||||
),
|
||||
medium: (
|
||||
'h1': ('font-size': 48),
|
||||
'h2': ('font-size': 40),
|
||||
'h3': ('font-size': 31),
|
||||
'h4': ('font-size': 25),
|
||||
'h5': ('font-size': 20),
|
||||
'h6': ('font-size': 16),
|
||||
),
|
||||
);
|
||||
$header-text-rendering: optimizeLegibility;
|
||||
$small-font-size: 80%;
|
||||
$header-small-font-color: $medium-gray;
|
||||
$paragraph-lineheight: 1.6;
|
||||
$paragraph-margin-bottom: 1rem;
|
||||
$paragraph-text-rendering: optimizeLegibility;
|
||||
$code-color: $black;
|
||||
$code-font-family: $font-family-monospace;
|
||||
$code-font-weight: $global-weight-normal;
|
||||
$code-background: $light-gray;
|
||||
$code-border: 1px solid $medium-gray;
|
||||
$code-padding: rem-calc(2 5 1);
|
||||
$anchor-color: $primary-color;
|
||||
$anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
|
||||
$anchor-text-decoration: none;
|
||||
$anchor-text-decoration-hover: none;
|
||||
$hr-width: $global-width;
|
||||
$hr-border: 1px solid $medium-gray;
|
||||
$hr-margin: rem-calc(20) auto;
|
||||
$list-lineheight: $paragraph-lineheight;
|
||||
$list-margin-bottom: $paragraph-margin-bottom;
|
||||
$list-style-type: disc;
|
||||
$list-style-position: outside;
|
||||
$list-side-margin: 1.25rem;
|
||||
$list-nested-side-margin: 1.25rem;
|
||||
$defnlist-margin-bottom: 1rem;
|
||||
$defnlist-term-weight: $global-weight-bold;
|
||||
$defnlist-term-margin-bottom: 0.3rem;
|
||||
$blockquote-color: $dark-gray;
|
||||
$blockquote-padding: rem-calc(9 20 0 19);
|
||||
$blockquote-border: 1px solid $medium-gray;
|
||||
$cite-font-size: rem-calc(13);
|
||||
$cite-color: $dark-gray;
|
||||
$cite-pseudo-content: '\2014 \0020';
|
||||
$keystroke-font: $font-family-monospace;
|
||||
$keystroke-color: $black;
|
||||
$keystroke-background: $light-gray;
|
||||
$keystroke-padding: rem-calc(2 4 0);
|
||||
$keystroke-radius: $global-radius;
|
||||
$abbr-underline: 1px dotted $black;
|
||||
|
||||
// 5. Typography Helpers
|
||||
// ---------------------
|
||||
|
||||
$lead-font-size: $global-font-size * 1.25;
|
||||
$lead-lineheight: 1.6;
|
||||
$subheader-lineheight: 1.4;
|
||||
$subheader-color: $dark-gray;
|
||||
$subheader-font-weight: $global-weight-normal;
|
||||
$subheader-margin-top: 0.2rem;
|
||||
$subheader-margin-bottom: 0.5rem;
|
||||
$stat-font-size: 2.5rem;
|
||||
|
||||
// 6. Abide
|
||||
// --------
|
||||
|
||||
$abide-inputs: true;
|
||||
$abide-labels: true;
|
||||
$input-background-invalid: get-color(alert);
|
||||
$form-label-color-invalid: get-color(alert);
|
||||
$input-error-color: get-color(alert);
|
||||
$input-error-font-size: rem-calc(12);
|
||||
$input-error-font-weight: $global-weight-bold;
|
||||
|
||||
// 7. Accordion
|
||||
// ------------
|
||||
|
||||
$accordion-background: $white;
|
||||
$accordion-plusminus: true;
|
||||
$accordion-title-font-size: rem-calc(12);
|
||||
$accordion-item-color: $primary-color;
|
||||
$accordion-item-background-hover: $light-gray;
|
||||
$accordion-item-padding: 1.25rem 1rem;
|
||||
$accordion-content-background: $white;
|
||||
$accordion-content-border: 1px solid $light-gray;
|
||||
$accordion-content-color: $body-font-color;
|
||||
$accordion-content-padding: 1rem;
|
||||
|
||||
// 8. Accordion Menu
|
||||
// -----------------
|
||||
|
||||
$accordionmenu-arrows: true;
|
||||
$accordionmenu-arrow-color: $primary-color;
|
||||
$accordionmenu-arrow-size: 6px;
|
||||
|
||||
// 9. Badge
|
||||
// --------
|
||||
|
||||
$badge-background: $primary-color;
|
||||
$badge-color: $white;
|
||||
$badge-color-alt: $black;
|
||||
$badge-palette: $foundation-palette;
|
||||
$badge-padding: 0.3em;
|
||||
$badge-minwidth: 2.1em;
|
||||
$badge-font-size: 0.6rem;
|
||||
|
||||
// 10. Breadcrumbs
|
||||
// ---------------
|
||||
|
||||
$breadcrumbs-margin: 0 0 $global-margin 0;
|
||||
$breadcrumbs-item-font-size: rem-calc(11);
|
||||
$breadcrumbs-item-color: $primary-color;
|
||||
$breadcrumbs-item-color-current: $black;
|
||||
$breadcrumbs-item-color-disabled: $medium-gray;
|
||||
$breadcrumbs-item-margin: 0.75rem;
|
||||
$breadcrumbs-item-uppercase: true;
|
||||
$breadcrumbs-item-slash: true;
|
||||
|
||||
// 11. Button
|
||||
// ----------
|
||||
|
||||
$button-padding: 0.85em 1em;
|
||||
$button-margin: 0 0 $global-margin 0;
|
||||
$button-fill: solid;
|
||||
$button-background: $primary-color;
|
||||
$button-background-hover: scale-color($button-background, $lightness: -15%);
|
||||
$button-color: $white;
|
||||
$button-color-alt: $black;
|
||||
$button-radius: $global-radius;
|
||||
$button-sizes: (
|
||||
tiny: 0.6rem,
|
||||
small: 0.75rem,
|
||||
default: 0.9rem,
|
||||
large: 1.25rem,
|
||||
);
|
||||
$button-palette: $foundation-palette;
|
||||
$button-opacity-disabled: 0.25;
|
||||
$button-background-hover-lightness: -20%;
|
||||
$button-hollow-hover-lightness: -50%;
|
||||
$button-transition: background-color 0.25s ease-out, color 0.25s ease-out;
|
||||
|
||||
// 12. Button Group
|
||||
// ----------------
|
||||
|
||||
$buttongroup-margin: 1rem;
|
||||
$buttongroup-spacing: 1px;
|
||||
$buttongroup-child-selector: '.button';
|
||||
$buttongroup-expand-max: 6;
|
||||
$buttongroup-radius-on-each: true;
|
||||
|
||||
// 13. Callout
|
||||
// -----------
|
||||
|
||||
$callout-background: $white;
|
||||
$callout-background-fade: 85%;
|
||||
$callout-border: 1px solid rgba($black, 0.25);
|
||||
$callout-margin: 0 0 1rem 0;
|
||||
$callout-padding: 1rem;
|
||||
$callout-font-color: $body-font-color;
|
||||
$callout-font-color-alt: $body-background;
|
||||
$callout-radius: $global-radius;
|
||||
$callout-link-tint: 30%;
|
||||
|
||||
// 14. Card
|
||||
// --------
|
||||
|
||||
$card-background: $white;
|
||||
$card-font-color: $body-font-color;
|
||||
$card-divider-background: $light-gray;
|
||||
$card-border: 1px solid $light-gray;
|
||||
$card-shadow: none;
|
||||
$card-border-radius: $global-radius;
|
||||
$card-padding: $global-padding;
|
||||
$card-margin: $global-margin;
|
||||
|
||||
// 15. Close Button
|
||||
// ----------------
|
||||
|
||||
$closebutton-position: right top;
|
||||
$closebutton-offset-horizontal: (
|
||||
small: 0.66rem,
|
||||
medium: 1rem,
|
||||
);
|
||||
$closebutton-offset-vertical: (
|
||||
small: 0.33em,
|
||||
medium: 0.5rem,
|
||||
);
|
||||
$closebutton-size: (
|
||||
small: 1.5em,
|
||||
medium: 2em,
|
||||
);
|
||||
$closebutton-lineheight: 1;
|
||||
$closebutton-color: $dark-gray;
|
||||
$closebutton-color-hover: $black;
|
||||
|
||||
// 16. Drilldown
|
||||
// -------------
|
||||
|
||||
$drilldown-transition: transform 0.15s linear;
|
||||
$drilldown-arrows: true;
|
||||
$drilldown-arrow-color: $primary-color;
|
||||
$drilldown-arrow-size: 6px;
|
||||
$drilldown-background: $white;
|
||||
|
||||
// 17. Dropdown
|
||||
// ------------
|
||||
|
||||
$dropdown-padding: 1rem;
|
||||
$dropdown-background: $body-background;
|
||||
$dropdown-border: 1px solid $medium-gray;
|
||||
$dropdown-font-size: 1rem;
|
||||
$dropdown-width: 300px;
|
||||
$dropdown-radius: $global-radius;
|
||||
$dropdown-sizes: (
|
||||
tiny: 100px,
|
||||
small: 200px,
|
||||
large: 400px,
|
||||
);
|
||||
|
||||
// 18. Dropdown Menu
|
||||
// -----------------
|
||||
|
||||
$dropdownmenu-arrows: true;
|
||||
$dropdownmenu-arrow-color: $anchor-color;
|
||||
$dropdownmenu-arrow-size: 6px;
|
||||
$dropdownmenu-min-width: 200px;
|
||||
$dropdownmenu-background: $white;
|
||||
$dropdownmenu-border: 1px solid $medium-gray;
|
||||
|
||||
// 19. Forms
|
||||
// ---------
|
||||
|
||||
$fieldset-border: 1px solid $medium-gray;
|
||||
$fieldset-padding: rem-calc(20);
|
||||
$fieldset-margin: rem-calc(18 0);
|
||||
$legend-padding: rem-calc(0 3);
|
||||
$form-spacing: rem-calc(16);
|
||||
$helptext-color: $black;
|
||||
$helptext-font-size: rem-calc(13);
|
||||
$helptext-font-style: italic;
|
||||
$input-prefix-color: $black;
|
||||
$input-prefix-background: $light-gray;
|
||||
$input-prefix-border: 1px solid $medium-gray;
|
||||
$input-prefix-padding: 1rem;
|
||||
$form-label-color: $black;
|
||||
$form-label-font-size: rem-calc(14);
|
||||
$form-label-font-weight: $global-weight-normal;
|
||||
$form-label-line-height: 1.8;
|
||||
$select-background: $white;
|
||||
$select-triangle-color: $dark-gray;
|
||||
$select-radius: $global-radius;
|
||||
$input-color: $black;
|
||||
$input-placeholder-color: $medium-gray;
|
||||
$input-font-family: inherit;
|
||||
$input-font-size: rem-calc(16);
|
||||
$input-font-weight: $global-weight-normal;
|
||||
$input-background: $white;
|
||||
$input-background-focus: $white;
|
||||
$input-background-disabled: $light-gray;
|
||||
$input-border: 1px solid $medium-gray;
|
||||
$input-border-focus: 1px solid $dark-gray;
|
||||
$input-shadow: inset 0 1px 2px rgba($black, 0.1);
|
||||
$input-shadow-focus: 0 0 5px $medium-gray;
|
||||
$input-cursor-disabled: not-allowed;
|
||||
$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
|
||||
$input-number-spinners: true;
|
||||
$input-radius: $global-radius;
|
||||
$form-button-radius: $global-radius;
|
||||
|
||||
// 20. Label
|
||||
// ---------
|
||||
|
||||
$label-background: $primary-color;
|
||||
$label-color: $white;
|
||||
$label-color-alt: $black;
|
||||
$label-palette: $foundation-palette;
|
||||
$label-font-size: 0.8rem;
|
||||
$label-padding: 0.33333rem 0.5rem;
|
||||
$label-radius: $global-radius;
|
||||
|
||||
// 21. Media Object
|
||||
// ----------------
|
||||
|
||||
$mediaobject-margin-bottom: $global-margin;
|
||||
$mediaobject-section-padding: $global-padding;
|
||||
$mediaobject-image-width-stacked: 100%;
|
||||
|
||||
// 22. Menu
|
||||
// --------
|
||||
|
||||
$menu-margin: 0;
|
||||
$menu-margin-nested: 1rem;
|
||||
$menu-item-padding: 0.7rem 1rem;
|
||||
$menu-item-color-active: $white;
|
||||
$menu-item-background-active: get-color(primary);
|
||||
$menu-icon-spacing: 0.25rem;
|
||||
$menu-item-background-hover: $light-gray;
|
||||
$menu-border: $light-gray;
|
||||
|
||||
// 23. Meter
|
||||
// ---------
|
||||
|
||||
$meter-height: 1rem;
|
||||
$meter-radius: $global-radius;
|
||||
$meter-background: $medium-gray;
|
||||
$meter-fill-good: $success-color;
|
||||
$meter-fill-medium: $warning-color;
|
||||
$meter-fill-bad: $alert-color;
|
||||
|
||||
// 24. Off-canvas
|
||||
// --------------
|
||||
|
||||
$offcanvas-size: 250px;
|
||||
$offcanvas-vertical-size: 250px;
|
||||
$offcanvas-background: $light-gray;
|
||||
$offcanvas-shadow: 0 0 10px rgba($black, 0.7);
|
||||
$offcanvas-push-zindex: 1;
|
||||
$offcanvas-overlap-zindex: 10;
|
||||
$offcanvas-reveal-zindex: 1;
|
||||
$offcanvas-transition-length: 0.5s;
|
||||
$offcanvas-transition-timing: ease;
|
||||
$offcanvas-fixed-reveal: true;
|
||||
$offcanvas-exit-background: rgba($white, 0.25);
|
||||
$maincontent-class: 'off-canvas-content';
|
||||
|
||||
// 25. Orbit
|
||||
// ---------
|
||||
|
||||
$orbit-bullet-background: $medium-gray;
|
||||
$orbit-bullet-background-active: $dark-gray;
|
||||
$orbit-bullet-diameter: 1.2rem;
|
||||
$orbit-bullet-margin: 0.1rem;
|
||||
$orbit-bullet-margin-top: 0.8rem;
|
||||
$orbit-bullet-margin-bottom: 0.8rem;
|
||||
$orbit-caption-background: rgba($black, 0.5);
|
||||
$orbit-caption-padding: 1rem;
|
||||
$orbit-control-background-hover: rgba($black, 0.5);
|
||||
$orbit-control-padding: 1rem;
|
||||
$orbit-control-zindex: 10;
|
||||
|
||||
// 26. Pagination
|
||||
// --------------
|
||||
|
||||
$pagination-font-size: rem-calc(14);
|
||||
$pagination-margin-bottom: $global-margin;
|
||||
$pagination-item-color: $black;
|
||||
$pagination-item-padding: rem-calc(3 10);
|
||||
$pagination-item-spacing: rem-calc(1);
|
||||
$pagination-radius: $global-radius;
|
||||
$pagination-item-background-hover: $light-gray;
|
||||
$pagination-item-background-current: $primary-color;
|
||||
$pagination-item-color-current: $white;
|
||||
$pagination-item-color-disabled: $medium-gray;
|
||||
$pagination-ellipsis-color: $black;
|
||||
$pagination-mobile-items: false;
|
||||
$pagination-mobile-current-item: false;
|
||||
$pagination-arrows: true;
|
||||
|
||||
// 27. Progress Bar
|
||||
// ----------------
|
||||
|
||||
$progress-height: 1rem;
|
||||
$progress-background: $medium-gray;
|
||||
$progress-margin-bottom: $global-margin;
|
||||
$progress-meter-background: $primary-color;
|
||||
$progress-radius: $global-radius;
|
||||
|
||||
// 28. Responsive Embed
|
||||
// --------------------
|
||||
|
||||
$responsive-embed-margin-bottom: rem-calc(16);
|
||||
$responsive-embed-ratios: (
|
||||
default: 4 by 3,
|
||||
widescreen: 16 by 9,
|
||||
);
|
||||
|
||||
// 29. Reveal
|
||||
// ----------
|
||||
|
||||
$reveal-background: $white;
|
||||
$reveal-width: 600px;
|
||||
$reveal-max-width: $global-width;
|
||||
$reveal-padding: $global-padding;
|
||||
$reveal-border: 1px solid $medium-gray;
|
||||
$reveal-radius: $global-radius;
|
||||
$reveal-zindex: 1005;
|
||||
$reveal-overlay-background: rgba($black, 0.45);
|
||||
|
||||
// 30. Slider
|
||||
// ----------
|
||||
|
||||
$slider-width-vertical: 0.5rem;
|
||||
$slider-transition: all 0.2s ease-in-out;
|
||||
$slider-height: 0.5rem;
|
||||
$slider-background: $light-gray;
|
||||
$slider-fill-background: $medium-gray;
|
||||
$slider-handle-height: 1.4rem;
|
||||
$slider-handle-width: 1.4rem;
|
||||
$slider-handle-background: $primary-color;
|
||||
$slider-opacity-disabled: 0.25;
|
||||
$slider-radius: $global-radius;
|
||||
|
||||
// 31. Switch
|
||||
// ----------
|
||||
|
||||
$switch-background: $medium-gray;
|
||||
$switch-background-active: $primary-color;
|
||||
$switch-height: 2rem;
|
||||
$switch-height-tiny: 1.5rem;
|
||||
$switch-height-small: 1.75rem;
|
||||
$switch-height-large: 2.5rem;
|
||||
$switch-radius: $global-radius;
|
||||
$switch-margin: $global-margin;
|
||||
$switch-paddle-background: $white;
|
||||
$switch-paddle-offset: 0.25rem;
|
||||
$switch-paddle-radius: $global-radius;
|
||||
$switch-paddle-transition: all 0.25s ease-out;
|
||||
|
||||
// 32. Table
|
||||
// ---------
|
||||
|
||||
$table-background: $white;
|
||||
$table-color-scale: 5%;
|
||||
$table-border: 1px solid smart-scale($table-background, $table-color-scale);
|
||||
$table-padding: rem-calc(8 10 10);
|
||||
$table-hover-scale: 2%;
|
||||
$table-row-hover: darken($table-background, $table-hover-scale);
|
||||
$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
|
||||
$table-is-striped: true;
|
||||
$table-striped-background: smart-scale($table-background, $table-color-scale);
|
||||
$table-stripe: even;
|
||||
$table-head-background: smart-scale($table-background, $table-color-scale / 2);
|
||||
$table-head-row-hover: darken($table-head-background, $table-hover-scale);
|
||||
$table-foot-background: smart-scale($table-background, $table-color-scale);
|
||||
$table-foot-row-hover: darken($table-foot-background, $table-hover-scale);
|
||||
$table-head-font-color: $body-font-color;
|
||||
$table-foot-font-color: $body-font-color;
|
||||
$show-header-for-stacked: false;
|
||||
|
||||
// 33. Tabs
|
||||
// --------
|
||||
|
||||
$tab-margin: 0;
|
||||
$tab-background: $white;
|
||||
$tab-color: $primary-color;
|
||||
$tab-background-active: $light-gray;
|
||||
$tab-active-color: $primary-color;
|
||||
$tab-item-font-size: rem-calc(12);
|
||||
$tab-item-background-hover: $white;
|
||||
$tab-item-padding: 1.25rem 1.5rem;
|
||||
$tab-expand-max: 6;
|
||||
$tab-content-background: $white;
|
||||
$tab-content-border: $light-gray;
|
||||
$tab-content-color: $body-font-color;
|
||||
$tab-content-padding: 1rem;
|
||||
|
||||
// 34. Thumbnail
|
||||
// -------------
|
||||
|
||||
$thumbnail-border: solid 4px $white;
|
||||
$thumbnail-margin-bottom: $global-margin;
|
||||
$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
|
||||
$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
|
||||
$thumbnail-transition: box-shadow 200ms ease-out;
|
||||
$thumbnail-radius: $global-radius;
|
||||
|
||||
// 35. Title Bar
|
||||
// -------------
|
||||
|
||||
$titlebar-background: $black;
|
||||
$titlebar-color: $white;
|
||||
$titlebar-padding: 0.5rem;
|
||||
$titlebar-text-font-weight: bold;
|
||||
$titlebar-icon-color: $white;
|
||||
$titlebar-icon-color-hover: $medium-gray;
|
||||
$titlebar-icon-spacing: 0.25rem;
|
||||
|
||||
// 36. Tooltip
|
||||
// -----------
|
||||
|
||||
$has-tip-font-weight: $global-weight-bold;
|
||||
$has-tip-border-bottom: dotted 1px $dark-gray;
|
||||
$tooltip-background-color: $black;
|
||||
$tooltip-color: $white;
|
||||
$tooltip-padding: 0.75rem;
|
||||
$tooltip-font-size: $small-font-size;
|
||||
$tooltip-pip-width: 0.75rem;
|
||||
$tooltip-pip-height: $tooltip-pip-width * 0.866;
|
||||
$tooltip-radius: $global-radius;
|
||||
|
||||
// 37. Top Bar
|
||||
// -----------
|
||||
|
||||
$topbar-padding: 0.5rem;
|
||||
$topbar-background: $light-gray;
|
||||
$topbar-submenu-background: $topbar-background;
|
||||
$topbar-title-spacing: 0.5rem 1rem 0.5rem 0;
|
||||
$topbar-input-width: 200px;
|
||||
$topbar-unstack-breakpoint: medium;
|
||||
4
src/scss/_settings.scss
Executable file
4
src/scss/_settings.scss
Executable file
@@ -0,0 +1,4 @@
|
||||
@import "foundationSettings";
|
||||
|
||||
$hoverColor: #f2f2f2;
|
||||
$hoverColorDark: #e8e8e8;
|
||||
94
src/scss/stories.css
Normal file
94
src/scss/stories.css
Normal file
@@ -0,0 +1,94 @@
|
||||
.author {
|
||||
color: #979797; }
|
||||
.author:after {
|
||||
content: ':';
|
||||
padding-right: 2px; }
|
||||
|
||||
.chat-img-container, .author-image-container {
|
||||
width: 2.4rem;
|
||||
position: relative; }
|
||||
.chat-img-container .chat-img, .chat-img-container .author-image, .author-image-container .chat-img, .author-image-container .author-image {
|
||||
position: absolute;
|
||||
margin: 0.2em;
|
||||
border-radius: 50%;
|
||||
width: 1.8em; }
|
||||
|
||||
.chat {
|
||||
border-bottom: 1px solid #ececec; }
|
||||
.chat.overview {
|
||||
cursor: pointer; }
|
||||
.chat .chat-name {
|
||||
font-weight: bold; }
|
||||
.chat .chat-last-message {
|
||||
color: #555555;
|
||||
overflow: hidden;
|
||||
white-space: nowrap; }
|
||||
.chat .chat-last-message .isWriting {
|
||||
color: #aa1c1d; }
|
||||
.chat .chat-last-message-timestamp {
|
||||
font-size: 0.8rem; }
|
||||
.chat .unread-message-counter {
|
||||
background-color: red;
|
||||
border-radius: 50%;
|
||||
color: white;
|
||||
font-size: 0.7rem;
|
||||
border: 1px solid #9b0000;
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
line-height: 1.2rem;
|
||||
text-align: center;
|
||||
vertical-align: middle; }
|
||||
.chat .unread-message-counter:empty {
|
||||
display: none; }
|
||||
|
||||
#chat-title {
|
||||
border-bottom: none; }
|
||||
#chat-title .chat-img {
|
||||
width: 1.4em;
|
||||
position: relative; }
|
||||
|
||||
.message {
|
||||
margin-bottom: 0.1rem; }
|
||||
.message.my-message {
|
||||
text-align: right; }
|
||||
.message.my-message .author-image-container, .message.my-message .author {
|
||||
display: none; }
|
||||
.message.my-message .bubble {
|
||||
background-color: rgba(255, 0, 0, 0.5);
|
||||
border-radius: 5px 5px 0 5px; }
|
||||
.message .author-image {
|
||||
bottom: 0; }
|
||||
.message .bubble {
|
||||
display: inline-block;
|
||||
padding: 0.2rem;
|
||||
border: 1px solid #646464;
|
||||
border-radius: 5px 5px 5px 0;
|
||||
max-width: 80%;
|
||||
text-align: left; }
|
||||
.message .bubble .author {
|
||||
font-size: 0.7rem;
|
||||
text-align: left;
|
||||
line-height: 0.9; }
|
||||
.message .bubble .message-text {
|
||||
line-height: 1; }
|
||||
.message .bubble .time {
|
||||
line-height: 0.9;
|
||||
font-size: 0.5rem;
|
||||
text-align: right; }
|
||||
|
||||
#answer {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
min-height: 50px; }
|
||||
|
||||
.answer-button-container .answer-button {
|
||||
overflow: hidden;
|
||||
margin-top: -0.1em;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
padding: 0 0.1em 0.1em;
|
||||
text-align: center;
|
||||
vertical-align: middle; }
|
||||
137
src/scss/stories.scss
Normal file
137
src/scss/stories.scss
Normal file
@@ -0,0 +1,137 @@
|
||||
$borderColor: #ececec;
|
||||
|
||||
//Allgemein
|
||||
.author {
|
||||
color: #979797;
|
||||
&:after {
|
||||
content: ':';
|
||||
padding-right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-img-container, .author-image-container {
|
||||
width: 2.4rem;
|
||||
position: relative;
|
||||
.chat-img, .author-image {
|
||||
position: absolute;
|
||||
margin: 0.2em;
|
||||
border-radius: 50%;
|
||||
width: 1.8em;
|
||||
}
|
||||
}
|
||||
|
||||
//Overview
|
||||
.chat {
|
||||
border-bottom: 1px solid $borderColor;
|
||||
&.overview {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chat-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.chat-last-message {
|
||||
color: #555555;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
.isWriting {
|
||||
color: #aa1c1d;
|
||||
}
|
||||
}
|
||||
.chat-last-message-timestamp {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.unread-message-counter {
|
||||
background-color: red;
|
||||
border-radius: 50%;
|
||||
color: white;
|
||||
font-size: 0.7rem;
|
||||
border: 1px solid #9b0000;
|
||||
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
line-height: 1.2rem;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------Chat
|
||||
#chat-title {
|
||||
border-bottom: none;
|
||||
.chat-img {
|
||||
width: 1.4em;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-bottom: 0.1rem;
|
||||
|
||||
&.my-message {
|
||||
text-align: right;
|
||||
|
||||
.author-image-container, .author {
|
||||
display: none;
|
||||
}
|
||||
.bubble {
|
||||
background-color: rgba(255, 0, 0, 0.5);
|
||||
border-radius: 5px 5px 0 5px;
|
||||
}
|
||||
}
|
||||
.author-image {
|
||||
bottom: 0;
|
||||
}
|
||||
.bubble {
|
||||
display: inline-block;
|
||||
padding: 0.2rem;
|
||||
border: 1px solid #646464;
|
||||
border-radius: 5px 5px 5px 0;
|
||||
max-width: 80%;
|
||||
text-align: left;
|
||||
|
||||
.author {
|
||||
font-size: 0.7rem;
|
||||
text-align: left;
|
||||
line-height: 0.9;
|
||||
}
|
||||
.message-text {
|
||||
line-height: 1;
|
||||
}
|
||||
.time {
|
||||
line-height: 0.9;
|
||||
font-size: 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#answer {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.answer-button-container {
|
||||
.answer-button {
|
||||
overflow: hidden;
|
||||
margin-top: -0.1em;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
padding: 0 0.1em 0.1em;
|
||||
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@import "editStory";
|
||||
Reference in New Issue
Block a user