import("./views/forgotView")}
- />
- )
- })
- },
- {
- path: "/resetPassword/:token",
- component: ({ params } = {}) => ({
- title: "Reset password",
- component: h(resetPasswordView(context), {
- store: stores.resetPassword,
- params
- })
- })
- },
- {
- path: "/verifyEmail/:code",
- component: () => ({
- title: "Verify Email",
- component: h(registrationCompleteView(context), {
- store: stores.verifyEmailCode
- })
- }),
- action: ({ params }) => stores.verifyEmailCode.execute({ code: params.code })
- }
- ];
- }
-
- const stores = Stores();
-
- return {
- stores: () => stores,
- routes: () => Routes(stores)
- };
-}
diff --git a/client/src/app/parts/auth/authModule.spec.js b/client/src/app/parts/auth/authModule.spec.js
deleted file mode 100644
index 066a14f8..00000000
--- a/client/src/app/parts/auth/authModule.spec.js
+++ /dev/null
@@ -1 +0,0 @@
-describe.skip("Auth", function() {});
diff --git a/client/src/app/parts/core/coreModule.js b/client/src/app/parts/core/coreModule.js
deleted file mode 100644
index 6af5dd22..00000000
--- a/client/src/app/parts/core/coreModule.js
+++ /dev/null
@@ -1,10 +0,0 @@
-function Containers(/*context*/) {
- return {};
-}
-
-// Part
-export default function(context) {
- return {
- containers: Containers(context)
- };
-}
diff --git a/client/src/app/parts/core/coreModule.spec.js b/client/src/app/parts/core/coreModule.spec.js
deleted file mode 100644
index 1f900c7f..00000000
--- a/client/src/app/parts/core/coreModule.spec.js
+++ /dev/null
@@ -1,3 +0,0 @@
-describe("Core", function() {
- it("default locale, set a new one", () => {});
-});
diff --git a/client/src/app/parts/db/SchemaComponent.js b/client/src/app/parts/db/SchemaComponent.js
deleted file mode 100644
index 3a64ff0d..00000000
--- a/client/src/app/parts/db/SchemaComponent.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import map from "lodash/map";
-import React, { createElement as h } from "react";
-import { observer } from "mobx-react";
-import spinner from "components/spinner";
-import glamorous from "glamorous";
-
-export default context => {
- const { tr } = context;
- const Panel = require("components/panel").default(context);
-
- const DbTables = glamorous("div")({
- display: "flex",
- flexWrap: "wrap",
- justifyContent: "flex-start",
- alignContent: "stretch",
- alignItems: "stretch"
- });
-
- const DbPanel = glamorous(Panel.Panel)({
- flexGrow: "1",
- flexShrink: "1",
- margin: "10px",
- padding: "0px",
- maxHeight: "300px",
- overflowY: "auto",
- overflowX: "hidden"
- });
-
- function ColumnItem({ column, columnName }) {
- return (
-
-
- {`${column.column_name}: `}
- |
- {`${column.data_type}`} |
-
- );
- }
-
- function TableItem({ table, tableName }) {
- const columns = map(table.columns, (column, columnName) => (
-
- ));
- return (
-
- {tableName}
-
-
-
-
- );
- }
-
- function SchemaComponent({ store }) {
- const { loading, data } = store.opGet;
- return (
-
-
{tr.t("Tables")}
- {loading && h(spinner(context))}
-
{data && data.message}
-
- {data
- && map(data.tables, (table, tableName) => (
-
- ))}
-
-
- );
- }
- return observer(SchemaComponent);
-};
diff --git a/client/src/app/parts/db/dbModule.js b/client/src/app/parts/db/dbModule.js
deleted file mode 100644
index 0787e9e0..00000000
--- a/client/src/app/parts/db/dbModule.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { createElement as h } from "react";
-import { observable, action } from "mobx";
-import AsyncOp from "utils/asyncOp";
-import asyncView from "components/AsyncView";
-
-export default function(context) {
- const { rest } = context;
- const asyncOpCreate = AsyncOp(context);
-
- function Stores() {
- const schemaStore = observable({
- opGet: asyncOpCreate(data => rest.get(`db/schema`, data)),
- get: action(async function() {
- await this.opGet.fetch();
- })
- });
- return {
- schema: schemaStore
- };
- }
-
- function Routes(stores) {
- return [
- {
- path: "/dbschema",
- component: () => ({
- title: "Schema explorer",
- component: h(asyncView(context), {
- store: stores.schema,
- getModule: () => import("./SchemaComponent")
- })
- }),
- action: () => stores.schema.get()
- }
- ];
- }
-
- const stores = Stores();
- return {
- stores: () => stores,
- routes: () => Routes(stores)
- };
-}
diff --git a/client/src/app/parts/hello/Hello.js b/client/src/app/parts/hello/Hello.js
deleted file mode 100644
index 74a66d04..00000000
--- a/client/src/app/parts/hello/Hello.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import React from "react";
-import { observable } from "mobx";
-import { observer } from "mobx-react";
-import glamorous from "glamorous";
-
-export default context => {
- const { tr, theme } = context;
- const { palette } = theme;
-
- const store = observable({
- show: false,
- toggle() {
- store.show = !store.show;
- },
- word: "World"
- });
-
- const HelloView = glamorous("div")({
- width: 300,
- padding: 20,
- border: `1px solid ${palette.borderColor}`,
- display: "flex",
- flexDirection: "column",
- alignItems: "center",
- "> * ": {
- margin: 20
- }
- });
-
- function Word({ store }) {
- return {store.word}
;
- }
-
- function Hello() {
- return (
-
- {tr.t("Hello")}
-
- {store.show && }
-
- );
- }
- return {
- store,
- view: observer(Hello)
- };
-};
diff --git a/client/src/app/parts/hello/HelloModule.js b/client/src/app/parts/hello/HelloModule.js
deleted file mode 100644
index 4349b7f5..00000000
--- a/client/src/app/parts/hello/HelloModule.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { createElement as h } from "react";
-import createHello from "./Hello";
-
-export default context => {
- const hello = createHello(context);
- function Routes() {
- return [
- {
- path: "/hello",
- component: () => ({
- title: "Hello",
- component: h(hello.view)
- })
- //action: () => hello.store.get()
- }
- ];
- }
-
- return {
- stores: () => ({ hello: hello.store }),
- routes: () => Routes()
- };
-};
diff --git a/client/src/app/parts/theme/ThemeView.js b/client/src/app/parts/theme/ThemeView.js
deleted file mode 100644
index cf46e3e7..00000000
--- a/client/src/app/parts/theme/ThemeView.js
+++ /dev/null
@@ -1,142 +0,0 @@
-import * as React from "react";
-import { observable } from "mobx";
-import { observer } from "mobx-react";
-import glamorous from "glamorous";
-import ColorPicker from "react-color/lib/components/photoshop/Photoshop";
-import deepForceUpdate from "preact-deep-force-update";
-
-export default context => {
- const { theme } = context;
- const { palette } = theme;
- //console.log("theme primary", palette.primary);
-
- const store = observable({
- showPicker: false,
- colorValue: "",
- colorName: ""
- });
- const ColorListView = glamorous("div")({
- width: 300
- });
-
- const ColorRowView = glamorous("div")({
- display: "flex",
- flexDirection: "row",
- alignContent: "center",
- alignItems: "center",
- margin: 10,
- cursor: "pointer",
- border: `1px dotted grey`
- });
- const ColorTextView = glamorous("div")({
- display: "flex",
- flexDirection: "row",
- alignContent: "center",
- alignItems: "center",
- margin: 10,
- cursor: "pointer"
- });
- const Color = glamorous("div")({
- height: 40,
- width: 40,
- margin: 6,
- background: "black"
- });
-
- function onChangeColor(event) {
- console.log("onChangeColor ", event.hex);
- palette[store.colorName] = event.hex;
- setTimeout(() => deepForceUpdate(context.rootInstance), 1);
- }
- function onAcceptColor(event) {
- console.log("onAcceptColor ", event.hex);
- store.showPicker = false;
- }
- function onShowPicker(colorName) {
- console.log("onShowPicker ", colorName);
- store.colorName = colorName;
- store.colorValue = palette[colorName];
- store.showPicker = true;
- }
-
- function onCancelColor() {
- store.showPicker = false;
- }
- function ColorRow({ colorName }) {
- return (
- onShowPicker(colorName)}>
-
- {colorName}
-
- );
- }
- function ColorGroupLightDark({ colorName, display }) {
- return (
- onShowPicker(colorName)}>
-
-
-
- {display}
-
- );
- }
- const ColorGroupTextView = glamorous("div")({
- flex: 1,
- flexDirection: "column",
- border: `1px dotted grey`,
- margin: 10
- });
-
- function ColorGroupText({ colorName, display }) {
- console.log("ColorGroupText ", colorName, display);
- return (
-
- onShowPicker(colorName)}>
-
- {display}
-
- onShowPicker(`${colorName}OnPrimary`)}>
-
- {`${display} On Primary`}
-
- onShowPicker(`${colorName}OnSecondary`)}>
-
- {`${display} On Secondary`}
-
-
- );
- }
- const colors = ["background", "borderColor"];
-
- function ThemeView() {
- //console.log("ThemeView: ", theme, store.colorValue);
- //console.log("ThemeView: colorValue ", store.colorValue);
- return (
-
- {store.showPicker && (
- onChangeColor(event)}
- onAccept={event => onAcceptColor(event)}
- onCancel={event => onCancelColor(event)}
- />
- )}
-
-
-
-
-
- {colors.map((color, key) => )}
-
-
- );
- }
- return observer(ThemeView);
-};
diff --git a/client/src/app/parts/theme/themeModule.js b/client/src/app/parts/theme/themeModule.js
deleted file mode 100644
index 2383673b..00000000
--- a/client/src/app/parts/theme/themeModule.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { observable } from "mobx";
-
-export default function() {
- function Stores() {
- const sideBarStore = observable({
- open: false,
- toogle() {
- this.open = !this.open;
- }
- });
- return {
- sideBar: sideBarStore
- };
- }
-
- const stores = Stores();
- return {
- stores: () => stores
- };
-}
diff --git a/client/src/app/router.js b/client/src/app/router.js
deleted file mode 100644
index 15c9a90b..00000000
--- a/client/src/app/router.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import React, { createElement as h } from "react";
-import Router from "universal-router";
-import { render } from "react-dom";
-import { keyframes } from "glamor";
-
-import { parse } from "qs";
-import appView from "components/applicationView";
-import asyncView from "components/AsyncView";
-
-import Animate from "react-leanimate/Animate";
-import createRoutes from "./routes";
-
-
-const animation = {
- showFromLeft: keyframes({
- "0%": { transform: "translateX(-50%)", opacity: 0 },
- "100%": { transform: "translateX(0%)", opacity: 1 }
- }),
- hideToRight: keyframes({
- "0%": { transform: "translateX(0%)", opacity: 1 },
- "100%": { transform: "translateX(50%)", opacity: 0 }
- })
-};
-
-export default context => {
- const { tr, history, config } = context;
-
- const router = new Router(createRoutes(context), {
- resolveRoute(routerContext, params) {
- const { route } = routerContext;
- //console.log("resolveRoute ", routerContext, params);
-
- if (typeof route.load === "function") {
- return route.load(routerContext);
- }
- if (typeof route.action === "function") {
- route.action(routerContext, params);
- }
- if (typeof route.component === "function") {
- return route.component(routerContext);
- }
- return undefined;
- }
- });
-
- const onRenderComplete = route => {
- document.title = `${route.title} - ${config.title}`;
- };
-
- async function onLocationChange(location) {
- //console.log("onLocationChange ", location);
- let component;
- let route;
- try {
- route = await router.resolve({
- pathname: location.pathname,
- query: parse(location.search)
- });
- component = route.component; // eslint-disable-line prefer-destructuring
- } catch (error) {
- console.error("Routing exception:", error.message);
- if (error.code === 404) {
- component = h(asyncView(context), {
- getModule: () => import("./components/notFound")
- });
- route = { title: tr.t("Page Not Found") };
- }
- //TODO display error message
- }
- if (component) {
- const Layout = appView(context);
- const layout = (
-
-
-
- );
- context.rootInstance = render(
- layout,
- document.getElementById("application"),
- () => onRenderComplete(route, location)
- );
- }
- }
-
- history.listen(onLocationChange);
-
- return {
- instance: router,
- start() {
- onLocationChange(history.location);
- }
- };
-};
diff --git a/client/src/app/router.spec.js b/client/src/app/router.spec.js
deleted file mode 100644
index dd9b6a2a..00000000
--- a/client/src/app/router.spec.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import chai from "chai";
-import chaiAsPromised from "chai-as-promised";
-import Router from "./router";
-import App from "./app";
-
-chai.use(chaiAsPromised);
-const { expect, assert } = chai;
-
-describe("Router", function() {
- const { context } = App({});
- it("/login", async () => {
- const router = Router(context).instance;
- const component = await router.resolve("/login");
- assert(component);
- assert.equal(component.title, "Login");
- });
- it("/app/profile not authenticated", async () => {
- const router = Router(context).instance;
- expect(router.resolve("/profile")).to.be.rejectedWith(Error);
- });
- it("/app/profile authenticated", async () => {
- const router = Router(context).instance;
- context.parts.auth.stores().auth.authenticated = true;
- const route = await router.resolve("/profile");
- assert.equal(route.title, "My Profile");
- });
-});
diff --git a/client/src/app/routes.js b/client/src/app/routes.js
deleted file mode 100644
index 3ba02c90..00000000
--- a/client/src/app/routes.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { createElement as h } from "react";
-import asyncView from "components/AsyncView";
-
-export default context => {
- const {parts} = context;
- const AsyncView = asyncView(context);
-
- function isAuthenticated({ pathname }) {
- console.log("isAuthenticated ", pathname);
- const { authenticated } = context.parts.auth.stores().auth;
- if (!authenticated) {
- setTimeout(() => context.history.push(`/login?nextPath=${pathname}`), 1);
- throw new Error({ name: "redirect", status: 302 });
- }
- }
-
- function createPart(partName, partCreate, routerContext) {
- const part = partCreate.default(context);
- context.parts[partName] = part;
- routerContext.route.children = part.routes();
- return routerContext.next();
- }
-
- return [
- {
- path: "",
- component: () => ({
- title: "Home",
- component: h(AsyncView, {
- getModule: () => import("./parts/landing/landingScreen")
- })
- })
- },
- {
- path: "/guide",
- component: () => ({
- title: "Component Guide",
- component: h(AsyncView, {
- getModule: () => import("./components/componentGuide")
- })
- })
- },
- ...parts.auth.routes(),
- ...parts.db.routes(),
- ...parts.hello.routes(),
- {
- path: "/profile",
- children: [],
- load: async routerContext => {
- isAuthenticated(routerContext);
- const partCreate = await import("./parts/profile/profileModule");
- return createPart("profile", partCreate, routerContext);
- }
- },
- {
- path: "/users",
- children: [],
- load: async routerContext => {
- isAuthenticated(routerContext);
- const partCreate = await import("./parts/admin/adminModule");
- return createPart("admin", partCreate, routerContext);
- }
- }
- ];
-};
diff --git a/client/src/app/test/app.spec.js b/client/src/app/test/app.spec.js
deleted file mode 100644
index cac5d51d..00000000
--- a/client/src/app/test/app.spec.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { assert } from "chai";
-import App from "../app";
-
-describe("App", function() {
- const app = App({});
- it("start", async () => {
- await app.start();
- });
- it("parts", async () => {
- const { parts } = app.context;
- assert.isAbove(Object.keys(parts).length, 2);
- assert(parts.core);
- });
-});
diff --git a/client/src/app/theme.js b/client/src/app/theme.js
deleted file mode 100644
index 6cdad0cc..00000000
--- a/client/src/app/theme.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import Theme from "mdlean/lib/theme";
-
-const theme = Theme();
-//console.log("Theme: ", theme);
-
-export default () => theme;
diff --git a/client/src/app_admin/AdminApp.js b/client/src/app_admin/AdminApp.js
new file mode 100644
index 00000000..e4de6824
--- /dev/null
+++ b/client/src/app_admin/AdminApp.js
@@ -0,0 +1,16 @@
+import Context from "../context";
+import App from "../app";
+import layout from "./Layout";
+import createRoutes from "./routes";
+
+export default async () => {
+ const context = await Context({
+ config: {
+ title: "Admin",
+ routeAfterLogin: "/admin/users",
+ defaultPath: "/admin/users"
+ }
+ });
+
+ return App({ context, routes: createRoutes({ context }), layout });
+};
diff --git a/client/src/app_admin/Layout.js b/client/src/app_admin/Layout.js
new file mode 100644
index 00000000..cf083894
--- /dev/null
+++ b/client/src/app_admin/Layout.js
@@ -0,0 +1,30 @@
+import React, { createElement as h } from "react";
+import { observer } from "mobx-react";
+import navBar from "components/navbar";
+import footer from "components/footer";
+import RootView from "components/RootView";
+import MainView from "components/MainView";
+import APP_MENU from "./menuItems";
+
+export default context => {
+ const {
+ alertStack: { View: AlertStack }
+ } = context;
+
+ const NavBar = navBar(context);
+ const Footer = footer(context);
+
+ const Layout = ({ children }) => (
+
+
+ {children}
+
+
+
+ );
+
+ return ({ children }) =>
+ h(observer(Layout), {
+ children
+ });
+};
diff --git a/client/src/app_admin/index.js b/client/src/app_admin/index.js
new file mode 100644
index 00000000..880b0909
--- /dev/null
+++ b/client/src/app_admin/index.js
@@ -0,0 +1,2 @@
+import App from "./AdminApp";
+App().catch(error => console.error(error));
\ No newline at end of file
diff --git a/client/src/app_admin/menuItems.ts b/client/src/app_admin/menuItems.ts
new file mode 100644
index 00000000..37d32ec9
--- /dev/null
+++ b/client/src/app_admin/menuItems.ts
@@ -0,0 +1,10 @@
+export default () => [
+ {
+ route: "/admin/users",
+ text: "USERS"
+ },
+ {
+ route: "/admin/auth/logout",
+ text: "LOGOUT"
+ }
+];
diff --git a/client/src/app_admin/routes.js b/client/src/app_admin/routes.js
new file mode 100644
index 00000000..7b13c9c9
--- /dev/null
+++ b/client/src/app_admin/routes.js
@@ -0,0 +1,31 @@
+import {createPart} from "../router"
+
+export default ({context}) => [
+ {
+ path: "/admin",
+ children: [
+ {
+ path: "/auth",
+ children: [],
+ action: async routerContext =>
+ createPart({
+ name: "auth",
+ context,
+ partCreate: await import("parts/auth/authModule"),
+ routerContext
+ })
+ },
+ {
+ path: "/users",
+ children: [],
+ action: async routerContext =>
+ createPart({
+ name: "users",
+ context,
+ partCreate: await import("./users/usersModule"),
+ routerContext
+ })
+ },
+ ]
+ }
+];
diff --git a/client/src/app/parts/admin/userComponent.js b/client/src/app_admin/users/userComponent.js
similarity index 100%
rename from client/src/app/parts/admin/userComponent.js
rename to client/src/app_admin/users/userComponent.js
diff --git a/client/src/app/parts/admin/users.js b/client/src/app_admin/users/users.js
similarity index 100%
rename from client/src/app/parts/admin/users.js
rename to client/src/app_admin/users/users.js
diff --git a/client/src/app/parts/admin/usersColumns.js b/client/src/app_admin/users/usersColumns.js
similarity index 100%
rename from client/src/app/parts/admin/usersColumns.js
rename to client/src/app_admin/users/usersColumns.js
diff --git a/client/src/app/parts/admin/adminModule.js b/client/src/app_admin/users/usersModule.js
similarity index 55%
rename from client/src/app/parts/admin/adminModule.js
rename to client/src/app_admin/users/usersModule.js
index ffd29dfe..f8e8ba0b 100644
--- a/client/src/app/parts/admin/adminModule.js
+++ b/client/src/app_admin/users/usersModule.js
@@ -21,7 +21,7 @@ export default function(context) {
}
function selectOne(userId) {
- context.history.push(`/users/${userId}`);
+ context.history.push(`users/${userId}`);
}
const users = usersCreate(context, {
@@ -33,19 +33,31 @@ export default function(context) {
return [
{
path: "",
- component: () => ({
- title: "Users",
- component: users.component
- }),
- action: () => users.store.selectPage(1)
- },
- {
- path: "/:userId",
- component: () => ({
- title: "User",
- component: h(user(context), { store: stores.user })
- }),
- action: ({ params }) => stores.user.get(params.userId)
+ protected: true,
+ children: [
+ {
+ path: "",
+ action: routerContext => {
+ users.store.selectPage(1);
+ return {
+ routerContext,
+ title: "Users",
+ component: users.component
+ };
+ }
+ },
+ {
+ path: "/:userId",
+ action: routerContext => {
+ stores.user.get(routerContext.params.userId);
+ return {
+ routerContext,
+ title: "User",
+ component: h(user(context), { store: stores.user })
+ };
+ }
+ }
+ ]
}
];
}
diff --git a/client/src/app_micro/Micro.js b/client/src/app_micro/Micro.js
new file mode 100644
index 00000000..70d4efde
--- /dev/null
+++ b/client/src/app_micro/Micro.js
@@ -0,0 +1,105 @@
+/** @jsx jsx */
+import { jsx, css } from "@emotion/core";
+import { observer } from "mobx-react";
+import { observable } from "mobx";
+import Context from "../context";
+import App from "../app";
+import createLink from "components/link";
+
+export default async () => {
+ const context = await Context();
+ const { tr, palette } = context;
+ const Link = createLink(context);
+
+ const store = observable({
+ show: false,
+ toggle() {
+ store.show = !store.show;
+ }
+ });
+
+ const Menu = () => (
+
+ Main
+ Page
+
+ );
+
+ const layout = () => ({ children }) => (
+
+
+
+ {children}
+
+
+ );
+
+ const Intro = observer(() => (
+
+
Edit app_micro/Micro.js to get started
+
+ {store.show &&
More info here
}
+
+ ));
+
+ const PageA = () => PageA
;
+
+ const routes = [
+ {
+ path: "/",
+ action: () => ({
+ title: "Intro",
+ component:
+ })
+ },
+ {
+ path: "/page",
+ action: () => ({
+ title: "Page",
+ component:
+ })
+ }
+ ];
+
+ return App({ context, routes, layout });
+};
diff --git a/client/src/app_micro/index.js b/client/src/app_micro/index.js
new file mode 100644
index 00000000..9fb48a7b
--- /dev/null
+++ b/client/src/app_micro/index.js
@@ -0,0 +1,2 @@
+import App from "./Micro";
+App().catch(error => console.error(error));
diff --git a/client/src/app_micro/test/app.spec.js b/client/src/app_micro/test/app.spec.js
new file mode 100644
index 00000000..b18c4517
--- /dev/null
+++ b/client/src/app_micro/test/app.spec.js
@@ -0,0 +1,14 @@
+import { assert } from "chai";
+import App from "../Micro";
+
+describe("App", async function() {
+ let app;
+ beforeAll(async () => {
+ app = await App();
+ })
+ it("/", async () => {
+ const route = await app.router.instance.resolve("/");
+ assert(route);
+ //assert.equal(route.title, "Hello");
+ });
+});
diff --git a/client/src/app_public/Layout.js b/client/src/app_public/Layout.js
new file mode 100644
index 00000000..e59ca665
--- /dev/null
+++ b/client/src/app_public/Layout.js
@@ -0,0 +1,32 @@
+import React, { createElement as h } from "react";
+import { observer } from "mobx-react";
+import navBar from "components/navbar";
+import footer from "components/footer";
+import authBar from "components/authBar";
+import RootView from "components/RootView";
+import MainView from "components/MainView";
+import APP_MENU from "./menuItems";
+
+export default context => {
+ const {
+ alertStack: { View: AlertStack }
+ } = context;
+
+ const NavBar = navBar(context);
+ const Footer = footer(context);
+ const AuthBar = authBar(context);
+
+ const Layout = ({ children }) => (
+
+
+ {children}
+
+
+
+ );
+
+ return ({ children }) =>
+ h(observer(Layout), {
+ children
+ });
+};
diff --git a/client/src/app_public/PublicApp.js b/client/src/app_public/PublicApp.js
new file mode 100644
index 00000000..ddc09f5e
--- /dev/null
+++ b/client/src/app_public/PublicApp.js
@@ -0,0 +1,14 @@
+import Context from "../context";
+import App from "../app";
+import createRoutes from "./routes";
+import layout from "./Layout";
+
+export default async () => {
+ const context = await Context({
+ config: {
+ title: "Starhackit"
+ }
+ });
+
+ return App({ context, routes: createRoutes({ context }), layout });
+};
diff --git a/client/src/app_public/index.js b/client/src/app_public/index.js
new file mode 100644
index 00000000..944b5d03
--- /dev/null
+++ b/client/src/app_public/index.js
@@ -0,0 +1,2 @@
+import App from "./PublicApp";
+App().catch(error => console.error(error));
\ No newline at end of file
diff --git a/client/src/app/parts/landing/cardComponent.js b/client/src/app_public/landing/cardComponent.js
similarity index 82%
rename from client/src/app/parts/landing/cardComponent.js
rename to client/src/app_public/landing/cardComponent.js
index c679aed3..0a903394 100644
--- a/client/src/app/parts/landing/cardComponent.js
+++ b/client/src/app_public/landing/cardComponent.js
@@ -1,10 +1,9 @@
import React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
import fontIcon from "components/FontIcon";
export default context => {
- const { theme } = context;
- const { palette } = theme;
+ const { palette } = context;
const FontIcon = fontIcon(context);
function MediaIcon({ icon }) {
return (
@@ -22,27 +21,27 @@ export default context => {
);
}
- const CardView = glamorous("div")(() => ({
- width: "150",
+ const CardView = styled("div")(() => ({
+ width: "150px",
flexGrow: 1,
flexShrink: 0,
- flexBasis: "150",
+ flexBasis: "150px",
padding: 10,
margin: 10,
boxShadow: `2px 2px 2px 2px ${palette.borderColor}`
}));
- const CardContainer = glamorous("div")({
+ const CardContainer = styled("div")({
height: "100%",
display: "flex",
flexDirection: "column",
flexWrap: "wrap",
justifyContent: "space-between",
- alignContent: "space-between",
+ alignContent: "center",
alignItems: "center"
});
- const CardItem = glamorous("div")({
+ const CardItem = styled("div")({
order: 0,
flex: "0 1 auto",
boxSizing: "border-box",
diff --git a/client/src/app/parts/landing/content.js b/client/src/app_public/landing/content.js
similarity index 94%
rename from client/src/app/parts/landing/content.js
rename to client/src/app_public/landing/content.js
index c091ec7b..b56ffc89 100644
--- a/client/src/app/parts/landing/content.js
+++ b/client/src/app_public/landing/content.js
@@ -30,11 +30,11 @@ export default () => ({
],
frontend: [
{
- img: require("./img/preact.svg"),
+ img: require("./img/react.svg"),
height: "100",
- title: "Preact",
- link: "https://preactjs.com/",
- text: "Fast 3kB patent free alternative to React with the same ES6 API."
+ title: "React",
+ link: "https://reactjs.org/",
+ text: "A library for building user interfaces"
},
{
img: require("./img/mobx.svg"),
@@ -44,10 +44,10 @@ export default () => ({
text: "Simple, scalable state management"
},
{
- img: require("./img/glamorous.png"),
- title: "Glamorous",
+ img: require("./img/emotion.png"),
+ title: "Emotion",
height: "150",
- link: "https://github.com/paypal/glamorous",
+ link: "https://emotion.sh",
text: "Style React Components with Style."
},
{
diff --git a/client/src/app/parts/landing/img/ansible.png b/client/src/app_public/landing/img/ansible.png
similarity index 100%
rename from client/src/app/parts/landing/img/ansible.png
rename to client/src/app_public/landing/img/ansible.png
diff --git a/client/src/app/parts/landing/img/code-climate.png b/client/src/app_public/landing/img/code-climate.png
similarity index 100%
rename from client/src/app/parts/landing/img/code-climate.png
rename to client/src/app_public/landing/img/code-climate.png
diff --git a/client/src/app/parts/landing/img/database.svg b/client/src/app_public/landing/img/database.svg
similarity index 100%
rename from client/src/app/parts/landing/img/database.svg
rename to client/src/app_public/landing/img/database.svg
diff --git a/client/src/app/parts/landing/img/docker.png b/client/src/app_public/landing/img/docker.png
similarity index 100%
rename from client/src/app/parts/landing/img/docker.png
rename to client/src/app_public/landing/img/docker.png
diff --git a/client/src/app_public/landing/img/emotion.png b/client/src/app_public/landing/img/emotion.png
new file mode 100644
index 00000000..16cef233
Binary files /dev/null and b/client/src/app_public/landing/img/emotion.png differ
diff --git a/client/src/app/parts/landing/img/es7.png b/client/src/app_public/landing/img/es7.png
similarity index 100%
rename from client/src/app/parts/landing/img/es7.png
rename to client/src/app_public/landing/img/es7.png
diff --git a/client/src/app/parts/landing/img/eslint.svg b/client/src/app_public/landing/img/eslint.svg
similarity index 100%
rename from client/src/app/parts/landing/img/eslint.svg
rename to client/src/app_public/landing/img/eslint.svg
diff --git a/client/src/app/icons/github.svg b/client/src/app_public/landing/img/github.svg
similarity index 100%
rename from client/src/app/icons/github.svg
rename to client/src/app_public/landing/img/github.svg
diff --git a/client/src/app/parts/landing/img/glamorous.png b/client/src/app_public/landing/img/glamorous.png
similarity index 100%
rename from client/src/app/parts/landing/img/glamorous.png
rename to client/src/app_public/landing/img/glamorous.png
diff --git a/client/src/app/parts/landing/img/gulp.png b/client/src/app_public/landing/img/gulp.png
similarity index 100%
rename from client/src/app/parts/landing/img/gulp.png
rename to client/src/app_public/landing/img/gulp.png
diff --git a/client/src/app/parts/landing/img/i18next.svg b/client/src/app_public/landing/img/i18next.svg
similarity index 100%
rename from client/src/app/parts/landing/img/i18next.svg
rename to client/src/app_public/landing/img/i18next.svg
diff --git a/client/src/app/parts/landing/img/mobx.svg b/client/src/app_public/landing/img/mobx.svg
similarity index 100%
rename from client/src/app/parts/landing/img/mobx.svg
rename to client/src/app_public/landing/img/mobx.svg
diff --git a/client/src/app/parts/landing/img/mocha.svg b/client/src/app_public/landing/img/mocha.svg
similarity index 100%
rename from client/src/app/parts/landing/img/mocha.svg
rename to client/src/app_public/landing/img/mocha.svg
diff --git a/client/src/app/parts/landing/img/nightwatch.png b/client/src/app_public/landing/img/nightwatch.png
similarity index 100%
rename from client/src/app/parts/landing/img/nightwatch.png
rename to client/src/app_public/landing/img/nightwatch.png
diff --git a/client/src/app/parts/landing/img/nodejs.png b/client/src/app_public/landing/img/nodejs.png
similarity index 100%
rename from client/src/app/parts/landing/img/nodejs.png
rename to client/src/app_public/landing/img/nodejs.png
diff --git a/client/src/app/parts/landing/img/nodemon.svg b/client/src/app_public/landing/img/nodemon.svg
similarity index 100%
rename from client/src/app/parts/landing/img/nodemon.svg
rename to client/src/app_public/landing/img/nodemon.svg
diff --git a/client/src/app/parts/landing/img/passportjs.png b/client/src/app_public/landing/img/passportjs.png
similarity index 100%
rename from client/src/app/parts/landing/img/passportjs.png
rename to client/src/app_public/landing/img/passportjs.png
diff --git a/client/src/app/parts/landing/img/pm2.png b/client/src/app_public/landing/img/pm2.png
similarity index 100%
rename from client/src/app/parts/landing/img/pm2.png
rename to client/src/app_public/landing/img/pm2.png
diff --git a/client/src/app/parts/landing/img/preact.svg b/client/src/app_public/landing/img/preact.svg
similarity index 100%
rename from client/src/app/parts/landing/img/preact.svg
rename to client/src/app_public/landing/img/preact.svg
diff --git a/client/src/app/parts/landing/img/protection.svg b/client/src/app_public/landing/img/protection.svg
similarity index 100%
rename from client/src/app/parts/landing/img/protection.svg
rename to client/src/app_public/landing/img/protection.svg
diff --git a/client/src/app/parts/landing/img/rabbitmq.png b/client/src/app_public/landing/img/rabbitmq.png
similarity index 100%
rename from client/src/app/parts/landing/img/rabbitmq.png
rename to client/src/app_public/landing/img/rabbitmq.png
diff --git a/client/src/app/parts/landing/img/raml.png b/client/src/app_public/landing/img/raml.png
similarity index 100%
rename from client/src/app/parts/landing/img/raml.png
rename to client/src/app_public/landing/img/raml.png
diff --git a/client/src/app/parts/landing/img/react.svg b/client/src/app_public/landing/img/react.svg
similarity index 100%
rename from client/src/app/parts/landing/img/react.svg
rename to client/src/app_public/landing/img/react.svg
diff --git a/client/src/app/parts/landing/img/redux.svg b/client/src/app_public/landing/img/redux.svg
similarity index 100%
rename from client/src/app/parts/landing/img/redux.svg
rename to client/src/app_public/landing/img/redux.svg
diff --git a/client/src/app/parts/landing/img/sequelize.svg b/client/src/app_public/landing/img/sequelize.svg
similarity index 100%
rename from client/src/app/parts/landing/img/sequelize.svg
rename to client/src/app_public/landing/img/sequelize.svg
diff --git a/client/src/app/parts/landing/img/stack.svg b/client/src/app_public/landing/img/stack.svg
similarity index 100%
rename from client/src/app/parts/landing/img/stack.svg
rename to client/src/app_public/landing/img/stack.svg
diff --git a/client/src/app/parts/landing/img/starhackit-logo-text.png b/client/src/app_public/landing/img/starhackit-logo-text.png
similarity index 100%
rename from client/src/app/parts/landing/img/starhackit-logo-text.png
rename to client/src/app_public/landing/img/starhackit-logo-text.png
diff --git a/client/src/app/parts/landing/img/starhackit-logo.png b/client/src/app_public/landing/img/starhackit-logo.png
similarity index 100%
rename from client/src/app/parts/landing/img/starhackit-logo.png
rename to client/src/app_public/landing/img/starhackit-logo.png
diff --git a/client/src/app/parts/landing/img/travis.png b/client/src/app_public/landing/img/travis.png
similarity index 100%
rename from client/src/app/parts/landing/img/travis.png
rename to client/src/app_public/landing/img/travis.png
diff --git a/client/src/app/parts/landing/img/users.svg b/client/src/app_public/landing/img/users.svg
similarity index 100%
rename from client/src/app/parts/landing/img/users.svg
rename to client/src/app_public/landing/img/users.svg
diff --git a/client/src/app/parts/landing/img/vagrant.png b/client/src/app_public/landing/img/vagrant.png
similarity index 100%
rename from client/src/app/parts/landing/img/vagrant.png
rename to client/src/app_public/landing/img/vagrant.png
diff --git a/client/src/app/parts/landing/img/webpack.svg b/client/src/app_public/landing/img/webpack.svg
similarity index 100%
rename from client/src/app/parts/landing/img/webpack.svg
rename to client/src/app_public/landing/img/webpack.svg
diff --git a/client/src/app/parts/landing/landingModule.js b/client/src/app_public/landing/landingModule.js
similarity index 100%
rename from client/src/app/parts/landing/landingModule.js
rename to client/src/app_public/landing/landingModule.js
diff --git a/client/src/app/parts/landing/landingScreen.js b/client/src/app_public/landing/landingScreen.js
similarity index 89%
rename from client/src/app/parts/landing/landingScreen.js
rename to client/src/app_public/landing/landingScreen.js
index 7b94c2e2..57ef4bf9 100644
--- a/client/src/app/parts/landing/landingScreen.js
+++ b/client/src/app_public/landing/landingScreen.js
@@ -1,5 +1,5 @@
import React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
import button from "mdlean/lib/button";
import Row from "components/Row";
import Title from "components/Title";
@@ -7,17 +7,16 @@ import cardComponent from "./cardComponent";
import Content from "./content";
export default async context => {
- const { tr, theme } = context;
- const { palette } = theme;
+ const { tr, palette } = context;
const CardIcon = cardComponent(context);
const { features, frontend, backend, tools } = Content();
- const Section = glamorous("section")(() => ({
+ const Section = styled("section")(() => ({
borderTop: `1px solid ${palette.borderColor}`,
paddingBottom: 30
}));
- const HeaderView = glamorous("section")({
+ const HeaderView = styled("section")({
padding: 20
});
@@ -34,7 +33,7 @@ export default async context => {
label="Clone the code on GitHub"
href="https://github.com/FredericHeem/starhackit"
icon={
-
+
}
/>
@@ -53,7 +52,7 @@ export default async context => {
);
}
- const E2eImg = glamorous("img")({
+ const E2eImg = styled("img")({
width: "100%",
maxWidth: "1200"
});
diff --git a/client/src/app_public/menuItems.ts b/client/src/app_public/menuItems.ts
new file mode 100644
index 00000000..21c04415
--- /dev/null
+++ b/client/src/app_public/menuItems.ts
@@ -0,0 +1,11 @@
+export default () => [
+
+ {
+ route: "guide",
+ text: "COMPONENTS"
+ },
+ {
+ route: "hello",
+ text: "HELLO WORLD"
+ }
+];
diff --git a/client/src/app_public/routes.js b/client/src/app_public/routes.js
new file mode 100644
index 00000000..5e7f06b1
--- /dev/null
+++ b/client/src/app_public/routes.js
@@ -0,0 +1,53 @@
+import { createElement as h } from "react";
+import asyncView from "components/AsyncView";
+import {createPart} from "../router"
+
+export default ({context}) => [
+ {
+ path: "/public",
+ children: [
+ {
+ path: "",
+ action: routerContext => ({
+ routerContext,
+ title: "Home",
+ component: h(asyncView(context), {
+ getModule: () => import("./landing/landingScreen")
+ })
+ })
+ },
+ {
+ path: "/guide",
+ action: routerContext => ({
+ routerContext,
+ title: "Component Guide",
+ component: h(asyncView(context), {
+ getModule: () => import("components/componentGuide")
+ })
+ })
+ },
+ {
+ path: "/hello",
+ children: [],
+ action: async routerContext =>
+ createPart({
+ name: "hello",
+ context,
+ partCreate: await import("parts/hello/hello"),
+ routerContext
+ })
+ },
+ {
+ path: "/auth",
+ children: [],
+ action: async routerContext =>
+ createPart({
+ name: "auth",
+ context,
+ partCreate: await import("parts/auth/authModule"),
+ routerContext
+ })
+ }
+ ]
+ }
+];
diff --git a/client/src/app_user/Layout.js b/client/src/app_user/Layout.js
new file mode 100644
index 00000000..0aba2e75
--- /dev/null
+++ b/client/src/app_user/Layout.js
@@ -0,0 +1,45 @@
+import React, { createElement as h } from "react";
+import { observer } from "mobx-react";
+import footer from "components/footer";
+import MainView from "components/MainView";
+import navBar from "components/navbar";
+import APP_MENU from "./menuItems";
+
+export default context => {
+ const {
+ alertStack: { View: AlertStack }
+ } = context;
+
+ const NavBar = navBar(context);
+ const Footer = footer(context);
+
+ const Layout = ({ children }) => (
+
+ );
+
+ return ({ children }) =>
+ h(observer(Layout), {
+ children
+ });
+};
diff --git a/client/src/app_user/UserApp.js b/client/src/app_user/UserApp.js
new file mode 100644
index 00000000..0203217e
--- /dev/null
+++ b/client/src/app_user/UserApp.js
@@ -0,0 +1,16 @@
+import Context from "../context";
+import App from "../app";
+import layout from "./layout";
+import createRoutes from "./routes";
+
+export default async () => {
+ const context = await Context({
+ config: {
+ routeAfterLogin: "/user/profile",
+ defaultPath: "/user/profile",
+ title: "Your Area"
+ }
+ });
+
+ return App({ context, routes: createRoutes({ context }), layout });
+};
diff --git a/client/src/app_user/index.js b/client/src/app_user/index.js
new file mode 100644
index 00000000..79ba327e
--- /dev/null
+++ b/client/src/app_user/index.js
@@ -0,0 +1,2 @@
+import App from "./UserApp";
+App().catch(error => console.error(error));
diff --git a/client/src/app_user/menuItems.ts b/client/src/app_user/menuItems.ts
new file mode 100644
index 00000000..68de6bbb
--- /dev/null
+++ b/client/src/app_user/menuItems.ts
@@ -0,0 +1,10 @@
+export default () => [
+ {
+ route: "/user/profile",
+ text: "PROFILE"
+ },
+ {
+ route: "/user/auth/logout",
+ text: "LOGOUT"
+ }
+];
diff --git a/client/src/app/parts/profile/components/profileForm.js b/client/src/app_user/profile/components/profileForm.js
similarity index 100%
rename from client/src/app/parts/profile/components/profileForm.js
rename to client/src/app_user/profile/components/profileForm.js
diff --git a/client/src/app/parts/profile/profileModule.js b/client/src/app_user/profile/profileModule.js
similarity index 91%
rename from client/src/app/parts/profile/profileModule.js
rename to client/src/app_user/profile/profileModule.js
index 0063e890..0f32cd17 100644
--- a/client/src/app/parts/profile/profileModule.js
+++ b/client/src/app_user/profile/profileModule.js
@@ -1,7 +1,7 @@
import { observable, action } from "mobx";
import React, { createElement as h } from "react";
import validate from "validate.js";
-import rules from "services/rules";
+import rules from "utils/rules";
import AsyncOp from "utils/asyncOp";
import alert from "components/alert";
import profileView from "./views/profileView";
@@ -14,12 +14,14 @@ export default function(context) {
return [
{
path: "",
- component: () => ({
- title: "My Profile",
- component: h(profileView(context), { store: stores.profile })
- }),
- action: () => {
+ protected: true,
+ action: routerContext => {
stores.profile.get();
+ return {
+ routerContext,
+ title: "My Profile",
+ component: h(profileView(context), { store: stores.profile })
+ }
}
}
];
diff --git a/client/src/app/parts/profile/views/profileView.js b/client/src/app_user/profile/views/profileView.js
similarity index 100%
rename from client/src/app/parts/profile/views/profileView.js
rename to client/src/app_user/profile/views/profileView.js
diff --git a/client/src/app_user/routes.js b/client/src/app_user/routes.js
new file mode 100644
index 00000000..68544f9a
--- /dev/null
+++ b/client/src/app_user/routes.js
@@ -0,0 +1,32 @@
+
+import {createPart} from "../router"
+
+export default ({ context }) => [
+ {
+ path: "/user",
+ children: [
+ {
+ path: "/profile",
+ children: [],
+ action: async routerContext =>
+ createPart({
+ name: "profile",
+ context,
+ partCreate: await import("./profile/profileModule"),
+ routerContext
+ })
+ },
+ {
+ path: "/auth",
+ children: [],
+ action: async routerContext =>
+ createPart({
+ name: "auth",
+ context,
+ partCreate: await import("parts/auth/authModule"),
+ routerContext
+ })
+ }
+ ]
+ }
+];
diff --git a/client/src/app_user/test/app.spec.js b/client/src/app_user/test/app.spec.js
new file mode 100644
index 00000000..ac620fb4
--- /dev/null
+++ b/client/src/app_user/test/app.spec.js
@@ -0,0 +1,14 @@
+import { assert } from "chai";
+import App from "../UserApp";
+
+describe("App", async function() {
+ let app;
+ beforeAll(async () => {
+ app = await App();
+ })
+
+ it("parts", async () => {
+ const { parts } = app.context;
+ assert.isAbove(Object.keys(parts).length, 1);
+ });
+});
diff --git a/client/src/app_user/test/router.spec.js b/client/src/app_user/test/router.spec.js
new file mode 100644
index 00000000..672371ff
--- /dev/null
+++ b/client/src/app_user/test/router.spec.js
@@ -0,0 +1,24 @@
+import chai from "chai";
+import chaiAsPromised from "chai-as-promised";
+import UserApp from "../UserApp";
+
+chai.use(chaiAsPromised);
+const { expect, assert } = chai;
+
+describe("Router", async function() {
+ const { router, context } = await UserApp();
+ it("/login", async () => {
+ // console.log("CONTEXT ", context);
+ const route = await router.instance.resolve("/user/auth/login");
+ assert(route);
+ assert.equal(route.title, "Login");
+ });
+ it("/app/profile not authenticated", async () => {
+ expect(router.instance.resolve("/profile")).to.be.rejectedWith(Error);
+ });
+ it.skip("/app/profile authenticated", async () => {
+ context.parts.auth.stores().auth.authenticated = true;
+ const route = await router.instance.resolve("/profile");
+ assert.equal(route.title, "My Profile");
+ });
+});
diff --git a/client/src/app/components/AsyncRoute.js b/client/src/components/AsyncRoute.js
similarity index 100%
rename from client/src/app/components/AsyncRoute.js
rename to client/src/components/AsyncRoute.js
diff --git a/client/src/app/components/AsyncView.js b/client/src/components/AsyncView.js
similarity index 82%
rename from client/src/app/components/AsyncView.js
rename to client/src/components/AsyncView.js
index d238346a..4610639d 100644
--- a/client/src/app/components/AsyncView.js
+++ b/client/src/components/AsyncView.js
@@ -3,7 +3,7 @@ import createAsyncRoute from "components/AsyncRoute";
import spinner from "components/spinner";
export default context => {
- const { theme } = context;
+ const { palette } = context;
const AsyncRoute = createAsyncRoute(context);
return function AsyncView({ getModule, ...rest }) {
return (
@@ -12,7 +12,7 @@ export default context => {
getComponent={() => getModule().then(module => module.default(context))}
loading={() => (
- {h(spinner(context), { size: 40, color: theme.palette.primary })}
+ {h(spinner(context), { size: 40, color: palette.primary })}
)}
/>
diff --git a/client/src/components/ErrorBoundary.tsx b/client/src/components/ErrorBoundary.tsx
new file mode 100644
index 00000000..37cff91c
--- /dev/null
+++ b/client/src/components/ErrorBoundary.tsx
@@ -0,0 +1,27 @@
+import React, { createElement as h } from "react";
+
+export default class ErrorBoundary extends React.Component {
+ public state = { error: null, info: null };
+
+ public componentDidCatch(error, info) {
+ this.setState({
+ hasError: true,
+ error: error.toString(),
+ info: JSON.stringify(info, null, 4)
+ });
+ }
+
+ public render() {
+ if (this.state.error) {
+ return (
+
+
Something went wrong.
+ {this.state.error}
+ {this.state.info}
+
+ );
+ }
+
+ return this.props.children;
+ }
+}
diff --git a/client/src/app/components/FontIcon.js b/client/src/components/FontIcon.js
similarity index 60%
rename from client/src/app/components/FontIcon.js
rename to client/src/components/FontIcon.js
index 36f4958b..8008a7ae 100644
--- a/client/src/app/components/FontIcon.js
+++ b/client/src/components/FontIcon.js
@@ -1,10 +1,10 @@
import * as React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
export default context => {
- const { theme } = context;
- const IconView = glamorous("i")({
- color: theme.palette.textColor
+ const { palette } = context;
+ const IconView = styled("i")({
+ color: palette.textColor
});
return function FontIcon({ className, style, color }) {
diff --git a/client/src/components/FormGroup.js b/client/src/components/FormGroup.js
new file mode 100644
index 00000000..06e625f6
--- /dev/null
+++ b/client/src/components/FormGroup.js
@@ -0,0 +1,6 @@
+import styled from "@emotion/styled";
+
+export default () => styled("div")({
+ marginTop: 20,
+ marginBottom: 20
+ });
diff --git a/client/src/components/MainView.js b/client/src/components/MainView.js
new file mode 100644
index 00000000..5298e455
--- /dev/null
+++ b/client/src/components/MainView.js
@@ -0,0 +1,13 @@
+import styled from "@emotion/styled";
+
+export default styled("main")({
+ display: "flex",
+ flexGrow: "1",
+ justifyContent: "center",
+ alignItems: "flex-start",
+ marginTop: 20,
+ marginRight: 20,
+ "@media(max-width: 600px)": {
+ margin: 10
+ }
+});
diff --git a/client/src/components/Page.js b/client/src/components/Page.js
new file mode 100644
index 00000000..4fabe6b3
--- /dev/null
+++ b/client/src/components/Page.js
@@ -0,0 +1,7 @@
+import styled from "@emotion/styled";
+
+export default () => styled("section")({
+ maxWidth: "600px",
+ minWidth: "400px",
+ width: "100%"
+ });
diff --git a/client/src/components/Paper.js b/client/src/components/Paper.js
new file mode 100644
index 00000000..85573f20
--- /dev/null
+++ b/client/src/components/Paper.js
@@ -0,0 +1,12 @@
+import styled from "@emotion/styled";
+
+export default ({ palette }) => {
+ return styled("div")(() => ({
+ boxShadow: `2px 2px 2px 2px ${palette.borderColor}`,
+ padding: 20,
+ margin: 10,
+ "@media(max-width: 600px)": {
+ margin: 0
+ }
+ }));
+};
diff --git a/client/src/components/RootView.js b/client/src/components/RootView.js
new file mode 100644
index 00000000..5bdc0630
--- /dev/null
+++ b/client/src/components/RootView.js
@@ -0,0 +1,8 @@
+import styled from "@emotion/styled";
+
+export default styled("main")({
+ display: "flex",
+ minHeight: "100vh",
+ minWidth: "100vw",
+ flexDirection: "column"
+});
diff --git a/client/src/app/components/Row.js b/client/src/components/Row.js
similarity index 71%
rename from client/src/app/components/Row.js
rename to client/src/components/Row.js
index 4983df8c..5bf80903 100644
--- a/client/src/app/components/Row.js
+++ b/client/src/components/Row.js
@@ -1,6 +1,6 @@
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
-export default glamorous("div")({
+export default styled("div")({
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
diff --git a/client/src/components/Strike.js b/client/src/components/Strike.js
new file mode 100644
index 00000000..0aa747bf
--- /dev/null
+++ b/client/src/components/Strike.js
@@ -0,0 +1,8 @@
+import styled from "@emotion/styled";
+export default ({ palette }) => {
+ return styled("div")(() => ({
+ position: "relative",
+ borderBottom: `1px solid ${palette.borderColor}`,
+ marginBottom: 20
+ }));
+};
diff --git a/client/src/app/components/Title.js b/client/src/components/Title.js
similarity index 53%
rename from client/src/app/components/Title.js
rename to client/src/components/Title.js
index a7e289c5..0a75b815 100644
--- a/client/src/app/components/Title.js
+++ b/client/src/components/Title.js
@@ -1,6 +1,6 @@
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
-export default glamorous("div")({
+export default styled("div")({
textAlign: "center",
fontWeight: "bold",
fontSize: 26,
diff --git a/client/src/components/UserInfo.js b/client/src/components/UserInfo.js
new file mode 100644
index 00000000..3f918913
--- /dev/null
+++ b/client/src/components/UserInfo.js
@@ -0,0 +1,50 @@
+import React from "react";
+import styled from "@emotion/styled";
+import { observable, action } from "mobx";
+import { observer } from "mobx-react";
+import menu from "./menu";
+
+const MENU = [
+ {
+ route: "settings",
+ text: "SETTINGS"
+ }
+];
+
+export default context => {
+ const { parts, history } = context;
+ const me = parts.auth.stores().me.data;
+ const Menu = menu(context);
+
+ const store = observable({
+ userMenuOpen: false,
+ toggleUserMenu() {
+ store.userMenuOpen = !store.userMenuOpen;
+ },
+ navChange: action(function(menuItem) {
+ history.push(menuItem.route);
+ })
+ });
+
+ const CurrentUser = styled("div")(() => ({
+ marginLeft: "auto",
+ marginRight: 10
+ }));
+
+ const userMenu = () => MENU;
+
+ const UserInfo = observer(() => (
+
+ store.toggleUserMenu()} style={{ marginRight: 10 }}>{me.get("email")}
+ {store.userMenuOpen && (
+
+ ));
+
+ return () => {me && me.get("email") && };
+};
diff --git a/client/src/app/components/alert/alert.examples.js b/client/src/components/alert/alert.examples.js
similarity index 100%
rename from client/src/app/components/alert/alert.examples.js
rename to client/src/components/alert/alert.examples.js
diff --git a/client/src/app/components/alert/alert.js b/client/src/components/alert/alert.js
similarity index 64%
rename from client/src/app/components/alert/alert.js
rename to client/src/components/alert/alert.js
index 27cc6595..221cf5e5 100644
--- a/client/src/app/components/alert/alert.js
+++ b/client/src/components/alert/alert.js
@@ -1,43 +1,50 @@
-import * as React from "react";
-import glamorous from "glamorous";
+/** @jsx jsx */
+import { jsx } from "@emotion/core";
+import styled from "@emotion/styled";
export default ({ tr }) => {
- const AlertView = glamorous("div")({
+ const AlertView = styled("div")({
display: "flex",
alignItems: "center",
justifyContent: "space-between",
- padding: 20,
+ padding: 10,
margin: 10,
fontWeight: 500,
textAlign: "center"
});
- const AlertDangerView = glamorous(AlertView)({
+ const AlertDangerView = styled(AlertView)({
border: "1px solid #ebccd1",
color: "#a94442",
backgroundColor: "#f2dede"
});
- const AlertWarningView = glamorous(AlertView)({
+ const AlertWarningView = styled(AlertView)({
border: "1px solid #faebcc",
color: "#8a6d3b",
backgroundColor: "#fcf8e3"
});
- const AlertInfoView = glamorous(AlertView)({
+ const AlertInfoView = styled(AlertView)({
border: "1px solid #bce8f1",
color: "#31708f",
backgroundColor: "#d9edf7"
});
- const CloseIconView = glamorous("span")({
- cursor: "pointer",
- margin: 10
- });
-
function CloseIcon({ onClick }) {
- return {"\u2716"};
+ return (
+
+ {"\u2716"}
+
+ );
}
+
function createAlert(AlertView) {
return function Alert({
name,
@@ -50,13 +57,11 @@ export default ({ tr }) => {
- {tr.t(name)}
-{' '}
-{code && `(${code})`}
+ {tr.t(name)} {code && `(${code})`}
{`${message}`}
-
+ {onRemove && }
);
};
diff --git a/client/src/app/components/alert/index.js b/client/src/components/alert/index.js
similarity index 100%
rename from client/src/app/components/alert/index.js
rename to client/src/components/alert/index.js
diff --git a/client/src/app/components/alertAjax/alertAjax.js b/client/src/components/alertAjax/alertAjax.js
similarity index 83%
rename from client/src/app/components/alertAjax/alertAjax.js
rename to client/src/components/alertAjax/alertAjax.js
index 579e38c9..9e55b43c 100644
--- a/client/src/app/components/alertAjax/alertAjax.js
+++ b/client/src/components/alertAjax/alertAjax.js
@@ -15,11 +15,10 @@ export default context => {
return null;
}
debug("error:", error);
- const { status } = error.response;
- debug("error status :", status);
- if (![401, 422].includes(status)) {
+ if (![401, 422].includes(get(error, "response.status"))) {
return null;
}
+
const message = get(error, "response.data.error.message", error.message);
return ;
diff --git a/client/src/app/components/alertAjax/index.js b/client/src/components/alertAjax/index.js
similarity index 100%
rename from client/src/app/components/alertAjax/index.js
rename to client/src/components/alertAjax/index.js
diff --git a/client/src/app/components/alertStack/alertStack.js b/client/src/components/alertStack/alertStack.js
similarity index 84%
rename from client/src/app/components/alertStack/alertStack.js
rename to client/src/components/alertStack/alertStack.js
index 5052bfcf..f3861fa7 100644
--- a/client/src/app/components/alertStack/alertStack.js
+++ b/client/src/components/alertStack/alertStack.js
@@ -1,8 +1,8 @@
-import * as React from "react";
+/** @jsx jsx */
import { observable } from "mobx";
import { observer } from "mobx-react";
-import { keyframes } from "glamor";
-import glamorous from "glamorous";
+import { jsx, keyframes } from "@emotion/core";
+import styled from "@emotion/styled";
export default (context, { limit = 10 }) => {
const store = observable({
@@ -26,9 +26,7 @@ export default (context, { limit = 10 }) => {
component,
status: "inserting"
};
- component.attributes.onRemove = () => {
- store.remove(message.id);
- };
+
if (messages.length >= limit) {
store.remove(messages[0].id);
}
@@ -48,11 +46,13 @@ export default (context, { limit = 10 }) => {
}
});
- const AlertView = glamorous("div")({
+ const AlertView = styled("div")({
margin: 10,
padding: 10,
display: "flex",
- justifyContent: "space-between"
+ justifyContent: "flex-start",
+ alignItems: "center",
+ cursor: "pointer"
});
const animationFadeIn = keyframes({
@@ -77,10 +77,14 @@ export default (context, { limit = 10 }) => {
const css = animation[message.status];
const { component } = message;
- return {component};
+ return (
+ store.remove(message.id)} >
+ {component}
+
+ );
});
- const AlertsView = glamorous("div")({
+ const AlertsView = styled("div")({
minWidth: 300,
maxWidth: 600,
position: "fixed",
diff --git a/client/src/app/components/alertStack/index.js b/client/src/components/alertStack/index.js
similarity index 100%
rename from client/src/app/components/alertStack/index.js
rename to client/src/components/alertStack/index.js
diff --git a/client/src/components/appBarView.js b/client/src/components/appBarView.js
new file mode 100644
index 00000000..e10bce13
--- /dev/null
+++ b/client/src/components/appBarView.js
@@ -0,0 +1,11 @@
+import styled from "@emotion/styled";
+
+export default context =>
+ styled("div")({
+ height: 80,
+ display: "flex",
+ justifyContent: "space-between",
+ alignItems: "center",
+ backgroundColor: context.palette.primary,
+ color: context.palette.textPrimaryOnPrimary
+ });
diff --git a/client/src/components/authBar.js b/client/src/components/authBar.js
new file mode 100644
index 00000000..7b976e53
--- /dev/null
+++ b/client/src/components/authBar.js
@@ -0,0 +1,16 @@
+/** @jsx jsx */
+import { jsx, css } from "@emotion/core";
+import button from "mdlean/lib/button";
+
+export default context => {
+ const Button = button(context);
+ function AuthBar() {
+ return (
+
+
+
+
+ );
+ }
+ return AuthBar;
+};
diff --git a/client/src/app/components/button/button.examples.js b/client/src/components/button/button.examples.js
similarity index 92%
rename from client/src/app/components/button/button.examples.js
rename to client/src/components/button/button.examples.js
index 1e60a7d5..1763d7dd 100644
--- a/client/src/app/components/button/button.examples.js
+++ b/client/src/components/button/button.examples.js
@@ -1,16 +1,16 @@
import * as React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
import button from "mdlean/lib/button";
import paper from "components/Paper";
/* eslint-disable jsx-extras/jsx-no-string-literals */
export default context => {
const Button = button(context);
const Paper = paper(context);
- const ButtonExamplesView = glamorous(Paper)({
+ const ButtonExamplesView = styled(Paper)({
maxWidth: 500
});
- const ButtonGroupView = glamorous("div")({
+ const ButtonGroupView = styled("div")({
"> button": {
margin: 6
}
diff --git a/client/src/app/components/componentGuide.js b/client/src/components/componentGuide.js
similarity index 84%
rename from client/src/app/components/componentGuide.js
rename to client/src/components/componentGuide.js
index 3e31a11d..a13c7a63 100644
--- a/client/src/app/components/componentGuide.js
+++ b/client/src/components/componentGuide.js
@@ -1,5 +1,5 @@
import React, { createElement as h } from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
import spinners from "./spinner/spinner.examples";
import alerts from "./alert/alert.examples";
import panels from "./panel/panel.examples";
@@ -9,19 +9,19 @@ import buttons from "./button/button.examples";
export default context => {
const { tr, parts } = context;
- const ViewContainer = glamorous("div")({
+ const ViewContainer = styled("div")({
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-start"
});
- const GuideView = glamorous("div")({
+ const GuideView = styled("div")({
//height: "100vh",
display: "flex",
margin: 20
});
- const Content = glamorous("div")({
+ const Content = styled("div")({
//flex: "1 1 auto",
//overflow: "auto"
});
@@ -47,19 +47,19 @@ export default context => {
{h(panels(context))}
{tr.t("Authentication")}
-
+ {/*
{parts.auth
.routes()
- .map(route => h("div", { key: route.path }, route.component().component)
+ .map(route => h("div", { key: route.path }, route.action({params: {}}).component)
)}
-
+
{tr.t("Profile")}
{parts.profile
.routes()
- .map(route => h("div", { key: route.path }, route.component().component)
+ .map(route => h("div", { key: route.path }, route.action({}).component)
)}
-
+ */}
);
diff --git a/client/src/app/components/footer.js b/client/src/components/footer.js
similarity index 81%
rename from client/src/app/components/footer.js
rename to client/src/components/footer.js
index 75011b6a..e516a47c 100644
--- a/client/src/app/components/footer.js
+++ b/client/src/components/footer.js
@@ -1,9 +1,8 @@
import React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
-export default ({ tr, theme }) => {
- const { palette } = theme;
- const FooterView = glamorous("footer")(() => ({
+export default ({ tr, palette }) => {
+ const FooterView = styled("footer")(() => ({
padding: 20,
textAlign: "center",
background: palette.primaryLight
diff --git a/client/src/app/components/input/index.js b/client/src/components/input/index.js
similarity index 100%
rename from client/src/app/components/input/index.js
rename to client/src/components/input/index.js
diff --git a/client/src/app/components/input/input.examples.js b/client/src/components/input/input.examples.js
similarity index 87%
rename from client/src/app/components/input/input.examples.js
rename to client/src/components/input/input.examples.js
index ed41f4a5..a5645336 100644
--- a/client/src/app/components/input/input.examples.js
+++ b/client/src/components/input/input.examples.js
@@ -1,5 +1,5 @@
import * as React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
import paper from "components/Paper";
import input from "./input";
@@ -9,8 +9,8 @@ export default context => {
const InputEmpty = input(context);
const InputWithValue = input(context);
const InputDisabled = input(context);
- const InputExamplesView = glamorous(Paper)({});
- const ListView = glamorous("div")({
+ const InputExamplesView = styled(Paper)({});
+ const ListView = styled("div")({
"> div": {
marginBottom: 30
}
diff --git a/client/src/app/components/input/input.js b/client/src/components/input/input.js
similarity index 79%
rename from client/src/app/components/input/input.js
rename to client/src/components/input/input.js
index 999a8c75..a7b26dd4 100644
--- a/client/src/app/components/input/input.js
+++ b/client/src/components/input/input.js
@@ -1,11 +1,10 @@
-import React from "react";
+/** @jsx jsx */
import { observable } from "mobx";
import { observer } from "mobx-react";
-import glamorous from "glamorous";
-import { keyframes } from "glamor";
+import styled from "@emotion/styled";
+import { jsx, keyframes } from '@emotion/core'
-export default ({ theme }) => {
- const { palette } = theme;
+export default ({ palette }) => {
const store = observable({
focus: false
});
@@ -18,7 +17,7 @@ export default ({ theme }) => {
const styles = {
root: {
margin: "auto",
- width: "256",
+ width: "256px",
padding: 0,
position: "relative"
},
@@ -79,18 +78,18 @@ export default ({ theme }) => {
color: "red"
}
};
- const InputContainerView = glamorous("div")(styles.root);
- const LabelView = glamorous("label")(styles.label.root);
- const InputView = glamorous("input")(styles.input);
- const UnderlineView = glamorous("hr")(styles.underline.root);
- const UnderlineStaticView = glamorous(UnderlineView)(styles.underline.static);
- const UnderlineFocusView = glamorous(UnderlineView)(
+ const InputContainerView = styled("div")(styles.root);
+ const LabelView = styled("label")(styles.label.root);
+ const InputView = styled("input")(styles.input);
+ const UnderlineView = styled("hr")(styles.underline.root);
+ const UnderlineStaticView = styled(UnderlineView)(styles.underline.static);
+ const UnderlineFocusView = styled(UnderlineView)(
styles.underline.focusOff
);
- const UnderlineErrorView = glamorous(UnderlineView)(
+ const UnderlineErrorView = styled(UnderlineView)(
styles.underline.errorOff
);
- const ErrorView = glamorous("div")(styles.error);
+ const ErrorView = styled("div")(styles.error);
return observer(function Input(props) {
const { id, label, onChange, error, ...otherProps } = props;
diff --git a/client/src/components/link.js b/client/src/components/link.js
new file mode 100644
index 00000000..86e97985
--- /dev/null
+++ b/client/src/components/link.js
@@ -0,0 +1,17 @@
+/** @jsx jsx */
+import { jsx } from "@emotion/core";
+
+export default context => {
+
+ const Link = ({ to, children }) => (
+ context.history.push(to)}
+ >
+ {children}
+
+ );
+
+ return Link;
+};
diff --git a/client/src/components/menu.js b/client/src/components/menu.js
new file mode 100644
index 00000000..e2c7bd2a
--- /dev/null
+++ b/client/src/components/menu.js
@@ -0,0 +1,38 @@
+import * as React from "react";
+import styled from "@emotion/styled";
+import button from "mdlean/lib/button";
+
+export default context => {
+ const MenuItemView = styled("div")({
+ width: "100%",
+ minWidth: 150
+ });
+
+ function MenuItem({ menu, navChange }) {
+ const Button = button(context);
+ return (
+
+
+ );
+ }
+
+ const MenuView = styled("div")({
+ padding: 0
+ });
+
+ function Menu({ menuItems = [], navChange, css }) {
+ return (
+
+ {menuItems.map((menu, key) => (
+
+ ))}
+
+ );
+ }
+ return Menu;
+};
diff --git a/client/src/components/navbar.js b/client/src/components/navbar.js
new file mode 100644
index 00000000..dd3d8247
--- /dev/null
+++ b/client/src/components/navbar.js
@@ -0,0 +1,100 @@
+/** @jsx jsx */
+import { jsx } from "@emotion/core";
+import { createElement as h } from "react";
+import drawer from "mdlean/lib/drawer";
+import { observable, action } from "mobx";
+import { observer } from "mobx-react";
+import styled from "@emotion/styled";
+import button from "mdlean/lib/button";
+import menu from "./menu";
+import appBarView from "components/appBarView";
+import titleView from "components/titleView";
+
+export default context => {
+ const {
+ history,
+ palette,
+ config: { defaultPath, title }
+ } = context;
+ const AppBarView = appBarView(context);
+ const Drawer = drawer(context);
+ const Menu = menu(context);
+ const store = observable({
+ drawerOpen: false,
+ toggleDrawer() {
+ this.drawerOpen = !this.drawerOpen;
+ },
+ closeDrawer() {
+ store.drawerOpen = false;
+ },
+ navChange: action(function(menuItem) {
+ history.push(menuItem.route);
+ })
+ });
+
+ const BurgerButton = styled(button(context))({
+ height: 50,
+ width: 50
+ });
+
+ function BurgerIcon() {
+ return (
+
+ );
+ }
+
+ function IconLeft({ onDrawerClick }) {
+ return (
+
+
+
+ );
+ }
+
+ const TitleView = titleView(context)(button(context));
+
+ const NavBar = observer(({ right, appMenu }) => {
+ return (
+
+ );
+ });
+
+ return props => ;
+};
diff --git a/client/src/app/components/notFound.js b/client/src/components/notFound.js
similarity index 83%
rename from client/src/app/components/notFound.js
rename to client/src/components/notFound.js
index 1ea6d6d8..71b16424 100644
--- a/client/src/app/components/notFound.js
+++ b/client/src/components/notFound.js
@@ -1,10 +1,10 @@
import * as React from "react";
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
export default context => {
const { tr } = context;
- const NotFoundView = glamorous("div")({
+ const NotFoundView = styled("div")({
margin: 20
});
diff --git a/client/src/app/components/panel/index.js b/client/src/components/panel/index.js
similarity index 100%
rename from client/src/app/components/panel/index.js
rename to client/src/components/panel/index.js
diff --git a/client/src/app/components/panel/panel.examples.js b/client/src/components/panel/panel.examples.js
similarity index 100%
rename from client/src/app/components/panel/panel.examples.js
rename to client/src/components/panel/panel.examples.js
diff --git a/client/src/app/components/panel/panel.js b/client/src/components/panel/panel.js
similarity index 60%
rename from client/src/app/components/panel/panel.js
rename to client/src/components/panel/panel.js
index b511e11c..029b9e6a 100644
--- a/client/src/app/components/panel/panel.js
+++ b/client/src/components/panel/panel.js
@@ -1,20 +1,19 @@
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
-export default function({ theme }) {
- const { palette } = theme;
- const Panel = glamorous("div")({
+export default function({ palette }) {
+ const Panel = styled("div")({
borderBottom: `1px solid ${palette.primaryDark}`,
padding: "0.5rem"
});
- const Header = glamorous("div")({
+ const Header = styled("div")({
fontSize: "2rem",
fontWeight: "bold",
padding: "0.5rem",
backgroundColor: palette.primaryLight
});
- const Body = glamorous("div")({
+ const Body = styled("div")({
padding: "0.5rem",
backgroundColor: palette.background
});
diff --git a/client/src/app/components/restTable/index.js b/client/src/components/restTable/index.js
similarity index 100%
rename from client/src/app/components/restTable/index.js
rename to client/src/components/restTable/index.js
diff --git a/client/src/app/components/restTable/restTableComponent.js b/client/src/components/restTable/restTableComponent.js
similarity index 100%
rename from client/src/app/components/restTable/restTableComponent.js
rename to client/src/components/restTable/restTableComponent.js
diff --git a/client/src/app/components/restTable/restTableStore.js b/client/src/components/restTable/restTableStore.js
similarity index 100%
rename from client/src/app/components/restTable/restTableStore.js
rename to client/src/components/restTable/restTableStore.js
diff --git a/client/src/app/components/spinner/index.js b/client/src/components/spinner/index.js
similarity index 100%
rename from client/src/app/components/spinner/index.js
rename to client/src/components/spinner/index.js
diff --git a/client/src/app/components/spinner/spinner.examples.js b/client/src/components/spinner/spinner.examples.js
similarity index 88%
rename from client/src/app/components/spinner/spinner.examples.js
rename to client/src/components/spinner/spinner.examples.js
index df2e611f..b52b2774 100644
--- a/client/src/app/components/spinner/spinner.examples.js
+++ b/client/src/components/spinner/spinner.examples.js
@@ -3,8 +3,7 @@ import paper from "components/Paper";
import spinner from "./spinner";
export default context => {
- const { tr, theme } = context;
- const { palette } = theme;
+ const { tr, palette } = context;
const Paper = paper(context);
const Spinner = spinner(context);
return function SpinnerExamples() {
diff --git a/client/src/app/components/spinner/spinner.js b/client/src/components/spinner/spinner.js
similarity index 83%
rename from client/src/app/components/spinner/spinner.js
rename to client/src/components/spinner/spinner.js
index 1ce3b48c..c052e91f 100644
--- a/client/src/app/components/spinner/spinner.js
+++ b/client/src/components/spinner/spinner.js
@@ -1,13 +1,13 @@
-import * as React from "react";
-import glamorous from "glamorous";
-import { keyframes } from "glamor";
+/** @jsx jsx */
+import styled from "@emotion/styled";
+import { jsx, keyframes } from '@emotion/core'
const animation = keyframes({
"0%": { transform: "rotate(0deg)" },
"100%": { transform: "rotate(360deg)" }
});
-const SvgView = glamorous("svg")({
+const SvgView = styled("svg")({
animation: `${animation} 4s linear infinite`
});
diff --git a/client/src/app/components/table.js b/client/src/components/table.js
similarity index 72%
rename from client/src/app/components/table.js
rename to client/src/components/table.js
index fb2e466d..72c02ba9 100644
--- a/client/src/app/components/table.js
+++ b/client/src/components/table.js
@@ -1,6 +1,6 @@
-import glamorous from "glamorous";
+import styled from "@emotion/styled";
-export default ({ theme: { palette } }) => view => glamorous(view)(() => ({
+export default ({ palette }) => view => styled(view)(() => ({
borderCollapse: "collapse",
borderSpacing: 0,
padding: 20,
diff --git a/client/src/components/titleView.js b/client/src/components/titleView.js
new file mode 100644
index 00000000..4859502f
--- /dev/null
+++ b/client/src/components/titleView.js
@@ -0,0 +1,10 @@
+import styled from "@emotion/styled";
+
+export default context => component =>
+ styled(component)({
+ fontSize: 34,
+ fontWeight: "bold",
+ margin: 10,
+ lineHeight: "normal",
+ color: context.palette.textPrimaryOnPrimary
+ });
diff --git a/client/src/app/config.js b/client/src/config.js
similarity index 100%
rename from client/src/app/config.js
rename to client/src/config.js
diff --git a/client/src/context.js b/client/src/context.js
new file mode 100644
index 00000000..19e50f86
--- /dev/null
+++ b/client/src/context.js
@@ -0,0 +1,31 @@
+import tr from "i18next";
+import { createBrowserHistory } from "history";
+import formatter from "utils/formatter";
+import alertStackCreate from "components/alertStack";
+import Rest from "./utils/rest";
+import palette from "./palette";
+import intl from "utils/intl";
+import I18n from "utils/i18n";
+
+import rootConfig from "./config";
+
+export default async (option = {}) => {
+ const config = { ...rootConfig, ...option.config };
+ const context = {
+ palette: palette(),
+ tr,
+ formatter: formatter("en"),
+ history: createBrowserHistory(),
+ config,
+ parts: {}
+ };
+ context.alertStack = alertStackCreate(context, { limit: 3 });
+ context.rest = Rest(context);
+
+ const i18n = I18n({ debug: config.debug.i18n });
+ const language = await i18n.load();
+ context.formatter.setLocale(language);
+ await intl(language);
+
+ return context;
+};
diff --git a/client/src/index.ejs b/client/src/index.ejs
index 3e37b917..7beeb7b7 100644
--- a/client/src/index.ejs
+++ b/client/src/index.ejs
@@ -7,7 +7,7 @@
<% for (var css in htmlWebpackPlugin.files.css) { %>
-
+
<% } %>
@@ -83,8 +83,8 @@
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
-
+
<% } %>
-