Working on 'static' pages

This commit is contained in:
Tom Moor 2017-10-22 16:33:10 -07:00
parent 4d53c4aa00
commit aceaf261d2
10 changed files with 249 additions and 76 deletions

View File

@ -1,7 +1,7 @@
// @flow
import React from 'react';
import { withRouter } from 'react-router-dom';
import Helmet from 'react-helmet';
import { Helmet } from 'react-helmet';
import styled from 'styled-components';
import { observer, inject } from 'mobx-react';
import keydown from 'react-keydown';
@ -99,18 +99,15 @@ type Props = {
return (
<Container column auto>
<Helmet
title="Atlas"
meta={[
{
name: 'viewport',
content: 'width=device-width, initial-scale=1.0',
},
]}
/>
<Helmet>
<title>Atlas</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
</Helmet>
{this.props.ui.progressBarVisible && <LoadingIndicatorBar />}
{this.props.notifications}
<Flex auto>

View File

@ -1,11 +1,13 @@
// @flow
import React from 'react';
import Helmet from 'react-helmet';
import { Helmet } from 'react-helmet';
type Props = {
title: string,
};
const PageTitle = ({ title }: Props) => <Helmet title={`${title} - Atlas`} />;
const PageTitle = ({ title }: Props) => (
<Helmet><title>{`${title} - Atlas`}</title></Helmet>
);
export default PageTitle;

View File

@ -4,8 +4,8 @@ import { observer, inject } from 'mobx-react';
import AuthStore from 'stores/AuthStore';
type Props = {
children: React.Element<any>,
scopes?: Array<string>,
children: React$Element<*>,
scopes?: string[],
auth: AuthStore,
redirectUri: string,
};
@ -32,9 +32,7 @@ type Props = {
};
const urlParams = Object.keys(params)
.map(key => {
return `${key}=${encodeURIComponent(params[key])}`;
})
.map(key => `${key}=${encodeURIComponent(params[key])}`)
.join('&');
return `${baseUrl}?${urlParams}`;

View File

@ -142,7 +142,7 @@
"react-addons-css-transition-group": "15.3.2",
"react-dom": "^15.6.1",
"react-dropzone": "3.6.0",
"react-helmet": "3.1.0",
"react-helmet": "^5.2.0",
"react-keydown": "^1.7.3",
"react-modal": "^2.2.1",
"react-portal": "^3.1.0",
@ -166,6 +166,7 @@
"string-hash": "^1.1.0",
"style-loader": "^0.18.2",
"styled-components": "^2.0.0",
"styled-components-grid": "^1.0.0-preview.15",
"url-loader": "0.5.7",
"uuid": "2.0.2",
"validator": "5.2.0",

View File

@ -50,7 +50,7 @@ router.post('auth.slack', async ctx => {
// Signal to backend that the user is logged in.
// This is only used to signal SSR rendering, not
// used for auth.
ctx.cookies.set('loggedId', 'true', {
ctx.cookies.set('loggedIn', 'true', {
httpOnly: false,
expires: new Date('2100'),
});

40
server/pages/Home.js Normal file
View File

@ -0,0 +1,40 @@
// @flow
import React from 'react';
import styled from 'styled-components';
import Grid from 'styled-components-grid';
const Unit = Grid.Unit;
const Header = styled.div`
width: 100%;
padding: 3em;
text-align: center;
`;
export default function Home() {
return (
<Grid>
<Header>
<h1>Your teams knowledge base</h1>
<p>
Documentation, meeting notes, playbooks, onboarding, work logs, brainstorming, decisions, & more
</p>
<a href="">Sign In</a>
</Header>
<Unit size={{ desktop: 1 / 2 }} />
<Unit size={{ desktop: 1 / 2 }}>
<h2>Blazing Fast</h2>
<p>
Atlas is fast, really fast. Weve trimmed 100ms and 50ms there to make sure that documents load instantly, search is speedy and there are keyboard shortcuts for everything.
</p>
</Unit>
<Unit size={{ desktop: 1 / 2 }}>
<h2>Markdown Support</h2>
<p>
Documents are stored in Markdown and you can export them at any time. Markdown shortcuts are also built right into the editor so you can easily format using markdown syntax or our GUI.
</p>
</Unit>
<Unit size={{ desktop: 1 / 2 }} />
</Grid>
);
}

View File

@ -0,0 +1,26 @@
// @flow
import React from 'react';
import { Helmet } from 'react-helmet';
type Props = {
children?: React$Element<*>,
};
export default function Layout({ children }: Props) {
return (
<html lang="en">
<head>
<Helmet>
<title>Atlas</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Helmet>
{'{{HEAD}}'}
{'{{CSS}}'}
</head>
<body>
{children}
</body>
</html>
);
}

View File

@ -1,13 +1,22 @@
import React from 'react';
import path from 'path';
import fs from 'fs';
import httpErrors from 'http-errors';
import Koa from 'koa';
import Router from 'koa-router';
import sendfile from 'koa-sendfile';
import ReactDOMServer from 'react-dom/server';
import subdomainRedirect from './middlewares/subdomainRedirect';
import { Helmet } from 'react-helmet';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';
import Layout from './pages/components/Layout';
import Home from './pages/Home';
const isProduction = process.env.NODE_ENV === 'production';
const koa = new Koa();
const router = new Router();
const sheet = new ServerStyleSheet();
const readFile = src => {
return new Promise((resolve, reject) => {
@ -18,6 +27,25 @@ const readFile = src => {
});
};
const renderPage = children => {
const html = ReactDOMServer.renderToString(
<StyleSheetManager sheet={sheet.instance}>
<Layout>
{children}
</Layout>
</StyleSheetManager>
);
// helmet returns an object of meta tags with toString methods, urgh.
const helmet = Helmet.renderStatic();
let head = '';
Object.keys(helmet).forEach(key => (head += helmet[key].toString()));
return html
.replace('{{CSS}}', sheet.getStyleTags())
.replace('{{HEAD}}', head);
};
router.get('/_health', ctx => (ctx.body = 'OK'));
if (process.env.NODE_ENV === 'production') {
@ -31,30 +59,32 @@ if (process.env.NODE_ENV === 'production') {
path.join(__dirname, '../dist/', ctx.path.substring(8))
);
});
router.get('/', async ctx => {
const html = await readFile(path.join(__dirname, '../dist/index.html'));
ctx.body = html;
if (!ctx.status) ctx.throw(httpErrors.NotFound());
});
router.get('*', async ctx => {
await sendfile(ctx, path.join(__dirname, '../dist/index.html'));
if (!ctx.status) ctx.throw(httpErrors.NotFound());
});
koa.use(subdomainRedirect());
} else {
router.get('*', async ctx => {
console.log(ctx.cookies.get('loggedIn'));
const html = await readFile(path.join(__dirname, './static/dev.html'));
ctx.body = html;
if (!ctx.status) ctx.throw(httpErrors.NotFound());
});
}
router.get('/', async ctx => {
if (ctx.cookies.get('loggedIn')) {
if (isProduction) {
ctx.body = await readFile(path.join(__dirname, '../dist/index.html'));
} else {
ctx.body = await readFile(path.join(__dirname, './static/dev.html'));
}
} else {
ctx.body = await renderPage(<Home />);
}
if (!ctx.status) ctx.throw(httpErrors.NotFound());
});
router.get('*', async ctx => {
if (isProduction) {
ctx.body = await readFile(path.join(__dirname, '../dist/index.html'));
} else {
ctx.body = await readFile(path.join(__dirname, './static/dev.html'));
}
if (!ctx.status) ctx.throw(httpErrors.NotFound());
});
koa.use(subdomainRedirect());
koa.use(router.routes());
// 404 handler

64
server/static/home.html Normal file
View File

@ -0,0 +1,64 @@
<!doctype html>
<html lang="en">
<head>
<title>Atlas</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://unpkg.com/tachyons@4.8.1/css/tachyons.min.css">
</head>
</head>
<body class="sans-serif dark-gray">
<section class="fl w-100 pa6 tc">
<h1 class="f2">Your teams knowledge base</h1>
<p class="f4 mid-gray">Documentation, meeting notes, playbooks, onboarding, work logs, brainstorming, decisions, &amp; more…</p>
<a href="" class="bg-dark-gray br2 pa2 white no-underline">Sign In</a>
</section>
<section class="fl w-100">
<div class="fl w-50-l pa6">
</div>
<div class="fl w-50-l pa6 bg-light-gray">
<h2 class="f3">Blazing Fast</h2>
<p>Atlas is fast, really fast. Weve trimmed 100ms and 50ms there to make sure that documents load instantly, search is speedy and there are keyboard shortcuts for everything.</p>
</div>
</section>
<section class="fl w-100">
<div class="fl w-50-l pa6 bg-light-gray">
<h2 class="f3">Markdown Support</h2>
<p>Documents are stored in Markdown and you can export them at any time. Markdown shortcuts are also built right into the editor so you can easily format using markdown syntax or our GUI.</p>
</div>
<div class="fl w-50-l pa6">
</div>
</section>
<section class="fl w-100">
<div class="fl w-50-l pa6">
</div>
<div class="fl w-50-l pa6 bg-light-gray">
<h2 class="f3">Beautiful Editor</h2>
<p>We built a custom editor from the ground up to be great looking, extensible, and a pleasure to use whether you're typing up quick notes or pages of documentation.</p>
</div>
</section>
<div class="fl w-33-l pa5">
<h2 class="f4">Powerful Search</h2>
<p>Built-in search makes that one document easy to find in a large knowledgebase.</p>
</div>
<div class="fl w-33-l pa5">
<h2 class="f4">API &amp; Integrations</h2>
<p>Atlas is built on it's own API, treat Atlas as a CMS or automatically great documents from outside events.</p>
</div>
<div class="fl w-33-l pa5">
<h2 class="f4">Open Source</h2>
<p>Want to contribute or host Atlas yourself? All of the code is on GitHub.</p>
</div>
<footer class="fl w-100">
<ul>
<li>About Us</li>
<li>Pricing</li>
<li>Contact</li>
</ul>
</footer>
</body>
</html>

View File

@ -2223,7 +2223,7 @@ decompress-response@^3.2.0:
dependencies:
mimic-response "^1.0.0"
deep-equal@1.0.1, deep-equal@~1.0.1:
deep-equal@^1.0.1, deep-equal@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
@ -2967,7 +2967,7 @@ execa@^0.7.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
exenv@^1.2.0:
exenv@^1.2.0, exenv@^1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
@ -3096,14 +3096,6 @@ fbemitter@^2.1.1:
dependencies:
fbjs "^0.8.4"
fbjs@0.1.0-alpha.10:
version "0.1.0-alpha.10"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.1.0-alpha.10.tgz#46e457c09cbefb51fc752a3e030e7b67fcc384c8"
dependencies:
core-js "^1.0.0"
promise "^7.0.3"
whatwg-fetch "^0.9.0"
fbjs@^0.8.4, fbjs@^0.8.5, fbjs@^0.8.9:
version "0.8.14"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.14.tgz#d1dbe2be254c35a91e09f31f9cd50a40b2a0ed1c"
@ -5538,7 +5530,7 @@ lodash.isstring@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
lodash.keys@^3.0.0, lodash.keys@^3.1.2:
lodash.keys@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
dependencies:
@ -7124,7 +7116,7 @@ progress@^1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
promise@7.x, promise@^7.0.3, promise@^7.1.1:
promise@7.x, promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
dependencies:
@ -7291,6 +7283,13 @@ react-addons-test-utils@^15.3.1:
version "15.6.0"
resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.0.tgz#062d36117fe8d18f3ba5e06eb33383b0b85ea5b9"
react-create-component-from-tag-prop@^1.2.1:
version "1.3.1"
resolved "https://registry.npmjs.org/react-create-component-from-tag-prop/-/react-create-component-from-tag-prop-1.3.1.tgz#5389407d99f88ba2b36351780a6094470b44a7c7"
dependencies:
lodash "^4.17.4"
react "^15.5.4"
react-deep-force-update@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c"
@ -7314,15 +7313,14 @@ react-dropzone@3.6.0:
dependencies:
attr-accept "^1.0.3"
react-helmet@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-3.1.0.tgz#63486194682f33004826f3687dc49a138b557050"
react-helmet@^5.2.0:
version "5.2.0"
resolved "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.0.tgz#a81811df21313a6d55c5f058c4aeba5d6f3d97a7"
dependencies:
deep-equal "1.0.1"
object-assign "^4.0.1"
react-side-effect "1.0.2"
shallowequal "0.2.2"
warning "2.1.0"
deep-equal "^1.0.1"
object-assign "^4.1.1"
prop-types "^15.5.4"
react-side-effect "^1.1.0"
react-keydown@^1.7.3:
version "1.9.4"
@ -7374,11 +7372,12 @@ react-router@^4.2.0:
prop-types "^15.5.4"
warning "^3.0.0"
react-side-effect@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.0.2.tgz#98e354decdbf0281e4223d87852d33e345eda561"
react-side-effect@^1.1.0:
version "1.1.3"
resolved "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.1.3.tgz#512c25abe0dec172834c4001ec5c51e04d41bc5c"
dependencies:
fbjs "0.1.0-alpha.10"
exenv "^1.2.1"
shallowequal "^1.0.1"
react-test-renderer@^15.3.1:
version "15.6.1"
@ -7398,6 +7397,16 @@ react-transform-hmr@^1.0.3:
global "^4.3.0"
react-proxy "^1.1.7"
react@^15.5.4:
version "15.6.2"
resolved "https://registry.npmjs.org/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72"
dependencies:
create-react-class "^15.6.0"
fbjs "^0.8.9"
loose-envify "^1.1.0"
object-assign "^4.1.0"
prop-types "^15.5.10"
react@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"
@ -7999,11 +8008,9 @@ sha.js@^2.4.0, sha.js@^2.4.8:
dependencies:
inherits "^2.0.1"
shallowequal@0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-0.2.2.tgz#1e32fd5bcab6ad688a4812cb0cc04efc75c7014e"
dependencies:
lodash.keys "^3.1.2"
shallowequal@^1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.0.2.tgz#1561dbdefb8c01408100319085764da3fcf83f8f"
shebang-command@^1.2.0:
version "1.2.0"
@ -8402,6 +8409,18 @@ style-loader@^0.18.2:
loader-utils "^1.0.2"
schema-utils "^0.3.0"
styled-components-breakpoint@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/styled-components-breakpoint/-/styled-components-breakpoint-1.0.1.tgz#51fb474d9449e228b6f3f2cd232631ec65c149bc"
styled-components-grid@^1.0.0-preview.15:
version "1.0.0-preview.15"
resolved "https://registry.npmjs.org/styled-components-grid/-/styled-components-grid-1.0.0-preview.15.tgz#90c6a4caa22292f7a2d80f055395f3fa18cd6720"
dependencies:
prop-types "^15.5.8"
react-create-component-from-tag-prop "^1.2.1"
styled-components-breakpoint "^1.0.1"
styled-components@^2.0.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.1.2.tgz#bb419978e1287c5d0d88fa9106b2dd75f66a324c"
@ -9023,7 +9042,7 @@ walker@~1.0.5:
dependencies:
makeerror "1.0.x"
warning@2.1.0, warning@^2.0.0:
warning@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-2.1.0.tgz#21220d9c63afc77a8c92111e011af705ce0c6901"
dependencies:
@ -9118,10 +9137,6 @@ whatwg-fetch@>=0.10.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
whatwg-fetch@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0"
whatwg-url@^4.3.0:
version "4.8.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.8.0.tgz#d2981aa9148c1e00a41c5a6131166ab4683bbcc0"