Skip to content

Commit

Permalink
Merge pull request #23 from zarathustra323/tweaks
Browse files Browse the repository at this point in the history
RC 3.1 Features
  • Loading branch information
zarathustra323 authored Aug 28, 2018
2 parents 074f53e + d9ef164 commit b88295c
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 13 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"react-dom": "^16.4.2",
"react-moment": "^0.7.9",
"react-share": "^2.2.0",
"react-visibility-sensor": "^3.11.1",
"reactstrap": "^6.3.1",
"validator": "^10.5.0"
},
Expand Down
14 changes: 10 additions & 4 deletions src/apollo/WithApollo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getDataFromTree } from 'react-apollo';
import PropTypes from 'prop-types';
import initApollo from './init';
import apolloConfig from './config';

import isNotFound from '../lib/not-found';

export default (App) => {
class WithApollo extends React.Component {
Expand All @@ -28,7 +28,7 @@ export default (App) => {
ctx,
rest,
}) {
const { req } = ctx;
const { req, res } = ctx;

// Await the App's initial props.
let appProps = {};
Expand Down Expand Up @@ -56,8 +56,14 @@ export default (App) => {
// 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);
if (isNotFound(e)) {
e.code = 'ENOENT';
res.statusCode = 404;
throw e;
} else {
// eslint-disable-next-line no-console
console.error('SERVER ERROR in getDataFromTree', e);
}
}
// Clear the head state so duplicate head data is prevented.
Head.rewind();
Expand Down
12 changes: 12 additions & 0 deletions src/components/StoryView/Body.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Container } from 'reactstrap';
import VisibilitySensor from 'react-visibility-sensor';
import SocialShare from './SocialShare';
import { GTAGTracker } from '../../lib/gtag';

const createMarkup = html => ({ __html: html });

class StoryViewBody extends React.Component {
constructor(props) {
super(props);
this.trackEndOfContent = this.trackEndOfContent.bind(this);
}

/**
*
*/
Expand All @@ -22,6 +28,11 @@ class StoryViewBody extends React.Component {
});
}

trackEndOfContent(isVisible) {
const { tracker } = this.props;
if (isVisible) tracker.trackEndOfContent();
}

