frontend/app/index.jsx (251 lines of code) (raw):

import React, { useMemo } from "react"; import { render } from "react-dom"; import { BrowserRouter, Route, Switch } from "react-router-dom"; import { CssBaseline } from "@material-ui/core"; import ProjectsListComponent from "./ProjectsListComponent"; import axios from "axios"; import ProjectDeliverablesComponent from "./ProjectDeliverablesComponent"; import CreateDeliverable from "./CreateDeliverable"; import { Header, AppSwitcher, handleUnauthorized, PlutoThemeProvider, UserContextProvider, SystemNotification, Header, JwtDataShape, OAuthContextData, OAuthContextProvider, SystemNotification, verifyExistingLogin, UserContextProvider, } from "@guardian/pluto-headers"; import NotLoggedIn from "./NotLoggedIn"; import GuardianMaster from "./Master/GuardianMaster"; import YoutubeMaster from "./Master/YoutubeMaster"; import MainstreamMaster from "./Master/MainstreamMaster"; import DailymotionMaster from "./Master/DailymotionMaster"; import { Helmet } from "react-helmet"; import AssetSearchComponent from "./AssetSearchComponent"; import BundleRedirect from "./BundleRedirect"; import InvalidDeliverablesComponent from "./InvalidDeliverablesComponent"; import DeliverablesDashFront from "./DeliverablesDash/DeliverablesDashFront"; import DeliverableItem from "./DeliverableItem/DeliverableItem"; import DeliverablesFront from "./DeliverablesFront/DeliverablesFront"; require("./app.css"); axios.interceptors.request.use(function (config) { const token = window.localStorage.getItem("pluto:access-token"); if (token) config.headers.Authorization = `Bearer ${token}`; // Only apply deployment root when url begins with /api if (config.url.startsWith("/api")) { //deploymentRootPath is set in the index template from server-side configuration and referenced here config.baseURL = deploymentRootPath; } return config; }); function parseBool(str) { return /^true$/i.test(str); } class App extends React.Component { constructor(props) { super(props); this.state = { loading: true, isLoggedIn: false, tokenExpired: false, plutoConfig: {}, userProfile: undefined, isAdmin: false, }; this.handleUnauthorizedFailed = this.handleUnauthorizedFailed.bind(this); this.onLoginValid = this.onLoginValid.bind(this); this.oAuthConfigLoaded = this.oAuthConfigLoaded.bind(this); axios.interceptors.response.use( (response) => response, async (error) => { handleUnauthorized( this.state.plutoConfig, error, this.handleUnauthorizedFailed ); return Promise.reject(error); } ); } handleUnauthorizedFailed() { this.setState({ isLoggedIn: false, tokenExpired: true, }); } async onLoginValid(valid, loginData) { this.setState( { isLoggedIn: valid, userProfile: loginData, }, () => { this.setState({ loading: false }); } ); } componentDidMount() { setTimeout(() => { if (!this.state.isLoggedIn) { console.log("Not logged in, redirecting to pluto-start."); window.location.assign( "/refreshLogin?returnTo=" + window.location.pathname ); } }, 3000); } haveToken() { return window.localStorage.getItem("pluto:access-token"); } isUserAdmin(profile, adminClaim) { if (profile.roles) { if (profile.roles.includes(adminClaim)) { return true; } } if (profile[adminClaim]) { if (parseBool(profile[adminClaim])) { return true; } } return false; } oAuthConfigLoaded(oAuthConfig) { //If we already have a user token at mount, verify it and update our internal state. //If we do not, 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) => { const adminValue = this.isUserAdmin( profile, oAuthConfig.adminClaimName ); this.setState({ userProfile: profile, isLoggedIn: true, isAdmin: adminValue, }); }) .catch((err) => { console.error("Could not verify existing user profile: ", err); }); } } render() { if (!this.state.loading && !this.state.isLoggedIn) { console.log("not logged in, redirecting to route"); return <NotLoggedIn tokenExpired={this.state.tokenExpired} timeOut={5} />; } return ( <PlutoThemeProvider> <CssBaseline /> <Helmet> <title>Pluto – Deliverables</title> </Helmet> <OAuthContextProvider onLoaded={this.oAuthConfigLoaded}> <UserContextProvider value={{ profile: this.state.userProfile, updateProfile: (newValue) => this.setState({ userProfile: newValue }), }} > <> <Header /> <AppSwitcher onLoginValid={this.onLoginValid} /> </> <div className="main-body"> <Switch> <Route path="/item/:assetId" component={DeliverableItem} /> <Route path="/project/:projectid/new" component={CreateDeliverable} /> <Route path="/project/new" component={CreateDeliverable} /> <Route path="/project/:projectid/asset/:assetid/atom" render={(props) => ( <GuardianMaster {...props} isAdmin={this.state.isAdmin} /> )} /> <Route path="/project/:projectid/asset/:assetid/youtube" render={(props) => ( <YoutubeMaster {...props} isAdmin={this.state.isAdmin} /> )} /> <Route path="/project/:projectid/asset/:assetid/mainstream" render={(props) => <MainstreamMaster {...props} />} /> <Route path="/project/:projectid/asset/:assetid/dailymotion" render={(props) => <DailymotionMaster {...props} />} /> <Route path="/project/:projectid" component={ProjectDeliverablesComponent} /> <Route path="/invalid/date/:date" component={(props) => ( <InvalidDeliverablesComponent {...props} key={window.location.pathname} /> )} /> <Route path="/invalid/type/:kind" component={(props) => ( <InvalidDeliverablesComponent {...props} key={window.location.pathname} /> )} /> <Route path="/invalid/status/:status" component={(props) => ( <InvalidDeliverablesComponent {...props} key={window.location.pathname} /> )} /> <Route path="/invalid" component={(props) => ( <InvalidDeliverablesComponent {...props} key={window.location.pathname} /> )} /> <Route path="/bundle/:bundleId" component={BundleRedirect} /> <Route path="/search" component={AssetSearchComponent} /> <Route path="/dash" component={DeliverablesDashFront} /> <Route path="/projects" component={ProjectsListComponent} /> <Route exact path="/" component={DeliverablesFront} /> </Switch> </div> <SystemNotification /> </UserContextProvider> </OAuthContextProvider> </PlutoThemeProvider> ); } } render( <BrowserRouter basename={deploymentRootPath}> <App /> </BrowserRouter>, document.getElementById("app") );