From b7a04bcb89da90a63bc46b0c5abe2bfe454171d0 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Mon, 15 Jun 2020 19:02:18 -0400 Subject: [PATCH 1/3] improvement(example): Move Auth0Provider plumbing out of example.js and to ConnectedRouter. --- example.js | 70 +++++-------------------- lib/components/app/app-nav.js | 25 +++++---- lib/components/app/responsive-webapp.js | 33 ++++++++++-- lib/index.js | 2 + lib/util/auth.js | 8 +-- 5 files changed, 65 insertions(+), 73 deletions(-) diff --git a/example.js b/example.js index 086eddcff..94cce701e 100644 --- a/example.js +++ b/example.js @@ -11,21 +11,15 @@ import { Provider } from 'react-redux' import thunk from 'redux-thunk' import createLogger from 'redux-logger' -// Auth0 -import { Auth0Provider } from 'use-auth0-hooks' -import { accountLinks, getAuth0Callbacks, getAuth0Config } from './lib/util/auth' -import { AUTH0_AUDIENCE, AUTH0_SCOPE, URL_ROOT } from './lib/util/constants' - // import Bootstrap Grid components for layout -import { Nav, Navbar, Grid, Row, Col } from 'react-bootstrap' +import { Grid, Row, Col } from 'react-bootstrap' // import OTP-RR components import { - AppMenu, + AppNav, DefaultMainPanel, Map, MobileMain, - NavLoginButtonAuth0, ResponsiveWebapp, createOtpReducer, createUserReducer @@ -81,37 +75,13 @@ const store = createStore( compose(applyMiddleware(...middleware)) ) -// Auth0 config and callbacks. -const auth0Config = getAuth0Config(otpConfig.persistence) -const auth0Callbacks = getAuth0Callbacks(store) - // define a simple responsive UI using Bootstrap and OTP-RR class OtpRRExample extends Component { render () { /** desktop view **/ const desktopView = (
- - - -
- -
-
OpenTripPlanner
-
-
- - {auth0Config && ( - - - - )} -
+ @@ -146,34 +116,20 @@ class OtpRRExample extends Component { } } -const innerProvider = ( - - { /** +// render the app +render( + ( + + { /** * If not using router history, simply include OtpRRExample here: * e.g. * */ - } - - -) - -// render the app -render(auth0Config - ? ( - - {innerProvider} - + } + + ) - : innerProvider -, + , -document.getElementById('root') + document.getElementById('root') ) diff --git a/lib/components/app/app-nav.js b/lib/components/app/app-nav.js index fc98a06b8..4bcf80d01 100644 --- a/lib/components/app/app-nav.js +++ b/lib/components/app/app-nav.js @@ -4,10 +4,9 @@ import { connect } from 'react-redux' import NavLoginButtonAuth0 from '../user/nav-login-button-auth0.js' import { accountLinks, getAuth0Config } from '../../util/auth' - import AppMenu from './app-menu' -const AppNav = ({ otpConfig }) => { +const AppNav = ({ otpConfig, title }) => { const { branding, persistence } = otpConfig const showLogin = Boolean(getAuth0Config(persistence)) @@ -15,15 +14,23 @@ const AppNav = ({ otpConfig }) => { -
+ {/* TODO: Reconcile CSS class and inline style. */} +
-
+ + {branding && ( +
+ )} + + {title && ( +
OpenTripPlanner
+ )} diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js index 2738aa27d..2ef74197d 100644 --- a/lib/components/app/responsive-webapp.js +++ b/lib/components/app/responsive-webapp.js @@ -6,6 +6,7 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import { connect } from 'react-redux' import { Route, Switch, withRouter } from 'react-router' +import { Auth0Provider } from 'use-auth0-hooks' import PrintLayout from './print-layout' import { setMapCenter, setMapZoom } from '../../actions/config' @@ -13,6 +14,8 @@ import { formChanged, parseUrlQueryString } from '../../actions/form' import { getCurrentPosition, receivedPositionResponse } from '../../actions/location' import { setLocationToCurrent } from '../../actions/map' import { handleBackButtonPress, matchContentToUrl } from '../../actions/ui' +import { getAuth0Callbacks, getAuth0Config } from '../../util/auth' +import { AUTH0_AUDIENCE, AUTH0_SCOPE, URL_ROOT } from '../../util/constants' import { getActiveItinerary, getTitle } from '../../util/state' import AfterSignInScreen from '../user/after-signin-screen' import UserAccountScreen from '../user/user-account-screen' @@ -180,8 +183,12 @@ class RouterWrapper extends Component { } render () { - const { routerConfig } = this.props - return ( + const { dispatch, persistence, routerConfig } = this.props + // Initialize Auth0Provider in this component so it is available everywhere. + const auth0Config = getAuth0Config(persistence) + const auth0Callbacks = getAuth0Callbacks(dispatch) + + const router = ( @@ -241,7 +248,27 @@ class RouterWrapper extends Component {
) + + return ( + auth0Config + ? ( + + {router} + + ) + : router + ) } } -const mapStateToWrapperProps = (state, ownProps) => ({ routerConfig: state.otp.config.reactRouter }) +const mapStateToWrapperProps = (state, ownProps) => ({ + persistence: state.otp.config.persistence, + routerConfig: state.otp.config.reactRouter +}) export default connect(mapStateToWrapperProps)(RouterWrapper) diff --git a/lib/index.js b/lib/index.js index 8a12bb97a..8dc1da335 100644 --- a/lib/index.js +++ b/lib/index.js @@ -37,6 +37,7 @@ import ViewerContainer from './components/viewers/viewer-container' import ResponsiveWebapp from './components/app/responsive-webapp' import AppMenu from './components/app/app-menu' +import AppNav from './components/app/app-nav' import DefaultMainPanel from './components/app/default-main-panel' import { setAutoPlan, setMapCenter } from './actions/config' @@ -97,6 +98,7 @@ export { // app components, ResponsiveWebapp, AppMenu, + AppNav, DefaultMainPanel, // actions diff --git a/lib/util/auth.js b/lib/util/auth.js index 3356926a7..dd2b5aaeb 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -42,9 +42,9 @@ export function getAuth0Config (persistence) { * Gets the callback methods for Auth0. * Note: Methods inside are originally copied from https://github.com/sandrinodimattia/use-auth0-hooks#readme * and some methods from that example may still be untouched. - * @param reduxStore The redux store to carry out the navigation action. + * @param dispatch The dispatch method to carry out the actions. */ -export function getAuth0Callbacks (reduxStore) { +export function getAuth0Callbacks (dispatch) { return { /** * When it hasn't been possible to retrieve a new access token. @@ -60,7 +60,7 @@ export function getAuth0Callbacks (reduxStore) { * @param {Error} err */ onLoginError: err => { - if (err) reduxStore.dispatch(push(`/oops`)) + if (err) dispatch(push(`/oops`)) }, /** * Where to send the user after they have signed in. @@ -74,7 +74,7 @@ export function getAuth0Callbacks (reduxStore) { // so that the AfterLoginScreen can redirect back there when logged-in user info is fetched. // (For routing, it is easier to deal with the path without the hash sign.) const urlHashWithoutHash = (appState.urlHash.split('#')[1] || '/') - reduxStore.dispatch(setPathBeforeSignIn(urlHashWithoutHash)) + dispatch(setPathBeforeSignIn(urlHashWithoutHash)) } else if (appState && appState.returnTo) { // TODO: Handle other after-login situations. // Careful! From 0cf1737698da95a83d65cc9a40a696afa9f5db48 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 17 Jun 2020 17:05:23 -0400 Subject: [PATCH 2/3] refactor(actions/auth): Extract auth callbacks into actions. --- example.js | 4 +- lib/actions/auth.js | 56 +++++++++++++++ .../app/{app-nav.js => desktop-nav.js} | 22 ++++-- lib/components/app/responsive-webapp.js | 44 +++++++++--- lib/components/mobile/navigation-bar.js | 11 ++- lib/components/user/before-signin-screen.js | 17 +++++ lib/components/user/user-account-screen.js | 4 +- lib/index.js | 4 +- lib/util/auth.js | 69 ------------------- 9 files changed, 137 insertions(+), 94 deletions(-) create mode 100644 lib/actions/auth.js rename lib/components/app/{app-nav.js => desktop-nav.js} (75%) create mode 100644 lib/components/user/before-signin-screen.js diff --git a/example.js b/example.js index 94cce701e..41142d151 100644 --- a/example.js +++ b/example.js @@ -16,8 +16,8 @@ import { Grid, Row, Col } from 'react-bootstrap' // import OTP-RR components import { - AppNav, DefaultMainPanel, + DesktopNav, Map, MobileMain, ResponsiveWebapp, @@ -81,7 +81,7 @@ class OtpRRExample extends Component { /** desktop view **/ const desktopView = (
- + diff --git a/lib/actions/auth.js b/lib/actions/auth.js new file mode 100644 index 000000000..ffbf56c92 --- /dev/null +++ b/lib/actions/auth.js @@ -0,0 +1,56 @@ +import { push } from 'connected-react-router' + +import { setPathBeforeSignIn } from '../actions/user' + +/** + * This function is called by the Auth0Provider component, with the described parameter(s), + * when a new access token could not be retrieved. + * @param {Error} err + * @param {AccessTokenRequestOptions} options + */ +export function showAccessTokenError (err, options) { + return function (dispatch, getState) { + // TODO: improve this. + console.error('Failed to retrieve access token: ', err) + } +} + +/** + * This function is called by the Auth0Provider component, with the described parameter(s), + * when signing-in fails for some reason. + * @param {Error} err + */ +export function showLoginError (err) { + return function (dispatch, getState) { + // TODO: improve this. + if (err) dispatch(push('/oops')) + } +} + +/** + * This function is called by the Auth0Provider component, with the described parameter(s), + * after the user signs in. + * @param {Error} err + */ +export function processSignIn (appState) { + return function (dispatch, getState) { + if (appState && appState.urlHash) { + // At this stage after login, Auth0 has already redirected to /signedin (Auth0-whitelisted) + // which shows the AfterLoginScreen. + // + // Here, we save the URL hash prior to login (contains a combination of itinerary search, stop/trip view, etc.), + // so that the AfterLoginScreen can redirect back there when logged-in user info is fetched. + // (For routing, it is easier to deal with the path without the hash sign.) + const urlHashWithoutHash = (appState.urlHash.split('#')[1] || '/') + dispatch(setPathBeforeSignIn(urlHashWithoutHash)) + } else if (appState && appState.returnTo) { + // TODO: Handle other after-login situations. + // Note that when redirecting from a login-protected (e.g. account) page while logged out, + // then returnTo is set by Auth0 to this object format: + // { + // pathname: "/" + // query: { ... } + // } + } + } +} diff --git a/lib/components/app/app-nav.js b/lib/components/app/desktop-nav.js similarity index 75% rename from lib/components/app/app-nav.js rename to lib/components/app/desktop-nav.js index 4bcf80d01..cd123ec6d 100644 --- a/lib/components/app/app-nav.js +++ b/lib/components/app/desktop-nav.js @@ -1,3 +1,4 @@ +import PropTypes from 'prop-types' import React from 'react' import { Nav, Navbar } from 'react-bootstrap' import { connect } from 'react-redux' @@ -6,7 +7,11 @@ import NavLoginButtonAuth0 from '../user/nav-login-button-auth0.js' import { accountLinks, getAuth0Config } from '../../util/auth' import AppMenu from './app-menu' -const AppNav = ({ otpConfig, title }) => { +/** + * The desktop navigation bar, featuring a sign-in button/menu. + * TODO: merge with the mobile navigation bar. + */ +const DesktopNav = ({ otpConfig, title }) => { const { branding, persistence } = otpConfig const showLogin = Boolean(getAuth0Config(persistence)) @@ -22,14 +27,13 @@ const AppNav = ({ otpConfig, title }) => { {branding && (
)} {title && ( -
OpenTripPlanner
+
{title}
)} @@ -48,6 +52,14 @@ const AppNav = ({ otpConfig, title }) => { ) } +DesktopNav.propTypes = { + title: PropTypes.string +} + +DesktopNav.defaultProps = { + title: 'OpenTripPlanner' +} + // connect to the redux store const mapStateToProps = (state, ownProps) => { @@ -59,4 +71,4 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = { } -export default connect(mapStateToProps, mapDispatchToProps)(AppNav) +export default connect(mapStateToProps, mapDispatchToProps)(DesktopNav) diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js index 2ef74197d..8ff54780b 100644 --- a/lib/components/app/responsive-webapp.js +++ b/lib/components/app/responsive-webapp.js @@ -9,15 +9,17 @@ import { Route, Switch, withRouter } from 'react-router' import { Auth0Provider } from 'use-auth0-hooks' import PrintLayout from './print-layout' +import * as authActions from '../../actions/auth' import { setMapCenter, setMapZoom } from '../../actions/config' import { formChanged, parseUrlQueryString } from '../../actions/form' import { getCurrentPosition, receivedPositionResponse } from '../../actions/location' import { setLocationToCurrent } from '../../actions/map' import { handleBackButtonPress, matchContentToUrl } from '../../actions/ui' -import { getAuth0Callbacks, getAuth0Config } from '../../util/auth' +import { getAuth0Config } from '../../util/auth' import { AUTH0_AUDIENCE, AUTH0_SCOPE, URL_ROOT } from '../../util/constants' import { getActiveItinerary, getTitle } from '../../util/state' import AfterSignInScreen from '../user/after-signin-screen' +import BeforeSignInScreen from '../user/before-signin-screen' import UserAccountScreen from '../user/user-account-screen' import withLoggedInUserSupport from '../user/with-logged-in-user-support' @@ -171,7 +173,13 @@ const WebappWithRouter = withRouter( ) ) -class RouterWrapper extends Component { +/** + * The routing component for the application. + * This is the top-most "standard" component, + * and we initialize the Auth0Provider here + * so that Auth0 services are available everywhere. + */ +class RouterWrapperWithAuth0 extends Component { /** * Combine the router props with the other props that get * passed to the exported component. This way, it is possible for @@ -183,10 +191,13 @@ class RouterWrapper extends Component { } render () { - const { dispatch, persistence, routerConfig } = this.props - // Initialize Auth0Provider in this component so it is available everywhere. - const auth0Config = getAuth0Config(persistence) - const auth0Callbacks = getAuth0Callbacks(dispatch) + const { + auth0Config, + processSignIn, + routerConfig, + showAccessTokenError, + showLoginError + } = this.props const router = ( {router} @@ -267,8 +281,16 @@ class RouterWrapper extends Component { ) } } + const mapStateToWrapperProps = (state, ownProps) => ({ - persistence: state.otp.config.persistence, + auth0Config: getAuth0Config(state.otp.config.persistence), routerConfig: state.otp.config.reactRouter }) -export default connect(mapStateToWrapperProps)(RouterWrapper) + +const mapWrapperDispatchToProps = { + processSignIn: authActions.processSignIn, + showAccessTokenError: authActions.showAccessTokenError, + showLoginError: authActions.showLoginError +} + +export default connect(mapStateToWrapperProps, mapWrapperDispatchToProps)(RouterWrapperWithAuth0) diff --git a/lib/components/mobile/navigation-bar.js b/lib/components/mobile/navigation-bar.js index 81f6e5910..cac315e1c 100644 --- a/lib/components/mobile/navigation-bar.js +++ b/lib/components/mobile/navigation-bar.js @@ -26,8 +26,13 @@ class MobileNavigationBar extends Component { } render () { - const { headerAction, headerText, persistence, showBackButton, title } = this.props - const auth0Config = getAuth0Config(persistence) + const { + auth0Config, + headerAction, + headerText, + showBackButton, + title + } = this.props return ( @@ -75,7 +80,7 @@ class MobileNavigationBar extends Component { const mapStateToProps = (state, ownProps) => { return { - persistence: state.otp.config.persistence + auth0Config: getAuth0Config(state.otp.config.persistence) } } diff --git a/lib/components/user/before-signin-screen.js b/lib/components/user/before-signin-screen.js new file mode 100644 index 000000000..b6f2e7e96 --- /dev/null +++ b/lib/components/user/before-signin-screen.js @@ -0,0 +1,17 @@ +import React from 'react' + +/** + * This screen is flashed just before the Auth0 login page is shown. + * TODO: improve this screen. + */ +const BeforeSignInScreen = () => ( +
+

