diff --git a/Dockerfile b/Dockerfile index 70ac83c4..51c9420a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,13 @@ FROM node:12.13.1-alpine +ARG ASSET_PREFIX +ENV ASSET_PREFIX $ASSET_PREFIX + ENV APP_UID=9999 ENV APP_GID=9999 RUN apk --no-cache add shadow -RUN groupmod -g $APP_GID node +RUN groupmod -g $APP_GID node RUN usermod -u $APP_UID -g $APP_GID node RUN mkdir -p /usr/src diff --git a/components/Link.tsx b/components/Link.tsx index 50aac79f..1b2106cc 100644 --- a/components/Link.tsx +++ b/components/Link.tsx @@ -1,7 +1,9 @@ import styled from '@emotion/styled'; import { css } from '@emotion/core'; +import Link from 'next/link'; import defaultTheme from './theme'; +import getInternalLink from '../global/utils/getInternalLink'; const StyledLink = styled('a')` ${({ theme }: { theme: typeof defaultTheme }) => css` @@ -30,10 +32,16 @@ export const StyledLinkAsButton = styled(StyledLink)` position: relative; text-decoration: none; &:hover { - background-color: ${theme.colors.accent_dark}; color: ${theme.colors.white}; + background-color: ${theme.colors.accent_dark}; } `} `; +export const InternalLink = ({ children, path }: { children: React.ReactNode; path: string }) => ( + + {children} + +); + export default StyledLink; diff --git a/components/NavBar.tsx b/components/NavBar.tsx index d1fbd163..585e66f8 100644 --- a/components/NavBar.tsx +++ b/components/NavBar.tsx @@ -5,7 +5,8 @@ import UserDropdown from './UserDropdown'; import defaultTheme from './theme'; import { OvertureLogo } from './theme/icons'; import useAuthContext from '../global/hooks/useAuthContext'; -import { StyledLinkAsButton } from './Link'; +import { StyledLinkAsButton, InternalLink as Link } from './Link'; +import getInternalLink from '../global/utils/getInternalLink'; const NavBar: React.ComponentType = ({ labName = 'Data Management System', labIcon }) => { const { token } = useAuthContext(); @@ -32,28 +33,29 @@ const NavBar: React.ComponentType = ({ labName = 'Data Management System', cursor: pointer; `} > - css` - display: flex; - align-items: center; - text-decoration: none; - ${theme.typography.heading}; - color: ${theme.colors.accent_dark}; - `} - > - {labIcon || } - {/* set to default until labname config is implemented */} - {labName && ( - - {labName} - - )} - + + css` + display: flex; + align-items: center; + text-decoration: none; + ${theme.typography.heading}; + color: ${theme.colors.accent_dark}; + `} + > + {labIcon || } + {/* set to default until labname config is implemented */} + {labName && ( + + {labName} + + )} + +
= ({ labName = 'Data Management System', border-right: 2px solid ${theme.colors.white}; `} > - css` - display: flex; - flex: 1; - height: 100%; - justify-content: center; - align-items: center; - text-decoration: none; - color: ${theme.colors.accent2_dark}; - `} - href="/repository" - > - Data Explorer - + + css` + display: flex; + flex: 1; + height: 100%; + justify-content: center; + align-items: center; + text-decoration: none; + color: ${theme.colors.accent2_dark}; + cursor: pointer; + `} + > + Data Explorer + +
{token ? (
= ({ labName = 'Data Management System', justify-content: center; `} > - css` - width: 70px; - ${theme.typography.button}; - line-height: 20px; - `} - href="/login" - > - Log in - + + css` + width: 70px; + ${theme.typography.button}; + line-height: 20px; + `} + > + Log in + +
)} diff --git a/components/UserDropdown.tsx b/components/UserDropdown.tsx index 9acf44f5..238bcca4 100644 --- a/components/UserDropdown.tsx +++ b/components/UserDropdown.tsx @@ -7,6 +7,8 @@ import defaultTheme from './theme'; import { Avatar, ChevronDown } from './theme/icons'; import useAuthContext from '../global/hooks/useAuthContext'; import { UserWithId } from '../global/types'; +import getInternalLink from '../global/utils/getInternalLink'; +import { InternalLink as Link } from './Link'; const getDisplayName = (user?: UserWithId) => { const greeting = 'Hello'; @@ -153,7 +155,11 @@ const UserDropdown = () => { `} >
  • - Profile & Token + + + Profile & Token + +
  • logout()}>Logout diff --git a/components/pages/repository/getConfigError.tsx b/components/pages/repository/getConfigError.tsx index 862ee431..8ac2d03c 100644 --- a/components/pages/repository/getConfigError.tsx +++ b/components/pages/repository/getConfigError.tsx @@ -9,11 +9,9 @@ import { getConfig } from '../../../global/config'; import { Project } from './'; const ArrangerAdminUILink = () => { - const { NEXT_PUBLIC_ARRANGER_API } = getConfig(); - const splitApi: string[] = NEXT_PUBLIC_ARRANGER_API.split('//'); - const adminUiUrl: string = [splitApi[0], '//ui.', splitApi[1]].join(''); + const { NEXT_PUBLIC_ARRANGER_ADMIN_UI } = getConfig(); return ( - + Arranger Admin UI ); diff --git a/global/config.ts b/global/config.ts index 784b0b36..fe40aa17 100644 --- a/global/config.ts +++ b/global/config.ts @@ -13,6 +13,8 @@ export const getConfig = () => { NEXT_PUBLIC_ARRANGER_GRAPHQL_FIELD: publicConfig.NEXT_PUBLIC_ARRANGER_GRAPHQL_FIELD || '', NEXT_PUBLIC_ARRANGER_INDEX: publicConfig.NEXT_PUBLIC_ARRANGER_INDEX || '', NEXT_PUBLIC_ARRANGER_API: publicConfig.NEXT_PUBLIC_ARRANGER_API || 'http://localhost:5050', + NEXT_PUBLIC_ARRANGER_ADMIN_UI: publicConfig.NEXT_PUBLIC_ARRANGER_ADMIN_UI, + NEXT_PUBLIC_BASE_PATH: publicConfig.NEXT_PUBLIC_BASE_PATH || '', } as { NEXT_PUBLIC_EGO_API_ROOT: string; NEXT_PUBLIC_EGO_CLIENT_ID: string; @@ -21,5 +23,7 @@ export const getConfig = () => { NEXT_PUBLIC_ARRANGER_GRAPHQL_FIELD: string; NEXT_PUBLIC_ARRANGER_INDEX: string; NEXT_PUBLIC_ARRANGER_API: string; + NEXT_PUBLIC_ARRANGER_ADMIN_UI: string; + NEXT_PUBLIC_BASE_PATH: string; }; }; diff --git a/global/hooks/useAuthContext.tsx b/global/hooks/useAuthContext.tsx index e3addeca..a9b58130 100644 --- a/global/hooks/useAuthContext.tsx +++ b/global/hooks/useAuthContext.tsx @@ -4,6 +4,7 @@ import { useRouter } from 'next/router'; import { EGO_JWT_KEY } from '../utils/constants'; import { decodeToken, extractUser, isValidJwt } from '../utils/egoTokenUtils'; import { UserWithId } from '../../global/types'; +import getInternalLink from '../utils/getInternalLink'; type T_AuthContext = { token?: string; @@ -38,7 +39,7 @@ export const AuthProvider = ({ const logout = () => { removeToken(); - router.push('/repository'); + router.push(getInternalLink({ path: 'repository' })); }; if (token !== egoJwt) { diff --git a/global/utils/getInternalLink.ts b/global/utils/getInternalLink.ts new file mode 100644 index 00000000..5d791035 --- /dev/null +++ b/global/utils/getInternalLink.ts @@ -0,0 +1,8 @@ +import urlJoin from 'url-join'; + +import { getConfig } from '../config'; + +export default ({ path }: { path: string }) => { + const { NEXT_PUBLIC_BASE_PATH } = getConfig(); + return urlJoin(NEXT_PUBLIC_BASE_PATH, path); +}; diff --git a/next.config.js b/next.config.js index ee6f3f7f..98441130 100644 --- a/next.config.js +++ b/next.config.js @@ -9,5 +9,10 @@ module.exports = withCSS({ NEXT_PUBLIC_ARRANGER_GRAPHQL_FIELD: process.env.NEXT_PUBLIC_ARRANGER_GRAPHQL_FIELD, NEXT_PUBLIC_ARRANGER_INDEX: process.env.NEXT_PUBLIC_ARRANGER_INDEX, NEXT_PUBLIC_ARRANGER_API: process.env.NEXT_PUBLIC_ARRANGER_API_URL, + NEXT_PUBLIC_ARRANGER_ADMIN_UI: process.env.NEXT_PUBLIC_ARRANGER_ADMIN_UI_URL, + // using ASSET_PREFIX for the public runtime BASE_PATH because basePath in the top level config was not working + // with the dms reverse proxy setup + NEXT_PUBLIC_BASE_PATH: process.env.ASSET_PREFIX, }, + assetPrefix: process.env.ASSET_PREFIX || '', }); diff --git a/pages/_app.tsx b/pages/_app.tsx index 0ebe15a2..7f859933 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -5,6 +5,7 @@ import { EGO_JWT_KEY } from '../global/utils/constants'; import { PageWithConfig } from '../global/utils/pages/types'; import { useEffect, useState } from 'react'; import Router from 'next/router'; +import getInternalLink from '../global/utils/getInternalLink'; const DMSApp = ({ Component, @@ -18,7 +19,7 @@ const DMSApp = ({ const egoJwt = localStorage.getItem(EGO_JWT_KEY) || undefined; setInitialToken(egoJwt); if (!Component.isPublic && !egoJwt) { - Router.push('/login'); + Router.push(getInternalLink({ path: 'login' })); } }); diff --git a/pages/logged-in.tsx b/pages/logged-in.tsx index 04b1f864..27b6187d 100644 --- a/pages/logged-in.tsx +++ b/pages/logged-in.tsx @@ -8,6 +8,7 @@ import { EGO_JWT_KEY } from '../global/utils/constants'; import Router from 'next/router'; import { isValidJwt } from '../global/utils/egoTokenUtils'; import PageLayout from '../components/PageLayout'; +import getInternalLink from '../global/utils/getInternalLink'; const fetchEgoToken = () => { const { NEXT_PUBLIC_EGO_API_ROOT, NEXT_PUBLIC_EGO_CLIENT_ID } = getConfig(); @@ -31,7 +32,7 @@ const fetchEgoToken = () => { .then((jwt) => { if (isValidJwt(jwt)) { localStorage.setItem(EGO_JWT_KEY, jwt); - setTimeout(() => Router.push('/repository'), 2000); + setTimeout(() => Router.push(getInternalLink({ path: 'repository' })), 2000); } else { throw new Error('Invalid jwt, cannot login.'); } @@ -39,7 +40,7 @@ const fetchEgoToken = () => { .catch((err) => { console.warn(err); localStorage.removeItem(EGO_JWT_KEY); - Router.push('/login'); + Router.push(getInternalLink({ path: 'login' })); }); };