diff --git a/cypress/component/AuthDialog.cy.tsx b/cypress/component/AuthDialog.cy.tsx index d501de9a..59bde208 100644 --- a/cypress/component/AuthDialog.cy.tsx +++ b/cypress/component/AuthDialog.cy.tsx @@ -6,7 +6,7 @@ const props = { onClose: () => {}, }; -describe('ContinuousField', () => { +describe('AuthDialog', () => { it('Displays a MUI dialog with the title and "sing in with google" button', () => { cy.mount( diff --git a/cypress/component/ResultCard.cy.tsx b/cypress/component/ResultCard.cy.tsx index c583c4a2..3bb8e563 100644 --- a/cypress/component/ResultCard.cy.tsx +++ b/cypress/component/ResultCard.cy.tsx @@ -41,12 +41,13 @@ describe('ResultCard', () => { cy.get('[data-cy="card-some uuid"]').should('contain', '5 subjects match / 10 total subjects'); cy.get('[data-cy="card-some uuid-checkbox"] input').should('be.checked'); cy.get('[data-cy="card-some uuid"] button') + .eq(1) .should('contain', 'ASL') - .should('have.class', 'bg-zinc-800'); + .should('have.css', 'background-color', 'rgb(113, 113, 122)'); cy.get('[data-cy="card-some uuid"] button') .eq(2) .should('contain', 'DWI') - .should('have.class', 'bg-red-700'); + .should('have.css', 'background-color', 'rgb(205, 92, 92)'); cy.get('[data-cy="card-some uuid-available-pipelines-button"]').trigger('mouseover', { force: true, diff --git a/cypress/component/SmallScreenSizeDialog.cy.tsx b/cypress/component/SmallScreenSizeDialog.cy.tsx new file mode 100644 index 00000000..24869be3 --- /dev/null +++ b/cypress/component/SmallScreenSizeDialog.cy.tsx @@ -0,0 +1,18 @@ +import SmallScreenSizeDialog from '../../src/components/SmallScreenSizeDialog'; + +const props = { + onClose: () => {}, +}; + +describe('SmallScreenSizeDialog', () => { + it('Displays a MUI dialog with the title and "sing in with google" button', () => { + cy.mount(); + cy.get('[data-cy="small-screen-size-dialog"]').should('be.visible'); + cy.get('[data-cy="small-screen-size-dialog"]').should('contain', 'Unsupported Screen Size'); + cy.get('[data-cy="small-screen-size-dialog"]').should( + 'contain', + 'not optimized for use on smaller screens' + ); + cy.get('[data-cy="close-small-screen-size-dialog-button"]').should('be.visible'); + }); +}); diff --git a/cypress/e2e/Alert.cy.ts b/cypress/e2e/Feedback.cy.ts similarity index 86% rename from cypress/e2e/Alert.cy.ts rename to cypress/e2e/Feedback.cy.ts index 9c3ec5e3..2ba028bf 100644 --- a/cypress/e2e/Alert.cy.ts +++ b/cypress/e2e/Feedback.cy.ts @@ -5,7 +5,7 @@ import { nodeOptions, } from '../fixtures/mocked-responses'; -describe('Alert', () => { +describe('Feedback', () => { it('Correctly displays and dismisses the alert', () => { cy.intercept( { @@ -71,4 +71,11 @@ describe('Alert', () => { cy.get('[data-cy="openneuro-alert"]').find('[data-testid="CloseIcon"]').click(); cy.get('[data-cy="openneuro-alert"]').should('not.exist'); }); + it.only('Displays and closes small screen size dialog', () => { + cy.viewport(766, 500); + cy.visit('/'); + cy.get('[data-cy="small-screen-size-dialog"]').should('be.visible'); + cy.get('[data-cy="close-small-screen-size-dialog-button"]').click(); + cy.get('[data-cy="small-screen-size-dialog"]').should('not.exist'); + }); }); diff --git a/src/App.tsx b/src/App.tsx index 1b87d6d5..1a2b98d4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { useSearchParams } from 'react-router-dom'; import axios, { AxiosResponse } from 'axios'; import { Alert, Grow, IconButton } from '@mui/material'; +import useMediaQuery from '@mui/material/useMediaQuery'; import CloseIcon from '@mui/icons-material/Close'; import { SnackbarKey, SnackbarProvider, closeSnackbar, enqueueSnackbar } from 'notistack'; import { jwtDecode } from 'jwt-decode'; @@ -24,9 +25,15 @@ import ResultContainer from './components/ResultContainer'; import Navbar from './components/Navbar'; import AuthDialog from './components/AuthDialog'; import ChatbotFeature from './components/Chatbot'; +import SmallScreenSizeDialog from './components/SmallScreenSizeDialog'; import './App.css'; +import logo from './assets/logo.png'; function App() { + // Screen is considered small if the width is less than 768px (according to tailwind docs) + const [isScreenSizeSmall, setIsScreenSizeSmall] = useState( + useMediaQuery('(max-width: 767px)') + ); const [diagnosisOptions, setDiagnosisOptions] = useState([]); const [assessmentOptions, setAssessmentOptions] = useState([]); const [availableNodes, setAvailableNodes] = useState([ @@ -427,15 +434,14 @@ function App() { return ( <> -
- {enableAuth && ( - login(credential)} - onClose={() => setOpenAuthDialog(false)} - /> - )} -
+ {enableAuth && ( + login(credential)} + onClose={() => setOpenAuthDialog(false)} + /> + )} + setIsScreenSizeSmall(false)} /> )} -
{enableChatbot && }
+ {enableChatbot && } -
-
+
+ {/* 380px is currently the smallest width for the query form without dropdowns being affected */} +
submitQuery()} />
-
- +
+ {loading ? ( + Logo + ) : ( + + )}
diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 00000000..8f691efa Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/components/AuthDialog.tsx b/src/components/AuthDialog.tsx index 66877e10..111c355b 100644 --- a/src/components/AuthDialog.tsx +++ b/src/components/AuthDialog.tsx @@ -3,8 +3,6 @@ import DialogContent from '@mui/material/DialogContent'; import DialogTitle from '@mui/material/DialogTitle'; import DialogActions from '@mui/material/DialogActions'; import Button from '@mui/material/Button'; -import useMediaQuery from '@mui/material/useMediaQuery'; -import { useTheme } from '@mui/material/styles'; import { GoogleLogin } from '@react-oauth/google'; function AuthDialog({ @@ -16,11 +14,8 @@ function AuthDialog({ onAuth: (credential: string | undefined) => void; onClose: () => void; }) { - const theme = useTheme(); - const fullScreen = useMediaQuery(theme.breakpoints.down('md')); - return ( - + You must log in to a trusted identity provider in order to query all available nodes! diff --git a/src/components/CategoricalField.tsx b/src/components/CategoricalField.tsx index c01334a9..a39404bd 100644 --- a/src/components/CategoricalField.tsx +++ b/src/components/CategoricalField.tsx @@ -21,7 +21,6 @@ function CategoricalField({ {...params} label={label} placeholder="Select an option" - className="w-full" /> )} multiple={multiple} diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 83246a55..205a5692 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -16,6 +16,7 @@ import Logout from '@mui/icons-material/Logout'; import Login from '@mui/icons-material/Login'; import Avatar from '@mui/material/Avatar'; import { enableAuth } from '../utils/constants'; +import logo from '../assets/logo.png'; function Navbar({ isLoggedIn, @@ -58,11 +59,7 @@ function Navbar({
- Logo + Logo
Neurobagel Query diff --git a/src/components/QueryForm.tsx b/src/components/QueryForm.tsx index ca21f6fd..8c6cfd10 100644 --- a/src/components/QueryForm.tsx +++ b/src/components/QueryForm.tsx @@ -92,8 +92,8 @@ function QueryForm({ minNumImagingSessionsHelperText !== ''; return ( -
-
+
+
({ @@ -105,14 +105,14 @@ function QueryForm({ inputValue={selectedNode} />
-
+
-
+
{minAgeExceedsMaxAge && ( -
+
Value of maximum age must be greater than or equal to value of minimum age
)} -
+
({ @@ -137,9 +137,9 @@ function QueryForm({ inputValue={sex} />
-
-
-
+
+
+
({ @@ -151,7 +151,7 @@ function QueryForm({ disabled={isControl} />
-
+
} @@ -161,21 +161,21 @@ function QueryForm({
-
+
-
+
-
+
({ label: a.Label, id: a.TermURL }))} @@ -183,7 +183,7 @@ function QueryForm({ inputValue={assessmentTool} />
-
+
({ @@ -194,7 +194,7 @@ function QueryForm({ inputValue={imagingModality} />
-
+
({ @@ -211,7 +211,7 @@ function QueryForm({ title={Please select a pipeline name} placement="right" > -
+
) : ( -
+
({ @@ -235,7 +235,7 @@ function QueryForm({
)} -
+
-
+
{imageModals.sort().map((modal) => ( diff --git a/src/components/ResultContainer.tsx b/src/components/ResultContainer.tsx index b94e4f5e..de181496 100644 --- a/src/components/ResultContainer.tsx +++ b/src/components/ResultContainer.tsx @@ -207,24 +207,26 @@ function ResultContainer({ response }: { response: QueryResponse | null }) { return ( <> -
- handleSelectAll(event.target.checked)} - checked={selectAll} - /> - } - /> -
-
- - {summaryStats} - +
+
+ handleSelectAll(event.target.checked)} + checked={selectAll} + /> + } + /> +
+
+ + {summaryStats} + +
-
+
{response.responses.map((item) => ( ))}
-
- - setOpenDialog(false)} /> -
-
- downloadResults(identifier)} - /> - downloadResults(identifier)} - /> +
+
+ + setOpenDialog(false)} /> +
+
+ downloadResults(identifier)} + /> + downloadResults(identifier)} + /> +
); } return ( -
-
- Results -
+
{renderResults()}
); diff --git a/src/components/SmallScreenSizeDialog.tsx b/src/components/SmallScreenSizeDialog.tsx new file mode 100644 index 00000000..d52cf3d4 --- /dev/null +++ b/src/components/SmallScreenSizeDialog.tsx @@ -0,0 +1,33 @@ +import { + Button, + Dialog, + DialogContent, + DialogTitle, + DialogActions, + DialogContentText, +} from '@mui/material'; +import WarningIcon from '@mui/icons-material/Warning'; + +function SmallScreenSizeDialog({ open, onClose }: { open: boolean; onClose: () => void }) { + return ( + + + Unsupported Screen Size! + + + + We're sorry, but the Query Tool is not optimized for use on smaller screens. For the + best experience, please access this tool on a device with a larger screen, such as a + tablet, laptop, or desktop computer. Thank you for your understanding! + + + + + + + ); +} + +export default SmallScreenSizeDialog; diff --git a/src/main.tsx b/src/main.tsx index 27eb04e4..12eccf5a 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,11 +1,12 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; -import { StyledEngineProvider } from '@mui/material/styles'; +import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles'; import { GoogleOAuthProvider } from '@react-oauth/google'; import App from './App'; import { appBasePath, enableAuth, clientID } from './utils/constants'; import './index.css'; +import theme from './theme'; const router = createBrowserRouter([ { @@ -18,7 +19,9 @@ const app = ( {/* CSS injection order for MUI and tailwind: https://mui.com/material-ui/guides/interoperability/#tailwind-css */} - + + + ); diff --git a/src/theme.ts b/src/theme.ts new file mode 100644 index 00000000..7c34b2bf --- /dev/null +++ b/src/theme.ts @@ -0,0 +1,21 @@ +import { createTheme } from '@mui/material'; + +const NBTheme = createTheme({ + palette: { + primary: { + light: '#F5A89B', + main: '#D9748D', + dark: '#A8556F', + contrastText: '#FFFFFF', + }, + }, + components: { + MuiButton: { + defaultProps: { + sx: { textTransform: 'none' }, + }, + }, + }, +}); + +export default NBTheme; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 06be5be5..d641f9ae 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -35,36 +35,36 @@ export const modalities: { label: 'Arterial Spin Labeling', TermURL: 'nidm:ArterialSpinLabeling', name: 'ASL', - bgColor: 'bg-zinc-800', + bgColor: 'rgb(113, 113, 122)', }, 'http://purl.org/nidash/nidm#DiffusionWeighted': { label: 'Diffusion Weighted', TermURL: 'nidm:DiffusionWeighted', name: 'DWI', - bgColor: 'bg-red-700', + bgColor: 'rgb(205, 92, 92)', }, 'http://purl.org/nidash/nidm#EEG': { label: 'Electroencephalogram', TermURL: 'nidm:EEG', name: 'EEG', - bgColor: 'bg-rose-300', + bgColor: 'rgb(253, 164, 164)', }, 'http://purl.org/nidash/nidm#FlowWeighted': { label: 'Flow Weighted', TermURL: 'nidm:FlowWeighted', name: 'Flow', - bgColor: 'bg-sky-700', + bgColor: 'rgb(70, 130, 180)', }, 'http://purl.org/nidash/nidm#T1Weighted': { label: 'T1 Weighted', TermURL: 'nidm:T1Weighted', name: 'T1', - bgColor: 'bg-yellow-500', + bgColor: 'rgb(189, 183, 107)', }, 'http://purl.org/nidash/nidm#T2Weighted': { label: 'T2 Weighted', TermURL: 'nidm:T2Weighted', name: 'T2', - bgColor: 'bg-green-600', + bgColor: 'rgb(143, 188, 143)', }, }; diff --git a/tailwind.config.js b/tailwind.config.js index 07517aba..c652f132 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,14 +1,6 @@ /** @type {import('tailwindcss').Config} */ export default { content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], - theme: { - extend: { - gridTemplateRows: { - 9: 'repeat(9, auto)', - 10: 'repeat(10, auto)', - }, - }, - }, plugins: [], corePlugins: { preflight: false,