diff --git a/compose/neurosynth-frontend/cypress/e2e/pages/AuthenticatedLandingPage.cy.tsx b/compose/neurosynth-frontend/cypress/e2e/pages/AuthenticatedLandingPage.cy.tsx deleted file mode 100644 index 8cf127438..000000000 --- a/compose/neurosynth-frontend/cypress/e2e/pages/AuthenticatedLandingPage.cy.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/// - -export {}; - -const PATH = '/'; -const PAGE_NAME = 'AuthenticatedLandingPage'; - -describe(PAGE_NAME, () => { - beforeEach(() => { - cy.clearLocalStorage().clearSessionStorage(); - cy.intercept('GET', 'https://api.appzi.io/**', { fixture: 'appzi' }).as('appziFixture'); - }); - - it('should load successfully', () => { - cy.login('real'); - }); - - // describe('Tour ', () => { - // it('should open immediately if it is the users first time logging in', () => { - // cy.login('mocked', { 'https://neurosynth-compose/loginsCount': 1 }) - // .get('.reactour__popover') - // .should('exist') - // .and('be.visible'); - // }); - - // it('should not open immediately if not authenticated', () => { - // cy.visit(PATH).get('.reactour__popover').should('not.exist'); - // }); - - // it('should not open immediately if it is not the first time logging in', () => { - // cy.login('mocked', { 'https://neurosynth-compose/loginsCount': 2 }) - // .get('.reactour__popover') - // .should('not.exist'); - // }); - - // it('should open when the button is clicked', () => { - // cy.login('mocked', { 'https://neurosynth-compose/loginsCount': 2 }) - // .get('[data-testid="HelpIcon"]') - // .click() - // .get('.reactour__popover') - // .should('exist') - // .and('be.visible'); - // }); - - // it('should not open if its the first time logging in but the page has been seen already', () => { - // cy.login('mocked', { 'https://neurosynth-compose/loginsCount': 1 }) - // .get('body') - // .click(0, 0) - // .then((_res) => { - // localStorage.setItem(`hasSeen${PAGE_NAME}`, 'true'); - // }) - // .visit('/') - // .get('.reactour__popover') - // .should('not.exist'); - // }); - - // it('should close when clicked out', () => { - // // 1. ARRANGE - // cy.login('mocked', { 'https://neurosynth-compose/loginsCount': 2 }) - // .get('[data-testid="HelpIcon"]') - // .click() - // .get('body') - // .click(0, 0) - // .get('.reactour__popover') - // .should('not.exist'); - // }); - - // it('should close when the close button is clicked', () => { - // cy.login('mocked', { 'https://neurosynth-compose/loginsCount': 2 }) - // .get('[data-testid="HelpIcon"]') - // .click() - // .get('[aria-label="Close Tour"]') - // .click() - // .get('.reactour__popover') - // .should('not.exist'); - // }); - // }); -}); diff --git a/compose/neurosynth-frontend/cypress/e2e/pages/LandingPage.cy.tsx b/compose/neurosynth-frontend/cypress/e2e/pages/LandingPage.cy.tsx index 0d4ccdb5a..ecaf748a0 100644 --- a/compose/neurosynth-frontend/cypress/e2e/pages/LandingPage.cy.tsx +++ b/compose/neurosynth-frontend/cypress/e2e/pages/LandingPage.cy.tsx @@ -7,10 +7,24 @@ const PAGE_NAME = 'LandingPage'; describe(PAGE_NAME, () => { beforeEach(() => { cy.intercept('GET', 'https://api.appzi.io/**', { fixture: 'appzi' }).as('appziFixture'); + cy.intercept('GET', `**/api/base-studies/**`, { fixture: 'baseStudies' }).as( + 'baseStudiesFixture' + ); + cy.intercept('GET', `**/api/points/**`, { fixture: 'points' }).as('pointsFixture'); }); it('should load successfully', () => { - cy.visit('/'); + cy.visit('/').wait('@baseStudiesFixture').wait('@pointsFixture'); + }); + + it('should authenticate for real and redirect to projects page', () => { + cy.login('real').visit('/'); + cy.contains('Projects'); + }); + + it('should authenticate and redirect to the projects page', () => { + cy.login('mocked').visit('/'); + cy.contains('Projects'); }); it('should change the viewport property', () => { diff --git a/compose/neurosynth-frontend/cypress/e2e/pages/NotFound.cy.tsx b/compose/neurosynth-frontend/cypress/e2e/pages/NotFound.cy.tsx index a66db92d4..7d77b2426 100644 --- a/compose/neurosynth-frontend/cypress/e2e/pages/NotFound.cy.tsx +++ b/compose/neurosynth-frontend/cypress/e2e/pages/NotFound.cy.tsx @@ -9,38 +9,4 @@ describe('NotFoundPage', () => { cy.visit('/page-that-doesnt-exist'); cy.contains('Requested resource not found'); }); - - // it('should route the non existent studyset resource to the not found page', () => { - // cy.intercept('GET', '**/api/studysets/*', { statusCode: 404 }).as('studysetsRequestError'); - // cy.intercept('GET', '**/api/annotations/*', { statusCode: 404 }).as( - // 'annotationsRequestError' - // ); - - // cy.visit('/studysets/studyset-that-doesnt-exist') - // .wait(['@studysetsRequestError', '@annotationsRequestError']) - // .get('body') - // .contains('Requested resource not found'); - // }); - - // it('should route the non existent meta-analysis resource to the not found page', () => { - // cy.intercept('GET', '**/api/meta-analyses/**', { statusCode: 404 }).as( - // 'metaAnalysisRequestError' - // ); - - // cy.visit('/meta-analyses/meta-analysis-that-doesnt-exist') - // .wait(['@metaAnalysisRequestError']) - // .get('body') - // .contains('Requested resource not found'); - // }); - - // it('should route the non existent annotation resource to the not found page', () => { - // cy.intercept('GET', '**/api/annotations/*', { - // statusCode: 404, - // }).as('annotationRequestError'); - - // cy.visit('/annotations/annotation-doesnt-exist') - // .wait(['@annotationRequestError']) - // .get('body') - // .contains('Requested resource not found'); - // }); }); diff --git a/compose/neurosynth-frontend/cypress/fixtures/baseStudies.json b/compose/neurosynth-frontend/cypress/fixtures/baseStudies.json new file mode 100644 index 000000000..7dfbd7db4 --- /dev/null +++ b/compose/neurosynth-frontend/cypress/fixtures/baseStudies.json @@ -0,0 +1,5 @@ +{ + "metadata": { + "total_count": 100 + } +} \ No newline at end of file diff --git a/compose/neurosynth-frontend/cypress/fixtures/points.json b/compose/neurosynth-frontend/cypress/fixtures/points.json new file mode 100644 index 000000000..7dfbd7db4 --- /dev/null +++ b/compose/neurosynth-frontend/cypress/fixtures/points.json @@ -0,0 +1,5 @@ +{ + "metadata": { + "total_count": 100 + } +} \ No newline at end of file diff --git a/compose/neurosynth-frontend/cypress/support/commands.ts b/compose/neurosynth-frontend/cypress/support/commands.ts index 44d445bea..5270630cc 100644 --- a/compose/neurosynth-frontend/cypress/support/commands.ts +++ b/compose/neurosynth-frontend/cypress/support/commands.ts @@ -10,34 +10,6 @@ import * as jose from 'jose'; // commands please read more here: // https://on.cypress.io/custom-commands // *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -// -// declare global { -// namespace Cypress { -// interface Chainable { -// login(email: string, password: string): Chainable -// drag(subject: string, options?: Partial): Chainable -// dismiss(subject: string, options?: Partial): Chainable -// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable -// } -// } -// } - const constructMockAuthJWT = async (jwtPayload = {}): Promise => { const jwt = await new jose.SignJWT({ ...jwtPayload }) .setProtectedHeader({ alg: 'HS256' }) @@ -51,6 +23,7 @@ const createMockRequest = async ( audience: string, client_id: string, domain: string, + scope: string, extraClaims = {} ) => { const access_token = await constructMockAuthJWT({ @@ -60,7 +33,7 @@ const createMockRequest = async ( iat: 1659719697, exp: 1659806097, azp: 'EmcOFhu0XAINM4EyslaKpZ3u09QlBvef', - scope: 'openid profile email', + scope: scope, }); const id_token = await constructMockAuthJWT({ @@ -85,7 +58,7 @@ const createMockRequest = async ( access_token: access_token, expires_in: 86400, id_token: id_token, - scope: 'openid profile email read:current_user update:current_user_metadata delete:current_user_metadata create:current_user_metadata create:current_user_device_credentials delete:current_user_device_credentials update:current_user_identities', + scope: scope, token_type: 'Bearer', }, }; @@ -99,12 +72,14 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => { const password = Cypress.env('auth0Password'); const domain = Cypress.env('auth0Domain'); + const scope = 'openid profile email offline_access'; + /** * To prevent rate limiting errors form auth0, we stub our own request func and return a mocked response */ if (loginMode === 'mocked') { cy.stub(cy, 'request').callsFake(() => - cy.wrap(createMockRequest(audience, client_id, domain, extraClaims)) + cy.wrap(createMockRequest(audience, client_id, domain, scope, extraClaims)) ); } @@ -121,7 +96,7 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => { username, password, audience, - scope: 'openid profile email', + scope, client_id, client_secret, }, @@ -153,7 +128,7 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => { }, expires_in, id_token, - scope: 'openid profile email read:current_user update:current_user_metadata delete:current_user_metadata create:current_user_metadata create:current_user_device_credentials delete:current_user_device_credentials update:current_user_identities', + scope, token_type: 'Bearer', }, expiresAt: Math.floor(Date.now() / 1000) + expires_in, @@ -165,13 +140,10 @@ Cypress.Commands.add('login', (loginMode = 'mocked', extraClaims = {}) => { * the isAuthenticated state. This code is in tandem with setting the auth0 provider cacheLocation=localstorage. */ cy.addToLocalStorage( - `@@auth0spajs@@::${client_id}::${audience}::openid profile email`, + `@@auth0spajs@@::${client_id}::${audience}::${scope}`, JSON.stringify(session) ); }); - - // this will always run after the previous commands are complete - cy.visit('/'); }); Cypress.Commands.add('clearSessionStorage', () => { @@ -192,7 +164,6 @@ declare global { namespace Cypress { interface Chainable { login(loginMode: 'real' | 'mocked', extraClaims?: any): Chainable; - mockLogin(extraClaims?: any): Chainable; clearSessionStorage(): Chainable; addToLocalStorage(key: string, value: string): Chainable; } diff --git a/compose/neurosynth-frontend/package.json b/compose/neurosynth-frontend/package.json index 931295693..8f7ae6624 100644 --- a/compose/neurosynth-frontend/package.json +++ b/compose/neurosynth-frontend/package.json @@ -59,7 +59,7 @@ "test-with-coverage": "npm run test -- --coverage --watchAll=false", "cy:e2e-headless": "cypress run", "cy:e2e-headless-local": "env-cmd -f .env.dev cypress run", - "cy:e2e-browser": "env-cmd -f .env.dev cypress open -b chrome --e2e", + "cy:e2e-browser": "env-cmd -f .env.staging cypress open -b chrome --e2e", "cy:install": "cypress install", "cy:ci": "start-server-and-test start-ci:dev 3000 cy:e2e-headless", "eject": "react-scripts eject" diff --git a/compose/neurosynth-frontend/src/components/Dialogs/ConfirmationDialog/ConfirmationDialog.tsx b/compose/neurosynth-frontend/src/components/Dialogs/ConfirmationDialog/ConfirmationDialog.tsx index e72ac7c93..3978f7861 100644 --- a/compose/neurosynth-frontend/src/components/Dialogs/ConfirmationDialog/ConfirmationDialog.tsx +++ b/compose/neurosynth-frontend/src/components/Dialogs/ConfirmationDialog/ConfirmationDialog.tsx @@ -46,7 +46,7 @@ const ConfirmationDialog: React.FC = (props) => { {props.dialogMessage && dialogContent} - + + text="NEW PROJECT" + /> + + + + + )} + + ); +}; + +export default DangerZone; diff --git a/compose/neurosynth-frontend/src/components/ProjectComponents/EditMetaAnalyses/EditMetaAnalyses.tsx b/compose/neurosynth-frontend/src/components/ProjectComponents/EditMetaAnalyses/EditMetaAnalyses.tsx index 64f835689..b5b98feeb 100644 --- a/compose/neurosynth-frontend/src/components/ProjectComponents/EditMetaAnalyses/EditMetaAnalyses.tsx +++ b/compose/neurosynth-frontend/src/components/ProjectComponents/EditMetaAnalyses/EditMetaAnalyses.tsx @@ -1,7 +1,8 @@ -import { Box, Button, Stepper } from '@mui/material'; +import { Stepper } from '@mui/material'; import CurationStep from 'components/ProjectComponents/EditMetaAnalyses/CurationStep/CurationStep'; import ExtractionStep from 'components/ProjectComponents/EditMetaAnalyses/ExtractionStep/ExtractionStep'; import SpecificationStep from 'components/ProjectComponents/EditMetaAnalyses/SpecificationStep/SpecificationStep'; +import { useGetStudysetById } from 'hooks'; import useGetCurationSummary from 'hooks/useGetCurationSummary'; import useGetExtractionSummary from 'hooks/useGetExtractionSummary'; import ProjectPageStyles from 'pages/Projects/ProjectPage/ProjectPage.styles'; @@ -10,17 +11,13 @@ import { useProjectExtractionMetadata, } from 'pages/Projects/ProjectPage/ProjectStore'; import { useParams } from 'react-router-dom'; -import { useClearProvenance } from 'pages/Projects/ProjectPage/ProjectStore'; -import { useGetStudysetById } from 'hooks'; - -const env = process.env.REACT_APP_ENV as 'DEV' | 'STAGING' | 'PROD'; +import DangerZone from './DangerZone/DangerZone'; const EditMetaAnalyses: React.FC = (props) => { const { projectId }: { projectId: string } = useParams(); const extractionMetadata = useProjectExtractionMetadata(); const { total, included, uncategorized } = useGetCurationSummary(); const { data: studyset } = useGetStudysetById(extractionMetadata?.studysetId || ''); - const clearProvenance = useClearProvenance(); const curationStepHasBeenInitialized = useProjectCurationColumns().length > 0; @@ -47,18 +44,7 @@ const EditMetaAnalyses: React.FC = (props) => { disabled={disableExtractionStep} /> - {(env === 'DEV' || env === 'STAGING') && ( - - - - )} + ); }; diff --git a/compose/neurosynth-frontend/src/components/ProjectComponents/ViewMetaAnalyses/ViewMetaAnalyses.tsx b/compose/neurosynth-frontend/src/components/ProjectComponents/ViewMetaAnalyses/ViewMetaAnalyses.tsx index 0867af044..7d5adbddf 100644 --- a/compose/neurosynth-frontend/src/components/ProjectComponents/ViewMetaAnalyses/ViewMetaAnalyses.tsx +++ b/compose/neurosynth-frontend/src/components/ProjectComponents/ViewMetaAnalyses/ViewMetaAnalyses.tsx @@ -1,5 +1,5 @@ import { Add } from '@mui/icons-material'; -import { Box, Button, Typography } from '@mui/material'; +import { Box, Button, Link, Typography } from '@mui/material'; import CreateMetaAnalysisSpecificationDialogBase from 'components/Dialogs/CreateMetaAnalysisSpecificationDialog/CreateMetaAnalysisSpecificationDialogBase'; import StateHandlerComponent from 'components/StateHandlerComponent/StateHandlerComponent'; import { useGetMetaAnalysesByProjectId } from 'hooks'; @@ -18,16 +18,19 @@ const ViewMetaAnalyses: React.FC = () => { isOpen={createMetaAnalysisDialogIsOpen} onCloseDialog={() => setCreateMetaAnalysisDialogIsOpen(false)} /> - - - {(data || []).length === 0 && ( - - No Meta-Analyses for this project. Create one using the button on the - right. - - )} - - + + {(data || []).length === 0 ? ( + + No Meta-Analyses for this project. Get started by{' '} + setCreateMetaAnalysisDialogIsOpen(true)} + > + clicking here + + + ) : ( - + )} {(data || []).map((metaAnalysis, index) => ( diff --git a/compose/neurosynth-frontend/src/hooks/__mocks__/index.ts b/compose/neurosynth-frontend/src/hooks/__mocks__/index.ts index c0491c76d..c24845283 100644 --- a/compose/neurosynth-frontend/src/hooks/__mocks__/index.ts +++ b/compose/neurosynth-frontend/src/hooks/__mocks__/index.ts @@ -100,6 +100,12 @@ const useCreateProject = jest.fn().mockReturnValue({ mutate: jest.fn(), }); +const useDeleteProject = jest.fn().mockReturnValue({ + isLoading: false, + isError: false, + mutate: jest.fn(), +}); + const useIsMounted = () => { return { __esModule: true, @@ -129,4 +135,5 @@ export { useUpdateStudy, useGetAnnotationsByStudysetId, useCreateProject, + useDeleteProject, }; diff --git a/compose/neurosynth-frontend/src/hooks/projects/useDeleteProject.tsx b/compose/neurosynth-frontend/src/hooks/projects/useDeleteProject.tsx new file mode 100644 index 000000000..14cdd0255 --- /dev/null +++ b/compose/neurosynth-frontend/src/hooks/projects/useDeleteProject.tsx @@ -0,0 +1,22 @@ +import { AxiosError, AxiosResponse } from 'axios'; +import { useSnackbar } from 'notistack'; +import { useMutation, useQueryClient } from 'react-query'; +import API from 'utils/api'; + +const useDeleteProject = () => { + const queryClient = useQueryClient(); + const { enqueueSnackbar } = useSnackbar(); + return useMutation( + (id) => API.NeurosynthServices.ProjectsService.projectsIdDelete(id), + { + onSuccess: () => { + queryClient.invalidateQueries('projects'); + }, + onError: () => { + enqueueSnackbar('There was an error deleting the project', { variant: 'error' }); + }, + } + ); +}; + +export default useDeleteProject; diff --git a/compose/neurosynth-frontend/src/neurosynth-compose-typescript-sdk b/compose/neurosynth-frontend/src/neurosynth-compose-typescript-sdk index 47eb6e2ac..c88b71f64 160000 --- a/compose/neurosynth-frontend/src/neurosynth-compose-typescript-sdk +++ b/compose/neurosynth-frontend/src/neurosynth-compose-typescript-sdk @@ -1 +1 @@ -Subproject commit 47eb6e2ac83e6a762e4a762c21666ab1234ec51e +Subproject commit c88b71f6490bde7bb90b575a7690cdee9ad40f64 diff --git a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx index aa1336d92..40d03025e 100644 --- a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx +++ b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectPage.tsx @@ -79,7 +79,7 @@ const ProjectPage: React.FC = (props) => { > {projectName || 'No name'} @@ -92,7 +92,7 @@ const ProjectPage: React.FC = (props) => { textToEdit={projectDescription || ''} > {projectDescription || 'No description'} @@ -100,7 +100,7 @@ const ProjectPage: React.FC = (props) => { - + { + return { + name: name || '', + description: description || '', + provenance: { + curationMetadata: { + columns: [], + prismaConfig: { + isPrisma: false, + identification: { + exclusionTags: [], + }, + screening: { + exclusionTags: [], + }, + eligibility: { + exclusionTags: [], + }, + }, + infoTags: [], + exclusionTags: [], + identificationSources: [], + }, + extractionMetadata: { + studysetId: undefined, + annotationId: undefined, + studyStatusList: [], + }, + metaAnalysisMetadata: { + canEditMetaAnalyses: false, + }, + }, + }; +}; diff --git a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts index 845bc3ca4..6b9e4e6a0 100644 --- a/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts +++ b/compose/neurosynth-frontend/src/pages/Projects/ProjectPage/ProjectStore.ts @@ -231,11 +231,6 @@ const useProjectStore = create()((set, get) => { new Date(latestStoreDataLastUpdated).getTime() !== new Date(serverLastUpdated).getTime() ) { - console.log({ - serverLastUpdated, - SLU: new Date(serverLastUpdated).getTime(), - NSDLU: new Date(latestStoreDataLastUpdated).getTime(), - }); const enqueueSnackbar = oldDebouncedStoreData.metadata.enqueueSnackbar; if (enqueueSnackbar) { enqueueSnackbar( diff --git a/compose/neurosynth-frontend/src/pages/Projects/ProjectsPage/ProjectsPage.tsx b/compose/neurosynth-frontend/src/pages/Projects/ProjectsPage/ProjectsPage.tsx index 25f9b3ab4..cff478471 100644 --- a/compose/neurosynth-frontend/src/pages/Projects/ProjectsPage/ProjectsPage.tsx +++ b/compose/neurosynth-frontend/src/pages/Projects/ProjectsPage/ProjectsPage.tsx @@ -1,19 +1,38 @@ import { useAuth0 } from '@auth0/auth0-react'; -import { Box, TableCell, TableRow, Typography } from '@mui/material'; +import { Box, Link, TableCell, TableRow, Typography } from '@mui/material'; import StateHandlerComponent from 'components/StateHandlerComponent/StateHandlerComponent'; import NeurosynthTable from 'components/Tables/NeurosynthTable/NeurosynthTable'; import NeurosynthTableStyles from 'components/Tables/NeurosynthTable/NeurosynthTable.styles'; import useGetProjects from 'hooks/projects/useGetProjects'; import { useIsMutating } from 'react-query'; import { useHistory } from 'react-router-dom'; +import { generateNewProjectData } from '../ProjectPage/ProjectStore.helpers'; +import { useCreateProject, useGuard } from 'hooks'; +import ProgressLoader from 'components/ProgressLoader/ProgressLoader'; const ProjectsPage: React.FC = (props) => { - const { user } = useAuth0(); - const { data, isError, isLoading, isFetching } = useGetProjects(user?.sub); + const { user, isAuthenticated } = useAuth0(); + const { + data, + isError, + isLoading: getProjectsIsLoading, + isFetching, + } = useGetProjects(user?.sub); const createProjectIsFetchingNum = useIsMutating('create-project'); const history = useHistory(); + const { mutate, isLoading: createProjectIsLoading } = useCreateProject(); + useGuard('/', 'not authenticated', !isAuthenticated); + + const handleCreateProject = () => { + mutate(generateNewProjectData('Untitled', ''), { + onSuccess: (arg) => { + history.push(`/projects/${arg.data.id || ''}`); + }, + }); + }; const createProjectIsFetching = createProjectIsFetchingNum > 0; + const noProjects = (data?.length || []) === 0; return ( @@ -23,45 +42,64 @@ const ProjectsPage: React.FC = (props) => { - No projects found - ), - }} - headerCells={[ - { - text: 'Name', - key: 'name', - styles: { color: 'primary.contrastText', fontWeight: 'bold' }, - }, - { - text: 'Description', - key: 'description', - styles: { color: 'primary.contrastText', fontWeight: 'bold' }, - }, - ]} - rows={(data || []).map((project, index) => ( - history.push(`/projects/${project?.id}`)} - > - - {project?.name || No name} - - - {project?.description || ( - No description - )} - - - ))} - /> + {noProjects ? ( + + You haven't created a project yet.{' '} + {createProjectIsLoading ? ( + + ) : ( + + Click here to get started + + )} + + ) : ( + + No projects found + + ), + }} + headerCells={[ + { + text: 'Name', + key: 'name', + styles: { color: 'primary.contrastText', fontWeight: 'bold' }, + }, + { + text: 'Description', + key: 'description', + styles: { color: 'primary.contrastText', fontWeight: 'bold' }, + }, + ]} + rows={(data || []).map((project, index) => ( + history.push(`/projects/${project?.id}`)} + > + + {project?.name || No name} + + + {project?.description || ( + No description + )} + + + ))} + /> + )} ); }; diff --git a/compose/neurosynth-frontend/src/stores/AnnotationStore.helpers.ts b/compose/neurosynth-frontend/src/stores/AnnotationStore.helpers.ts index 989573e8a..1a1562bdd 100644 --- a/compose/neurosynth-frontend/src/stores/AnnotationStore.helpers.ts +++ b/compose/neurosynth-frontend/src/stores/AnnotationStore.helpers.ts @@ -18,7 +18,6 @@ export const noteKeyArrToDefaultNoteKeyObj = (noteKeys: NoteKeyType[]): Annotati acc[curr.key] = null; return acc; }, {} as AnnotationNoteType); - console.log(x); return x; }; diff --git a/compose/neurosynth-frontend/tsconfig.json b/compose/neurosynth-frontend/tsconfig.json index 20c6853ab..65367e6db 100644 --- a/compose/neurosynth-frontend/tsconfig.json +++ b/compose/neurosynth-frontend/tsconfig.json @@ -2,12 +2,7 @@ "compilerOptions": { "baseUrl": "src", "target": "es6", - "lib": [ - "dom", - "dom.iterable", - "es6", - "esnext" - ], + "lib": ["dom", "dom.iterable", "es6", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -21,12 +16,7 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", - "types": [ - "cypress", - "node" - ] + "types": ["cypress", "node"] }, - "include": [ - "src" - ] + "include": ["src"] }