Source

components/JcuApp.tsx

import * as React from 'react'
import {Component} from 'react'

import {Grommet} from "grommet"
import {HashRouter as Router} from 'react-router-dom'

import jcuTheme from '../themes/jcu'
import sithTheme from '../themes/sith'

import {ResponsiveLayoutProvider, JcuNotificationLayer, ErrorBoundary} from './layout'
import {NavItem} from './navigation'
import {ApiContextProvider, ConfigContextProvider, AxaOidcProvider, ConfigContext} from '../services'
import {JcuInnerApp} from "./JcuInnerApp"
import {FullAppErrorPage, LogoutPage} from "./pages";

/**
 * Enum for different login modes for the JcuApp
 * @enum {number}
 * @memberOf JcuApp
 * @property NONE No login required or offered
 * @property OPTIONAL No login required, but login can be required for access to restricted content
 * @property FORCED Login is required to use the app. Automatically redirects users to Forgerock when the app loads.
 */
export enum LoginMode {
    NONE,
    OPTIONAL,
    REQUIRED,
    FORCED
}

/**
 * Different "shapes" JcuApp content can be, used to control the size and behaviour
 * of the wrapping elements.
 *
 * Later we will add a shape for apps that fill the screen without scrolling, like
 * a slippy map.
 *
 * @enum {number}
 * @memberOf JcuApp
 * @property COLUMN Assume that the app's content is in a vertically-scrolling column constrained
 *      to some reasonable width, where "reasonable" is defined by the theme (usually around 1000 pixels)
 * @property WIDECOLUMN App content can fill the full width of the browser window, no matter how
 *      silly that gets
 */
export enum Shape {
    COLUMN,
    WIDECOLUMN
}

type JcuAppProps = {
    title: string
    basePath: string
    login: LoginMode
    navItems?: NavItem[]
    popup?: boolean
    theme?: string
    logoutPage?: React.ReactElement
    openPage?: React.ReactElement
    closePage?: React.ReactElement
    safePaths?: string[]
    shape?: Shape,
    legacyHeader?: boolean
}

/**
 * @param {string} title Title to appear in heading of application
 * @param {string} basePath Base path of the application (e.g. App-specific hosting URL)
 * @param {LoginMode} login Enum dictating the login type (e.g FORCED login)
 * @param {NavItem[]} [navItems] An array of NavItems to be added to the app router and navigation bar
 * @param {boolean} [popup] Boolean prop to set whether the login mode should be popup or redirect
 * @param {string} [theme] Theme to be used by application, specified by a predefined name
 * @param {React.ReactElement} [logoutPage] React element to load upon successful user logout
 * @param {React.ReactElement} [openPage] React element to load before the config provided application open date
 * @param {React.ReactElement} [closePage] React element to load after the config provided application close date
 * @param {string[]} [safePaths] List of internal app routes that can be accessed without authentication (e.g. for FORCED login apps)
 * @param {Shape} [shape] The layout "shape" of this app. Defaults to `COLUMN`, a vertically scrolling column
 *      with the width constrained to some reasonable limit.
 * @component
 * @category Core
 */
export class JcuApp extends Component<JcuAppProps> {
    static defaultProps = {
        login: LoginMode.NONE,
        popup: false,
        theme: 'jcu',
        safePaths: [],
        shape: Shape.COLUMN,
        legacyHeader: false
    }

    constructor(props: JcuAppProps) {
        super(props)

    }

    render = () => {
        if (process.env.NODE_ENV !== 'production') {
            // non-production warning space
            if (this.props.legacyHeader) {
                console.warn(
                    "The legacyHeader flag is deprecated. " +
                    "It should only be used to maintain legacy layout functionality for applications that are unable to be updated for functional reasons." +
                    "It should not be used to maintain a legacy layout for aesthetic purposes."
                )
            }
        }

        if (window.location.pathname === this.props.basePath + '/loggedout') {
            return (
                //@ts-ignore
                <Grommet theme={jcuTheme} full>
                    {this.props.logoutPage || <LogoutPage basePath={this.props.basePath || '/'}/>}
                </Grommet>
            )
        } else {
            return (
                <ErrorBoundary errorPage={<FullAppErrorPage/>}>
                    <ConfigContextProvider basePath={this.props.basePath}>
                        <ConfigContext.Consumer>
                            {(config) => {
                                // get the theme selection from config
                                let theme: any = jcuTheme // jcuTheme is the default
                                if (config && config.appearance && config.appearance.theme === 'sith') {
                                    theme = sithTheme
                                }
                                // @ts-ignore
                                return (
                                    <Grommet theme={theme} full>
                                        <Router>
                                            <AxaOidcProvider>
                                                <ApiContextProvider>
                                                    <ResponsiveLayoutProvider>
                                                        <JcuNotificationLayer/>
                                                        <JcuInnerApp title={this.props.title}
                                                                     navItems={this.props.navItems}
                                                                     login={this.props.login}
                                                                     safePaths={this.props.safePaths}
                                                                     shape={this.props.shape}
                                                                     legacyHeader={this.props.legacyHeader}
                                                                     openPage={this.props.openPage}
                                                                     closePage={this.props.closePage}
                                                        >
                                                            {this.props.children}
                                                        </JcuInnerApp>
                                                    </ResponsiveLayoutProvider>
                                                </ApiContextProvider>
                                            </AxaOidcProvider>
                                        </Router>
                                    </Grommet>
                                )
                            }}
                        </ConfigContext.Consumer>
                    </ConfigContextProvider>
                </ErrorBoundary>
            )
        }
    }
}