Skip to content

Commit

Permalink
518 extraction phase can we make the list of studies more spreadsheet…
Browse files Browse the repository at this point in the history
… like (#824)

* feat: added wireframes for extraction

* feat: added table

* feat: implemented table and table ordering during study edit

* feat: preserve table state in session storage and fix unit tests

* feat: finished integration tests

* fix: table pagination resets on data update

* feat: updated table with feedback

* fix: integration test
  • Loading branch information
nicoalee authored Sep 23, 2024
1 parent ac12969 commit 83b42d9
Show file tree
Hide file tree
Showing 14 changed files with 334 additions and 309 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ describe('ExtractionTable', () => {
});

it('should sort by year desc', () => {
cy.contains('Year').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(0).click();

cy.wait('@studysetFixture').then((studysetFixture) => {
const studyset = studysetFixture.response?.body as StudysetReturn;
Expand All @@ -227,8 +226,8 @@ describe('ExtractionTable', () => {
});

it('should sort by year asc', () => {
cy.contains('Year').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(0).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(0).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@studysetFixture').then((studysetFixture) => {
Expand All @@ -250,8 +249,7 @@ describe('ExtractionTable', () => {
});

it('should sort by name asc', () => {
cy.contains('Name').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(1).click();

cy.wait('@studysetFixture').then((studysetFixture) => {
const studyset = studysetFixture.response?.body as StudysetReturn;
Expand All @@ -272,8 +270,8 @@ describe('ExtractionTable', () => {
});

it('should sort by name desc', () => {
cy.contains('Name').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(1).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(1).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@studysetFixture').then((studysetFixture) => {
Expand All @@ -293,8 +291,7 @@ describe('ExtractionTable', () => {
});

it('should sort by authors desc', () => {
cy.contains('Authors').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(2).click();

cy.wait('@studysetFixture').then((studysetFixture) => {
const studyset = studysetFixture.response?.body as StudysetReturn;
Expand All @@ -313,8 +310,8 @@ describe('ExtractionTable', () => {
});

it('should sort by authors asc', () => {
cy.contains('Authors').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(2).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(2).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@studysetFixture').then((studysetFixture) => {
Expand All @@ -334,8 +331,7 @@ describe('ExtractionTable', () => {
});

it('should sort by journal desc', () => {
cy.contains('Journal').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(3).click();

cy.wait('@studysetFixture').then((studysetFixture) => {
const studyset = studysetFixture.response?.body as StudysetReturn;
Expand All @@ -354,8 +350,8 @@ describe('ExtractionTable', () => {
});

it('should sort by journal desc', () => {
cy.contains('Journal').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(3).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(3).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@studysetFixture').then((studysetFixture) => {
Expand All @@ -375,8 +371,7 @@ describe('ExtractionTable', () => {
});

it('should sort by doi desc', () => {
cy.contains('DOI').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(4).click();

cy.wait('@studysetFixture').then((studysetFixture) => {
const studyset = studysetFixture.response?.body as StudysetReturn;
Expand All @@ -396,8 +391,8 @@ describe('ExtractionTable', () => {
});
});
it('should sort by doi asc', () => {
cy.contains('DOI').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(4).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(4).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@studysetFixture').then((studysetFixture) => {
Expand All @@ -417,8 +412,7 @@ describe('ExtractionTable', () => {
});

it('should sort by pmid desc', () => {
cy.contains('PMID').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(5).click();

cy.wait('@studysetFixture').then((studysetFixture) => {
const studyset = studysetFixture.response?.body as StudysetReturn;
Expand All @@ -443,8 +437,8 @@ describe('ExtractionTable', () => {
});

it('should sort by pmid asc', () => {
cy.contains('PMID').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(5).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(5).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@studysetFixture').then((studysetFixture) => {
Expand All @@ -468,8 +462,7 @@ describe('ExtractionTable', () => {
});

it('should sort by status desc', () => {
cy.contains('Status').click();
cy.get('[data-testid="ArrowDownwardIcon"]').should('exist');
cy.get('[data-testid="ArrowDownwardIcon"]').eq(6).click();

cy.wait('@projectFixture').then((projectFixture) => {
const project = projectFixture?.response?.body as INeurosynthProjectReturn;
Expand Down Expand Up @@ -525,8 +518,8 @@ describe('ExtractionTable', () => {
});

it('should sort by status asc', () => {
cy.contains('Status').click();
cy.get('[data-testid="ArrowDownwardIcon"]').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(6).click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(6).click();
cy.get('[data-testid="ArrowUpwardIcon"]').should('exist');

cy.wait('@projectFixture').then((projectFixture) => {
Expand Down Expand Up @@ -583,7 +576,7 @@ describe('ExtractionTable', () => {
});
});

describe.only('pagination', () => {
describe('pagination', () => {
beforeEach(() => {
cy.fixture('studyset').then((studyset) => {
// as we are artificially creating new studies below, the out of sync popup wil appear. That's expected and
Expand Down Expand Up @@ -668,7 +661,7 @@ describe('ExtractionTable', () => {
});

it('should save the filter and sorting to the table state', () => {
cy.contains('Year').click();
cy.get('[data-testid="ArrowDownwardIcon"]').eq(0).click(); // click on year sort
cy.get('input').eq(1).click();
cy.get(`input`).eq(1).type('Activation');

Expand All @@ -681,7 +674,7 @@ describe('ExtractionTable', () => {
cy.window().then((window) => {
const state = window.sessionStorage.getItem(`abc123-extraction-table`);
const parsedState = JSON.parse(state || '{}');
console.log(parsedState);

cy.wrap(parsedState).should('deep.equal', {
columnFilters: [{ id: 'name', value: 'Activation' }],
sorting: [{ id: 'year', desc: true }],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
.completed {
background-color: #e5ffe5;
background-color: #f8fff8;
}

.savedforlater {
background-color: #effbff;
background-color: #f1fbff;
}

.uncategorized {
/* background-color: #ffffeb; */
background-color: white;
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,12 @@ const ExtractionTable: React.FC = () => {
getPaginationRowModel: getPaginationRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnFiltersChange: setColumnFilters,
autoResetPageIndex: false,
state: {
pagination: pagination,
columnFilters: columnFilters,
sorting: sorting,
},
meta: {
studyStatusMap,
},
});

const handleRowsPerPageChange = useCallback(
Expand Down Expand Up @@ -294,6 +292,7 @@ const ExtractionTable: React.FC = () => {
)}
{header.column.getCanFilter() ? (
<ExtractionTableFilterInput
table={table}
column={header.column}
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Box, IconButton, Link, Tooltip, Typography } from '@mui/material';
import { CellContext, HeaderContext } from '@tanstack/react-table';
import { IExtractionTableStudy } from './ExtractionTable';
import { ArrowDownward } from '@mui/icons-material';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import { Box, IconButton, Tooltip, Typography } from '@mui/material';
import { CellContext, HeaderContext } from '@tanstack/react-table';
import { IExtractionTableStudy } from './ExtractionTable';

export const ExtractionTableAuthorCell: React.FC<CellContext<IExtractionTableStudy, string>> = (
props
Expand All @@ -18,41 +18,35 @@ export const ExtractionTableAuthorHeader: React.FC<

return (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Sort by author" placement="top">
<Typography
sx={{ ':hover': { cursor: 'pointer' } }}
underline="hover"
variant="h6"
component={Link}
onClick={() => {
if (!!isSorted) {
table.resetSorting();
} else {
table.setSorting([{ id: 'authors', desc: true }]);
}
}}
<Typography sx={{ marginRight: '4px' }} variant="h6">
Authors
</Typography>
{!isSorted ? (
<Tooltip title="Sort by author" placement="top">
<IconButton
size="small"
onClick={() => {
if (!!isSorted) {
table.resetSorting();
} else {
table.setSorting([{ id: 'authors', desc: true }]);
}
}}
>
<ArrowDownward sx={{ color: 'lightgray' }} />
</IconButton>
</Tooltip>
) : isSorted === 'asc' ? (
<IconButton size="small" onClick={() => table.resetSorting()}>
<ArrowUpwardIcon sx={{ color: 'secondary.main' }} />
</IconButton>
) : (
<IconButton
size="small"
onClick={() => table.setSorting([{ id: 'authors', desc: false }])}
>
Authors
</Typography>
</Tooltip>
{!!isSorted && (
<>
{isSorted === 'asc' ? (
<IconButton
size="small"
onClick={() => table.setSorting([{ id: 'authors', desc: true }])}
>
<ArrowUpwardIcon />
</IconButton>
) : (
<IconButton
size="small"
onClick={() => table.setSorting([{ id: 'authors', desc: false }])}
>
<ArrowDownward />
</IconButton>
)}
</>
<ArrowDownward sx={{ color: 'secondary.main' }} />
</IconButton>
)}
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Box, IconButton, Link, Tooltip, Typography } from '@mui/material';
import { CellContext, HeaderContext } from '@tanstack/react-table';
import { IExtractionTableStudy } from './ExtractionTable';
import { ArrowDownward } from '@mui/icons-material';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import { Box, IconButton, Tooltip, Typography } from '@mui/material';
import { CellContext, HeaderContext } from '@tanstack/react-table';
import { IExtractionTableStudy } from './ExtractionTable';

export const ExtractionTableDOICell: React.FC<CellContext<IExtractionTableStudy, string>> = (
props
Expand All @@ -22,41 +22,35 @@ export const ExtractionTableDOIHeader: React.FC<HeaderContext<IExtractionTableSt
const isSorted = column.getIsSorted();
return (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Tooltip title="Sort by doi" placement="top">
<Typography
sx={{ ':hover': { cursor: 'pointer' } }}
underline="hover"
variant="h6"
component={Link}
onClick={() => {
if (!!isSorted) {
table.resetSorting();
} else {
table.setSorting([{ id: 'doi', desc: true }]);
}
}}
<Typography sx={{ marginRight: '4px' }} variant="h6">
DOI
</Typography>
{!isSorted ? (
<Tooltip title="Sort by DOI" placement="top">
<IconButton
size="small"
onClick={() => {
if (!!isSorted) {
table.resetSorting();
} else {
table.setSorting([{ id: 'doi', desc: true }]);
}
}}
>
<ArrowDownward sx={{ color: 'lightgray' }} />
</IconButton>
</Tooltip>
) : isSorted === 'asc' ? (
<IconButton size="small" onClick={() => table.resetSorting()}>
<ArrowUpwardIcon sx={{ color: 'secondary.main' }} />
</IconButton>
) : (
<IconButton
size="small"
onClick={() => table.setSorting([{ id: 'doi', desc: false }])}
>
DOI
</Typography>
</Tooltip>
{!!isSorted && (
<>
{isSorted === 'asc' ? (
<IconButton
size="small"
onClick={() => table.setSorting([{ id: 'doi', desc: true }])}
>
<ArrowUpwardIcon />
</IconButton>
) : (
<IconButton
size="small"
onClick={() => table.setSorting([{ id: 'doi', desc: false }])}
>
<ArrowDownward />
</IconButton>
)}
</>
<ArrowDownward sx={{ color: 'secondary.main' }} />
</IconButton>
)}
</Box>
);
Expand Down
Loading

0 comments on commit 83b42d9

Please sign in to comment.