diff --git a/components/Button.tsx b/components/Button.tsx index 4d5eae99..41aab7cf 100644 --- a/components/Button.tsx +++ b/components/Button.tsx @@ -67,14 +67,7 @@ const Button = React.forwardRef< } >( ( - { - children, - onClick = (e) => {}, - disabled = false, - isAsync = false, - className, - isLoading: controlledLoadingState, - }, + { children, onClick = (e) => {}, disabled = false, isAsync = false, className, isLoading: controlledLoadingState }, ref = React.createRef(), ) => { const [isLoading, setLoading] = React.useState(false); diff --git a/components/NavBar.tsx b/components/NavBar.tsx index ddb58236..11ac3baa 100644 --- a/components/NavBar.tsx +++ b/components/NavBar.tsx @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 The Ontario Institute for Cancer Research. All rights reserved + * Copyright (c) 2025 The Ontario Institute for Cancer Research. All rights reserved * * This program and the accompanying materials are made available under the terms of * the GNU Affero General Public License v3.0. You should have received a copy of the @@ -19,34 +19,32 @@ * */ -import React from 'react'; +import { getConfig } from '@/global/config'; import { css, useTheme } from '@emotion/react'; import { useRouter } from 'next/router'; +import React from 'react'; + +import useAuthContext from '@/global/hooks/useAuthContext'; +import { EXPLORER_PATH, LOGIN_PATH, USER_PATH } from '@/global/utils/constants'; -import UserDropdown from './UserDropdown'; -import defaultTheme from './theme'; -import { OvertureLogo } from './theme/icons'; -import useAuthContext from '../global/hooks/useAuthContext'; -import { StyledLinkAsButton, InternalLink as Link } from './Link'; -import { EXPLORER_PATH, LOGIN_PATH, USER_PATH } from '../global/utils/constants'; -import { getConfig } from '../global/config'; +import { InternalLink, StyledLinkAsButton } from '@/components/Link'; +import NavbarLinkButton from '@/components/NavbarLinkButton'; +import UserDropdown from '@/components/UserDropdown'; +import defaultTheme from '@/components/theme'; +import { OvertureLogo } from '@/components/theme/icons'; const NavBar: React.ComponentType = () => { const { user } = useAuthContext(); const router = useRouter(); const theme: typeof defaultTheme = useTheme(); - const { - NEXT_PUBLIC_AUTH_PROVIDER, - NEXT_PUBLIC_LAB_NAME, - NEXT_PUBLIC_LOGO_FILENAME, - NEXT_PUBLIC_BASE_PATH, - } = getConfig(); + const { NEXT_PUBLIC_AUTH_PROVIDER, NEXT_PUBLIC_LAB_NAME, NEXT_PUBLIC_LOGO_FILENAME, NEXT_PUBLIC_BASE_PATH } = + getConfig(); const activeLinkStyle = ` background-color: ${theme.colors.grey_2}; color: ${theme.colors.accent2_dark}; - `; +`; const labIcon = NEXT_PUBLIC_LOGO_FILENAME ? ( { align-items: center; margin-left: 16px; cursor: pointer; + gap: 10px; `} > - + css` display: flex; @@ -100,7 +99,8 @@ const NavBar: React.ComponentType = () => { {NEXT_PUBLIC_LAB_NAME} - + +
{ align-items: center; `} > -
css` - display: flex; - align-items: center; - justify-content: center; - width: 144px; - background-color: ${theme.colors.white}; - height: 100%; - &:hover { - background-color: ${theme.colors.grey_2}; - } - 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.accent_dark}; - cursor: pointer; - ${router.pathname === EXPLORER_PATH ? activeLinkStyle : ''} - `} - > - Data Explorer - - -
- {NEXT_PUBLIC_AUTH_PROVIDER && (user ? (
{ justify-content: center; `} > - + css` width: 70px; @@ -175,7 +142,7 @@ const NavBar: React.ComponentType = () => { > Log in - +
))}
diff --git a/components/NavbarLinkButton.tsx b/components/NavbarLinkButton.tsx new file mode 100644 index 00000000..3b2bac20 --- /dev/null +++ b/components/NavbarLinkButton.tsx @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2025 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of + * the GNU Affero General Public License v3.0. You should have received a copy of the + * GNU Affero General Public License along with this program. + * If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import { css, Theme, useTheme } from '@emotion/react'; +import { useRouter } from 'next/router'; + +import { InternalLink } from '@/components/Link'; +import defaultTheme from '@/components/theme'; + +type NavbarLinkProps = { + path: string; + label: string; +}; + +const getContainerStyles = (theme: typeof defaultTheme) => css` + display: flex; + align-items: center; + justify-content: center; + width: 144px; + background-color: ${theme.colors.white}; + height: 100%; + &:hover { + background-color: ${theme.colors.grey_2}; + } + border-right: 2px solid ${theme.colors.white}; +`; + +const getLinkStyles = (theme: Theme, isActive: boolean) => css` + display: flex; + flex: 1; + height: 100%; + justify-content: center; + align-items: center; + text-decoration: none; + color: ${theme.colors.accent_dark}; + cursor: pointer; + ${isActive + ? ` + background-color: ${theme.colors.grey_2}; + color: ${theme.colors.accent2_dark}; + ` + : ''} +`; + +/** + * @param {NavbarLinkProps} props - The properties for the NavbarLinkButton component. + * @param {string} props.path - The path for the link. + * @param {string} props.label - The label for the link. + * @return JSX.Element - A styled link button for the navigation bar. + */ +const NavbarLinkButton = ({ path, label }: NavbarLinkProps) => { + const router = useRouter(); + const theme: typeof defaultTheme = useTheme(); + const isActive = router.pathname === path; + + return ( +
+ + {label} + +
+ ); +}; + +export default NavbarLinkButton; diff --git a/components/UserDropdown.tsx b/components/UserDropdown.tsx index 028feff3..f1b9d64f 100644 --- a/components/UserDropdown.tsx +++ b/components/UserDropdown.tsx @@ -75,23 +75,23 @@ const CurrentUser = () => { const StyledListLink = styled('a')` ${({ theme }) => css` - text-decoration: none; - height: 40px; - display: flex; - align-items: center; - background: ${theme.colors.white}; - padding: 6px 12px; - color: ${theme.colors.black}; - background-color: ${theme.colors.white}; - border: 1px solid ${theme.colors.grey_3}; - outline: none; - font-size: 16px; - cursor: pointer; - width: 100%; - &:hover { - background-color: ${theme.colors.grey_1}; - } - `} + text-decoration: none; + height: 40px; + display: flex; + align-items: center; + background: ${theme.colors.white}; + padding: 6px 12px; + color: ${theme.colors.black}; + background-color: ${theme.colors.white}; + border: 1px solid ${theme.colors.grey_3}; + outline: none; + font-size: 16px; + cursor: pointer; + width: 100%; + &:hover { + background-color: ${theme.colors.grey_1}; + } + `} `; const UserDropdown = () => { @@ -120,14 +120,10 @@ const UserDropdown = () => { }; }, [open]); - const fillColor = - router.pathname === USER_PATH ? theme.colors.accent2_dark : theme.colors.accent_dark; + const fillColor = router.pathname === USER_PATH ? theme.colors.accent2_dark : theme.colors.accent_dark; const handleLogout = () => { - if ( - NEXT_PUBLIC_AUTH_PROVIDER === AUTH_PROVIDER.EGO || - NEXT_PUBLIC_AUTH_PROVIDER === AUTH_PROVIDER.KEYCLOAK - ) { + if (NEXT_PUBLIC_AUTH_PROVIDER === AUTH_PROVIDER.EGO || NEXT_PUBLIC_AUTH_PROVIDER === AUTH_PROVIDER.KEYCLOAK) { signOut(); } }; diff --git a/global/utils/constants.ts b/global/utils/constants.ts index d003c98c..edb29629 100644 --- a/global/utils/constants.ts +++ b/global/utils/constants.ts @@ -23,8 +23,7 @@ import urlJoin from 'url-join'; import { getConfig } from '../config'; -const { NEXT_PUBLIC_EGO_API_ROOT, NEXT_PUBLIC_KEYCLOAK_HOST, NEXT_PUBLIC_KEYCLOAK_REALM } = - getConfig(); +const { NEXT_PUBLIC_EGO_API_ROOT, NEXT_PUBLIC_KEYCLOAK_HOST, NEXT_PUBLIC_KEYCLOAK_REALM } = getConfig(); export const EGO_JWT_KEY = 'EGO_JWT'; export const EGO_API_KEY_ENDPOINT = `${NEXT_PUBLIC_EGO_API_ROOT}/o/api_key`; @@ -35,15 +34,11 @@ export const USER_PATH = '/user'; export const LOGIN_PATH = '/login'; // external docs links -export const HELP_URL = 'https://github.com/overture-stack/stage/issues/new/choose' +export const HELP_URL = 'https://github.com/overture-stack/stage/issues/new/choose'; export const EMAIL_SETTING_URL = 'admin@example.com'; // keycloak -export const KEYCLOAK_URL_ISSUER = urlJoin( - NEXT_PUBLIC_KEYCLOAK_HOST, - 'realms', - NEXT_PUBLIC_KEYCLOAK_REALM, -); +export const KEYCLOAK_URL_ISSUER = urlJoin(NEXT_PUBLIC_KEYCLOAK_HOST, 'realms', NEXT_PUBLIC_KEYCLOAK_REALM); export const KEYCLOAK_URL_TOKEN = urlJoin(KEYCLOAK_URL_ISSUER, 'protocol/openid-connect/token'); export const KEYCLOAK_API_KEY_ENDPOINT = urlJoin(KEYCLOAK_URL_ISSUER, 'apikey/api_key');