feat: OHIF-120 - Study List Route Template (#1693)
* fix pagination size * clean up, start a very basic route configuration * quick navigation between routes * configure webpack to read .env variables * export studylist filter * split studylist filter into a component * minor fix in studylist pagination * update studylistfilter imports * create studylist container with study list content * moving file * study list filter doc page * catch change in ui-v2 * fix: 1px gap that shows text underneath * Shift to routes folder Co-authored-by: Danny Brown <danny.ri.brown@gmail.com>
This commit is contained in:
parent
01b314522d
commit
cee09fcf8d
@ -35,6 +35,7 @@ export {
|
|||||||
StudyBrowser,
|
StudyBrowser,
|
||||||
StudyItem,
|
StudyItem,
|
||||||
StudyListExpandedRow,
|
StudyListExpandedRow,
|
||||||
|
StudyListFilter,
|
||||||
StudyListPagination,
|
StudyListPagination,
|
||||||
StudyListTable,
|
StudyListTable,
|
||||||
Svg,
|
Svg,
|
||||||
|
|||||||
@ -73,8 +73,11 @@ const StudyListFilter = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="sticky z-10 border-b-4 border-black" style={{ top: 58 }}>
|
<div
|
||||||
<div className="bg-custom-navyDark pt-3 pb-3 ">
|
className="sticky z-10 border-b-4 border-black"
|
||||||
|
style={{ top: '57px' }}
|
||||||
|
>
|
||||||
|
<div className="bg-primary-dark pt-3 pb-3 ">
|
||||||
<InputGroup
|
<InputGroup
|
||||||
inputMeta={filtersMeta}
|
inputMeta={filtersMeta}
|
||||||
values={filterValues}
|
values={filterValues}
|
||||||
118
platform/ui/src/components/StudyListFilter/StudyListFilter.mdx
Normal file
118
platform/ui/src/components/StudyListFilter/StudyListFilter.mdx
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
---
|
||||||
|
name: Study List Filter
|
||||||
|
menu: Data Display
|
||||||
|
route: components/studyListFilter
|
||||||
|
---
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Playground, Props } from 'docz';
|
||||||
|
import { StudyListFilter } from '@ohif/ui';
|
||||||
|
|
||||||
|
# Study List Filter
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { StudyListFilter } from '@ohif/ui';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic usage
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
{() => {
|
||||||
|
const defaultFilterValues = {
|
||||||
|
patientName: '',
|
||||||
|
mrn: '',
|
||||||
|
studyDate: {
|
||||||
|
startDate: null,
|
||||||
|
endDate: null,
|
||||||
|
},
|
||||||
|
description: '',
|
||||||
|
modality: undefined,
|
||||||
|
accession: '',
|
||||||
|
sortBy: '',
|
||||||
|
sortDirection: 'none',
|
||||||
|
page: 0,
|
||||||
|
resultsPerPage: 25,
|
||||||
|
};
|
||||||
|
const [filterValues, setFilterValues] = useState(defaultFilterValues);
|
||||||
|
const filtersMeta = [
|
||||||
|
{
|
||||||
|
name: 'patientName',
|
||||||
|
displayName: 'Patient Name',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mrn',
|
||||||
|
displayName: 'MRN',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'studyDate',
|
||||||
|
displayName: 'Study date',
|
||||||
|
inputType: 'DateRange',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
displayName: 'Description',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'modality',
|
||||||
|
displayName: 'Modality',
|
||||||
|
inputType: 'MultiSelect',
|
||||||
|
inputProps: {
|
||||||
|
options: [
|
||||||
|
{ value: 'SEG', label: 'SEG' },
|
||||||
|
{ value: 'CT', label: 'CT' },
|
||||||
|
{ value: 'MR', label: 'MR' },
|
||||||
|
{ value: 'SR', label: 'SR' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'accession',
|
||||||
|
displayName: 'Accession',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'instances',
|
||||||
|
displayName: 'Instances',
|
||||||
|
inputType: 'None',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const isFiltering = (filterValues, defaultFilterValues) => {
|
||||||
|
return Object.keys(defaultFilterValues).some(name => {
|
||||||
|
return filterValues[name] !== defaultFilterValues[name];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<StudyListFilter
|
||||||
|
numOfStudies={100}
|
||||||
|
filtersMeta={filtersMeta}
|
||||||
|
filterValues={filterValues}
|
||||||
|
setFilterValues={setFilterValues}
|
||||||
|
clearFilters={() => setFilterValues(defaultFilterValues)}
|
||||||
|
isFiltering={isFiltering(filterValues, defaultFilterValues)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={StudyListFilter} />
|
||||||
1
platform/ui/src/components/StudyListFilter/index.js
Normal file
1
platform/ui/src/components/StudyListFilter/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './StudyListFilter';
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Button, ButtonGroup, Icon, IconButton, Typography } from '@ohif/ui';
|
import { Button, ButtonGroup, Icon, Typography } from '@ohif/ui';
|
||||||
|
|
||||||
const StudyListPagination = ({
|
const StudyListPagination = ({
|
||||||
onChangePage,
|
onChangePage,
|
||||||
@ -21,8 +21,7 @@ const StudyListPagination = ({
|
|||||||
<div className="relative mr-3">
|
<div className="relative mr-3">
|
||||||
<select
|
<select
|
||||||
defaultValue={perPage}
|
defaultValue={perPage}
|
||||||
className="block appearance-none w-full bg-transparent border border-custom-darkSlateBlue text-white text-base px-2 pr-4 rounded leading-tight focus:outline-none"
|
className="block appearance-none w-full bg-transparent border border-common-active text-white text-base px-2 pr-4 rounded leading-tight focus:outline-none h-8"
|
||||||
style={{ height: 28 }}
|
|
||||||
onChange={e => onChangePerPage(e.target.value)}
|
onChange={e => onChangePerPage(e.target.value)}
|
||||||
onBlur={() => {}}
|
onBlur={() => {}}
|
||||||
>
|
>
|
||||||
@ -48,22 +47,22 @@ const StudyListPagination = ({
|
|||||||
Page {currentPage}
|
Page {currentPage}
|
||||||
</Typography>
|
</Typography>
|
||||||
<ButtonGroup color="primary">
|
<ButtonGroup color="primary">
|
||||||
<IconButton
|
<Button
|
||||||
size="inherit"
|
size="initial"
|
||||||
className="border-common-active px-4 py-2 text-base"
|
className="border-common-active px-4 py-2 text-base"
|
||||||
color="white"
|
color="white"
|
||||||
onClick={() => navigateToPage(1)}
|
onClick={() => navigateToPage(1)}
|
||||||
>
|
>
|
||||||
<>{`<<`}</>
|
{`<<`}
|
||||||
</IconButton>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="inherit"
|
size="initial"
|
||||||
className="border-common-active py-2 px-2 text-base"
|
className="border-common-active py-2 px-2 text-base"
|
||||||
color="white"
|
color="white"
|
||||||
onClick={() => navigateToPage(currentPage - 1)}
|
onClick={() => navigateToPage(currentPage - 1)}
|
||||||
>{`< Previous`}</Button>
|
>{`< Previous`}</Button>
|
||||||
<Button
|
<Button
|
||||||
size="inherit"
|
size="initial"
|
||||||
className="border-common-active py-2 px-4 text-base"
|
className="border-common-active py-2 px-4 text-base"
|
||||||
color="white"
|
color="white"
|
||||||
onClick={() => navigateToPage(currentPage + 1)}
|
onClick={() => navigateToPage(currentPage + 1)}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import StudyListPagination from './StudyListPagination';
|
|||||||
import StudyListTable from './StudyListTable';
|
import StudyListTable from './StudyListTable';
|
||||||
import Svg from './Svg';
|
import Svg from './Svg';
|
||||||
import StudyItem from './StudyItem';
|
import StudyItem from './StudyItem';
|
||||||
|
import StudyListFilter from './StudyListFilter';
|
||||||
import Table from './Table';
|
import Table from './Table';
|
||||||
import TableBody from './TableBody';
|
import TableBody from './TableBody';
|
||||||
import TableCell from './TableCell';
|
import TableCell from './TableCell';
|
||||||
@ -66,6 +67,7 @@ export {
|
|||||||
StudyBrowser,
|
StudyBrowser,
|
||||||
StudyItem,
|
StudyItem,
|
||||||
StudyListExpandedRow,
|
StudyListExpandedRow,
|
||||||
|
StudyListFilter,
|
||||||
StudyListPagination,
|
StudyListPagination,
|
||||||
StudyListTable,
|
StudyListTable,
|
||||||
Svg,
|
Svg,
|
||||||
|
|||||||
@ -13,11 +13,11 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
StudyListPagination,
|
StudyListPagination,
|
||||||
StudyListTable,
|
StudyListTable,
|
||||||
|
StudyListFilter,
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
|
||||||
// fix imports after refactor
|
// fix imports after refactor
|
||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import StudyListFilter from './components/StudyListFilter';
|
|
||||||
|
|
||||||
const filtersMeta = [
|
const filtersMeta = [
|
||||||
{
|
{
|
||||||
@ -96,7 +96,7 @@ const defaultFilterValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const isFiltering = (filterValues, defaultFilterValues) => {
|
const isFiltering = (filterValues, defaultFilterValues) => {
|
||||||
return Object.keys(defaultFilterValues).some((name) => {
|
return Object.keys(defaultFilterValues).some(name => {
|
||||||
return filterValues[name] !== defaultFilterValues[name];
|
return filterValues[name] !== defaultFilterValues[name];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -109,7 +109,7 @@ const StudyList = () => {
|
|||||||
|
|
||||||
const tableDataSource = studies.map((study, key) => {
|
const tableDataSource = studies.map((study, key) => {
|
||||||
const rowKey = key + 1;
|
const rowKey = key + 1;
|
||||||
const isExpanded = expandedRows.some((k) => k === rowKey);
|
const isExpanded = expandedRows.some(k => k === rowKey);
|
||||||
const {
|
const {
|
||||||
AccessionNumber,
|
AccessionNumber,
|
||||||
Modalities,
|
Modalities,
|
||||||
@ -128,7 +128,7 @@ const StudyList = () => {
|
|||||||
Instances: 'Instances',
|
Instances: 'Instances',
|
||||||
};
|
};
|
||||||
|
|
||||||
const seriesTableDataSource = series.map((seriesItem) => {
|
const seriesTableDataSource = series.map(seriesItem => {
|
||||||
const { SeriesNumber, Modality, instances } = seriesItem;
|
const { SeriesNumber, Modality, instances } = seriesItem;
|
||||||
return {
|
return {
|
||||||
description: 'Patient Protocol',
|
description: 'Patient Protocol',
|
||||||
@ -238,8 +238,8 @@ const StudyList = () => {
|
|||||||
</StudyListExpandedRow>
|
</StudyListExpandedRow>
|
||||||
),
|
),
|
||||||
onClickRow: () =>
|
onClickRow: () =>
|
||||||
setExpandedRows((s) =>
|
setExpandedRows(s =>
|
||||||
isExpanded ? s.filter((n) => rowKey !== n) : [...s, rowKey]
|
isExpanded ? s.filter(n => rowKey !== n) : [...s, rowKey]
|
||||||
),
|
),
|
||||||
isExpanded,
|
isExpanded,
|
||||||
};
|
};
|
||||||
@ -248,13 +248,13 @@ const StudyList = () => {
|
|||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [perPage, setPerPage] = useState(25);
|
const [perPage, setPerPage] = useState(25);
|
||||||
const totalPages = Math.floor(numOfStudies / perPage);
|
const totalPages = Math.floor(numOfStudies / perPage);
|
||||||
const onChangePage = (page) => {
|
const onChangePage = page => {
|
||||||
if (page > totalPages) {
|
if (page > totalPages) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
};
|
};
|
||||||
const onChangePerPage = (perPage) => {
|
const onChangePerPage = perPage => {
|
||||||
setPerPage(perPage);
|
setPerPage(perPage);
|
||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,12 +18,10 @@ import {
|
|||||||
EmptyStudies,
|
EmptyStudies,
|
||||||
StudyListTable,
|
StudyListTable,
|
||||||
StudyListPagination,
|
StudyListPagination,
|
||||||
|
StudyListFilter
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
|
||||||
<!-- TEMPORARY IMPORTING -- SHOULD USE InputGroup after PR #1580 gets merged -->
|
|
||||||
|
|
||||||
import StudyListFilter from './components/StudyListFilter';
|
|
||||||
import { getMockedStudies } from '../../utils/';
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
@ -259,7 +257,7 @@ components.
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
const handleStudyList = (number) => {
|
const handleStudyList = (number) => {
|
||||||
const studies = getMockedStudies(number);
|
const studies = utils.getMockedStudies(number);
|
||||||
setStudies(studies);
|
setStudies(studies);
|
||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -94,7 +94,7 @@ module.exports = (env, argv) => {
|
|||||||
swDest: 'sw.js',
|
swDest: 'sw.js',
|
||||||
swSrc: path.join(SRC_DIR, 'service-worker.js'),
|
swSrc: path.join(SRC_DIR, 'service-worker.js'),
|
||||||
// Increase the limit to 4mb:
|
// Increase the limit to 4mb:
|
||||||
// maximumFileSizeToCacheInBytes: 4 * 1024 * 1024
|
maximumFileSizeToCacheInBytes: 4 * 1024 * 1024,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
// https://webpack.js.org/configuration/dev-server/
|
// https://webpack.js.org/configuration/dev-server/
|
||||||
|
|||||||
@ -1,13 +1,320 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import {
|
||||||
|
utils,
|
||||||
|
Icon,
|
||||||
|
StudyListExpandedRow,
|
||||||
|
Button,
|
||||||
|
NavBar,
|
||||||
|
Svg,
|
||||||
|
IconButton,
|
||||||
|
EmptyStudies,
|
||||||
|
StudyListTable,
|
||||||
|
StudyListPagination,
|
||||||
|
StudyListFilter,
|
||||||
|
} from '@ohif/ui';
|
||||||
|
|
||||||
|
function StudyListContainer() {
|
||||||
|
const defaultFilterValues = {
|
||||||
|
patientName: '',
|
||||||
|
mrn: '',
|
||||||
|
studyDate: {
|
||||||
|
startDate: null,
|
||||||
|
endDate: null,
|
||||||
|
},
|
||||||
|
description: '',
|
||||||
|
modality: undefined,
|
||||||
|
accession: '',
|
||||||
|
sortBy: '',
|
||||||
|
sortDirection: 'none',
|
||||||
|
page: 0,
|
||||||
|
resultsPerPage: 25,
|
||||||
|
};
|
||||||
|
const [filterValues, setFilterValues] = useState(defaultFilterValues);
|
||||||
|
const studies = utils.getMockedStudies(100);
|
||||||
|
const numOfStudies = studies.length;
|
||||||
|
const [expandedRows, setExpandedRows] = useState([]);
|
||||||
|
const filtersMeta = [
|
||||||
|
{
|
||||||
|
name: 'patientName',
|
||||||
|
displayName: 'Patient Name',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mrn',
|
||||||
|
displayName: 'MRN',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'studyDate',
|
||||||
|
displayName: 'Study date',
|
||||||
|
inputType: 'DateRange',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
displayName: 'Description',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'modality',
|
||||||
|
displayName: 'Modality',
|
||||||
|
inputType: 'MultiSelect',
|
||||||
|
inputProps: {
|
||||||
|
options: [
|
||||||
|
{ value: 'SEG', label: 'SEG' },
|
||||||
|
{ value: 'CT', label: 'CT' },
|
||||||
|
{ value: 'MR', label: 'MR' },
|
||||||
|
{ value: 'SR', label: 'SR' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'accession',
|
||||||
|
displayName: 'Accession',
|
||||||
|
inputType: 'Text',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'instances',
|
||||||
|
displayName: 'Instances',
|
||||||
|
inputType: 'None',
|
||||||
|
isSortable: true,
|
||||||
|
gridCol: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const isFiltering = (filterValues, defaultFilterValues) => {
|
||||||
|
return Object.keys(defaultFilterValues).some(name => {
|
||||||
|
return filterValues[name] !== defaultFilterValues[name];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const tableDataSource = studies.map((study, key) => {
|
||||||
|
const rowKey = key + 1;
|
||||||
|
const isExpanded = expandedRows.some(k => k === rowKey);
|
||||||
|
const {
|
||||||
|
AccessionNumber,
|
||||||
|
Modalities,
|
||||||
|
Instances,
|
||||||
|
StudyDescription,
|
||||||
|
PatientId,
|
||||||
|
PatientName,
|
||||||
|
StudyDate,
|
||||||
|
series,
|
||||||
|
} = study;
|
||||||
|
const seriesTableColumns = {
|
||||||
|
description: 'Description',
|
||||||
|
seriesNumber: 'Series',
|
||||||
|
modality: 'Modality',
|
||||||
|
Instances: 'Instances',
|
||||||
|
};
|
||||||
|
const seriesTableDataSource = series.map(seriesItem => {
|
||||||
|
const { SeriesNumber, Modality, instances } = seriesItem;
|
||||||
|
return {
|
||||||
|
description: 'Patient Protocol',
|
||||||
|
seriesNumber: SeriesNumber,
|
||||||
|
modality: Modality,
|
||||||
|
Instances: instances.length,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
row: [
|
||||||
|
{
|
||||||
|
key: 'patientName',
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Icon
|
||||||
|
name={isExpanded ? 'chevron-down' : 'chevron-right'}
|
||||||
|
className="mr-4"
|
||||||
|
/>
|
||||||
|
{PatientName}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'mrn',
|
||||||
|
content: PatientId,
|
||||||
|
gridCol: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'studyDate',
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<span className="mr-4">
|
||||||
|
{moment(StudyDate).format('MMM-DD-YYYY')}
|
||||||
|
</span>
|
||||||
|
<span>{moment(StudyDate).format('hh:mm A')}</span>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
gridCol: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'description',
|
||||||
|
content: StudyDescription,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'modality',
|
||||||
|
content: Modalities,
|
||||||
|
gridCol: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'accession',
|
||||||
|
content: AccessionNumber,
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'instances',
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Icon
|
||||||
|
name="group-layers"
|
||||||
|
className={classnames('inline-flex mr-2 w-4', {
|
||||||
|
'text-primary-active': isExpanded,
|
||||||
|
'text-secondary-light': !isExpanded,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
{Instances}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
gridCol: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
expandedContent: (
|
||||||
|
<StudyListExpandedRow
|
||||||
|
seriesTableColumns={seriesTableColumns}
|
||||||
|
seriesTableDataSource={seriesTableDataSource}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
rounded="full"
|
||||||
|
variant="contained"
|
||||||
|
className="mr-4 font-bold"
|
||||||
|
endIcon={<Icon name="launch-arrow" style={{ color: '#21a7c6' }} />}
|
||||||
|
>
|
||||||
|
<Link to="/viewer/123">Basic Viewer</Link>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
rounded="full"
|
||||||
|
variant="contained"
|
||||||
|
className="mr-4 font-bold"
|
||||||
|
endIcon={<Icon name="launch-arrow" style={{ color: '#21a7c6' }} />}
|
||||||
|
>
|
||||||
|
<Link to="/viewer/123">Segmentation</Link>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
rounded="full"
|
||||||
|
variant="outlined"
|
||||||
|
endIcon={<Icon name="launch-info" />}
|
||||||
|
className="font-bold"
|
||||||
|
>
|
||||||
|
Module 3
|
||||||
|
</Button>
|
||||||
|
<div className="ml-5 text-lg text-common-bright inline-flex items-center">
|
||||||
|
<Icon name="notificationwarning-diamond" className="mr-2 w-5 h-5" />
|
||||||
|
Feedback text lorem ipsum dolor sit amet
|
||||||
|
</div>
|
||||||
|
</StudyListExpandedRow>
|
||||||
|
),
|
||||||
|
onClickRow: () =>
|
||||||
|
setExpandedRows(s =>
|
||||||
|
isExpanded ? s.filter(n => rowKey !== n) : [...s, rowKey]
|
||||||
|
),
|
||||||
|
isExpanded,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const [perPage, setPerPage] = useState(25);
|
||||||
|
const totalPages = Math.floor(numOfStudies / perPage);
|
||||||
|
|
||||||
|
const onChangePage = page => {
|
||||||
|
if (page > totalPages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCurrentPage(page);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangePerPage = perPage => {
|
||||||
|
setPerPage(perPage);
|
||||||
|
setCurrentPage(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasStudies = numOfStudies > 0;
|
||||||
|
|
||||||
const StudyListContainer = () => {
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div
|
||||||
<div>StudyListContainer</div>
|
className={classnames('bg-black h-full', {
|
||||||
<Link to="/viewer/123">Go to Viewer Route</Link>
|
'h-screen': !hasStudies,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<NavBar className="justify-between border-b-4 border-black" isSticky>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="mx-3">
|
||||||
|
<Svg name="logo-ohif" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<span className="mr-3 text-common-light text-lg">
|
||||||
|
FOR INVESTIGATIONAL USE ONLY
|
||||||
|
</span>
|
||||||
|
<IconButton
|
||||||
|
variant="text"
|
||||||
|
color="inherit"
|
||||||
|
className="text-primary-active"
|
||||||
|
onClick={() => {}}
|
||||||
|
>
|
||||||
|
<React.Fragment>
|
||||||
|
<Icon name="settings" />
|
||||||
|
<Icon name="chevron-down" />
|
||||||
|
</React.Fragment>
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</NavBar>
|
||||||
|
<StudyListFilter
|
||||||
|
numOfStudies={numOfStudies}
|
||||||
|
filtersMeta={filtersMeta}
|
||||||
|
filterValues={filterValues}
|
||||||
|
setFilterValues={setFilterValues}
|
||||||
|
clearFilters={() => setFilterValues(defaultFilterValues)}
|
||||||
|
isFiltering={isFiltering(filterValues, defaultFilterValues)}
|
||||||
|
/>
|
||||||
|
{hasStudies ? (
|
||||||
|
<>
|
||||||
|
<StudyListTable
|
||||||
|
tableDataSource={tableDataSource.slice(
|
||||||
|
(currentPage - 1) * perPage,
|
||||||
|
(currentPage - 1) * perPage + perPage
|
||||||
|
)}
|
||||||
|
numOfStudies={numOfStudies}
|
||||||
|
filtersMeta={filtersMeta}
|
||||||
|
/>
|
||||||
|
<StudyListPagination
|
||||||
|
onChangePage={onChangePage}
|
||||||
|
onChangePerPage={onChangePerPage}
|
||||||
|
currentPage={currentPage}
|
||||||
|
perPage={perPage}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col items-center justify-center pt-48">
|
||||||
|
<EmptyStudies />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default StudyListContainer;
|
export default StudyListContainer;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Switch, Route } from 'react-router-dom';
|
import { Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
// Route Components
|
||||||
import StudyListContainer from './StudyListContainer';
|
import StudyListContainer from './StudyListContainer';
|
||||||
import NotFound from './NotFound';
|
import NotFound from './NotFound';
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user