diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2022-10-27 17:15:55 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-27 17:15:55 +0200 |
| commit | c4cfb6f6e0507f335fd88935857f20e88c34abd0 (patch) | |
| tree | 8dad74b6a213bb294dbcea33ebab34a3be193e77 /opendc-web/opendc-web-ui/src | |
| parent | fa7fdbb0126ea465130961dc37c4ef2d6feb36e9 (diff) | |
| parent | 5a3d5148a9d52487f102e52bd079006c916075c9 (diff) | |
merge: Update to Next.js 13 and React 18
This pull request updates the web interface to make use of Next.js 13 and React 18.
## Implementation Notes :hammer_and_pick:
* Drop dependency on FontAwesome
* Update to Next 13 and React 18
* Drop dependency on Roboto font
* Make root redirect non-permanent
* Do not optimize images for export
* Update to Node 18 for the build process
* Ensure consistency of build tasks
* Update README.md of web UI
* Default to anonymous auth domain
* Disable configuration of basePath
## External Dependencies :four_leaf_clover:
* Next.js 13
* React 18
* PatternFly 4
* Node 18
## Breaking API Changes :warning:
* The base path of the web UI cannot be configured anymore via the Quarkus extension.
The previous implementation relied on Next.js internals and this functionality cannot be
provided without resorting to hacks. Since this functionality was not actually used, we have
removed it for now.
Diffstat (limited to 'opendc-web/opendc-web-ui/src')
11 files changed, 46 insertions, 133 deletions
diff --git a/opendc-web/opendc-web-ui/src/auth.js b/opendc-web/opendc-web-ui/src/auth.js index 3d6cf87c..8c88f526 100644 --- a/opendc-web/opendc-web-ui/src/auth.js +++ b/opendc-web/opendc-web-ui/src/auth.js @@ -27,10 +27,11 @@ import { auth } from './config' /** * Helper function to provide the authentication context in case Auth0 is not - * configured. + * configured and the user is anonymous. */ -function useAuthDev() { +function useAnonymousAuth() { return { + isAnonymous: true, isAuthenticated: false, isLoading: false, logout: () => {}, @@ -39,15 +40,17 @@ function useAuthDev() { } /** - * Obtain the authentication context. + * Determine whether the auth domain is anonymous. */ -export const useAuth = auth.domain ? useAuth0 : useAuthDev +function isAnonymousDomain(config) { + return !config.domain || config.domain === '%%NEXT_PUBLIC_AUTH0_DOMAIN%%' +} /** * Force the user to be authenticated or redirect to the homepage. */ -export function useRequireAuth() { - const auth = useAuth() +function useRequireAuth0() { + const auth = useAuth0() const { loginWithRedirect, isLoading, isAuthenticated } = auth useEffect(() => { @@ -55,21 +58,31 @@ export function useRequireAuth() { loginWithRedirect() } }, [loginWithRedirect, isLoading, isAuthenticated]) - - return auth } /** + * Obtain the authentication context. + */ +export const useAuth = isAnonymousDomain(auth) ? useAnonymousAuth : useAuth0 + +/** + * Force the user to be authenticated or redirect to the homepage. + */ +export const useRequireAuth = isAnonymousDomain(auth) ? () => {} : useRequireAuth0 + +/** * AuthProvider which provides an authentication context. */ export function AuthProvider({ children }) { - if (auth.domain) { + const authConfig = auth + + if (!isAnonymousDomain(authConfig)) { return ( <Auth0Provider - domain={auth.domain} - clientId={auth.clientId} - redirectUri={auth.redirectUri} - audience={auth.audience} + domain={authConfig.domain} + clientId={authConfig.clientId} + redirectUri={authConfig.redirectUri} + audience={authConfig.audience} > {children} </Auth0Provider> diff --git a/opendc-web/opendc-web-ui/src/components/AppHeader.js b/opendc-web/opendc-web-ui/src/components/AppHeader.js index f9ef00aa..c046f9c7 100644 --- a/opendc-web/opendc-web-ui/src/components/AppHeader.js +++ b/opendc-web/opendc-web-ui/src/components/AppHeader.js @@ -43,14 +43,7 @@ export default function AppHeader({ nav }) { return ( <Masthead id="app-header" className={styles.header}> <MastheadMain> - <MastheadBrand - className={styles.logo} - component={(props) => ( - <Link href="/projects"> - <a {...props} /> - </Link> - )} - > + <MastheadBrand className={styles.logo} component={(props) => <Link href="/projects" {...props} />}> <Image src="/img/logo.svg" alt="OpenDC logo" width={25} height={25} /> <span>OpenDC</span> </MastheadBrand> diff --git a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js index 64218a0a..5fd2a1da 100644 --- a/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js +++ b/opendc-web/opendc-web-ui/src/components/portfolios/ScenarioTable.js @@ -59,7 +59,7 @@ function ScenarioTable({ portfolio, status }) { <Td dataLabel="Topology"> {scenario.topology ? ( <Link href={`/projects/${projectId}/topologies/${scenario.topology.number}`}> - <a>{scenario.topology.name}</a> + scenario.topology.name </Link> ) : ( 'Unknown Topology' diff --git a/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js b/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js index 70f02812..a26fed46 100644 --- a/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js +++ b/opendc-web/opendc-web-ui/src/components/projects/ProjectCollection.js @@ -1,3 +1,4 @@ +import Link from 'next/link' import { Gallery, Bullseye, @@ -25,7 +26,6 @@ import React, { useReducer, useMemo } from 'react' import { Project, Status } from '../../shapes' import { parseAndFormatDateTime } from '../../util/date-time' import { AUTH_DESCRIPTION_MAP, AUTH_ICON_MAP, AUTH_NAME_MAP } from '../../util/authorizations' -import NavItemLink from '../util/NavItemLink' import TableEmptyState from '../util/TableEmptyState' function ProjectCard({ project, onDelete }) { @@ -70,7 +70,7 @@ function ProjectCard({ project, onDelete }) { /> </CardActions> </CardHeader> - <CardTitle component={NavItemLink} className="pf-u-pb-0" href={`/projects/${id}`}> + <CardTitle component={Link} className="pf-u-pb-0" href={`/projects/${id}`}> {name} </CardTitle> <CardBody isFilled={false}> diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js index 469fd515..e7dc57c3 100644 --- a/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js +++ b/opendc-web/opendc-web-ui/src/components/topologies/map/controls/Toolbar.js @@ -2,9 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import { control, toolBar } from './Toolbar.module.scss' import { Button } from '@patternfly/react-core' -import { SearchPlusIcon, SearchMinusIcon } from '@patternfly/react-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCamera } from '@fortawesome/free-solid-svg-icons' +import { SearchPlusIcon, SearchMinusIcon, CameraIcon } from '@patternfly/react-icons' function Toolbar({ onZoom, onExport }) { return ( @@ -21,7 +19,7 @@ function Toolbar({ onZoom, onExport }) { onClick={() => onExport()} className={control} > - <FontAwesomeIcon icon={faCamera} /> + <CameraIcon /> </Button> </div> ) diff --git a/opendc-web/opendc-web-ui/src/components/util/BreadcrumbLink.js b/opendc-web/opendc-web-ui/src/components/util/BreadcrumbLink.js deleted file mode 100644 index c6ab214a..00000000 --- a/opendc-web/opendc-web-ui/src/components/util/BreadcrumbLink.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import PropTypes from 'prop-types' -import Link from 'next/link' - -const BreadcrumbLink = ({ children, href, ...props }) => ( - <Link href={href}> - <a {...props}>{children}</a> - </Link> -) - -BreadcrumbLink.propTypes = { - children: PropTypes.node, - href: PropTypes.string.isRequired, -} - -export default BreadcrumbLink diff --git a/opendc-web/opendc-web-ui/src/components/util/NavItemLink.js b/opendc-web/opendc-web-ui/src/components/util/NavItemLink.js deleted file mode 100644 index 83301361..00000000 --- a/opendc-web/opendc-web-ui/src/components/util/NavItemLink.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import Link from 'next/link' -import PropTypes from 'prop-types' - -function NavItemLink({ children, href, ...props }) { - return ( - <Link href={href}> - <a {...props}>{children}</a> - </Link> - ) -} - -NavItemLink.propTypes = { - children: PropTypes.node, - href: PropTypes.string.isRequired, -} - -export default NavItemLink diff --git a/opendc-web/opendc-web-ui/src/pages/_document.js b/opendc-web/opendc-web-ui/src/pages/_document.js index 011bf4da..9f84b2ab 100644 --- a/opendc-web/opendc-web-ui/src/pages/_document.js +++ b/opendc-web/opendc-web-ui/src/pages/_document.js @@ -63,12 +63,6 @@ class OpenDCDocument extends Document { content="OpenDC provides collaborative online datacenter modeling, diverse and effective datacenter simulation, and exploratory datacenter performance feedback." /> <meta property="og:locale" content="en_US" /> - - {/* CDN Dependencies */} - <link - href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" - rel="stylesheet" - /> </Head> <body> <Main /> diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js index e4e2156b..52938bcd 100644 --- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js +++ b/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js @@ -25,6 +25,7 @@ import ProjectOverview from '../../../components/projects/ProjectOverview' import { useProject } from '../../../data/project' import { AppPage } from '../../../components/AppPage' import Head from 'next/head' +import Link from 'next/link' import { Breadcrumb, BreadcrumbItem, @@ -34,7 +35,6 @@ import { Text, TextContent, } from '@patternfly/react-core' -import BreadcrumbLink from '../../../components/util/BreadcrumbLink' function Project() { const router = useRouter() @@ -44,10 +44,10 @@ function Project() { const breadcrumb = ( <Breadcrumb> - <BreadcrumbItem to="/projects" component={BreadcrumbLink}> + <BreadcrumbItem to="/projects" component={Link}> Projects </BreadcrumbItem> - <BreadcrumbItem to={`/projects/${projectId}`} component={BreadcrumbLink} isActive> + <BreadcrumbItem to={`/projects/${projectId}`} component={Link} isActive> Project details </BreadcrumbItem> </Breadcrumb> @@ -56,7 +56,7 @@ function Project() { return ( <AppPage breadcrumb={breadcrumb}> <Head> - <title>{project?.name ?? 'Project'} - OpenDC</title> + <title>{`${project?.name ?? 'Project'} - OpenDC`}</title> </Head> <PageSection variant={PageSectionVariants.light}> <TextContent> diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js index 615529e7..5d1e041b 100644 --- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js +++ b/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js @@ -23,6 +23,7 @@ import dynamic from 'next/dynamic' import { useRouter } from 'next/router' import Head from 'next/head' +import Link from 'next/link' import React, { useRef } from 'react' import { Breadcrumb, @@ -40,7 +41,6 @@ import { import { AppPage } from '../../../../components/AppPage' import ContextSelectionSection from '../../../../components/context/ContextSelectionSection' import PortfolioSelector from '../../../../components/context/PortfolioSelector' -import BreadcrumbLink from '../../../../components/util/BreadcrumbLink' import PortfolioOverview from '../../../../components/portfolios/PortfolioOverview' import { usePortfolio } from '../../../../data/project' @@ -61,17 +61,13 @@ function Portfolio() { const breadcrumb = ( <Breadcrumb> - <BreadcrumbItem to="/projects" component={BreadcrumbLink}> + <BreadcrumbItem to="/projects" component={Link}> Projects </BreadcrumbItem> - <BreadcrumbItem to={`/projects/${projectId}`} component={BreadcrumbLink}> + <BreadcrumbItem to={`/projects/${projectId}`} component={Link}> Project details </BreadcrumbItem> - <BreadcrumbItem - to={`/projects/${projectId}/portfolios/${portfolioNumber}`} - component={BreadcrumbLink} - isActive - > + <BreadcrumbItem to={`/projects/${projectId}/portfolios/${portfolioNumber}`} component={Link} isActive> Portfolio </BreadcrumbItem> </Breadcrumb> diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js index d3892710..48359365 100644 --- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js +++ b/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js @@ -22,12 +22,13 @@ import dynamic from 'next/dynamic' import { useRouter } from 'next/router' +import Head from 'next/head' +import Link from 'next/link' import ContextSelectionSection from '../../../../components/context/ContextSelectionSection' import TopologySelector from '../../../../components/context/TopologySelector' import TopologyOverview from '../../../../components/topologies/TopologyOverview' import { useDispatch } from 'react-redux' import React, { useEffect, useState } from 'react' -import Head from 'next/head' import { AppPage } from '../../../../components/AppPage' import { Breadcrumb, @@ -42,7 +43,6 @@ import { Text, TextContent, } from '@patternfly/react-core' -import BreadcrumbLink from '../../../../components/util/BreadcrumbLink' import { useTopology } from '../../../../data/topology' import { goToRoom } from '../../../../redux/actions/interaction-level' import { openTopology } from '../../../../redux/actions/topology' @@ -58,7 +58,6 @@ function Topology() { const topologyNumber = +router.query['topology'] const { data: topology } = useTopology(projectId, topologyNumber) - const project = topology?.project const dispatch = useDispatch() useEffect(() => { @@ -71,17 +70,13 @@ function Topology() { const breadcrumb = ( <Breadcrumb> - <BreadcrumbItem to="/projects" component={BreadcrumbLink}> + <BreadcrumbItem to="/projects" component={Link}> Projects </BreadcrumbItem> - <BreadcrumbItem to={`/projects/${projectId}`} component={BreadcrumbLink}> + <BreadcrumbItem to={`/projects/${projectId}`} component={Link}> Project details </BreadcrumbItem> - <BreadcrumbItem - to={`/projects/${projectId}/topologies/${topologyNumber}`} - component={BreadcrumbLink} - isActive - > + <BreadcrumbItem to={`/projects/${projectId}/topologies/${topologyNumber}`} component={Link} isActive> Topology </BreadcrumbItem> </Breadcrumb> @@ -96,7 +91,7 @@ function Topology() { return ( <AppPage breadcrumb={breadcrumb} contextSelectors={contextSelectors}> <Head> - <title>{project?.name ?? 'Topologies'} - OpenDC</title> + <title>{`${topology?.name ?? 'Topologies'} - OpenDC`}</title> </Head> <PageSection variant={PageSectionVariants.light}> <TextContent> |
