ohif-viewer/platform/ui/src/components/StudyBrowser/StudyBrowser.jsx

177 lines
5.3 KiB
React
Raw Normal View History

2020-06-30 20:57:24 +02:00
import React from 'react';
2020-04-21 20:12:46 +02:00
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { ButtonGroup, Button, StudyItem, ThumbnailList } from '@ohif/ui';
2020-04-14 00:35:32 +02:00
const buttonClasses = 'text-white text-base border-none bg-black p-2 min-w-18';
const activeButtonClasses = 'bg-primary-main';
2020-05-15 19:07:21 +02:00
const getTrackedSeries = displaySets => {
let trackedSeries = 0;
2020-05-15 19:07:21 +02:00
displaySets.forEach(displaySet => {
if (displaySet.isTracked) {
trackedSeries++;
}
});
return trackedSeries;
};
2020-05-18 17:21:57 +02:00
const StudyBrowser = ({
tabs,
activeTabName,
expandedStudyInstanceUIDs,
2020-05-22 21:33:07 +02:00
onClickTab,
2020-05-18 17:21:57 +02:00
onClickStudy,
onClickThumbnail,
2020-07-01 02:49:37 +02:00
onDoubleClickThumbnail,
onClickUntrack,
2020-07-01 02:49:37 +02:00
activeDisplaySetInstanceUID,
2020-05-18 17:21:57 +02:00
}) => {
2020-04-21 20:12:46 +02:00
const getTabContent = () => {
2020-05-22 21:33:07 +02:00
const tabData = tabs.find(tab => tab.name === activeTabName);
2020-04-21 20:12:46 +02:00
return tabData.studies.map(
({
studyInstanceUid,
2020-05-15 14:29:27 +02:00
date,
description,
numInstances,
2020-04-21 20:12:46 +02:00
modalities,
displaySets,
2020-04-21 20:12:46 +02:00
}) => {
const isExpanded = expandedStudyInstanceUIDs.includes(studyInstanceUid);
2020-04-21 20:12:46 +02:00
return (
<React.Fragment key={studyInstanceUid}>
<StudyItem
2020-05-15 14:29:27 +02:00
date={date}
description={description}
numInstances={numInstances}
2020-04-21 20:12:46 +02:00
modalities={modalities}
trackedSeries={getTrackedSeries(displaySets)}
isActive={isExpanded}
2020-04-21 20:12:46 +02:00
onClick={() => {
onClickStudy(studyInstanceUid);
2020-04-21 20:12:46 +02:00
}}
/>
{isExpanded && displaySets && (
2020-05-15 10:05:40 +02:00
<ThumbnailList
thumbnails={displaySets}
2020-07-01 02:49:37 +02:00
activeDisplaySetInstanceUID={activeDisplaySetInstanceUID}
2020-06-30 20:57:24 +02:00
onThumbnailClick={onClickThumbnail}
2020-07-01 02:49:37 +02:00
onThumbnailDoubleClick={onDoubleClickThumbnail}
2020-06-30 20:57:24 +02:00
onClickUntrack={onClickUntrack}
2020-05-15 10:05:40 +02:00
/>
2020-04-21 20:12:46 +02:00
)}
</React.Fragment>
);
}
);
};
return (
<React.Fragment>
<div className="flex flex-row items-center justify-center h-16 p-4 border-b w-100 border-secondary-light bg-primary-dark">
<ButtonGroup
variant="outlined"
color="inherit"
className="border rounded-md border-secondary-light"
>
2020-05-15 19:07:21 +02:00
{tabs.map(tab => {
const { name, label, studies } = tab;
2020-05-22 21:33:07 +02:00
const isActive = activeTabName === name;
const isDisabled = !studies.length;
return (
<Button
2020-04-21 20:12:46 +02:00
key={name}
className={classnames(
buttonClasses,
isActive && activeButtonClasses
)}
2020-04-14 00:35:32 +02:00
size="initial"
onClick={() => {
2020-05-22 21:33:07 +02:00
onClickTab(name);
}}
disabled={isDisabled}
>
2020-04-21 20:12:46 +02:00
{label}
</Button>
);
})}
</ButtonGroup>
</div>
<div className="flex flex-col flex-1 overflow-auto invisible-scrollbar">
2020-04-21 20:12:46 +02:00
{getTabContent()}
</div>
</React.Fragment>
);
};
2020-04-21 20:12:46 +02:00
StudyBrowser.propTypes = {
2020-05-22 21:33:07 +02:00
onClickTab: PropTypes.func.isRequired,
2020-05-15 10:05:40 +02:00
onClickStudy: PropTypes.func,
onClickThumbnail: PropTypes.func,
2020-07-01 02:49:37 +02:00
onDoubleClickThumbnail: PropTypes.func,
onClickUntrack: PropTypes.func,
2020-05-22 21:33:07 +02:00
activeTabName: PropTypes.string.isRequired,
expandedStudyInstanceUIDs: PropTypes.arrayOf(PropTypes.string).isRequired,
2020-07-01 02:49:37 +02:00
activeDisplaySetInstanceUID: PropTypes.string,
2020-04-21 20:12:46 +02:00
tabs: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
studies: PropTypes.arrayOf(
PropTypes.shape({
studyInstanceUid: PropTypes.string.isRequired,
date: PropTypes.string,
numInstances: PropTypes.number,
2020-05-15 14:29:27 +02:00
modalities: PropTypes.string,
2020-04-21 20:12:46 +02:00
description: PropTypes.string,
displaySets: PropTypes.arrayOf(
PropTypes.shape({
2020-05-15 19:07:21 +02:00
displaySetInstanceUID: PropTypes.string.isRequired,
2020-04-21 20:12:46 +02:00
imageSrc: PropTypes.string,
imageAltText: PropTypes.string,
seriesDate: PropTypes.string,
seriesNumber: PropTypes.number,
numInstances: PropTypes.number,
description: PropTypes.string,
componentType: PropTypes.oneOf([
'thumbnail',
'thumbnailTracked',
'thumbnailNoImage',
]).isRequired,
isTracked: PropTypes.bool,
viewportIdentificator: PropTypes.string,
/**
* Data the thumbnail should expose to a receiving drop target. Use a matching
* `dragData.type` to identify which targets can receive this draggable item.
* If this is not set, drag-n-drop will be disabled for this thumbnail.
*
* Ref: https://react-dnd.github.io/react-dnd/docs/api/use-drag#specification-object-members
*/
dragData: PropTypes.shape({
/** Must match the "type" a dropTarget expects */
type: PropTypes.string.isRequired,
}),
2020-04-21 20:12:46 +02:00
})
),
})
).isRequired,
})
),
};
const noop = () => {};
StudyBrowser.defaultProps = {
onClickTab: noop,
onClickStudy: noop,
onClickThumbnail: noop,
2020-07-01 02:49:37 +02:00
onDoubleClickThumbnail: noop,
onClickUntrack: noop,
};
export default StudyBrowser;