diff --git a/frontend/components/AtlasPreview/AtlasPreview.js b/frontend/components/AtlasPreview/AtlasPreview.js index e760e24f..8665df1b 100644 --- a/frontend/components/AtlasPreview/AtlasPreview.js +++ b/frontend/components/AtlasPreview/AtlasPreview.js @@ -1,7 +1,7 @@ // @flow import React from 'react'; import { observer } from 'mobx-react'; -import Link from 'react-router/lib/Link'; +import { Link } from 'react-router-dom'; import DocumentLink from './components/DocumentLink'; diff --git a/frontend/components/AtlasPreview/components/DocumentLink/DocumentLink.js b/frontend/components/AtlasPreview/components/DocumentLink/DocumentLink.js index e83ef42b..97991b3c 100644 --- a/frontend/components/AtlasPreview/components/DocumentLink/DocumentLink.js +++ b/frontend/components/AtlasPreview/components/DocumentLink/DocumentLink.js @@ -3,7 +3,7 @@ import React from 'react'; import { observer } from 'mobx-react'; import moment from 'moment'; -import Link from 'react-router/lib/Link'; +import { Link } from 'react-router-dom'; import styles from './DocumentLink.scss'; diff --git a/frontend/components/DocumentPreview/DocumentPreview.js b/frontend/components/DocumentPreview/DocumentPreview.js index 0e0777da..52870f06 100644 --- a/frontend/components/DocumentPreview/DocumentPreview.js +++ b/frontend/components/DocumentPreview/DocumentPreview.js @@ -1,7 +1,7 @@ // @flow import React from 'react'; import { toJS } from 'mobx'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import styles from './DocumentPreview.scss'; diff --git a/frontend/components/DropdownMenu/DropdownMenu.js b/frontend/components/DropdownMenu/DropdownMenu.js index 3455ab3c..1b6e5c9f 100644 --- a/frontend/components/DropdownMenu/DropdownMenu.js +++ b/frontend/components/DropdownMenu/DropdownMenu.js @@ -1,31 +1,20 @@ // @flow import React from 'react'; -import { browserHistory } from 'react-router'; import styles from './DropdownMenu.scss'; -class MenuItem extends React.Component { - onClick = () => { - if (this.props.to) { - browserHistory.push(this.props.to); - } else { - this.props.onClick(); - } - }; - - render() { - return ( -
- {this.props.children} -
- ); - } -} - -MenuItem.propTypes = { - onClick: React.PropTypes.func, - to: React.PropTypes.string, - children: React.PropTypes.node.isRequired, +const MenuItem = ({ + onClick, + children, +}: { + onClick?: Function, + children?: React.Element, +}) => { + return ( +
+ {children} +
+ ); }; // diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index 4c204c95..9ee33a01 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -1,6 +1,6 @@ // @flow import React from 'react'; -import { browserHistory, Link } from 'react-router'; +import { Link, withRouter } from 'react-router-dom'; import Helmet from 'react-helmet'; import styled from 'styled-components'; import { observer, inject } from 'mobx-react'; @@ -9,7 +9,9 @@ import keydown from 'react-keydown'; import classNames from 'classnames/bind'; import searchIcon from 'assets/icons/search.svg'; import { Flex } from 'reflexbox'; +import { textColor } from 'styles/constants.scss'; import styles from './Layout.scss'; + import DropdownMenu, { MenuItem } from 'components/DropdownMenu'; import LoadingIndicator from 'components/LoadingIndicator'; import UserStore from 'stores/UserStore'; @@ -17,6 +19,7 @@ import UserStore from 'stores/UserStore'; const cx = classNames.bind(styles); type Props = { + history: Object, children?: ?React.Element, actions?: ?React.Element, title?: ?React.Element, @@ -36,19 +39,23 @@ type Props = { @keydown(['/', 't']) search() { - // if (!this.props.user) return; - _.defer(() => browserHistory.push('/search')); + if (!this.props.user) return; + _.defer(() => this.props.history.push('/search')); } @keydown(['d']) dashboard() { - // if (!this.props.user) return; - _.defer(() => browserHistory.push('/')); + if (!this.props.user) return; + _.defer(() => this.props.history.push('/')); } render() { const user = this.props.user; + const handleLogout = () => { + user.logout(() => this.props.history.push('/')); + }; + return (
{this.props.search && -
- Search -
+ +
+ Search +
+
} }> - Settings - - Keyboard shortcuts - - API - Logout + + Settings + + + + Keyboard shortcuts + + + + API + + Logout } @@ -118,4 +132,8 @@ const Avatar = styled.img` border-radius: 50%; `; -export default inject('user')(Layout); +const MenuLink = styled(Link)` + color: ${textColor}; +`; + +export default withRouter(inject('user')(Layout)); diff --git a/frontend/components/Sidebar/Sidebar.js b/frontend/components/Sidebar/Sidebar.js index 72044dd5..d4a9f58b 100644 --- a/frontend/components/Sidebar/Sidebar.js +++ b/frontend/components/Sidebar/Sidebar.js @@ -1,6 +1,7 @@ // @flow import React from 'react'; import { observer } from 'mobx-react'; +import { withRouter } from 'react-router-dom'; import { Flex } from 'reflexbox'; import Tree from 'components/Tree'; @@ -18,6 +19,7 @@ type Props = { navigationTree: Object, onNavigationUpdate: Function, onNodeCollapse: Function, + history: Object, }; @observer class Sidebar extends React.Component { @@ -47,6 +49,7 @@ type Props = { allowUpdates={this.store.isEditing} onChange={this.props.onNavigationUpdate} onCollapse={this.props.onNodeCollapse} + history={this.props.history} /> @@ -79,4 +82,4 @@ type Props = { } } -export default Sidebar; +export default withRouter(Sidebar); diff --git a/frontend/components/Tree/Node.js b/frontend/components/Tree/Node.js index 6b06f3c7..ba8157a3 100644 --- a/frontend/components/Tree/Node.js +++ b/frontend/components/Tree/Node.js @@ -1,6 +1,6 @@ /* eslint-disable */ import React from 'react'; -import history from 'utils/History'; + import styles from './Tree.scss'; import classNames from 'classnames/bind'; const cx = classNames.bind(styles); @@ -60,6 +60,7 @@ class Node extends React.Component { paddingLeft={this.props.paddingLeft} onCollapse={this.props.onCollapse} onDragStart={this.props.onDragStart} + history={this.props.history} /> ); })} @@ -77,8 +78,7 @@ class Node extends React.Component { onClick = () => { const index = this.props.index; const node = index.node; - - if (!this.isModifying()) history.push(node.url); + if (!this.isModifying()) this.props.history.push(node.url); }; render() { diff --git a/frontend/components/Tree/UiTree.js b/frontend/components/Tree/UiTree.js index c0c97bc0..02d774d3 100644 --- a/frontend/components/Tree/UiTree.js +++ b/frontend/components/Tree/UiTree.js @@ -13,6 +13,7 @@ export default React.createClass({ paddingLeft: React.PropTypes.number, onCollapse: React.PropTypes.func, allowUpdates: React.PropTypes.bool, + history: React.PropTypes.object, }, getDefaultProps() { @@ -93,6 +94,7 @@ export default React.createClass({ onDragStart={this.dragStart} onCollapse={this.toggleCollapse} dragging={dragging && dragging.id} + history={this.props.history} />
); diff --git a/frontend/index.js b/frontend/index.js index 2c4aff64..d08aaf8e 100644 --- a/frontend/index.js +++ b/frontend/index.js @@ -2,10 +2,13 @@ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'mobx-react'; -import Router from 'react-router/lib/Router'; -import Route from 'react-router/lib/Route'; -import IndexRoute from 'react-router/lib/IndexRoute'; -import History from 'utils/History'; +import { + BrowserRouter as Router, + Switch, + Route, + Redirect, +} from 'react-router-dom'; +import { Flex } from 'reflexbox'; import stores from 'stores'; @@ -34,80 +37,66 @@ if (__DEV__) { DevTools = require('mobx-react-devtools').default; // eslint-disable-line global-require } -function requireAuth(nextState, replace) { - if (!stores.user.authenticated) { - replace({ - pathname: '/', - state: { nextPathname: nextState.location.pathname }, - }); +type AuthProps = { + children?: React.Element, +}; + +const Auth = ({ children }: AuthProps) => { + if (stores.user.authenticated) { + return {children}; + } else { + return ; } -} +}; + +const notFoundSearch = () => ; +const KeyboardShortcuts = () => ( + +); +const Api = () => ; +const DocumentEdit = () => ; +const DocumentNew = () => ; +const DocumentNewChild = () => ; render(
- - - + + + - - - - - - + + + + + + + + - - + + - - - + + + - + + - - - - - + + + + + {DevTools && } diff --git a/frontend/scenes/Atlas/Atlas.js b/frontend/scenes/Atlas/Atlas.js index ee294095..5fc61133 100644 --- a/frontend/scenes/Atlas/Atlas.js +++ b/frontend/scenes/Atlas/Atlas.js @@ -1,7 +1,6 @@ // @flow import React from 'react'; import { observer } from 'mobx-react'; -import { browserHistory } from 'react-router'; import keydown from 'react-keydown'; import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; import _ from 'lodash'; @@ -21,6 +20,8 @@ import styles from './Atlas.scss'; type Props = { params: Object, + history: Object, + match: Object, keydown: Object, }; @@ -30,11 +31,11 @@ class Atlas extends React.Component { props: Props; componentDidMount = () => { - const { id } = this.props.params; + const { id } = this.props.match.params; store.fetchCollection(id, data => { // Forward directly to root document if (data.type === 'atlas') { - browserHistory.replace(data.navigationTree.url); + this.props.history.replace(data.navigationTree.url); } }); }; @@ -50,7 +51,7 @@ class Atlas extends React.Component { onCreate = (event: Event) => { if (event) event.preventDefault(); - store.collection && browserHistory.push(`${store.collection.url}/new`); + store.collection && this.props.history.push(`${store.collection.url}/new`); }; render() { diff --git a/frontend/scenes/Dashboard/Dashboard.js b/frontend/scenes/Dashboard/Dashboard.js index 0a3af592..5e094468 100644 --- a/frontend/scenes/Dashboard/Dashboard.js +++ b/frontend/scenes/Dashboard/Dashboard.js @@ -1,7 +1,7 @@ // @flow import React from 'react'; import { observer, inject } from 'mobx-react'; -import { withRouter } from 'react-router'; +import { withRouter } from 'react-router-dom'; import { Flex } from 'reflexbox'; import DashboardStore from './DashboardStore'; diff --git a/frontend/scenes/Document/components/Breadcrumbs/Breadcrumbs.js b/frontend/scenes/Document/components/Breadcrumbs/Breadcrumbs.js index 6e1f9dbd..14e59899 100644 --- a/frontend/scenes/Document/components/Breadcrumbs/Breadcrumbs.js +++ b/frontend/scenes/Document/components/Breadcrumbs/Breadcrumbs.js @@ -1,6 +1,6 @@ // @flow import React from 'react'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import type { Document, NavigationNode } from 'types'; type Props = { diff --git a/frontend/scenes/Error404/Error404.js b/frontend/scenes/Error404/Error404.js index 89b3eb2e..bc1c767f 100644 --- a/frontend/scenes/Error404/Error404.js +++ b/frontend/scenes/Error404/Error404.js @@ -1,6 +1,6 @@ // @flow import React from 'react'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import Layout from 'components/Layout'; import CenteredContent from 'components/CenteredContent'; diff --git a/frontend/scenes/ErrorAuth/ErrorAuth.js b/frontend/scenes/ErrorAuth/ErrorAuth.js index 40f8447b..e5746fe6 100644 --- a/frontend/scenes/ErrorAuth/ErrorAuth.js +++ b/frontend/scenes/ErrorAuth/ErrorAuth.js @@ -1,6 +1,6 @@ // @flow import React from 'react'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import Layout from 'components/Layout'; import CenteredContent from 'components/CenteredContent'; diff --git a/frontend/scenes/Flatpage/Flatpage.js b/frontend/scenes/Flatpage/Flatpage.js index 240f264c..0abd0b53 100644 --- a/frontend/scenes/Flatpage/Flatpage.js +++ b/frontend/scenes/Flatpage/Flatpage.js @@ -1,5 +1,5 @@ // @flow -import React, { PropTypes } from 'react'; +import React from 'react'; import { observer } from 'mobx-react'; import Layout, { Title } from 'components/Layout'; @@ -8,13 +8,16 @@ import { DocumentHtml } from 'components/Document'; import { convertToMarkdown } from 'utils/markdown'; +type Props = { + title: string, + content: string, +}; + @observer class Flatpage extends React.Component { - static propTypes = { - route: PropTypes.object, - }; + props: Props; render() { - const { title, content } = this.props.route; + const { title, content } = this.props; return ( { - if (this.props.user.authenticated) { - browserHistory.replace('/dashboard'); - } - }; - get notifications(): React.Element[] { const notifications = []; const { state } = this.props.location; @@ -46,6 +40,8 @@ export default class Home extends React.Component { return ( + {this.props.user.authenticated && } + {showLandingPageCopy &&
diff --git a/frontend/scenes/Search/Search.js b/frontend/scenes/Search/Search.js index b8839db2..44291f8b 100644 --- a/frontend/scenes/Search/Search.js +++ b/frontend/scenes/Search/Search.js @@ -13,8 +13,7 @@ import CenteredContent from 'components/CenteredContent'; import DocumentPreview from 'components/DocumentPreview'; type Props = { - route: Object, - routeParams: Object, + notFound: ?boolean, }; @observer class Search extends React.Component { @@ -26,20 +25,6 @@ type Props = { this.store = new SearchStore(); } - componentDidMount = () => { - const { splat } = this.props.routeParams; - if (this.viewNotFound) { - let searchTerm = _.last(splat.split('/')); - searchTerm = searchTerm.split(/[\s-]+/gi).join(' '); - this.store.search(searchTerm); - } - }; - - get viewNotFound(): boolean { - const { sceneType } = this.props.route; - return sceneType === 'notFound'; - } - render() { const search = _.debounce(searchTerm => { this.store.search(searchTerm); @@ -54,7 +39,7 @@ type Props = { loading={this.store.isFetching} > - {this.viewNotFound && + {this.props.notFound &&

Not Found

We're unable to find the page you're accessing.

diff --git a/frontend/scenes/SlackAuth/SlackAuth.js b/frontend/scenes/SlackAuth/SlackAuth.js index dd3f800f..e29af7bf 100644 --- a/frontend/scenes/SlackAuth/SlackAuth.js +++ b/frontend/scenes/SlackAuth/SlackAuth.js @@ -1,51 +1,65 @@ // @flow import React from 'react'; +import { Redirect } from 'react-router'; +import queryString from 'query-string'; import { observer, inject } from 'mobx-react'; -import { browserHistory } from 'react-router'; import { client } from 'utils/ApiClient'; +import UserStore from 'stores/UserStore'; + +type Props = { + user: UserStore, + location: Object, +}; + @inject('user') @observer class SlackAuth extends React.Component { - static propTypes = { - user: React.PropTypes.object.isRequired, - location: React.PropTypes.object.isRequired, - route: React.PropTypes.object.isRequired, - }; + props: Props; - // $FlowIssue wtf + state: { redirectTo: string }; + + // $FlowFixMe not sure why this breaks componentDidMount = async () => { - const { error, code, state } = this.props.location.query; + const { error, code, state } = queryString.parse( + this.props.location.search + ); if (error) { if (error === 'access_denied') { // User selected "Deny" access on Slack OAuth - browserHistory.push('/'); + this.setState({ redirectTo: '/dashboard' }); } else { - browserHistory.push('/auth/error'); - } - // $FlowIssue wtf - return; - } - - if (this.props.route.apiPath) { - try { - await client.post(this.props.route.apiPath, { code }); - browserHistory.replace('/dashboard'); - } catch (e) { - browserHistory.push('/auth-error'); + this.setState({ redirectTo: '/auth/error' }); } } else { - // Regular Slack authentication - const redirectTo = sessionStorage.getItem('redirectTo'); - sessionStorage.removeItem('redirectTo'); + if (this.props.location.pathname === '/auth/slack/commands') { + // User adding webhook integrations + try { + await client.post('/auth.slackCommands', { code }); + this.setState({ redirectTo: '/dashboard' }); + } catch (e) { + this.setState({ redirectTo: '/auth/error' }); + } + } else { + // Regular Slack authentication + const redirectTo = sessionStorage.getItem('redirectTo'); + sessionStorage.removeItem('redirectTo'); - this.props.user.authWithSlack(code, state, redirectTo); + const { success } = await this.props.user.authWithSlack(code, state); + success + ? this.setState({ redirectTo: redirectTo || '/dashboard' }) + : this.setState({ redirectTo: '/auth/error' }); + } } }; render() { - return
; + return ( +
+ {this.state.redirectTo && } +
+ ); } } diff --git a/frontend/stores/UserStore.js b/frontend/stores/UserStore.js index b002e82f..30a90845 100644 --- a/frontend/stores/UserStore.js +++ b/frontend/stores/UserStore.js @@ -1,7 +1,6 @@ // @flow import { observable, action, computed } from 'mobx'; import invariant from 'invariant'; -import { browserHistory } from 'react-router'; import { client } from 'utils/ApiClient'; import type { User, Team } from 'types'; @@ -33,10 +32,10 @@ class UserStore { /* Actions */ - @action logout = () => { + @action logout = (cb: Function) => { this.user = null; this.token = null; - browserHistory.push('/'); + cb(); }; @action getOauthState = () => { @@ -45,22 +44,20 @@ class UserStore { return this.oauthState; }; - @action authWithSlack = async ( - code: string, - state: string, - redirectTo: ?string - ) => { + @action authWithSlack = async (code: string, state: string) => { if (state !== this.oauthState) { - browserHistory.push('/auth-error'); - return; + return { + success: false, + }; } let res; try { res = await client.post('/auth.slack', { code }); } catch (e) { - browserHistory.push('/auth-error'); - return; + return { + success: false, + }; } invariant( @@ -70,7 +67,10 @@ class UserStore { this.user = res.data.user; this.team = res.data.team; this.token = res.data.accessToken; - browserHistory.replace(redirectTo || '/'); + + return { + success: true, + }; }; constructor() { diff --git a/frontend/utils/ApiClient.js b/frontend/utils/ApiClient.js index 841979a9..4c304cc6 100644 --- a/frontend/utils/ApiClient.js +++ b/frontend/utils/ApiClient.js @@ -1,6 +1,5 @@ // @flow import _ from 'lodash'; -import { browserHistory } from 'react-router'; import stores from 'stores'; type Options = { @@ -63,15 +62,15 @@ class ApiClient { return response; } - // Handle 404 - if (response.status === 404) { - return browserHistory.push('/404'); - } + // // Handle 404 + // if (response.status === 404) { + // // return browserHistory.push('/404'); + // } - // Handle 401, log out user - if (response.status === 401) { - return stores.user.logout(); - } + // // Handle 401, log out user + // if (response.status === 401) { + // return stores.user.logout(); + // } // Handle failed responses const error = {}; diff --git a/frontend/utils/History.js b/frontend/utils/History.js deleted file mode 100644 index 76b01758..00000000 --- a/frontend/utils/History.js +++ /dev/null @@ -1,4 +0,0 @@ -// @flow -// https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md -import browserHistory from 'react-router/lib/browserHistory'; -export default browserHistory; diff --git a/package.json b/package.json index da27c903..fd574c93 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,7 @@ "react-helmet": "3.1.0", "react-keydown": "^1.7.3", "react-portal": "^3.1.0", - "react-router": "2.8.0", + "react-router-dom": "^4.1.1", "redis": "^2.6.2", "redis-lock": "^0.1.0", "reflexbox": "^2.2.3", @@ -187,4 +187,4 @@ "react-addons-test-utils": "^15.3.1", "react-test-renderer": "^15.3.1" } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e55054f1..076a6f53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2120,7 +2120,7 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" -deep-equal@1.0.1, deep-equal@^1.0.0, deep-equal@~1.0.0: +deep-equal@1.0.1, deep-equal@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -3689,14 +3689,15 @@ history@3.0.0: query-string "^4.1.0" warning "^2.0.0" -history@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/history/-/history-2.1.2.tgz#4aa2de897a0e4867e4539843be6ecdb2986bfdec" +history@^4.5.1, history@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.6.1.tgz#911cf8eb65728555a94f2b12780a0c531a14d2fd" dependencies: - deep-equal "^1.0.0" - invariant "^2.0.0" - query-string "^3.0.0" - warning "^2.0.0" + invariant "^2.2.1" + loose-envify "^1.2.0" + resolve-pathname "^2.0.0" + value-equal "^0.2.0" + warning "^3.0.0" hoek@2.x.x: version "2.16.3" @@ -5435,12 +5436,18 @@ longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0: +loose-envify@^1.0.0, loose-envify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.2.0.tgz#69a65aad3de542cf4ee0f4fe74e8e33c709ccb0f" dependencies: js-tokens "^1.0.1" +loose-envify@^1.2.0, loose-envify@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -6414,7 +6421,7 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" -path-to-regexp@^1.1.1: +path-to-regexp@^1.1.1, path-to-regexp@^1.5.3: version "1.6.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.6.0.tgz#4c59cfeab5e360a2657b180730a4bb4582ecec5b" dependencies: @@ -6929,12 +6936,6 @@ qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -query-string@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-3.0.3.tgz#ae2e14b4d05071d4e9b9eb4873c35b0dcd42e638" - dependencies: - strict-uri-encode "^1.0.0" - query-string@^4.1.0, query-string@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -7056,14 +7057,25 @@ react-proxy@^1.1.7: lodash "^4.6.1" react-deep-force-update "^1.0.0" -react-router@2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-2.8.0.tgz#cbc629fede81d96d0598c2bae1e348e7d03f6c17" +react-router-dom@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.1.1.tgz#3021ade1f2c160af97cf94e25594c5f294583025" dependencies: - history "^2.1.2" + history "^4.5.1" + loose-envify "^1.3.1" + prop-types "^15.5.4" + react-router "^4.1.1" + +react-router@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95" + dependencies: + history "^4.6.0" hoist-non-react-statics "^1.2.0" - invariant "^2.2.1" - loose-envify "^1.2.0" + invariant "^2.2.2" + loose-envify "^1.3.1" + path-to-regexp "^1.5.3" + prop-types "^15.5.4" warning "^3.0.0" react-side-effect@1.0.2: @@ -7447,6 +7459,10 @@ resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-pathname@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944" + resolve@1.1.7, resolve@1.1.x, resolve@^1.0.0, resolve@^1.1.6, resolve@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -8615,6 +8631,10 @@ validator@5.2.0, validator@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/validator/-/validator-5.2.0.tgz#e66fb3ec352348c1f7232512328738d8d66a9689" +value-equal@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d" + vary@^1.0.0, vary@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140"