Skip to content

Commit

Permalink
198 add publicprivate button for user owned studiesdatasetsannotations (
Browse files Browse the repository at this point in the history
#751)

* feat: update react router

* feat: added readonly annotations table and project owner

* add spaces

* [ENH] allow "post" to annotation-analysis endpoint (#742)

* allow "post" to annotation-analysis endpoint

* fix f string

* test more and fix formatting

* update openapi to main

* [FIX] match input study by either doi and/or pmid (#744)

* match input study by either doi and/or pmid

* black

* fix: e2e tests

* fix: update openapi version

* fix: sdk update

* fix: correct sdk version

* fix: openapi version

* chore: add tests for public private button

* fix: resolve merge conflicts

* feat: better loading text support

* fix: update codespell

* chore: remove only warn for codespell

* fix: added back exclude glob

* fix: try singlequote

* fix: try again

---------

Co-authored-by: James Kent <[email protected]>
  • Loading branch information
nicoalee and jdkent authored Apr 10, 2024
1 parent a92ca1d commit 90c259d
Show file tree
Hide file tree
Showing 8 changed files with 905 additions and 60 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ jobs:
uses: actions/checkout@v4
- name: Codespell
uses: codespell-project/actions-codespell@master
with:
exclude_file: compose/neurosynth-frontend/cypress/fixtures/*.json
36 changes: 34 additions & 2 deletions compose/neurosynth-frontend/cypress/e2e/pages/ProjectPage.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,45 @@ describe(PAGE_NAME, () => {
beforeEach(() => {
cy.clearLocalStorage().clearSessionStorage();
cy.intercept('GET', 'https://api.appzi.io/**', { fixture: 'appzi' }).as('appziFixture');
cy.intercept('GET', `**/api/studysets/*`, { fixture: 'studyset' }).as('studysetFixture');
cy.intercept('PUT', `**/api/projects/*`, { fixture: 'projects/projectPut' }).as(
'updateProjectFixture'
);
});

it('should load successfully', () => {
cy.intercept('GET', `**/api/projects/*`, { fixture: 'projects/projectExtractionStep' }).as(
'projectFixture'
);
cy.intercept('GET', `**/api/studysets/*`, { fixture: 'studyset' }).as('studysetFixture');
cy.visit(PATH).wait('@projectFixture');
});

it('should load successfully', () => {
it('should set the project from private to public', () => {
cy.intercept('GET', `**/api/projects/*`, { fixture: 'projects/projectExtractionStep' }).as(
'projectFixture'
);
cy.visit(PATH).wait('@projectFixture');
cy.contains('button', 'Public').click();
cy.wait('@updateProjectFixture').then((res) => {
assert.exists(res.request.body.public);
assert.isTrue(res.request.body.public);
});
});

it.only('should set the project from public to private', () => {
cy.fixture('projects/projectExtractionStep').then((projectFixture) => {
projectFixture.public = true;
cy.intercept('GET', `**/api/projects/*`, projectFixture).as('projectFixturePublic');
});
cy.visit(PATH)
.wait('@projectFixturePublic')
.then((res) => {
console.log({ res });
});
cy.contains('button', 'Private').click();
cy.wait('@updateProjectFixture').then((res) => {
assert.exists(res.request.body.public);
assert.isFalse(res.request.body.public);
});
});
});
711 changes: 711 additions & 0 deletions compose/neurosynth-frontend/cypress/fixtures/projects/projectPut.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const TextEdit: React.FC<ITextEdit> = (props) => {
}}
onClick={() => setEditMode(true)}
>
<EditIcon sx={{ fontSize: '20px' }} color="primary" />
<EditIcon sx={{ fontSize: '20px' }} color="secondary" />
</IconButton>
)}
</Box>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
import { Box, Typography } from '@mui/material';
import { useUpdateProjectIsLoading } from 'pages/Projects/ProjectPage/ProjectStore';
import {
useProjectMetadataHasUnsavedchanges,
useUpdateProjectIsLoading,
} from 'pages/Projects/ProjectPage/ProjectStore';

const ProjectIsLoadingText: React.FC<{ isLoading?: boolean }> = (props) => {
const updateProjectIsLoading = useUpdateProjectIsLoading();
const projectMetadataHasUnsavedchanges = useProjectMetadataHasUnsavedchanges();

const isLoading = updateProjectIsLoading || props.isLoading;

return (
<Box sx={{ marginLeft: '2rem' }}>
<Typography
sx={{
color: 'muted.main',
fontSize: '1.5rem',
display: isLoading ? 'inline' : 'none',
}}
>
updating...
</Typography>
</Box>
);
if (isLoading) {
return (
<Box sx={{ marginLeft: '2rem' }}>
<Typography
sx={{
color: 'muted.main',
fontSize: '1.25rem',
display: 'inline',
}}
>
updating...
</Typography>
</Box>
);
}

if (projectMetadataHasUnsavedchanges) {
return (
<Box sx={{ marginLeft: '2rem' }}>
<Typography
sx={{
color: 'muted.main',
fontSize: '1.25rem',
display: 'inline',
}}
>
unsaved changes
</Typography>
</Box>
);
}

return <></>;
};

export default ProjectIsLoadingText;
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { EAnalysisType } from 'hooks/metaAnalyses/useCreateAlgorithmSpecificatio
import useGetMetaAnalysisResultById from 'hooks/metaAnalyses/useGetMetaAnalysisResultById';
import useGetSpecificationById from 'hooks/metaAnalyses/useGetSpecificationById';
import useUpdateMetaAnalysis from 'hooks/metaAnalyses/useUpdateMetaAnalysis';
import useUserCanEdit from 'hooks/useUserCanEdit';
import {
Annotation,
ResultReturn,
Expand All @@ -40,7 +41,6 @@ import { useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { NeurostoreAnnotation } from 'utils/api';
import MetaAnalysisPageStyles from './MetaAnalysisPage.styles';
import useUserCanEdit from 'hooks/useUserCanEdit';
import { getResultStatus } from 'components/ProjectComponents/ViewMetaAnalyses/ViewMetaAnalysis';

const metaAnalysisSpecification: IMetaAnalysisParamsSpecification = metaAnalysisSpec;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Box, Tab, Tabs, Typography } from '@mui/material';
import LockIcon from '@mui/icons-material/Lock';
import PublicIcon from '@mui/icons-material/Public';
import { Box, Chip, Tab, Tabs, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
import NeurosynthBreadcrumbs from 'components/NeurosynthBreadcrumbs/NeurosynthBreadcrumbs';
import StateHandlerComponent from 'components/StateHandlerComponent/StateHandlerComponent';
import TextEdit from 'components/TextEdit/TextEdit';
Expand All @@ -7,12 +9,15 @@ import ProjectIsLoadingText from 'pages/CurationPage/ProjectIsLoadingText';
import {
useGetProjectIsLoading,
useInitProjectStoreIfRequired,
useProjectCreatedAt,
useProjectDescription,
useProjectIsPublic,
useProjectMetaAnalysisCanEdit,
useProjectName,
useProjectUser,
useProjectUsername,
useUpdateProjectDescription,
useUpdateProjectIsPublic,
useUpdateProjectName,
} from 'pages/Projects/ProjectPage/ProjectStore';
import { useMemo } from 'react';
Expand All @@ -36,13 +41,15 @@ const ProjectPage: React.FC = (props) => {

const updateProjectName = useUpdateProjectName();
const updateProjectDescription = useUpdateProjectDescription();
const updateProjectIsPublic = useUpdateProjectIsPublic();
const metaAnalysesTabEnabled = useProjectMetaAnalysisCanEdit();
const getProjectIsLoading = useGetProjectIsLoading();
const projectName = useProjectName();
const createdAt = useProjectCreatedAt();
const projectUser = useProjectUser();
const projectUserName = useProjectUsername();
const projectDescription = useProjectDescription();

const isPublic = useProjectIsPublic();
const userCanEdit = useUserCanEdit(projectUser || undefined);

const tab = useMemo(
Expand Down Expand Up @@ -72,43 +79,93 @@ const ProjectPage: React.FC = (props) => {
</Box>

<Box sx={{ marginBottom: '0.5rem' }}>
<TextEdit
onSave={(updatedName, label) => updateProjectName(updatedName)}
sx={{ input: { fontSize: '1.5rem' } }}
textToEdit={projectName || ''}
editIconIsVisible={userCanEdit}
>
<Typography
sx={{
color: projectName ? 'initial' : 'warning.dark',
<Box sx={{ marginBottom: '0.5rem' }}>
<ToggleButtonGroup
exclusive
onChange={(event, newVal) => {
// do not update if newVal is the same as the current value or if it doesnt exist
if (newVal === null || newVal === isPublic) return;
updateProjectIsPublic(newVal === 'PUBLIC');
}}
variant="h5"
color="primary"
value={isPublic ? 'PUBLIC' : 'PRIVATE'}
size="small"
>
{projectName || 'No name'}
</Typography>
</TextEdit>
<TextEdit
onSave={(updatedDescription, label) =>
updateProjectDescription(updatedDescription)
}
sx={{ input: { fontSize: '1.25rem' } }}
textToEdit={projectDescription || ''}
editIconIsVisible={userCanEdit}
multiline
>
<Typography
<ToggleButton
value="PUBLIC"
sx={{ borderRadius: '8px', paddingLeft: '14px', height: '30px' }}
>
Public <PublicIcon sx={{ marginLeft: '10px', fontSize: '20px' }} />
</ToggleButton>
<ToggleButton
value="PRIVATE"
sx={{ borderRadius: '8px', paddingLeft: '14px', height: '30px' }}
>
Private <LockIcon sx={{ marginLeft: '10px', fontSize: '20px' }} />
</ToggleButton>
</ToggleButtonGroup>
</Box>
<Box>
<TextEdit
onSave={(updatedName, label) => updateProjectName(updatedName)}
sx={{ input: { fontSize: '1.5rem' } }}
textToEdit={projectName || ''}
editIconIsVisible={userCanEdit}
>
<Typography
sx={{ color: projectName ? 'initial' : 'warning.dark' }}
variant="h5"
>
{projectName || 'No name'}
</Typography>
</TextEdit>
<TextEdit
onSave={(updatedDescription, label) =>
updateProjectDescription(updatedDescription)
}
sx={{ input: { fontSize: '1.25rem' } }}
textToEdit={projectDescription || ''}
editIconIsVisible={userCanEdit}
multiline
>
<Typography
sx={{
color: projectDescription ? 'muted.main' : 'warning.dark',
whiteSpace: 'pre-line',
}}
variant="body1"
>
{projectDescription || 'No description'}
</Typography>
</TextEdit>
<Box
sx={{
color: projectDescription ? 'muted.main' : 'warning.dark',
whiteSpace: 'pre-line',
marginTop: '0.2rem',
display: 'flex',
justifyContent: 'space-between',
}}
variant="body1"
>
{projectDescription || 'No description'}
</Typography>
</TextEdit>
<Typography variant="body1" sx={{ color: 'muted.main' }}>
Owner: {projectUserName || 'No owner'}
</Typography>
<Box>
{projectUserName && (
<Chip
size="small"
label={`Owner: ${projectUserName}`}
variant="outlined"
sx={{ marginRight: '0.5rem' }}
/>
)}
{createdAt && (
<Chip
size="small"
label={`Created: ${
createdAt.getMonth() + 1
}/${createdAt.getDate()}/${createdAt.getFullYear()} ${createdAt.getHours()}:${createdAt.getMinutes()}`}
variant="outlined"
/>
)}
</Box>
</Box>
</Box>
</Box>

<Box sx={{ borderBottom: 1, margin: '0.5rem 0 1rem 0', borderColor: 'divider' }}>
Expand Down
Loading

0 comments on commit 90c259d

Please sign in to comment.