Skip to content

Commit

Permalink
Merge pull request #17 from zarathustra323/messing-with-sasquatch
Browse files Browse the repository at this point in the history
Overhaul of web components
  • Loading branch information
zarathustra323 authored Aug 10, 2018
2 parents 4378690 + 8983765 commit 09bb4c6
Show file tree
Hide file tree
Showing 49 changed files with 1,731 additions and 1,298 deletions.
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = {
distDir: '../.next/build',

webpack: (config, { dev }) => {
config.plugins.push(new EnvironmentPlugin(['NODE_ENV', 'GA_TRACKING_ID']));
config.plugins.push(new EnvironmentPlugin(['NODE_ENV']));

config.module.rules.push({
test: /\.(graphql|gql)$/,
Expand Down
2 changes: 1 addition & 1 deletion nodemon.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"verbose": true,
"ignore": ["node_modules", ".next"],
"watch": ["server/**/*", "server.js"],
"watch": ["src/server/**/*", "server.js"],
"ext": "js json"
}
36 changes: 19 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,34 @@
}
},
"dependencies": {
"apollo-cache-inmemory": "^1.2.2",
"apollo-client": "^2.3.2",
"apollo-cache-inmemory": "^1.2.6",
"apollo-client": "^2.3.7",
"apollo-link": "^1.2.2",
"apollo-link-error": "^1.0.9",
"apollo-link-error": "^1.1.0",
"apollo-link-http": "^1.5.4",
"dotenv": "^5.0.1",
"express": "^4.16.3",
"graphql": "^0.13.2",
"graphql-tag": "^2.9.2",
"helmet": "^3.12.1",
"helmet": "^3.13.0",
"http-proxy-middleware": "^0.18.0",
"isomorphic-unfetch": "^2.0.0",
"next": "^6.0.3",
"prop-types": "^15.6.1",
"react": "^16.4.0",
"react-apollo": "^2.1.4",
"react-dom": "^16.4.0",
"reactstrap": "^6.3.0"
"isomorphic-unfetch": "^2.1.1",
"moment": "^2.19.1",
"next": "6.1.1-canary.4",
"prop-types": "^15.6.2",
"react": "^16.4.2",
"react-apollo": "^2.1.9",
"react-dom": "^16.4.2",
"react-moment": "^0.7.9",
"reactstrap": "^6.3.1"
},
"devDependencies": {
"eslint": "^4.19.1",
"eslint-config-airbnb": "^16.1.0",
"eslint-loader": "^2.0.0",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.8.2",
"nodemon": "^1.17.5"
"eslint-config-airbnb": "^17.0.0",
"eslint-loader": "^2.1.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-react": "^7.10.0",
"nodemon": "^1.18.3"
}
}
139 changes: 73 additions & 66 deletions src/apollo/WithApollo.jsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,89 @@
import React from 'react';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { ApolloProvider, getDataFromTree } from 'react-apollo';
import { getDataFromTree } from 'react-apollo';
import PropTypes from 'prop-types';
import initApollo from './init';
import apolloConfig from './config';

const getDisplayName = Component => Component.displayName || Component.name || 'Unknown';

