frontend/app/index.tsx (106 lines of code) (raw):

import React from "react"; import { render } from "react-dom"; import { BrowserRouter, Route, Switch } from "react-router-dom"; import { ThemeProvider, createTheme, Theme, CssBaseline, } from "@material-ui/core"; import { AppSwitcher, Header, JwtDataShape, OAuthContextData, OAuthContextProvider, SystemNotification, UserContextProvider, verifyExistingLogin, } from "@guardian/pluto-headers"; import MainPage from "./mainpage"; import axios from "axios"; import BranchesComponent from "./BranchesComponent"; interface RootProps {} interface RootState { userProfile?: JwtDataShape; } axios.interceptors.request.use((config) => { const token = window.localStorage.getItem("pluto:access-token"); if (token) config.headers.Authorization = `Bearer ${token}`; console.log(`interceptor: token is ${token}, url is ${config.url}`); // this is set in the index.scala.html template file and gives us the value of deployment-root from the server config // Only apply deployment root when url begins with /api if (config.url && config.url.startsWith("/api")) { config.baseURL = deploymentRootPath; } return config; }); class App extends React.Component<RootProps, RootState> { theme: Theme; constructor(props: RootProps) { super(props); this.theme = createTheme({ typography: { fontFamily: [ "sans-serif", '"Helvetica Neue"', "Helvetica", "Arial", "sans-serif", ].join(","), }, palette: { type: "dark", }, }); this.state = { userProfile: undefined, }; this.oAuthConfigLoaded = this.oAuthConfigLoaded.bind(this); } haveToken() { return window.localStorage.getItem("pluto:access-token"); } oAuthConfigLoaded(oAuthConfig: OAuthContextData) { //if we already have a user token at mount, verify it and update our internal state //if we don't, ignore for the time being; it will be set dynamically when the login occurs console.log("loaded oauthconfig: ", oAuthConfig); if (this.haveToken()) { verifyExistingLogin(oAuthConfig) .then((profile) => this.setState({ userProfile: profile })) .catch((err) => { console.error("Could not verify existing user profile: ", err); }); } } render() { return ( <OAuthContextProvider onLoaded={this.oAuthConfigLoaded}> <UserContextProvider value={{ profile: this.state.userProfile, updateProfile: (newValue) => this.setState({ userProfile: newValue }), }} > <ThemeProvider theme={this.theme}> <CssBaseline /> <Header /> <AppSwitcher /> <Switch> <Route path="/:deployment_name/branches" component={BranchesComponent} /> <Route exact path="/" component={MainPage} /> </Switch> <SystemNotification /> </ThemeProvider> </UserContextProvider> </OAuthContextProvider> ); } } //this is a global which is imported from the server-rendered html template declare const deploymentRootPath: string; render( <BrowserRouter basename={deploymentRootPath}> <App /> </BrowserRouter>, document.getElementById("app") );