Signing you in

+

+ In order to access this page you will need to sign in. + Please wait while we redirect you to the login page... +

+
+) + +export default BeforeSignInScreen diff --git a/lib/components/user/user-account-screen.js b/lib/components/user/user-account-screen.js index 6dd48772e..0c77fa85d 100644 --- a/lib/components/user/user-account-screen.js +++ b/lib/components/user/user-account-screen.js @@ -6,7 +6,7 @@ import { withLoginRequired } from 'use-auth0-hooks' import { routeTo } from '../../actions/ui' import { createOrUpdateUser } from '../../actions/user' import { isNewUser } from '../../util/user' -import AppNav from '../app/app-nav' +import DesktopNav from '../app/desktop-nav' import AccountSetupFinishPane from './account-setup-finish-pane' import ExistingAccountDisplay from './existing-account-display' import FavoriteLocationsPane from './favorite-locations-pane' @@ -121,7 +121,7 @@ class UserAccountScreen extends Component { return (
{/* TODO: Do mobile view. */} - +
{formContents}
diff --git a/lib/index.js b/lib/index.js index 8dc1da335..8c513a2c8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -37,7 +37,7 @@ import ViewerContainer from './components/viewers/viewer-container' import ResponsiveWebapp from './components/app/responsive-webapp' import AppMenu from './components/app/app-menu' -import AppNav from './components/app/app-nav' +import DesktopNav from './components/app/desktop-nav' import DefaultMainPanel from './components/app/default-main-panel' import { setAutoPlan, setMapCenter } from './actions/config' @@ -98,7 +98,7 @@ export { // app components, ResponsiveWebapp, AppMenu, - AppNav, + DesktopNav, DefaultMainPanel, // actions diff --git a/lib/util/auth.js b/lib/util/auth.js index dd2b5aaeb..5b6e06268 100644 --- a/lib/util/auth.js +++ b/lib/util/auth.js @@ -1,6 +1,3 @@ -import { push } from 'connected-react-router' - -import { setPathBeforeSignIn } from '../actions/user' import { PERSISTENCE_STRATEGY_OTP_MIDDLEWARE } from './constants' /** @@ -37,69 +34,3 @@ export function getAuth0Config (persistence) { } return null } - -/** - * Gets the callback methods for Auth0. - * Note: Methods inside are originally copied from https://github.com/sandrinodimattia/use-auth0-hooks#readme - * and some methods from that example may still be untouched. - * @param dispatch The dispatch method to carry out the actions. - */ -export function getAuth0Callbacks (dispatch) { - return { - /** - * When it hasn't been possible to retrieve a new access token. - * @param {Error} err - * @param {AccessTokenRequestOptions} options - */ - onAccessTokenError: (err, options) => { - console.error('Failed to retrieve access token: ', err) - }, - /** - * When signing in fails for some reason, we want to show it here. - * TODO: Implement the error URL. - * @param {Error} err - */ - onLoginError: err => { - if (err) dispatch(push(`/oops`)) - }, - /** - * Where to send the user after they have signed in. - */ - onRedirectCallback: appState => { - if (appState && appState.urlHash) { - // At this stage after login, Auth0 has already redirected to /signedin (Auth0-whitelisted) - // which shows the AfterLoginScreen. - // - // Here, we save the URL hash prior to login (contains a combination of itinerary search, stop/trip view, etc.), - // so that the AfterLoginScreen can redirect back there when logged-in user info is fetched. - // (For routing, it is easier to deal with the path without the hash sign.) - const urlHashWithoutHash = (appState.urlHash.split('#')[1] || '/') - dispatch(setPathBeforeSignIn(urlHashWithoutHash)) - } else if (appState && appState.returnTo) { - // TODO: Handle other after-login situations. - // Careful! - // - When redirecting from a login-protected (e.g. account) page while logged out, - // then returnTo is set by Auth0 to this object format: - // { - // pathname: "/" - // query: { ... } - // } - } - }, - /** - * When redirecting to the login page you'll end up in this state where the login page is still loading. - * You can render a message to show that the user is being redirected. - */ - onRedirecting: () => { - return ( -
-

Signing you in

-

- In order to access this page you will need to sign in. - Please wait while we redirect you to the login page... -

-
- ) - } - } -} From bb9f9e8926a9e638be4f1a9a33340e6c48792067 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Mon, 22 Jun 2020 15:54:16 -0400 Subject: [PATCH 3/3] refactor(DesktopNav): Use otpConfig.title for title. Address PR comments. --- lib/actions/auth.js | 7 +++-- lib/components/app/desktop-nav.js | 51 ++++++++++++++++++------------- lib/util/constants.js | 1 + 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/lib/actions/auth.js b/lib/actions/auth.js index ffbf56c92..cf5478e0f 100644 --- a/lib/actions/auth.js +++ b/lib/actions/auth.js @@ -30,7 +30,7 @@ export function showLoginError (err) { /** * This function is called by the Auth0Provider component, with the described parameter(s), * after the user signs in. - * @param {Error} err + * @param {Object} appState The state that was stored when calling useAuth().login(). */ export function processSignIn (appState) { return function (dispatch, getState) { @@ -41,7 +41,10 @@ export function processSignIn (appState) { // Here, we save the URL hash prior to login (contains a combination of itinerary search, stop/trip view, etc.), // so that the AfterLoginScreen can redirect back there when logged-in user info is fetched. // (For routing, it is easier to deal with the path without the hash sign.) - const urlHashWithoutHash = (appState.urlHash.split('#')[1] || '/') + const hashIndex = appState.urlHash.indexOf('#') + const urlHashWithoutHash = hashIndex >= 0 + ? appState.urlHash.substr(hashIndex + 1) + : '/' dispatch(setPathBeforeSignIn(urlHashWithoutHash)) } else if (appState && appState.returnTo) { // TODO: Handle other after-login situations. diff --git a/lib/components/app/desktop-nav.js b/lib/components/app/desktop-nav.js index cd123ec6d..558f166aa 100644 --- a/lib/components/app/desktop-nav.js +++ b/lib/components/app/desktop-nav.js @@ -1,20 +1,44 @@ -import PropTypes from 'prop-types' import React from 'react' import { Nav, Navbar } from 'react-bootstrap' import { connect } from 'react-redux' import NavLoginButtonAuth0 from '../user/nav-login-button-auth0.js' import { accountLinks, getAuth0Config } from '../../util/auth' +import { DEFAULT_APP_TITLE } from '../../util/constants' import AppMenu from './app-menu' /** - * The desktop navigation bar, featuring a sign-in button/menu. + * The desktop navigation bar, featuring a `branding` logo or a `title` text + * defined in config.yml, and a sign-in button/menu with account links. + * + * The `branding` and `title` parameters in config.yml are handled + * and shown in this order in the navigation bar: + * 1. If `branding` is defined, it is shown, and no title is displayed. + * 2. If `branding` is not defined but if `title` is, then `title` is shown. + * 3. If neither is defined, just show 'OpenTripPlanner' (DEFAULT_APP_TITLE). + * * TODO: merge with the mobile navigation bar. */ -const DesktopNav = ({ otpConfig, title }) => { - const { branding, persistence } = otpConfig +const DesktopNav = ({ otpConfig }) => { + const { branding, persistence, title = DEFAULT_APP_TITLE } = otpConfig const showLogin = Boolean(getAuth0Config(persistence)) + // Display branding and title in the order as described in the class summary. + let brandingOrTitle + if (branding) { + brandingOrTitle = ( +
+ ) + } else { + brandingOrTitle = ( +
{title}
+ ) + } + return ( @@ -24,17 +48,8 @@ const DesktopNav = ({ otpConfig, title }) => {
- {branding && ( -
- )} + {brandingOrTitle} - {title && ( -
{title}
- )} @@ -52,14 +67,6 @@ const DesktopNav = ({ otpConfig, title }) => { ) } -DesktopNav.propTypes = { - title: PropTypes.string -} - -DesktopNav.defaultProps = { - title: 'OpenTripPlanner' -} - // connect to the redux store const mapStateToProps = (state, ownProps) => { diff --git a/lib/util/constants.js b/lib/util/constants.js index d5591b214..3f16df29e 100644 --- a/lib/util/constants.js +++ b/lib/util/constants.js @@ -1,5 +1,6 @@ export const AUTH0_AUDIENCE = 'https://otp-middleware' export const AUTH0_SCOPE = '' +export const DEFAULT_APP_TITLE = 'OpenTripPlanner' export const PERSISTENCE_STRATEGY_OTP_MIDDLEWARE = 'otp_middleware' // Gets the root URL, e.g. https://otp-instance.example.com:8080, computed once for all.