Skip to content

Commit 99e51a3

Browse files
committed
Merge branch 'master' into dependabot/npm_and_yarn/compose/neurosynth-frontend/multi-ef36040a4f
2 parents 04a4395 + 6a998dc commit 99e51a3

File tree

16 files changed

+190
-247
lines changed

16 files changed

+190
-247
lines changed
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1 @@
1-
{
2-
"singleQuote": true,
3-
"semi": true,
4-
"trailingComma": "es5",
5-
"tabWidth": 4,
6-
"tabs": false,
7-
"printWidth": 120
8-
}
1+
{}

compose/neurosynth-frontend/cypress/e2e/workflows/ingestion/Ingestion.cy.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,9 @@ describe('Ingestion', () => {
66
beforeEach(() => {
77
cy.clearLocalStorage();
88
cy.intercept('GET', 'https://api.appzi.io/**', { fixture: 'appzi' }).as('appziFixture');
9-
cy.intercept('GET', `**/api/meta-analyses*`, { fixture: 'metaAnalyses' }).as(
10-
'metaAnalysesFixture'
11-
);
9+
cy.intercept('GET', `**/api/meta-analyses*`, { fixture: 'metaAnalyses' }).as('metaAnalysesFixture');
1210

13-
cy.intercept('POST', `https://www.google-analytics.com/*/**`, {}).as(
14-
'googleAnalyticsFixture'
15-
);
11+
cy.intercept('POST', `https://www.google-analytics.com/*/**`, {}).as('googleAnalyticsFixture');
1612

1713
cy.intercept('GET', `**/api/projects/*`, {
1814
fixture: 'IngestionFixtures/projectFixture',
@@ -48,9 +44,7 @@ describe('Ingestion', () => {
4844

4945
it('should show the dialog', () => {
5046
cy.login('mocked').visit(PATH);
51-
cy.contains('button', 'go to extraction').click();
52-
53-
cy.contains('button', 'extraction: get started').click();
47+
cy.contains('button', 'go to extraction').click(); // popup should open automatically as extraction has not been initialized in this mock
5448
cy.contains('button', 'NEXT').click();
5549

5650
cy.get('@baseStudiesFixture').its('request.body').should('not.have.a.property', 'doi');

compose/neurosynth-frontend/eslint.config.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ import eslint from '@eslint/js';
33
import teslint from 'typescript-eslint';
44
import eslintHooks from 'eslint-plugin-react-hooks';
55
import eslintCypress from 'eslint-plugin-cypress/flat';
6-
import eslintPrettier from 'eslint-plugin-prettier/recommended';
6+
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
7+
import eslintConfigPrettier from 'eslint-config-prettier';
78
import globals from 'globals';
89
import eslintReactRefresh from 'eslint-plugin-react-refresh';
910

1011
export default [
1112
eslint.configs.recommended,
1213
...teslint.configs.recommended,
1314
eslintCypress.configs.recommended,
14-
eslintPrettier,
15+
eslintConfigPrettier,
16+
eslintPluginPrettierRecommended,
1517
{
1618
languageOptions: {
1719
globals: {
@@ -33,6 +35,8 @@ export default [
3335
rules: {
3436
...eslintHooks.configs.recommended.rules,
3537
'react-refresh/only-export-components': 'warn',
38+
// to override prettier settings, set it here
39+
// "prettier/prettier": ["error", { printWidth: 20, tabWidth: 4, singleQuote: true }],
3640
},
3741
},
3842
];

compose/neurosynth-frontend/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<!DOCTYPE html>
2-
<html lang="en">
2+
<html lang="en" class="notranslate" translate="no">
33
<head>
44
<meta charset="utf-8" />
55
<link rel="icon" href="/favicon.ico" />
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
<meta name="theme-color" content="#000000" />
88
<meta name="description" content="Neurosynth-Compose App" />
9+
<meta name="google" content="notranslate" />
910
<link rel="apple-touch-icon" href="/logo192.png" />
1011
<!--
1112
manifest.json provides metadata used when your web app is installed on a
@@ -17,7 +18,7 @@
1718

1819
<link rel="preload" as="image" href="/static/brain-analysis.png" type="image/png">
1920

20-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css" crossorigin="anonymous" />
21+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@12.3.3/dist/handsontable.full.min.css" crossorigin="anonymous" />
2122

2223
<link
2324
rel="stylesheet"

compose/neurosynth-frontend/src/index.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ import App from './App';
1010
import './index.css';
1111

1212
export type Style = Record<string, SystemStyleObject>;
13-
export type ColorOptions =
14-
| 'inherit'
15-
| 'primary'
16-
| 'secondary'
17-
| 'success'
18-
| 'error'
19-
| 'info'
20-
| 'warning';
13+
export type ColorOptions = 'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning';
2114

2215
declare module '@mui/material/styles/createPalette' {
2316
interface Palette {
@@ -97,8 +90,15 @@ const env = import.meta.env.VITE_APP_ENV as 'DEV' | 'STAGING' | 'PROD';
9790
if (env === 'PROD') {
9891
Sentry.init({
9992
dsn: 'https://348a42291ed44c3baf7e2d94a0dfc08f@o4505036784992256.ingest.sentry.io/4505036786040832',
100-
integrations: [new Sentry.BrowserTracing(), new Sentry.Replay()],
101-
replaysSessionSampleRate: 0.5,
93+
integrations: [
94+
Sentry.browserTracingIntegration(),
95+
Sentry.replayIntegration({
96+
maskAllText: false,
97+
blockAllMedia: false,
98+
maskAllInputs: true,
99+
}),
100+
],
101+
replaysSessionSampleRate: 0.1,
102102
replaysOnErrorSampleRate: 1.0,
103103
});
104104
}

compose/neurosynth-frontend/src/pages/BaseNavigation/BaseNavigation.tsx

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -80,26 +80,13 @@ const BaseNavigation: React.FC = (_props) => {
8080
</ProtectedProjectRoute>
8181
}
8282
children={[
83-
<Route
84-
key="project-id-project"
85-
path="project"
86-
element={<ProjectEditMetaAnalyses />}
87-
/>,
83+
<Route key="project-id-project" path="project" element={<ProjectEditMetaAnalyses />} />,
8884
<Route
8985
key="project-id-meta-analyses"
9086
path="meta-analyses"
9187
element={<ProjectViewMetaAnalyses />}
9288
/>,
93-
<Route
94-
key="project-id-index"
95-
index
96-
element={<Navigate replace to="project" />}
97-
/>,
98-
<Route
99-
key="project-id-*"
100-
path="*"
101-
element={<Navigate replace to="project" />}
102-
/>,
89+
<Route key="project-id-index" index element={<Navigate replace to="project" />} />,
10390
]}
10491
/>
10592
<Route
@@ -138,10 +125,7 @@ const BaseNavigation: React.FC = (_props) => {
138125
<Route
139126
path="/projects/:projectId/extraction/studies/:studyId/edit"
140127
element={
141-
<ProtectedProjectRoute
142-
onlyOwnerCanAccess
143-
errorMessage="You do not have access to this project"
144-
>
128+
<ProtectedProjectRoute onlyOwnerCanAccess errorMessage="You do not have access to this project">
145129
<Box sx={BaseNavigationStyles.pagesContainer}>
146130
<EditStudyPage />
147131
</Box>
@@ -196,19 +180,17 @@ const BaseNavigation: React.FC = (_props) => {
196180
</Box>
197181
}
198182
/>
199-
{['/base-studies/:baseStudyId', '/base-studies/:baseStudyId/:studyVersionId'].map(
200-
(path) => (
201-
<Route
202-
key={path}
203-
path={path}
204-
element={
205-
<Box sx={BaseNavigationStyles.pagesContainer}>
206-
<BaseStudyPage />
207-
</Box>
208-
}
209-
/>
210-
)
211-
)}
183+
{['/base-studies/:baseStudyId', '/base-studies/:baseStudyId/:studyVersionId'].map((path) => (
184+
<Route
185+
key={path}
186+
path={path}
187+
element={
188+
<Box sx={BaseNavigationStyles.pagesContainer}>
189+
<BaseStudyPage />
190+
</Box>
191+
}
192+
/>
193+
))}
212194
<Route
213195
path="/meta-analyses"
214196
element={

compose/neurosynth-frontend/src/pages/Curation/CurationPage.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { useState } from 'react';
2121
import { useNavigate, useParams } from 'react-router-dom';
2222
import CurationDownloadIncludedStudiesButton from './components/CurationDownloadIncludedStudiesButton';
2323

24-
const CurationPage: React.FC = (props) => {
24+
const CurationPage: React.FC = () => {
2525
const [prismaIsOpen, setPrismaIsOpen] = useState(false);
2626
const { projectId } = useParams<{ projectId: string | undefined }>();
2727
const projectUser = useProjectUser();
@@ -38,14 +38,13 @@ const CurationPage: React.FC = (props) => {
3838
const { included, uncategorized } = useGetCurationSummary();
3939
const { data: studyset } = useGetStudysetById(studysetId || '', false);
4040

41-
const extractionStepInitialized =
42-
studysetId && annotationId && (studyset?.studies?.length || 0) > 0;
41+
const extractionStepInitialized = studysetId && annotationId && (studyset?.studies?.length || 0) > 0;
4342

4443
const handleMoveToExtractionPhase = () => {
4544
if (extractionStepInitialized) {
4645
navigate(`/projects/${projectId}/extraction`);
4746
} else {
48-
navigate(`/projects/${projectId}`, {
47+
navigate(`/projects/${projectId}/project`, {
4948
state: {
5049
projectPage: {
5150
openCurationDialog: true,
@@ -93,10 +92,7 @@ const CurationPage: React.FC = (props) => {
9392
<CurationDownloadIncludedStudiesButton />
9493
{isPrisma && (
9594
<>
96-
<PrismaDialog
97-
onCloseDialog={() => setPrismaIsOpen(false)}
98-
isOpen={prismaIsOpen}
99-
/>
95+
<PrismaDialog onCloseDialog={() => setPrismaIsOpen(false)} isOpen={prismaIsOpen} />
10096
<Button
10197
onClick={() => setPrismaIsOpen(true)}
10298
variant="outlined"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Box, Link, Paper, Typography } from '@mui/material';
2+
import { MetaAnalysisReturn, ResultReturn } from 'neurosynth-compose-typescript-sdk';
3+
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
4+
import useGetAnalysisById from 'hooks/analyses/useGetAnalysisById';
5+
import StudyPoints from 'pages/Study/components/StudyPoints';
6+
import { PointReturn } from 'neurostore-typescript-sdk';
7+
import StateHandlerComponent from 'components/StateHandlerComponent/StateHandlerComponent';
8+
import { studyPointsToStorePoints } from 'pages/Study/store/StudyStore.helpers';
9+
import { getResultStatus } from 'helpers/MetaAnalysis.helpers';
10+
11+
const DisplayMetaAnalysisResult: React.FC<{
12+
metaAnalysis: MetaAnalysisReturn | undefined;
13+
metaAnalysisResult: ResultReturn | undefined;
14+
}> = (props) => {
15+
const resultStatus = getResultStatus(props.metaAnalysis, props.metaAnalysisResult);
16+
17+
const { data, isLoading, isError } = useGetAnalysisById(
18+
props.metaAnalysis?.neurostore_analysis?.neurostore_id || undefined
19+
);
20+
21+
const { points, analysisSpace, analysisMap } = studyPointsToStorePoints(
22+
(data?.points || []) as PointReturn[],
23+
false
24+
);
25+
26+
const neurovaultLink = props.metaAnalysisResult?.neurovault_collection?.url || '';
27+
28+
return (
29+
<Paper sx={{ padding: '1rem', margin: '1rem 0' }}>
30+
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
31+
<Typography sx={{ marginBottom: '1rem' }} variant="h5">
32+
Result
33+
</Typography>
34+
{resultStatus.color === 'error' && (
35+
<Box sx={{ display: 'flex', alignItems: 'center' }}>
36+
<ErrorOutlineIcon color="error" sx={{ marginRight: '10px' }} />
37+
<Typography sx={{ color: 'error.main' }}>{resultStatus.statusText}</Typography>
38+
</Box>
39+
)}
40+
</Box>
41+
<Box sx={{ marginBottom: '1rem' }}>
42+
<Typography sx={{ fontWeight: 'bold' }} gutterBottom>
43+
Neurovault
44+
</Typography>
45+
<Link
46+
sx={{ fontWeight: 'normal' }}
47+
underline="hover"
48+
target="_blank"
49+
rel="noreferrer"
50+
href={neurovaultLink.includes('/api') ? neurovaultLink.replace(/\/api/, '') : neurovaultLink}
51+
>
52+
Neurovault Collection Link
53+
</Link>
54+
</Box>
55+
<StateHandlerComponent isLoading={isLoading} isError={isError}>
56+
<StudyPoints
57+
statistic={analysisMap}
58+
space={analysisSpace}
59+
height="200px"
60+
title="Peak Coordinates"
61+
points={points}
62+
/>
63+
</StateHandlerComponent>
64+
</Paper>
65+
);
66+
};
67+
68+
export default DisplayMetaAnalysisResult;

compose/neurosynth-frontend/src/pages/Project/components/MoveToExtractionDialog.tsx

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ const MoveToExtractionDialog: React.FC<IDialog> = (props) => {
7373
});
7474

7575
const newStudysetId = newStudyset.data.id;
76-
if (!newStudysetId)
77-
throw new Error('expected a studyset id but did not receive one');
76+
if (!newStudysetId) throw new Error('expected a studyset id but did not receive one');
7877

7978
tempStudysetId = newStudysetId;
8079

@@ -114,8 +113,7 @@ const MoveToExtractionDialog: React.FC<IDialog> = (props) => {
114113
});
115114

116115
const newAnnotationId = newAnnotation.data.id;
117-
if (!newAnnotationId)
118-
throw new Error('expected a studyset id but did not receive one');
116+
if (!newAnnotationId) throw new Error('expected a studyset id but did not receive one');
119117

120118
tempAnnotationId = newAnnotationId;
121119
updateExtractionMetadata({
@@ -140,15 +138,7 @@ const MoveToExtractionDialog: React.FC<IDialog> = (props) => {
140138
const stubsToBaseStudies: Array<
141139
Pick<
142140
BaseStudy,
143-
| 'name'
144-
| 'doi'
145-
| 'pmid'
146-
| 'pmcid'
147-
| 'year'
148-
| 'description'
149-
| 'publication'
150-
| 'authors'
151-
| 'level'
141+
'name' | 'doi' | 'pmid' | 'pmcid' | 'year' | 'description' | 'publication' | 'authors' | 'level'
152142
>
153143
> = includedStubs.map((stub) => ({
154144
name: stub.title,
@@ -252,14 +242,10 @@ const MoveToExtractionDialog: React.FC<IDialog> = (props) => {
252242
value={progress}
253243
/>
254244
</Box>
255-
<Box
256-
sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}
257-
>
245+
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
258246
<CircularProgress />
259247
<Typography>{progressText}</Typography>
260-
<Typography sx={{ marginTop: '1rem' }}>
261-
(This may take a minute)
262-
</Typography>
248+
<Typography sx={{ marginTop: '1rem' }}>(This may take a minute)</Typography>
263249
</Box>
264250
{/* need this empty div to space out elements properly */}
265251
<div></div>

compose/neurosynth-frontend/src/pages/Study/BaseStudyPage.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,7 @@ const BaseStudyPage: React.FC = (props) => {
2525

2626
// if studyVersionId doesnt exist, then it will not be queried.
2727
// In the second useEffect hook below, we keep trying to set the studyVersionId
28-
const {
29-
data: study,
30-
isLoading: studyIsLoading,
31-
isError: studyIsError,
32-
} = useGetStudyById(studyVersionId || '');
28+
const { data: study, isLoading: studyIsLoading, isError: studyIsError } = useGetStudyById(studyVersionId || '');
3329

3430
// init the study store with the given version when a new one is set
3531
useEffect(() => {
@@ -42,10 +38,7 @@ const BaseStudyPage: React.FC = (props) => {
4238
// on initial load, we keep trying to set the URL with the study version until one is set
4339
useEffect(() => {
4440
if (baseStudy && baseStudy.versions && baseStudy.versions.length > 0 && !studyVersionId) {
45-
navigate(
46-
`/base-studies/${baseStudyId}/${(baseStudy.versions as StudyReturn[])[0].id}`,
47-
{ replace: true }
48-
);
41+
navigate(`/base-studies/${baseStudyId}/${(baseStudy.versions as StudyReturn[])[0].id}`, { replace: true });
4942
}
5043
}, [baseStudy, baseStudyId, navigate, studyVersionId]);
5144

@@ -69,9 +62,7 @@ const BaseStudyPage: React.FC = (props) => {
6962
>
7063
{((baseStudy?.versions || []) as StudyReturn[]).map((version, index) => {
7164
// we want the date last "touched", prefer updated_at over created_at
72-
const parsedDate = new Date(
73-
version?.updated_at || version?.created_at || ''
74-
);
65+
const parsedDate = new Date(version?.updated_at || version?.created_at || '');
7566

7667
const dateStr = `${
7768
parsedDate.getMonth() + 1

0 commit comments

Comments
 (0)