/**
*
*/
Expand Down Expand Up @@ -104,6 +115,7 @@ class StoryViewBody extends React.Component {
/>
{/* eslint-disable-next-line react/no-danger */}
<div id={`body-${storyId}`} className="fr-view" dangerouslySetInnerHTML={createMarkup(body)} />
<VisibilitySensor onChange={this.trackEndOfContent} />
<hr className="mt-4 mb-4" />
<SocialShare
title={title}
Expand Down
9 changes: 9 additions & 0 deletions src/components/StoryView/SocialShare.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ class StoryViewSocialShare extends React.Component {
title,
teaser,
imageSrc,
tracker,
} = this.props;

const disabled = !tracker.enabled;

return (
<div className={`share-button-container ${className}`}>
<style jsx global>
Expand All @@ -50,6 +54,7 @@ class StoryViewSocialShare extends React.Component {
</style>

<FacebookShareButton
disabled={disabled}
url={url}
beforeOnClick={() => this.track('Facebook')}
className="d-inline-block mr-2 share-button"
Expand All @@ -58,6 +63,7 @@ class StoryViewSocialShare extends React.Component {
</FacebookShareButton>

<TwitterShareButton
disabled={disabled}
title={title}
url={url}
beforeOnClick={() => this.track('Twitter')}
Expand All @@ -67,6 +73,7 @@ class StoryViewSocialShare extends React.Component {
</TwitterShareButton>

<LinkedinShareButton
disabled={disabled}
title={title}
description={teaser}
url={url}
Expand All @@ -78,6 +85,7 @@ class StoryViewSocialShare extends React.Component {

{imageSrc.length > 0 && (
<PinterestShareButton
disabled={disabled}
media={imageSrc}
url={url}
beforeOnClick={() => this.track('Pinterest')}
Expand All @@ -88,6 +96,7 @@ class StoryViewSocialShare extends React.Component {
)}

<EmailShareButton
disabled={disabled}
url={url}
beforeOnClick={() => this.track('Email')}
className="d-inline-block mr-2 share-button"
Expand Down
27 changes: 22 additions & 5 deletions src/lib/gtag.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,41 @@ export const trackOutboundLink = (url, props) => {
});
};

export const trackEndOfContent = (props) => {
trackEvent('scroll_to_bottom', {
...props,
event_category: 'engagement',
value: 1,
});
};

export class GTAGTracker {
constructor(config = {}) {
constructor(config = {}, enabled = true) {
this.config = config;
this.enable(enabled);
}

enable(bit = true) {
this.enabled = Boolean(bit);
}

event(action) {
trackEvent(action, this.config);
if (this.enabled) trackEvent(action, this.config);
}

pageview() {
trackPageView(this.config);
if (this.enabled) trackPageView(this.config);
}

share(method) {
trackSocialShare(method, this.config);
if (this.enabled) trackSocialShare(method, this.config);
}

outboundLink(url) {
trackOutboundLink(url, this.config);
if (this.enabled) trackOutboundLink(url, this.config);
}

trackEndOfContent() {
if (this.enabled) trackEndOfContent(this.config);
}
}
14 changes: 14 additions & 0 deletions src/lib/not-found.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { isArray } = Array;

/**
* @todo This should use better error detection via ApolloError.
* This requires Apollo Server 2.0, however.
* @see https://www.apollographql.com/docs/apollo-server/features/errors.html
*
* @param {Error} e
*/
const isNotFound = e => isArray(e.graphQLErrors)
&& e.graphQLErrors[0].message
&& /found for ID/i.test(e.graphQLErrors[0].message);

export default isNotFound;
9 changes: 7 additions & 2 deletions src/pages/story.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Query } from 'react-apollo';
import Head from 'next/head';
import Error from 'next/error';

import { GTAGTracker } from '../lib/gtag';

import Title from '../components/Title';
import StoryView from '../components/StoryView';
import LoadingBar from '../components/LoadingBar';
import ErrorAlert from '../components/ErrorAlert';
import isNotFound from '../lib/not-found';

import pageQuery from '../gql/queries/pages/story.graphql';

Expand All @@ -22,6 +24,9 @@ const Story = ({ id, preview, publisherId }) => {
return <LoadingBar />;
}
if (error) {
if (isNotFound(error)) {
return <Error statusCode={404} />;
}
return <ErrorAlert message={error.message} />;
}
const { publishedStory } = data;
Expand All @@ -43,7 +48,7 @@ const Story = ({ id, preview, publisherId }) => {
page_title: title,
publisher_id: publisher.id,
advertiser_id: advertiser.id,
});
}, !preview);
tracker.pageview();

const { src } = primaryImage || {};
Expand Down Expand Up @@ -84,7 +89,7 @@ const Story = ({ id, preview, publisherId }) => {
{/* @todo Eventually use the publisher context. */}
<meta name="native-x:publisher" content={publisher.name} />
</Head>
<StoryView {...publishedStory} tracker={tracker} />
<StoryView {...publishedStory} tracker={tracker} preview={preview} />
</Fragment>
);
}}
Expand Down
31 changes: 29 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"

create-react-class@^15.5.1:
version "15.6.3"
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036"
dependencies:
fbjs "^0.8.9"
loose-envify "^1.3.1"
object-assign "^4.1.1"

[email protected], cross-spawn@^5.0.1, cross-spawn@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
Expand Down Expand Up @@ -2665,6 +2673,18 @@ fbjs@^0.8.16:
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"

fbjs@^0.8.9:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"

figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
Expand Down Expand Up @@ -4594,7 +4614,7 @@ [email protected]:
loose-envify "^1.3.1"
object-assign "^4.1.1"

prop-types@^15.5.0, prop-types@^15.6.2:
prop-types@^15.5.0, prop-types@^15.5.4, prop-types@^15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
dependencies:
Expand Down Expand Up @@ -4820,6 +4840,13 @@ react-transition-group@^2.3.1:
loose-envify "^1.3.1"
prop-types "^15.6.1"

react-visibility-sensor@^3.11.1:
version "3.11.1"
resolved "https://registry.yarnpkg.com/react-visibility-sensor/-/react-visibility-sensor-3.11.1.tgz#cdcee0e43a8c603e0feb9773fcd2b7105a1cd9c2"
dependencies:
create-react-class "^15.5.1"
prop-types "^15.5.4"

react@^16.4.2:
version "16.4.2"
resolved "https://registry.yarnpkg.com/react/-/react-16.4.2.tgz#2cd90154e3a9d9dd8da2991149fdca3c260e129f"
Expand Down Expand Up @@ -5658,7 +5685,7 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"

ua-parser-js@^0.7.9:
ua-parser-js@^0.7.18, ua-parser-js@^0.7.9:
version "0.7.18"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"

Expand Down

0 comments on commit b88295c

Please sign in to comment.