2019-10-30 16:53:58 -03:00
|
|
|
import React from 'react';
|
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
import { useDrag } from 'react-dnd';
|
|
|
|
|
import ImageThumbnail from './ImageThumbnail';
|
|
|
|
|
import classNames from 'classnames';
|
|
|
|
|
|
|
|
|
|
import './Thumbnail.styl';
|
|
|
|
|
|
|
|
|
|
function ThumbnailFooter({
|
2020-03-09 19:03:23 +00:00
|
|
|
SeriesDescription,
|
|
|
|
|
SeriesNumber,
|
|
|
|
|
InstanceNumber,
|
2019-10-30 16:53:58 -03:00
|
|
|
numImageFrames,
|
|
|
|
|
}) {
|
2020-03-09 19:03:23 +00:00
|
|
|
const infoOnly = !SeriesDescription;
|
2019-10-30 16:53:58 -03:00
|
|
|
|
|
|
|
|
const getInfo = (value, icon, className = '') => {
|
|
|
|
|
return (
|
|
|
|
|
<div className={classNames('item item-series', className)}>
|
|
|
|
|
<div className="icon">{icon}</div>
|
|
|
|
|
<div className="value">{value}</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
const getSeriesInformation = (
|
2020-03-09 19:03:23 +00:00
|
|
|
SeriesNumber,
|
|
|
|
|
InstanceNumber,
|
2019-10-30 16:53:58 -03:00
|
|
|
numImageFrames
|
|
|
|
|
) => {
|
2020-03-09 19:03:23 +00:00
|
|
|
if (!SeriesNumber && !InstanceNumber && !numImageFrames) {
|
2019-10-30 16:53:58 -03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="series-information">
|
2020-03-09 19:03:23 +00:00
|
|
|
{getInfo(SeriesNumber, 'S:')}
|
|
|
|
|
{getInfo(InstanceNumber, 'I:')}
|
2019-10-30 16:53:58 -03:00
|
|
|
{getInfo(numImageFrames, '', 'image-frames')}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={classNames('series-details', { 'info-only': infoOnly })}>
|
2020-03-09 19:03:23 +00:00
|
|
|
<div className="series-description">{SeriesDescription}</div>
|
|
|
|
|
{getSeriesInformation(SeriesNumber, InstanceNumber, numImageFrames)}
|
2019-10-30 16:53:58 -03:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Thumbnail(props) {
|
|
|
|
|
const {
|
|
|
|
|
active,
|
|
|
|
|
altImageText,
|
|
|
|
|
error,
|
2020-03-09 19:03:23 +00:00
|
|
|
displaySetInstanceUID,
|
2019-10-30 16:53:58 -03:00
|
|
|
imageId,
|
|
|
|
|
imageSrc,
|
2020-03-09 19:03:23 +00:00
|
|
|
InstanceNumber,
|
2019-10-30 16:53:58 -03:00
|
|
|
numImageFrames,
|
2020-03-09 19:03:23 +00:00
|
|
|
SeriesDescription,
|
|
|
|
|
SeriesNumber,
|
2019-10-30 16:53:58 -03:00
|
|
|
stackPercentComplete,
|
2020-03-09 19:03:23 +00:00
|
|
|
StudyInstanceUID,
|
2019-10-30 16:53:58 -03:00
|
|
|
onClick,
|
|
|
|
|
onDoubleClick,
|
|
|
|
|
onMouseDown,
|
|
|
|
|
supportsDrag,
|
|
|
|
|
} = props;
|
|
|
|
|
|
|
|
|
|
const [collectedProps, drag, dragPreview] = useDrag({
|
|
|
|
|
// `droppedItem` in `dropTarget`
|
|
|
|
|
// The only data it will have access to
|
|
|
|
|
item: {
|
2020-03-09 19:03:23 +00:00
|
|
|
StudyInstanceUID,
|
|
|
|
|
displaySetInstanceUID,
|
2019-10-30 16:53:58 -03:00
|
|
|
type: 'thumbnail', // Has to match `dropTarget`'s type
|
|
|
|
|
},
|
|
|
|
|
canDrag: function(monitor) {
|
|
|
|
|
return supportsDrag;
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const hasImage = imageSrc || imageId;
|
|
|
|
|
const hasAltText = altImageText !== undefined;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
ref={drag}
|
|
|
|
|
className={classNames('thumbnail', { active: active })}
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
onDoubleClick={onDoubleClick}
|
|
|
|
|
onMouseDown={onMouseDown}
|
|
|
|
|
>
|
|
|
|
|
{/* SHOW IMAGE */}
|
|
|
|
|
{hasImage && (
|
|
|
|
|
<ImageThumbnail
|
|
|
|
|
imageSrc={imageSrc}
|
|
|
|
|
imageId={imageId}
|
|
|
|
|
error={error}
|
|
|
|
|
stackPercentComplete={stackPercentComplete}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{/* SHOW TEXT ALTERNATIVE */}
|
|
|
|
|
{!hasImage && hasAltText && (
|
|
|
|
|
<div className={'alt-image-text p-x-1'}>
|
|
|
|
|
<h1>{altImageText}</h1>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{ThumbnailFooter(props)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const noop = () => {};
|
|
|
|
|
|
|
|
|
|
Thumbnail.propTypes = {
|
|
|
|
|
supportsDrag: PropTypes.bool,
|
|
|
|
|
id: PropTypes.string.isRequired,
|
2020-03-09 19:03:23 +00:00
|
|
|
displaySetInstanceUID: PropTypes.string.isRequired,
|
|
|
|
|
StudyInstanceUID: PropTypes.string.isRequired,
|
2019-10-30 16:53:58 -03:00
|
|
|
imageSrc: PropTypes.string,
|
|
|
|
|
imageId: PropTypes.string,
|
|
|
|
|
error: PropTypes.bool,
|
|
|
|
|
active: PropTypes.bool,
|
|
|
|
|
stackPercentComplete: PropTypes.number,
|
|
|
|
|
/**
|
|
|
|
|
altImageText will be used when no imageId or imageSrc is provided.
|
|
|
|
|
It will be displayed inside the <div>. This is useful when it is difficult
|
|
|
|
|
to make a preview for a type of DICOM series (e.g. DICOM-SR)
|
|
|
|
|
*/
|
|
|
|
|
altImageText: PropTypes.string,
|
2020-03-09 19:03:23 +00:00
|
|
|
SeriesDescription: PropTypes.string,
|
|
|
|
|
SeriesNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
|
|
|
InstanceNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
2019-10-30 16:53:58 -03:00
|
|
|
numImageFrames: PropTypes.number,
|
|
|
|
|
onDoubleClick: PropTypes.func,
|
|
|
|
|
onClick: PropTypes.func,
|
|
|
|
|
onMouseDown: PropTypes.func,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Thumbnail.defaultProps = {
|
|
|
|
|
supportsDrag: false,
|
|
|
|
|
active: false,
|
|
|
|
|
error: false,
|
|
|
|
|
stackPercentComplete: 0,
|
|
|
|
|
onDoubleClick: noop,
|
|
|
|
|
onClick: noop,
|
|
|
|
|
onMouseDown: noop,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export { Thumbnail };
|