diff --git a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx index dfdbf4d70..7c5120452 100644 --- a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx +++ b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx @@ -419,7 +419,7 @@ OHIFCornerstoneViewport.propTypes = { displaySets: PropTypes.array.isRequired, dataSource: PropTypes.object.isRequired, viewportOptions: PropTypes.object, - displaySetOptions: PropTypes.arrayOf(PropTypes.object), + displaySetOptions: PropTypes.arrayOf(PropTypes.any), servicesManager: PropTypes.object.isRequired, onElementEnabled: PropTypes.func, // Note: you SHOULD NOT use the initialImageIdOrIndex for manipulation diff --git a/modes/longitudinal/src/index.js b/modes/longitudinal/src/index.js index e902ba1ff..f3072cf2e 100644 --- a/modes/longitudinal/src/index.js +++ b/modes/longitudinal/src/index.js @@ -3,6 +3,10 @@ import toolbarButtons from './toolbarButtons.js'; import { id } from './id.js'; import initToolGroups from './initToolGroups.js'; +// Allow this mode by excluding non-imaging modalities such as SR, SEG +// Also, SM is not a simple imaging modalities, so exclude it. +const NON_IMAGE_MODALITIES = ['SM', 'ECG', 'SR', 'SEG']; + const ohif = { layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack', @@ -44,7 +48,7 @@ const extensionDependencies = { '@ohif/extension-dicom-video': '^3.0.1', }; -function modeFactory({ modeConfiguration }) { +function modeFactory() { return { // TODO: We're using this as a route segment // We should not be. @@ -119,11 +123,14 @@ function modeFactory({ modeConfiguration }) { study: [], series: [], }, - isValidMode: ({ modalities }) => { + + isValidMode: function({ modalities }) { const modalities_list = modalities.split('\\'); - // Slide Microscopy modality not supported by basic mode yet - return !modalities_list.includes('SM'); + // Exclude non-image modalities + return !!modalities_list.filter( + modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1 + ).length; }, routes: [ { @@ -131,7 +138,7 @@ function modeFactory({ modeConfiguration }) { /*init: ({ servicesManager, extensionManager }) => { //defaultViewerRouteInit },*/ - layoutTemplate: ({ location, servicesManager }) => { + layoutTemplate: () => { return { id: ohif.layout, props: { diff --git a/platform/ui/src/Types.ts b/platform/ui/src/Types.ts new file mode 100644 index 000000000..d6c8581e9 --- /dev/null +++ b/platform/ui/src/Types.ts @@ -0,0 +1,20 @@ +import PropTypes from 'prop-types'; + +/** + * StringNumber often comes back from DICOMweb for integer valued items. + */ +const StringNumber = PropTypes.oneOfType([PropTypes.string, PropTypes.number]); + +/** + * StringArray often comes back from dcmjs for single valued strings that + * might have multiple values such as window level descriptions. + */ +const StringArray = PropTypes.oneOfType([PropTypes.string, PropTypes.array]); + +const ThumbnailType = PropTypes.oneOf([ + 'thumbnail', + 'thumbnailTracked', + 'thumbnailNoImage', +]); + +export { StringNumber, StringArray, ThumbnailType }; diff --git a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx index d75313b76..5b1b31b0d 100644 --- a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx +++ b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx @@ -4,6 +4,7 @@ import classnames from 'classnames'; import { useTranslation } from 'react-i18next'; import { ButtonGroup, Button, StudyItem, ThumbnailList } from '../'; +import { StringNumber } from '../../Types'; const buttonClasses = 'text-white text-base border-none bg-black p-2 min-w-18'; const activeButtonClasses = 'bg-primary-main'; @@ -140,7 +141,7 @@ StudyBrowser.propTypes = { imageSrc: PropTypes.string, imageAltText: PropTypes.string, seriesDate: PropTypes.string, - seriesNumber: PropTypes.string, + seriesNumber: StringNumber, numInstances: PropTypes.number, description: PropTypes.string, componentType: PropTypes.oneOf([ diff --git a/platform/ui/src/components/Thumbnail/Thumbnail.tsx b/platform/ui/src/components/Thumbnail/Thumbnail.tsx index db0743cf2..176ea36a4 100644 --- a/platform/ui/src/components/Thumbnail/Thumbnail.tsx +++ b/platform/ui/src/components/Thumbnail/Thumbnail.tsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { useDrag } from 'react-dnd'; import { Icon } from '../'; +import { StringNumber } from '../../Types'; /** * @@ -98,7 +99,7 @@ Thumbnail.propTypes = { }), imageAltText: PropTypes.string, description: PropTypes.string.isRequired, - seriesNumber: PropTypes.string.isRequired, + seriesNumber: StringNumber.isRequired, numInstances: PropTypes.number.isRequired, isActive: PropTypes.bool.isRequired, onClick: PropTypes.func.isRequired, diff --git a/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx b/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx index 75cb70013..46ff0ab94 100644 --- a/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx +++ b/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Thumbnail, ThumbnailNoImage, ThumbnailTracked } from '../'; +import * as Types from '../../Types'; const ThumbnailList = ({ thumbnails, @@ -110,18 +111,11 @@ ThumbnailList.propTypes = { imageSrc: PropTypes.string, imageAltText: PropTypes.string, seriesDate: PropTypes.string, - seriesNumber: PropTypes.string, + seriesNumber: Types.StringNumber, numInstances: PropTypes.number, description: PropTypes.string, - componentType: PropTypes.oneOf([ - 'thumbnail', - 'thumbnailTracked', - 'thumbnailNoImage', - ]).isRequired, - viewportIdentificator: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.array, - ]), + componentType: Types.ThumbnailType.isRequired, + viewportIdentificator: Types.StringArray, isTracked: PropTypes.bool, /** * Data the thumbnail should expose to a receiving drop target. Use a matching diff --git a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx index fd9d74014..2e9f5dcf0 100644 --- a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx +++ b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { Icon, Thumbnail, Tooltip } from '../'; +import { StringNumber } from '../../Types'; const ThumbnailTracked = ({ displaySetInstanceUID, @@ -137,7 +138,7 @@ ThumbnailTracked.propTypes = { imageSrc: PropTypes.string, imageAltText: PropTypes.string, description: PropTypes.string.isRequired, - seriesNumber: PropTypes.string.isRequired, + seriesNumber: StringNumber.isRequired, numInstances: PropTypes.number.isRequired, onClick: PropTypes.func.isRequired, onDoubleClick: PropTypes.func.isRequired, diff --git a/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx b/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx index 8ca11ae58..d7916bbb1 100644 --- a/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx +++ b/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx @@ -4,6 +4,7 @@ import classnames from 'classnames'; import { Icon, ButtonGroup, Button, Tooltip, CinePlayer } from '../'; import useOnClickOutside from '../../utils/useOnClickOutside'; import { useTranslation } from 'react-i18next'; +import { StringNumber } from '../../Types'; const classes = { infoHeader: 'text-base text-primary-light', @@ -336,7 +337,7 @@ ViewportActionBar.propTypes = { isTracked: PropTypes.bool.isRequired, isRehydratable: PropTypes.bool.isRequired, studyDate: PropTypes.string.isRequired, - currentSeries: PropTypes.string.isRequired, + currentSeries: StringNumber.isRequired, seriesDescription: PropTypes.string.isRequired, modality: PropTypes.string.isRequired, patientInformation: PropTypes.shape({ diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js index 22661ea13..4d74012df 100644 --- a/platform/ui/src/index.js +++ b/platform/ui/src/index.js @@ -3,6 +3,9 @@ //export { utils }; /** CONTEXT/HOOKS */ +// Export types - need to do as two lines due to a bug in babel +import * as Types from './Types'; + export { useCine, CineProvider, @@ -104,3 +107,4 @@ export { export { getIcon, ICONS } from './components/Icon/getIcon'; export { BackgroundColor } from './pages/Colors/BackgroundColor'; export { ModalComponent } from './contextProviders/ModalComponent'; +export { Types }; diff --git a/platform/viewer/src/components/ViewportGrid.tsx b/platform/viewer/src/components/ViewportGrid.tsx index 8416daa6c..0bfb7fcb2 100644 --- a/platform/viewer/src/components/ViewportGrid.tsx +++ b/platform/viewer/src/components/ViewportGrid.tsx @@ -370,8 +370,9 @@ function _getViewportComponent(displaySets, viewportComponents) { const SOPClassHandlerId = displaySets[0].SOPClassHandlerId; for (let i = 0; i < viewportComponents.length; i++) { - if (!viewportComponents[i]) + if (!viewportComponents[i]) { throw new Error('viewport components not defined'); + } if (!viewportComponents[i].displaySetsToDisplay) { throw new Error('displaySetsToDisplay is null'); }