import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import throttle from 'lodash.throttle'; import { useDrag } from 'react-dnd'; import { classes } from '@ohif/core'; import ImageThumbnail from './ImageThumbnail'; import classNames from 'classnames'; import { Icon } from './../../elements/Icon'; import { Tooltip } from './../tooltip'; import { OverlayTrigger } from './../overlayTrigger'; import './Thumbnail.styl'; const StudyLoadingListener = classes.StudyLoadingListener; function ThumbnailFooter({ SeriesDescription, SeriesNumber, numImageFrames, hasWarnings, hasDerivedDisplaySets, }) { const [inconsistencyWarnings, inconsistencyWarningsSet] = useState([]); const [derivedDisplaySetsActive, derivedDisplaySetsActiveSet] = useState([]); useEffect(() => { let unmounted = false; hasWarnings.then(response => { if (!unmounted) { inconsistencyWarningsSet(response); } }); hasDerivedDisplaySets.then(response => { if (!unmounted) { derivedDisplaySetsActiveSet(response); } }); return () => { unmounted = true; }; }, [hasWarnings, hasDerivedDisplaySets]); const infoOnly = !SeriesDescription; const getInfo = (value, icon, className = '') => { return (
{icon}
{value}
); }; const getWarningContent = inconsistencyWarnings => { if (Array.isArray(inconsistencyWarnings)) { const listedWarnings = inconsistencyWarnings.map((warn, index) => { return
  • {warn}
  • ; }); return
      {listedWarnings}
    ; } else { return {inconsistencyWarnings}; } }; const getWarningInfo = (SeriesNumber, inconsistencyWarnings) => { return ( {inconsistencyWarnings && inconsistencyWarnings.length != 0 ? (
    Series Inconsistencies
    {getWarningContent(inconsistencyWarnings)}
    } >
    ) : ( )}
    ); }; const getDerivedInfo = derivedDisplaySetsActive => { return ( {derivedDisplaySetsActive ? (
    ) : ( )}
    ); }; const getSeriesInformation = ( SeriesNumber, numImageFrames, inconsistencyWarnings, derivedDisplaySetsActive ) => { if (!SeriesNumber && !numImageFrames) { return; } const seriesInformation = (
    {SeriesNumber !== undefined ? ( getInfo(SeriesNumber, 'S:') ) : ( )} {numImageFrames !== undefined ? ( getInfo(numImageFrames, '', 'image-frames') ) : ( )} {getDerivedInfo(derivedDisplaySetsActive)} {getWarningInfo(SeriesNumber, inconsistencyWarnings)}
    ); return seriesInformation; }; return (
    {SeriesDescription}
    {getSeriesInformation( SeriesNumber, numImageFrames, inconsistencyWarnings, derivedDisplaySetsActive )}
    ); } function Thumbnail(props) { const { active, altImageText, error, displaySetInstanceUID, imageId, imageSrc, StudyInstanceUID, onClick, onDoubleClick, onMouseDown, supportsDrag, showProgressBar, } = props; const [stackPercentComplete, setStackPercentComplete] = useState(0); useEffect(() => { const onProgressChange = throttle(({ detail }) => { const { progressId, progressData } = detail; if (`StackProgress:${displaySetInstanceUID}` === progressId) { const percent = progressData ? progressData.percentComplete : 0; if (percent > stackPercentComplete) { setStackPercentComplete(percent); } } }, 100); document.addEventListener( StudyLoadingListener.events.OnProgress, onProgressChange ); return () => { document.removeEventListener( StudyLoadingListener.events.OnProgress, onProgressChange ); }; }, [displaySetInstanceUID]); const [collectedProps, drag, dragPreview] = useDrag({ // `droppedItem` in `dropTarget` // The only data it will have access to item: { StudyInstanceUID, displaySetInstanceUID, type: 'thumbnail', // Has to match `dropTarget`'s type }, canDrag: function(monitor) { return supportsDrag; }, }); const hasImage = imageSrc || imageId; const hasAltText = altImageText !== undefined; return (
    {/* SHOW IMAGE */} {hasImage && ( )} {/* SHOW TEXT ALTERNATIVE */} {!hasImage && hasAltText && (

    {altImageText}

    )} {ThumbnailFooter(props)}
    ); } const noop = () => {}; Thumbnail.propTypes = { supportsDrag: PropTypes.bool, id: PropTypes.string.isRequired, displaySetInstanceUID: PropTypes.string.isRequired, StudyInstanceUID: PropTypes.string.isRequired, 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
    . This is useful when it is difficult to make a preview for a type of DICOM series (e.g. DICOM-SR) */ altImageText: PropTypes.string, SeriesDescription: PropTypes.string, SeriesNumber: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), hasWarnings: PropTypes.instanceOf(Promise), hasDerivedDisplaySets: PropTypes.instanceOf(Promise), numImageFrames: PropTypes.number, onDoubleClick: PropTypes.func, onClick: PropTypes.func, onMouseDown: PropTypes.func, showProgressBar: PropTypes.bool, }; Thumbnail.defaultProps = { supportsDrag: false, active: false, error: false, stackPercentComplete: 0, onDoubleClick: noop, onClick: noop, onMouseDown: noop, }; export { Thumbnail };