add static pages
This commit is contained in:
parent
bd78b8e4d7
commit
5ba5100a52
19 changed files with 320 additions and 7 deletions
11
imports/api/Utility/server/methods.js
Normal file
11
imports/api/Utility/server/methods.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { Meteor } from 'meteor/meteor';
|
||||
import { check } from 'meteor/check';
|
||||
import getPrivateFile from '../../../modules/server/get-private-file';
|
||||
import parseMarkdown from '../../../modules/parse-markdown';
|
||||
|
||||
Meteor.methods({
|
||||
'utility.getPage': function utilityReadFileAsText(fileName) {
|
||||
check(fileName, String);
|
||||
return parseMarkdown(getPrivateFile(`pages/${fileName}.md`));
|
||||
},
|
||||
});
|
||||
8
imports/modules/parse-markdown.js
Normal file
8
imports/modules/parse-markdown.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { Parser, HtmlRenderer } from 'commonmark';
|
||||
|
||||
export default (markdown, options) => {
|
||||
const reader = new Parser();
|
||||
const writer = options ? new HtmlRenderer(options) : new HtmlRenderer();
|
||||
const parsed = reader.parse(markdown);
|
||||
return writer.render(parsed);
|
||||
};
|
||||
3
imports/modules/server/get-private-file.js
Normal file
3
imports/modules/server/get-private-file.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import fs from 'fs';
|
||||
|
||||
export default path => fs.readFileSync(`assets/app/${path}`, 'utf8');
|
||||
|
|
@ -5,3 +5,5 @@ import '../../api/OAuth/server/methods';
|
|||
|
||||
import '../../api/Users/server/methods';
|
||||
import '../../api/Users/server/publications';
|
||||
|
||||
import '../../api/Utility/server/methods';
|
||||
|
|
|
|||
16
imports/ui/components/Content/Content.js
Normal file
16
imports/ui/components/Content/Content.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* eslint-disable react/no-danger */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import './Content.scss';
|
||||
|
||||
const Content = ({ content }) => (
|
||||
<div className="Content" dangerouslySetInnerHTML={{ __html: content }} />
|
||||
);
|
||||
|
||||
Content.propTypes = {
|
||||
content: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default Content;
|
||||
36
imports/ui/components/Content/Content.scss
Normal file
36
imports/ui/components/Content/Content.scss
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
@import '../../stylesheets/mixins';
|
||||
|
||||
.Content {
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin: 30px 0 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
> *:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
> *:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(tablet) {
|
||||
.Content {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
|
@ -39,7 +39,9 @@ body {
|
|||
color: $gray-light;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
a:hover,
|
||||
a:active,
|
||||
a:focus {
|
||||
text-decoration: none;
|
||||
color: $gray;
|
||||
}
|
||||
|
|
|
|||
24
imports/ui/components/PageHeader/PageHeader.js
Normal file
24
imports/ui/components/PageHeader/PageHeader.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import './PageHeader.scss';
|
||||
|
||||
const PageHeader = ({ title, subtitle }) => (
|
||||
<div className="PageHeader">
|
||||
<div className="PageHeader-container">
|
||||
<h1>{title}</h1>
|
||||
{subtitle ? <p>{subtitle}</p> : ''}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
PageHeader.defaultProps = {
|
||||
subtitle: '',
|
||||
};
|
||||
|
||||
PageHeader.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
subtitle: PropTypes.string,
|
||||
};
|
||||
|
||||
export default PageHeader;
|
||||
47
imports/ui/components/PageHeader/PageHeader.scss
Normal file
47
imports/ui/components/PageHeader/PageHeader.scss
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
@import '../../stylesheets/mixins';
|
||||
@import '../../stylesheets/colors';
|
||||
|
||||
.PageHeader {
|
||||
border-bottom: 1px solid $gray-lighter;
|
||||
padding: 0px 0 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 0;
|
||||
color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.PageHeader-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@include breakpoint(tablet) {
|
||||
.PageHeader {
|
||||
padding: 10px 0 30px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(desktop) {
|
||||
.PageHeader {
|
||||
padding: 20px 0 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,8 @@ import ResetPassword from '../../pages/ResetPassword/ResetPassword';
|
|||
import Profile from '../../pages/Profile/Profile';
|
||||
import NotFound from '../../pages/NotFound/NotFound';
|
||||
import Footer from '../../components/Footer/Footer';
|
||||
import Terms from '../../pages/Terms/Terms';
|
||||
import Privacy from '../../pages/Privacy/Privacy';
|
||||
|
||||
import './App.scss';
|
||||
|
||||
|
|
@ -41,6 +43,8 @@ const App = props => (
|
|||
<Public path="/logout" component={Logout} {...props} />
|
||||
<Route name="recover-password" path="/recover-password" component={RecoverPassword} />
|
||||
<Route name="reset-password" path="/reset-password/:token" component={ResetPassword} />
|
||||
<Route name="terms" path="/terms" component={Terms} />
|
||||
<Route name="privacy" path="/privacy" component={Privacy} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ const Index = () => (
|
|||
<Button href="https://pup.cleverbeagle.com">Read the Docs</Button>
|
||||
<Button href="https://github.com/cleverbeagle/pup"><i className="fa fa-star" /> Star on GitHub</Button>
|
||||
</div>
|
||||
<footer>
|
||||
<p>Need help and want to stay accountable building your product? <a href="https://cleverbeagle.com?utm_source=pupappindex&utm_campaign=oss">Check out Clever Beagle</a>.</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,14 +33,23 @@
|
|||
.btn {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn:last-child {
|
||||
background: darken($cb-blue, 20%);
|
||||
color: lighten($cb-blue, 30%);
|
||||
footer {
|
||||
margin: 20px -20px -20px;
|
||||
border-top: 1px solid darken($cb-blue, 10%);
|
||||
padding: 20px;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
p {
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: lighten($cb-blue, 35%);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p a {
|
||||
color: lighten($cb-blue, 35%);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,11 +57,19 @@
|
|||
@include breakpoint(tablet) {
|
||||
.Index {
|
||||
padding: 30px;
|
||||
|
||||
footer {
|
||||
margin: 30px -30px -30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(desktop) {
|
||||
.Index {
|
||||
padding: 40px;
|
||||
|
||||
footer {
|
||||
margin: 40px -40px -40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
44
imports/ui/pages/Page/Page.js
Normal file
44
imports/ui/pages/Page/Page.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { createContainer } from 'meteor/react-meteor-data';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import PageHeader from '../../components/PageHeader/PageHeader';
|
||||
import Content from '../../components/Content/Content';
|
||||
|
||||
import './Page.scss';
|
||||
|
||||
const Page = ({ title, subtitle, content }) => (
|
||||
<div className="Page">
|
||||
<PageHeader title={title} subtitle={subtitle} />
|
||||
<Content content={content} />
|
||||
</div>
|
||||
);
|
||||
|
||||
Page.defaultProps = {
|
||||
subtitle: '',
|
||||
};
|
||||
|
||||
Page.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
subtitle: PropTypes.string,
|
||||
content: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
const pageContent = new ReactiveVar('');
|
||||
|
||||
export default createContainer(({ content, page }) => {
|
||||
window.scrollTo(0, 0); // Force window to top of page.
|
||||
|
||||
Meteor.call('utility.getPage', page, (error, response) => {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
} else {
|
||||
pageContent.set(response);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
content: content || pageContent.get(),
|
||||
};
|
||||
}, Page);
|
||||
11
imports/ui/pages/Page/Page.scss
Normal file
11
imports/ui/pages/Page/Page.scss
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
@import '../../stylesheets/mixins';
|
||||
|
||||
.Page {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@include breakpoint(tablet) {
|
||||
.Page {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
14
imports/ui/pages/Privacy/Privacy.js
Normal file
14
imports/ui/pages/Privacy/Privacy.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import Page from '../Page/Page';
|
||||
|
||||
const Privacy = () => (
|
||||
<div className="Privacy">
|
||||
<Page
|
||||
title="Privacy Policy"
|
||||
subtitle="Last updated May 29th, 2017"
|
||||
page="privacy"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Privacy;
|
||||
14
imports/ui/pages/Terms/Terms.js
Normal file
14
imports/ui/pages/Terms/Terms.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import Page from '../Page/Page';
|
||||
|
||||
const Terms = () => (
|
||||
<div className="Terms">
|
||||
<Page
|
||||
title="Terms of Service"
|
||||
subtitle="Last updated May 29th, 2017"
|
||||
page="terms"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Terms;
|
||||
Loading…
Add table
Add a link
Reference in a new issue