export default function withApollo(apolloConfig) {
return (ComposedComponent) => {
class WithData extends React.Component {
static async getInitialProps(context) {
let serverState = { apollo: {} };
const {
req,
query,
pathname,
asPath,
} = context;
export default (App) => {
class WithApollo extends React.Component {
/**
*
* @param {*} props
*/
constructor(props) {
super(props);
const { apolloState } = this.props;
this.apollo = initApollo(apolloConfig, apolloState);
}

// Await the composed components initial props.
let composedProps = {};
if (ComposedComponent.getInitialProps) {
composedProps = await ComposedComponent.getInitialProps(context);
}
/**
*
* @param {*} ctx
*/
static async getInitialProps({
Component,
router,
ctx,
rest,
}) {
const { req } = ctx;

// Run all GraphQL queries in tree and extract their data.
if (!process.browser) {
const apollo = initApollo(apolloConfig, null, req);
const url = { query, pathname };
// Await the App's initial props.
let appProps = {};
if (App.getInitialProps) {
appProps = await App.getInitialProps({
Component,
router,
ctx,
...rest,
});
}

try {
// Run queries in the tree.
await getDataFromTree(
<ApolloProvider client={apollo}>
<ComposedComponent
url={url}
context={context}
{...composedProps}
/>
</ApolloProvider>,
{ router: { asPath, pathname, query } },
);
} catch (e) {
// Prevent errors from crashing SSR.
// Handle the error in components via data.error prop.
// eslint-disable-next-line no-console
console.error('SERVER ERROR', e);
}
// Clear the head state so duplicate head data is prevented.
Head.rewind();
serverState = {
apollo: { data: apollo.cache.extract() },
};
const apollo = initApollo(apolloConfig, {}, req);
// Run all GraphQL queries in tree and extract the data.
if (!process.browser) {
try {
// Run queries in the tree.
await getDataFromTree(<App
{...appProps}
Component={Component}
router={router}
apollo={apollo}
/>);
} catch (e) {
// Prevent errors from crashing SSR.
// Handle the error in components via data.error prop.
// @see http://dev.apollodata.com/react/api-queries.html#graphql-query-data-error
// eslint-disable-next-line no-console
console.error('SERVER ERROR in getDataFromTree', e);
}
return { serverState, ...composedProps };
// Clear the head state so duplicate head data is prevented.
Head.rewind();
}

constructor(props) {
super(props);
const { serverState } = this.props;
this.apollo = initApollo(apolloConfig, serverState.apollo.data);
}
// Extract the Apollo query data.
const apolloState = apollo.cache.extract();

render() {
return (
<ApolloProvider client={this.apollo}>
<ComposedComponent {...this.props} />
</ApolloProvider>
);
}
return {
...appProps,
apolloState,
};
}

WithData.displayName = `WithData(${getDisplayName(ComposedComponent)})`;
/**
*
*/
render() {
return <App {...this.props} apollo={this.apollo} />;
}
}

WithData.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
serverState: PropTypes.object.isRequired,
};
return WithData;
WithApollo.displayName = 'WithApollo(App)';
WithApollo.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
apolloState: PropTypes.object.isRequired,
};
}
return WithApollo;
};
5 changes: 1 addition & 4 deletions src/apollo/client.js → src/apollo/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { HttpLink } from 'apollo-link-http';
import { ApolloLink } from 'apollo-link';
import { onError } from 'apollo-link-error';
import fetch from 'isomorphic-unfetch';
import withApollo from './WithApollo';

const config = (req) => {
export default (req) => {
const headers = req ? req.headers : {};
const host = (req) ? req.ROOT_URI : '';
if (headers.host) {
Expand All @@ -29,5 +28,3 @@ const config = (req) => {
]),
};
};

export default withApollo(config);
39 changes: 0 additions & 39 deletions src/components/ActiveNavItem.jsx

This file was deleted.

26 changes: 0 additions & 26 deletions src/components/Analytics.jsx

This file was deleted.

25 changes: 25 additions & 0 deletions src/components/ErrorAlert.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Alert } from 'reactstrap';

const ErrorAlert = ({ message }) => (
<Alert className="mb-0" color="warning">
<h5 className="alert-heading">
Oh Snap!
</h5>
<hr />
<p className="mb-0">
{message}
</p>
</Alert>
);

ErrorAlert.defaultProps = {
message: 'An unknown, fatal error occurred.',
};

ErrorAlert.propTypes = {
message: PropTypes.string,
};

export default ErrorAlert;
51 changes: 51 additions & 0 deletions src/components/GoogleAnalytics.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';

/**
* Renders the global site script tag for gtag.js with Google Analytics.
*
* If no tracking ID is present, no script will be inserted.
* Also sets the accountKey globally.
*
* @see https://github.com/zeit/next.js/blob/master/examples/with-google-analytics
*/
const GoogleAnalytics = ({ trackingId, accountKey }) => {
if (!trackingId) return null;
/**
* Global Site Tag (gtag.js) - Google Analytics
*
*/
return (
<Fragment>
<script async src={`https://www.googletagmanager.com/gtag/js?id=${trackingId}`} />
<script
dangerouslySetInnerHTML={{ // eslint-disable-line react/no-danger
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
window.gtag('config', '${trackingId}', {
send_page_view: false,
custom_map: {
dimension1: 'account_key',
dimension2: 'story_id'
},
account_key: '${accountKey}'
});
`,
}}
/>
</Fragment>
);
};

GoogleAnalytics.defaultProps = {
trackingId: '',
};

GoogleAnalytics.propTypes = {
trackingId: PropTypes.string,
accountKey: PropTypes.string.isRequired,
};

export default GoogleAnalytics;
Loading

0 comments on commit 09bb4c6

Please sign in to comment.