{
+ const [studyGroupSelected, setStudyGroupSelected] = useState('Recent');
+ const [studyActive, setStudyActive] = useState(null);
+
+ return (
+
+
+
+ {studyGroupTypes.map((studyGroup) => {
+ const isActive = studyGroupSelected === studyGroup;
+ return (
+
+ );
+ })}
+
+
+
+ {studyGroup[studyGroupSelected].map(
+ ({
+ studyInstanceUid,
+ studyDate,
+ studyDescription,
+ instances,
+ modalities,
+ trackedSeries,
+ thumbnails,
+ }) => {
+ const isActive = studyActive === studyInstanceUid;
+ return (
+
+ {
+ setStudyActive(isActive ? null : studyInstanceUid);
+ }}
+ />
+ {isActive && thumbnails && (
+
+ )}
+
+ );
+ }
+ )}
+
+
+ );
+};
+
+export default StudyBrowser;
diff --git a/platform/ui/src/components/StudyBrowser/StudyBrowser.mdx b/platform/ui/src/components/StudyBrowser/StudyBrowser.mdx
new file mode 100644
index 000000000..6a8f93205
--- /dev/null
+++ b/platform/ui/src/components/StudyBrowser/StudyBrowser.mdx
@@ -0,0 +1,26 @@
+---
+name: StudyBrowser
+menu: General
+route: components/studyBrowser
+---
+
+import { Playground, Props } from 'docz';
+import { StudyBrowser } from '@ohif/ui';
+
+# StudyBrowser
+
+## Import
+
+```javascript
+import { StudyBrowser } from '@ohif/ui';
+```
+
+## Basic usage
+
+
+
+
+
+## Properties
+
+
diff --git a/platform/ui/src/components/StudyBrowser/index.js b/platform/ui/src/components/StudyBrowser/index.js
new file mode 100644
index 000000000..aa85fa066
--- /dev/null
+++ b/platform/ui/src/components/StudyBrowser/index.js
@@ -0,0 +1,2 @@
+import StudyBrowser from './StudyBrowser';
+export default StudyBrowser;
diff --git a/platform/ui/src/components/StudyBrowser/mockData.js b/platform/ui/src/components/StudyBrowser/mockData.js
new file mode 100644
index 000000000..337912300
--- /dev/null
+++ b/platform/ui/src/components/StudyBrowser/mockData.js
@@ -0,0 +1,56 @@
+const studyWithSR = {
+ studyInstanceUid: '1',
+ studyDate: '07-Sept-2010',
+ studyDescription: 'CHEST/ABD/PELVIS W/CONTRAST',
+ instances: 902,
+ modalities: 'CT,SR',
+ trackedSeries: 1,
+ thumbnails: [
+ {
+ displaySetInstanceUid: 'f69f6asdasd48c-223e-db7f-c4af-b8906641a66e',
+ seriesDescription: 'Multiple line image series description lorem sit',
+ seriesNumber: 1,
+ instanceNumber: 68,
+ viewportIdentificator: 'A',
+ isTracked: true,
+ },
+ {
+ displaySetInstanceUid: 'f69f648c-223e-db7f-c4asdasdaf-b8906641a66e',
+ seriesDescription: 'Multiple line image series description lorem sit',
+ seriesNumber: 1,
+ instanceNumber: 68,
+ viewportIdentificator: 'B',
+ },
+ {
+ displaySetInstanceUid: 'f69f648c-223e-dasdasdb7f-c4af-b8906641a66e',
+ seriesDescription: 'Multiple line image series description lorem sit',
+ seriesNumber: 1,
+ instanceNumber: 68,
+ },
+ {
+ displaySetInstanceUid: 'f69f648c-223e-db7f-c4afas-b8906asd641a66e',
+ seriesDescription: 'Multiple line description lorem ipsum dolor sit amet',
+ modality: 'SR',
+ seriesDate: '07-Sept-2010',
+ },
+ ],
+};
+
+const studySimple = {
+ studyInstanceUid: '2',
+ studyDate: '07-Sept-2010',
+ studyDescription: 'CHEST/ABD/PELVIS W/CONTRAST',
+ instances: 902,
+ modalities: 'CT',
+ trackedSeries: 0,
+ thumbnails: [
+ {
+ displaySetInstanceUid: 'f69f648c-223e-db7f-c4af-b8906641a66e',
+ seriesDescription: 'Multiple line image series description lorem sit',
+ seriesNumber: 1,
+ instanceNumber: 68,
+ },
+ ],
+};
+
+export { studyWithSR, studySimple };
diff --git a/platform/ui/src/components/StudyItem/StudyItem.jsx b/platform/ui/src/components/StudyItem/StudyItem.jsx
new file mode 100644
index 000000000..eaa85b10e
--- /dev/null
+++ b/platform/ui/src/components/StudyItem/StudyItem.jsx
@@ -0,0 +1,72 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classnames from 'classnames';
+
+import { Icon } from '@ohif/ui';
+
+const baseClasses =
+ 'first:border-0 border-t border-secondary-light cursor-pointer';
+
+const StudyItem = ({
+ studyDate,
+ studyDescription,
+ instances,
+ modalities,
+ trackedSeries,
+ isActive,
+ onClick,
+}) => {
+ return (
+
+
+
+
{studyDate}
+
+
+ {instances}
+
+
+
+
{modalities}
+
{studyDescription}
+
+
+ {!!trackedSeries && (
+
+
+
+ {trackedSeries} Tracked Series
+
+
+ )}
+
+ );
+};
+
+StudyItem.propTypes = {
+ studyDate: PropTypes.any,
+ studyDescription: PropTypes.any,
+ modalities: PropTypes.any,
+ instances: PropTypes.any,
+ trackedSeries: PropTypes.any,
+ isActive: PropTypes.any,
+ onClick: PropTypes.func.isRequired,
+};
+
+export default StudyItem;
diff --git a/platform/ui/src/components/StudyItem/index.js b/platform/ui/src/components/StudyItem/index.js
new file mode 100644
index 000000000..0c9680c4f
--- /dev/null
+++ b/platform/ui/src/components/StudyItem/index.js
@@ -0,0 +1,2 @@
+import StudyItem from './StudyItem';
+export default StudyItem;
diff --git a/platform/ui/src/components/Thumbnail/Thumbnail.jsx b/platform/ui/src/components/Thumbnail/Thumbnail.jsx
new file mode 100644
index 000000000..9f8cad358
--- /dev/null
+++ b/platform/ui/src/components/Thumbnail/Thumbnail.jsx
@@ -0,0 +1,117 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import classnames from 'classnames';
+
+import { Icon } from '@ohif/ui';
+
+const Thumbnail = ({
+ seriesDescription,
+ seriesNumber,
+ instanceNumber,
+ viewportIdentificator,
+ isTracked,
+ isActive,
+ onClick,
+}) => {
+ const trackedIcon = isTracked ? 'circled-checkmark' : 'dotted-circle';
+
+ return (
+
+
+
+
+
+ {viewportIdentificator}
+
+
+
+
+
+ Series is tracked
+
+ {viewportIdentificator && (
+
+ in viewport
+
+ {viewportIdentificator}
+
+
+ )}
+
+
+
+
+
+
+
+
+ {isTracked && (
+
+ )}
+
+
+
+ {'Thumbnail img'}
+
+
+
+ {'S: '}
+ {seriesNumber}
+
+
+ {instanceNumber}
+
+
+
{seriesDescription}
+
+
+ );
+};
+
+Thumbnail.propTypes = {
+ seriesDescription: PropTypes.string.isRequired,
+ seriesNumber: PropTypes.number.isRequired,
+ instanceNumber: PropTypes.number.isRequired,
+ isActive: PropTypes.bool.isRequired,
+ onClick: PropTypes.func.isRequired,
+ isTracked: PropTypes.bool,
+ viewportIdentificator: PropTypes.string,
+};
+
+export default Thumbnail;
diff --git a/platform/ui/src/components/Thumbnail/index.js b/platform/ui/src/components/Thumbnail/index.js
new file mode 100644
index 000000000..275561d01
--- /dev/null
+++ b/platform/ui/src/components/Thumbnail/index.js
@@ -0,0 +1,2 @@
+import Thumbnail from './Thumbnail';
+export default Thumbnail;
diff --git a/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx b/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx
new file mode 100644
index 000000000..ecafab2b0
--- /dev/null
+++ b/platform/ui/src/components/ThumbnailList/ThumbnailList.jsx
@@ -0,0 +1,73 @@
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+
+import { Thumbnail, ThumbnailSR } from '@ohif/ui';
+
+const ThumbnailList = ({ thumbnails }) => {
+ const [thumbnailActive, setThumbnailActive] = useState(null);
+
+ return (
+
+ {thumbnails.map(
+ ({
+ displaySetInstanceUid,
+ seriesDescription,
+ seriesNumber,
+ instanceNumber,
+ modality,
+ seriesDate,
+ viewportIdentificator,
+ isTracked,
+ }) => {
+ const isSR = modality && modality.toLowerCase() === 'sr';
+ const isActive = thumbnailActive === displaySetInstanceUid;
+
+ if (isSR) {
+ return (
+
+ );
+ } else {
+ return (
+ {
+ setThumbnailActive(
+ thumbnailActive === displaySetInstanceUid
+ ? null
+ : displaySetInstanceUid
+ );
+ }}
+ />
+ );
+ }
+ }
+ )}
+
+ );
+};
+
+ThumbnailList.propTypes = {
+ thumbnails: PropTypes.arrayOf(
+ PropTypes.shape({
+ displaySetInstanceUid: PropTypes.string,
+ seriesDescription: PropTypes.string,
+ seriesNumber: PropTypes.number,
+ instanceNumber: PropTypes.number,
+ modality: PropTypes.string,
+ seriesDate: PropTypes.string,
+ })
+ ),
+};
+
+export default ThumbnailList;
diff --git a/platform/ui/src/components/ThumbnailList/index.js b/platform/ui/src/components/ThumbnailList/index.js
new file mode 100644
index 000000000..e2cfade78
--- /dev/null
+++ b/platform/ui/src/components/ThumbnailList/index.js
@@ -0,0 +1,2 @@
+import ThumbnailList from './ThumbnailList';
+export default ThumbnailList;
diff --git a/platform/ui/src/components/ThumbnailSR/ThumbnailSR.jsx b/platform/ui/src/components/ThumbnailSR/ThumbnailSR.jsx
new file mode 100644
index 000000000..c3d949168
--- /dev/null
+++ b/platform/ui/src/components/ThumbnailSR/ThumbnailSR.jsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { Icon } from '@ohif/ui';
+
+const ThumbnailSR = ({ seriesDescription, seriesDate }) => {
+ return (
+
+
+
+
+
+
+
+ SR
+
+
{seriesDate}
+
+
{seriesDescription}
+
+
+
+ );
+};
+
+ThumbnailSR.propTypes = {
+ seriesDescription: PropTypes.string,
+ seriesDate: PropTypes.string,
+};
+
+export default ThumbnailSR;
diff --git a/platform/ui/src/components/ThumbnailSR/index.js b/platform/ui/src/components/ThumbnailSR/index.js
new file mode 100644
index 000000000..b9b2a119c
--- /dev/null
+++ b/platform/ui/src/components/ThumbnailSR/index.js
@@ -0,0 +1,2 @@
+import ThumbnailSR from './ThumbnailSR';
+export default ThumbnailSR;
diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js
index 05cb336f5..8bb14ec05 100644
--- a/platform/ui/src/components/index.js
+++ b/platform/ui/src/components/index.js
@@ -16,16 +16,21 @@ import NavBar from './NavBar';
import Select from './Select';
import SegmentationTable from './SegmentationTable';
import SidePanel from './SidePanel';
-import Svg from './Svg';
+import StudyBrowser from './StudyBrowser';
import StudyListExpandedRow from './StudyListExpandedRow';
import StudyListPagination from './StudyListPagination';
import StudyListTable from './StudyListTable';
+import Svg from './Svg';
+import StudyItem from './StudyItem';
import Table from './Table';
import TableBody from './TableBody';
import TableCell from './TableCell';
import TableHead from './TableHead';
import TableRow from './TableRow';
import ThemeWrapper from './ThemeWrapper/';
+import Thumbnail from './Thumbnail';
+import ThumbnailSR from './ThumbnailSR';
+import ThumbnailList from './ThumbnailList';
import Typography from './Typography';
export {
@@ -47,15 +52,20 @@ export {
Select,
SegmentationTable,
SidePanel,
- Svg,
+ StudyBrowser,
+ StudyItem,
StudyListExpandedRow,
StudyListPagination,
StudyListTable,
+ Svg,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
ThemeWrapper,
+ Thumbnail,
+ ThumbnailSR,
+ ThumbnailList,
Typography,
};
diff --git a/platform/ui/src/views/ToolbarHeader/ToolbarHeader.mdx b/platform/ui/src/views/ToolbarHeader/ToolbarHeader.mdx
index 0ed69f774..1b5abbe59 100644
--- a/platform/ui/src/views/ToolbarHeader/ToolbarHeader.mdx
+++ b/platform/ui/src/views/ToolbarHeader/ToolbarHeader.mdx
@@ -86,7 +86,7 @@ components.
{shouldShowTooltip && (
{tool.label}
diff --git a/platform/ui/src/views/Viewer/Viewer.js b/platform/ui/src/views/Viewer/Viewer.js
index dc466fe1c..3df503696 100644
--- a/platform/ui/src/views/Viewer/Viewer.js
+++ b/platform/ui/src/views/Viewer/Viewer.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { NavBar, SidePanel, Svg } from '@ohif/ui';
+import { NavBar, SidePanel, Svg, StudyBrowser } from '@ohif/ui';
const Viewer = () => {
return (
@@ -18,11 +18,9 @@ const Viewer = () => {
iconName="group-layers"
iconLabel="Studies"
componentLabel="Studies"
- defaultIsOpen={false}
+ defaultIsOpen={true}
>
-
- panel placeholder
-
+
CONTENT
diff --git a/platform/ui/src/views/Viewer/Viewer.mdx b/platform/ui/src/views/Viewer/Viewer.mdx
index 171baf086..f6b28b637 100644
--- a/platform/ui/src/views/Viewer/Viewer.mdx
+++ b/platform/ui/src/views/Viewer/Viewer.mdx
@@ -5,110 +5,32 @@ route: examples/viewer
---
import { Playground, Props } from 'docz';
-import {
- NavBar,
- SidePanel,
- Svg,
- MeasurementTable,
- SegmentationTable,
- ButtonGroup,
- Button,
- Icon,
- IconButton,
-} from '@ohif/ui';
+import { NavBar, SidePanel, Svg, StudyBrowser } from '@ohif/ui';
# Viewer
- {() => {
- const measurementTableData = {
- title: 'Measurements',
- amount: 10,
- data: new Array(10).fill(''),
- };
- const segmentationTableData = {
- title: 'Segments',
- amount: 12,
- data: new Array(12).fill(''),
- };
- return (
-
-
-
-
-
-
-
-
-
- panel placeholder
-
-
-
- CONTENT
-
-
-
-
-
- 07-Sep-2010
-
- CT
-
-
-
-
- CHEST/ABD/PELVIS W CONTRAST
-
-
-
-
-
-
-
- alert('Export')}>
-
-
-
-
-
-
-
-
-
+