diff --git a/.babelrc b/.babelrc index 300ae2519f..5d6b7f43c3 100644 --- a/.babelrc +++ b/.babelrc @@ -1,11 +1,12 @@ { - "presets": [ "env", "react", "stage-0" ], + "presets": ["env", "react", "stage-0"], "plugins": [ "transform-runtime", "babel-plugin-add-module-exports", "lodash", [ - "transform-imports", { + "transform-imports", + { "react-bootstrap": { "transform": "react-bootstrap/lib/${member}", "preventFullImport": true diff --git a/common/app/helperComponents/Loader.jsx b/common/app/helperComponents/Loader.jsx index 5d955457ea..07889fe4e6 100644 --- a/common/app/helperComponents/Loader.jsx +++ b/common/app/helperComponents/Loader.jsx @@ -5,7 +5,7 @@ function Loader() { return (
- +
diff --git a/common/app/helperComponents/SlimWidthRow.js b/common/app/helperComponents/SlimWidthRow.js new file mode 100644 index 0000000000..68119ceb73 --- /dev/null +++ b/common/app/helperComponents/SlimWidthRow.js @@ -0,0 +1,20 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Row, Col } from 'react-bootstrap'; + +function SlimWidthRow({ children, ...restProps }) { + return ( + + + { children } + + + ); +} + +SlimWidthRow.displayName = 'SlimWidthRow'; +SlimWidthRow.propTypes = { + children: PropTypes.any +}; + +export default SlimWidthRow; diff --git a/common/app/helperComponents/index.js b/common/app/helperComponents/index.js index 06f1160b3b..aeee5cce91 100644 --- a/common/app/helperComponents/index.js +++ b/common/app/helperComponents/index.js @@ -1,5 +1,6 @@ export { default as ButtonSpacer } from './ButtonSpacer.jsx'; export { default as FullWidthRow } from './FullWidthRow.jsx'; +export { default as SlimWidthRow } from './SlimWidthRow'; export { default as Loader } from './Loader.jsx'; export { default as SkeletonSprite } from './SkeletonSprite.jsx'; export { default as Spacer } from './Spacer.jsx'; diff --git a/common/models/article.json b/common/models/article.json index f3a425710e..870ec563b3 100644 --- a/common/models/article.json +++ b/common/models/article.json @@ -11,19 +11,29 @@ "type": "string", "required": true }, + "slugPart": { + "type": "string", + "required": true, + "description": "A kebab-case-string created from the title, will have the shortId appended to it" + }, + "meta": { + "type": "object", + "default": {}, + "description": "A place to keep the referral link and read time" + }, "title": { "type": "string", "required": true }, "author": { - "type": "string", + "type": "object", "required": true }, "subtitle": { "type": "string" }, "featureImage": { - "type": "string" + "type": "object" }, "draft": { "type": "string", @@ -32,6 +42,10 @@ "renderableContent": { "type": "string" }, + "youtubeId": { + "type": "string", + "description": "A youtube video id eg: 'EErY9zXGLNU'" + }, "published": { "type": "boolean", "required": true, @@ -52,6 +66,9 @@ "required": true, "default": 1 }, + "firstPublishedDate": { + "type": "date" + }, "createdDate": { "type": "date", "required": true diff --git a/news/NewsApp.js b/news/NewsApp.js index 6a528d2340..0ace6a717e 100644 --- a/news/NewsApp.js +++ b/news/NewsApp.js @@ -1,18 +1,34 @@ import React from 'react'; import { Grid } from 'react-bootstrap'; +import Helmet from 'react-helmet'; -import { FullWidthRow } from '../common/app/helperComponents'; +import { SlimWidthRow } from '../common/app/helperComponents'; import Nav from './components/Nav'; import { routes } from './routes'; const propTypes = {}; - +/* eslint-disable max-len */ +const styles = ` +.app-layout p, +.app-layout li, +.app-layout a, +.app-layout span { + font-size: 18px; +} +.app-layout hr { + background-image: linear-gradient(to right, rgba(0, 100, 0, 0), rgba(0, 100, 0, 0.75), rgba(0, 100, 0, 0)); +} +`; +/* eslint-enable max-len */ function NewsApp() { return (
+ + +
); diff --git a/news/components/BannerWide.js b/news/components/BannerWide.js new file mode 100644 index 0000000000..6dd9e1b168 --- /dev/null +++ b/news/components/BannerWide.js @@ -0,0 +1,52 @@ +import React from 'react'; + +const propTypes = {}; + +function BannerWide() { + return ( + + + + ); +} + +BannerWide.displayName = 'BannerWide'; +BannerWide.propTypes = propTypes; + +export default BannerWide; diff --git a/news/routes/Featured/Featured.js b/news/routes/Featured/Featured.js index d3533fc492..0e2fa41c86 100644 --- a/news/routes/Featured/Featured.js +++ b/news/routes/Featured/Featured.js @@ -1,14 +1,151 @@ -import React from 'react'; +import React, { Component } from 'react'; +import { withRouter } from 'react-router-dom'; +import { Image } from 'react-bootstrap'; +import Helmet from 'react-helmet'; + +import { getFeaturedList } from '../../utils/ajax'; +import { Loader, Spacer } from '../../../common/app/helperComponents'; +import BannerWide from '../../components/BannerWide'; const propTypes = {}; -function Featured() { - return ( -

Featured

- ); +const styles = ` + .featured-list { + list-style: none; + padding-left: 0; + } + + .featured-list-item .title { + color: #333; + } + + .featured-list-item a:hover, + .featured-list-item a:focus { + text-decoration: none; + text-decoration-line: none; + text-decoration-color: transparaent; + } + .featured-list-item a:hover > .meta-wrapper, + .featured-list-item a:focus > .meta-wrapper { + color: #006400; + } + + .meta-wrapper { + display: flex; + justify-content: space-between; + } + + .meta-wrapper span { + font-size: 14px; + } + + .meta-stats { + text-align: end; + } +`; + +class Featured extends Component { + constructor(props) { + super(props); + + this.state = { + fetchState: { + pending: false, + complete: false, + errored: false, + error: null + }, + featuredList: [] + }; + + this.fetchFeaturedList = this.fetchFeaturedList.bind(this); + } + + componentDidMount() { + return this.fetchFeaturedList(); + } + + fetchFeaturedList() { + return this.setState( + { + fetchState: { pending: true, complete: false, errored: false } + }, + () => + getFeaturedList().then(({ data }) => + this.setState({ + featuredList: data, + fetchState: { + pending: false, + complete: true, + errored: false, + error: null + } + }) + ) + ); + } + + createHandleArticleClick(slug, article) { + const { history } = this.props; + return e => { + e.preventDefault(); + return history.push({ pathname: slug, state: { article } }); + }; + } + + renderFeatured(articles) { + return articles.map(article => { + const slug = `/${article.author.username}/`.concat( + article.slugPart, + '--', + article.shortId + ); + const { featureImage, shortId, author, title, meta } = article; + return ( +
  • + {featureImage && featureImage.src ? () : ()} + +

    {title}

    +
    + By {author.name} + {`${meta.readTime} minute read`}
    {`${article.viewCount} views`}
    +
    +
    + +
  • + ); + }); + } + + render() { + const { + fetchState: { pending, complete, errored }, + featuredList + } = this.state; + if (pending || !complete) { + return ; + } + + if (complete && errored) { + return

    Oh noes!! Something went wrong!

    ; + } + return ( +
    + + + +

    Welcome to freeCodeCamp News

    +
    +

    Featured Articles

    +
      + {this.renderFeatured(featuredList)} +
    +
    + ); + } } Featured.displayName = 'Featured'; Featured.propTypes = propTypes; -export default Featured; +export default withRouter(Featured); diff --git a/news/routes/Show/Show.js b/news/routes/Show/Show.js index 6a16d81cf4..ef622f297d 100644 --- a/news/routes/Show/Show.js +++ b/news/routes/Show/Show.js @@ -1,14 +1,203 @@ -import React from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { withRouter } from 'react-router-dom'; +import Helmet from 'react-helmet'; +import Youtube from 'react-youtube'; +import { Image } from 'react-bootstrap'; -const propTypes = {}; +import Author from './components/Author'; +import { Loader } from '../../../common/app/helperComponents'; +import { getArticleById } from '../../utils/ajax'; -function ShowArticle() { - return ( -

    Show Article

    - ); +const propTypes = { + history: PropTypes.shape({ + push: PropTypes.func.isRequired + }), + match: PropTypes.shape({ + params: PropTypes.shape({ + username: PropTypes.string, + slug: PropTypes.string + }) + }) +}; + +const youtubeOpts = { + playerVars: { + // https://developers.google.com/youtube/player_parameters + autoplay: 0 + } +}; + +const styles = ` + article figure { + width: calc(100vw - 30px); + position: relative; + left: 50%; + right: 50%; + margin-left: -50vw; + margin-right: -50vw; + display: flex; + flex-direction: column; + align-items: center; + } + + .feature-image-wrapper { + padding-top: 32px; + } + .youtube-wrapper { + position: relative; + padding-bottom: 56.25%; /* 16:9 */ + padding-top: 25px; + height: 0; + overflow: hidden; + } + .youtube-wrapper iframe { + position: absolute; + left: 0; + width: 100%; + height: 100%; + } +`; + +class ShowArticle extends Component { + constructor(props) { + super(props); + + this.state = { + fetchState: { + pending: false, + complete: false, + errored: false, + error: null + }, + currentArticle: {}, + requiredArticle: '' + }; + + this.fetchArticle = this.fetchArticle.bind(this); + } + + componentDidMount() { + const { + history, + match: { + params: { username, slug } + }, + location: { state: { article } = {} } + } = this.props; + + if (username && !slug) { + return history.push('/'); + } + if (article) { + const [, shortId] = slug.split('--'); + return this.setState( + { + fetchState: { + complete: true + }, + currentArticle: article, + requiredArticle: shortId + }, + () => { + window.location.state = null; + } + ); + } + return this.fetchArticle(); + } + + fetchArticle() { + const { + match: { + params: { slug } + } + } = this.props; + + const [, shortId] = slug.split('--'); + return this.setState( + { + requiredArticle: shortId, + fetchState: { pending: true, complete: false, errored: false } + }, + () => + getArticleById(shortId) + .then(({ data }) => + this.setState({ + currentArticle: data, + fetchState: { + pending: false, + complete: true, + errored: false, + error: null + } + }) + ) + .catch(console.error) + ); + } + + youtubeReady(event) { + event.target.pauseVideo(); + } + + render() { + const { + fetchState: { pending, complete, errored }, + currentArticle: { + title, + renderableContent, + youtubeId, + featureImage, + author + } + } = this.state; + if (pending || !complete) { + return ; + } + + if (complete && errored) { + return

    Oh noes!! Something went wrong!

    ; + } + + return ( +
    + + + + +

    {title}

    +
    +
    + {featureImage.alt} + {featureImage.caption ? ( +
    + ) : null} +
    +
    +
    +
    +
    + {youtubeId ? ( + + ) : null} +
    +
    + ); + } } ShowArticle.displayName = 'ShowArticle'; ShowArticle.propTypes = propTypes; -export default ShowArticle; +export default withRouter(ShowArticle); diff --git a/news/routes/Show/components/Author.js b/news/routes/Show/components/Author.js new file mode 100644 index 0000000000..5189237061 --- /dev/null +++ b/news/routes/Show/components/Author.js @@ -0,0 +1,52 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Helmet from 'react-helmet'; + +const propTypes = { + author: PropTypes.objectOf(PropTypes.string) +}; + +const styles = ` + .author-block { + display: flex; + align-items: center; + justify-content: center; + margin-top: 15px; + } + + .author-block img { + border-radius: 20%; + } + + .author-bio { + display: flex; + flex-direction: column; + margin-left: 10px; + } + + .author-bio span { + font-size: 16px; + } +`; + +function Author({ author: { name, avatar, bio } }) { + return ( +
    + + + + +
    + + {name} + + {bio.slice(0, 101)} +
    +
    + ); +} + +Author.displayName = 'Author'; +Author.propTypes = propTypes; + +export default Author; diff --git a/news/routes/index.js b/news/routes/index.js index 8a44423119..cfa856166f 100644 --- a/news/routes/index.js +++ b/news/routes/index.js @@ -1,12 +1,13 @@ import React from 'react'; -import { Route } from 'react-router-dom'; +import { Route, Redirect } from 'react-router-dom'; -import EditArticle from './EditArticle'; +import Show from './Show'; import Featured from './Featured'; export const routes = [ , - -].map( - el => ({ ...el, key: el.props.path }) -); + } />, + +].map(el => ({ ...el, key: el.props.path })); + +// diff --git a/news/utils/ajax.js b/news/utils/ajax.js new file mode 100644 index 0000000000..124304f88c --- /dev/null +++ b/news/utils/ajax.js @@ -0,0 +1,23 @@ +import axios from 'axios'; +import qs from 'query-string'; + +export function getArticleById(shortId) { + return axios.get( + `/api/articles/findOne?${qs.stringify({ + filter: JSON.stringify({ where: { shortId } }) + })}` + ); +} + +export function getFeaturedList(skip = 0) { + return axios.get( + `/api/articles?${qs.stringify({ + filter: JSON.stringify({ + where: { featured: true, published: true }, + order: 'firstPublishedDate DESC', + limit: 10, + skip + }) + })}` + ); +} diff --git a/package-lock.json b/package-lock.json index c9cb467c90..b20fef3ef7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1137,6 +1137,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "1.5.2", + "is-buffer": "1.1.6" + } + }, "babel-cli": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", @@ -1172,6 +1181,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, "requires": { "chalk": "1.1.3", "esutils": "2.0.2", @@ -1182,6 +1192,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-generator": "6.26.1", @@ -1362,6 +1373,7 @@ "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, "requires": { "babel-messages": "6.23.0", "babel-runtime": "6.26.0", @@ -1399,6 +1411,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -1409,6 +1422,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -1420,6 +1434,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -1454,6 +1469,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, "requires": { "babel-helper-get-function-arity": "6.24.1", "babel-runtime": "6.26.0", @@ -1466,6 +1482,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1475,6 +1492,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1484,6 +1502,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1493,6 +1512,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -1516,6 +1536,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, "requires": { "babel-helper-optimise-call-expression": "6.24.1", "babel-messages": "6.23.0", @@ -1529,6 +1550,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -1626,6 +1648,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1640,6 +1663,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1711,7 +1735,8 @@ "babel-plugin-syntax-flow": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true }, "babel-plugin-syntax-function-bind": { "version": "6.13.0", @@ -1722,7 +1747,8 @@ "babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", @@ -1808,6 +1834,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1816,6 +1843,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1824,6 +1852,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0", @@ -1836,6 +1865,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, "requires": { "babel-helper-define-map": "6.26.0", "babel-helper-function-name": "6.24.1", @@ -1852,6 +1882,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -1861,6 +1892,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1869,6 +1901,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1878,6 +1911,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1886,6 +1920,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -1896,6 +1931,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1904,6 +1940,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, "requires": { "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", "babel-runtime": "6.26.0", @@ -1914,6 +1951,7 @@ "version": "6.26.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, "requires": { "babel-plugin-transform-strict-mode": "6.24.1", "babel-runtime": "6.26.0", @@ -1925,6 +1963,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -1935,6 +1974,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, "requires": { "babel-plugin-transform-es2015-modules-amd": "6.24.1", "babel-runtime": "6.26.0", @@ -1945,6 +1985,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, "requires": { "babel-helper-replace-supers": "6.24.1", "babel-runtime": "6.26.0" @@ -1954,6 +1995,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, "requires": { "babel-helper-call-delegate": "6.24.1", "babel-helper-get-function-arity": "6.24.1", @@ -1967,6 +2009,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1976,6 +2019,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1984,6 +2028,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -1994,6 +2039,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -2002,6 +2048,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -2010,6 +2057,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -2041,6 +2089,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, "requires": { "babel-plugin-syntax-flow": "6.18.0", "babel-runtime": "6.26.0" @@ -2082,6 +2131,7 @@ "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -2090,6 +2140,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, "requires": { "babel-helper-builder-react-jsx": "6.26.0", "babel-plugin-syntax-jsx": "6.18.0", @@ -2100,6 +2151,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.26.0" @@ -2109,6 +2161,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.26.0" @@ -2118,6 +2171,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, "requires": { "regenerator-transform": "0.10.1" } @@ -2135,6 +2189,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -2201,6 +2256,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", @@ -2232,6 +2288,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, "requires": { "babel-plugin-transform-flow-strip-types": "6.22.0" } @@ -2240,6 +2297,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-transform-react-display-name": "6.25.0", @@ -2300,6 +2358,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, "requires": { "babel-core": "6.26.0", "babel-runtime": "6.26.0", @@ -2322,12 +2381,14 @@ "babel-standalone": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-standalone/-/babel-standalone-6.26.0.tgz", - "integrity": "sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY=" + "integrity": "sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY=", + "dev": true }, "babel-template": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -2340,6 +2401,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-messages": "6.23.0", @@ -2356,6 +2418,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", @@ -2366,7 +2429,8 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true }, "backo2": { "version": "1.0.2", @@ -4358,7 +4422,8 @@ "convert-source-map": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=" + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true }, "cookie": { "version": "0.3.1", @@ -5212,6 +5277,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, "requires": { "repeating": "2.0.1" } @@ -6326,7 +6392,8 @@ "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "etag": { "version": "1.8.1", @@ -6970,6 +7037,24 @@ "readable-stream": "2.2.7" } }, + "follow-redirects": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.2.tgz", + "integrity": "sha512-kssLorP/9acIdpQ2udQVTiCS5LQmdEz9mvdIfDcl1gYX2tPKFADHSyFdvJS040XdFsPzemWtgI3q8mFVCxtX8A==", + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, "for-each": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", @@ -7605,7 +7690,8 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "dev": true, + "optional": true }, "json-schema": { "version": "0.2.3", @@ -8412,7 +8498,8 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true }, "globby": { "version": "4.0.0", @@ -9153,6 +9240,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -10320,7 +10408,8 @@ "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true }, "jshint": { "version": "2.9.5", @@ -10402,7 +10491,8 @@ "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true }, "jsonfile": { "version": "3.0.1", @@ -12174,7 +12264,7 @@ "loopback-connector": "4.5.0", "minimatch": "3.0.4", "qs": "6.5.1", - "shortid": "2.2.8", + "shortid": "2.2.12", "strong-globalize": "4.1.1", "traverse": "0.6.6", "uuid": "3.1.0" @@ -13805,6 +13895,22 @@ "prepend-http": "1.0.4", "query-string": "4.3.4", "sort-keys": "1.1.2" + }, + "dependencies": { + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + } } }, "normalizr": { @@ -15524,7 +15630,8 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true }, "process": { "version": "0.5.2", @@ -15712,12 +15819,12 @@ "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz", + "integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==", "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" + "decode-uri-component": "0.2.0", + "strict-uri-encode": "2.0.0" } }, "querystring": { @@ -16089,14 +16196,6 @@ } } }, - "react-no-ssr": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/react-no-ssr/-/react-no-ssr-1.1.0.tgz", - "integrity": "sha1-MTtI0uJgIPlp7ZjkcvEEgWBOPMg=", - "requires": { - "babel-runtime": "6.26.0" - } - }, "react-overlays": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz", @@ -16301,9 +16400,9 @@ } }, "react-youtube": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-7.5.0.tgz", - "integrity": "sha1-MXWpxOB4FkzxA85Lx4Cp5MpPH5Q=", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-7.6.0.tgz", + "integrity": "sha1-6kt6k5b2NbnyqfA7/io5uTy91Z0=", "requires": { "lodash": "4.17.5", "prop-types": "15.6.0", @@ -16553,7 +16652,8 @@ "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true }, "regenerator-runtime": { "version": "0.11.1", @@ -16564,6 +16664,7 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -16592,6 +16693,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, "requires": { "regenerate": "1.4.0", "regjsgen": "0.2.0", @@ -16618,12 +16720,14 @@ "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true }, "regjsparser": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, "requires": { "jsesc": "0.5.0" }, @@ -16631,7 +16735,8 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true } } }, @@ -16668,7 +16773,7 @@ "jsan": "3.1.9", "lodash": "4.17.5", "remotedev-serialize": "0.1.0", - "shortid": "2.2.8" + "shortid": "2.2.12" } }, "remove-trailing-separator": { @@ -17608,9 +17713,12 @@ "dev": true }, "shortid": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.8.tgz", - "integrity": "sha1-AzsRfWoul1gE9vCWnb59PQs1UTE=" + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.12.tgz", + "integrity": "sha512-sw0knB/ioTu/jVYgJz1IP1b5uhPZtZYwQ9ir/EqXZHI4+Jh8rzzGLM3LKptGHBKoDsgTBDfr4yCRNUX7hEIksQ==", + "requires": { + "nanoid": "1.1.0" + } }, "should": { "version": "4.6.5", @@ -17711,7 +17819,8 @@ "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true }, "slice-ansi": { "version": "1.0.0", @@ -18348,6 +18457,7 @@ "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, "requires": { "source-map": "0.5.7" } @@ -18623,9 +18733,9 @@ } }, "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" }, "string-convert": { "version": "0.2.1", @@ -19543,7 +19653,8 @@ "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true }, "to-iso-string": { "version": "0.0.2", @@ -19763,7 +19874,8 @@ "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true }, "tryit": { "version": "1.0.3", diff --git a/package.json b/package.json index 247bc4038b..d2cb3c137a 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,7 @@ "@freecodecamp/store": "^1.0.0", "accepts": "^1.3.0", "auth0-js": "^9.5.1", - "babel-core": "^6.26.0", - "babel-preset-es2015": "^6.24.1", - "babel-preset-react": "^6.24.1", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-standalone": "^6.26.0", + "axios": "^0.18.0", "berkeleys-redux-utils": "^4.0.0", "body-parser": "^1.13.2", "bootstrap": "~3.3.7", @@ -115,6 +110,7 @@ "pmx": "~0.6.2", "prismjs": "^1.11.0", "prop-types": "^15.6.0", + "query-string": "^6.1.0", "react": "^15.6.2", "react-addons-css-transition-group": "^15.4.2", "react-addons-shallow-compare": "^15.4.2", @@ -126,11 +122,10 @@ "react-images": "^0.5.11", "react-media": "^1.8.0", "react-motion": "^0.4.8", - "react-no-ssr": "^1.0.1", "react-redux": "^4.4.8", "react-router-dom": "^4.3.1", "react-test-renderer": "^15.6.2", - "react-youtube": "^7.5.0", + "react-youtube": "^7.6.0", "redux": "^3.7.2", "redux-actions": "^2.2.1", "redux-create-types": "0.0.1", @@ -144,6 +139,7 @@ "rx": "^4.1.0", "rx-dom": "^7.0.3", "sanitize-html": "^1.11.1", + "shortid": "^2.2.12", "snyk": "^1.69.1", "stripe": "^6.1.0", "uuid": "^3.0.1", @@ -152,6 +148,7 @@ "devDependencies": { "adler32": "~0.1.7", "babel-cli": "^6.3.17", + "babel-core": "^6.26.0", "babel-istanbul": "^0.12.1", "babel-loader": "^7.1.2", "babel-plugin-add-module-exports": "^0.2.1", @@ -159,8 +156,13 @@ "babel-plugin-transform-imports": "^1.4.1", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", + "babel-preset-es2015": "^6.24.1", + "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.3.13", "babel-preset-stage-3": "^6.24.1", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-standalone": "^6.26.0", "browser-sync": "^2.9.12", "browserify": "^16.1.1", "chunk-manifest-webpack-plugin": "^1.1.2", diff --git a/server/boot/news.js b/server/boot/news.js index a663c3036b..7d372b3f1d 100644 --- a/server/boot/news.js +++ b/server/boot/news.js @@ -11,10 +11,15 @@ function serveNewsApp(req, res) { ); + if (context.url) { + // 'client-side' routing hit on a redirect + return res.redirect(context.url); + } return res.render('layout-news', { title: 'News | freeCodeCamp', markup }); } export default function newsBoot(app) { + const router = app.loopback.Router(); router.get('/news', serveNewsApp);