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 = '';

View 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,
],
],
);

View 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',
)
)
),
),
);

View 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(
),
),
);

View 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',
),
),
),
);

View File

@@ -0,0 +1,7 @@
<?php
return [
'navigation' => [
'left' => [
],
],
];

View 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;

View 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',
],
],
],
],
],
],
],
);

View 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'>&lt;</button>
</div>
<div class='grow' id='answer'></div>
<div class = 'answer-button-container'>
<button id='next-button' class='answer-button'>&gt;</button>
</div>
</div>
</div>
</div>
</div>

View 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>

View File

@@ -0,0 +1,3 @@
<div>
<div id = 'tabs'></div>
</div>

View File

@@ -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>

View File

@@ -0,0 +1,3 @@
<div>
chats
</div>

View File

@@ -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>

View File

@@ -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>

View 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;
});
}
}

View 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!"
}

View File

@@ -0,0 +1,3 @@
{
"is-writing":"{0} is writing..."
}

View 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")];
}
}

View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,4 @@
@import "foundationSettings";
$hoverColor: #f2f2f2;
$hoverColorDark: #e8e8e8;

94
src/scss/stories.css Normal file
View 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
View 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";