From 3900e626416916ba9992d12ea442d54a50645f5b Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Tue, 20 Sep 2022 11:05:26 -0400 Subject: [PATCH] fix(datasource): configurability of additional data source extensions (#2931) * feat(dataSource):Support more than one data source type. * Add consumer type --- platform/core/package.json | 2 +- platform/core/src/index.test.js | 3 ++- platform/core/src/{index.js => index.ts} | 6 +++-- .../DicomMetadataStore/StudyMetadata.ts | 7 ------ .../HangingProtocolService.ts | 2 +- platform/core/src/types/Consumer.ts | 5 ++++ platform/core/src/types/IPubSub.ts | 12 ++++++++++ platform/core/src/types/StudyMetadata.ts | 23 +++++++++++++++++++ platform/core/src/types/index.ts | 9 ++++++++ .../components/StudyBrowser/StudyBrowser.tsx | 2 +- .../ui/src/components/Thumbnail/Thumbnail.tsx | 2 +- .../ThumbnailList/ThumbnailList.tsx | 2 +- .../ThumbnailTracked/ThumbnailTracked.tsx | 2 +- .../ViewportActionBar/ViewportActionBar.tsx | 2 +- platform/ui/src/index.js | 2 +- platform/ui/src/types/ThumbnailType.ts | 7 ++++++ platform/ui/src/{Types.ts => types/index.ts} | 9 +++----- .../viewer/src/routes/DataSourceWrapper.tsx | 15 ++++++++---- 18 files changed, 83 insertions(+), 29 deletions(-) rename platform/core/src/{index.js => index.ts} (96%) delete mode 100644 platform/core/src/services/DicomMetadataStore/StudyMetadata.ts create mode 100644 platform/core/src/types/Consumer.ts create mode 100644 platform/core/src/types/IPubSub.ts create mode 100644 platform/core/src/types/StudyMetadata.ts create mode 100644 platform/core/src/types/index.ts create mode 100644 platform/ui/src/types/ThumbnailType.ts rename platform/ui/src/{Types.ts => types/index.ts} (82%) diff --git a/platform/core/package.json b/platform/core/package.json index f5584fbf9..0e912e661 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -6,7 +6,7 @@ "license": "MIT", "repository": "OHIF/Viewers", "main": "dist/index.umd.js", - "module": "src/index.js", + "module": "src/index.ts", "sideEffects": "false", "publishConfig": { "access": "public" diff --git a/platform/core/src/index.test.js b/platform/core/src/index.test.js index 955c599e2..5d11a4c72 100644 --- a/platform/core/src/index.test.js +++ b/platform/core/src/index.test.js @@ -1,4 +1,4 @@ -import * as OHIF from './index.js'; +import * as OHIF from './index'; describe('Top level exports', () => { test('have not changed', () => { @@ -31,6 +31,7 @@ describe('Top level exports', () => { 'DisplaySetService', 'MeasurementService', 'ToolBarService', + 'Types', 'ViewportGridService', 'SegmentationService', 'HangingProtocolService', diff --git a/platform/core/src/index.js b/platform/core/src/index.ts similarity index 96% rename from platform/core/src/index.js rename to platform/core/src/index.ts index c45e3c6f2..d805be345 100644 --- a/platform/core/src/index.js +++ b/platform/core/src/index.ts @@ -1,6 +1,6 @@ import { ExtensionManager, MODULE_TYPES } from './extensions'; import { ServicesManager } from './services'; -import classes, { CommandsManager, HotkeysManager } from './classes/'; +import classes, { CommandsManager, HotkeysManager } from './classes'; import DICOMWeb from './DICOMWeb'; import errorHandler from './errorHandler.js'; @@ -8,8 +8,9 @@ import log from './log.js'; import object from './object.js'; import string from './string.js'; import user from './user.js'; -import utils from './utils/'; +import utils from './utils'; import defaults from './defaults'; +import * as Types from './types'; import { CineService, @@ -107,6 +108,7 @@ export { IWebApiDataSource, DicomMetadataStore, pubSubServiceInterface, + Types, }; export { OHIF }; diff --git a/platform/core/src/services/DicomMetadataStore/StudyMetadata.ts b/platform/core/src/services/DicomMetadataStore/StudyMetadata.ts deleted file mode 100644 index c391d09b0..000000000 --- a/platform/core/src/services/DicomMetadataStore/StudyMetadata.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** Defines a typescript type for study metadata */ -interface StudyMetadata { - readonly StudyInstanceUID: string; - StudyDescription?: string; -} - -export default StudyMetadata; diff --git a/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts b/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts index 573ae0617..0b1ebcf4b 100644 --- a/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts +++ b/platform/core/src/services/HangingProtocolService/HangingProtocolService.ts @@ -1,7 +1,7 @@ import pubSubServiceInterface from '../_shared/pubSubServiceInterface'; import sortBy from '../../utils/sortBy'; import ProtocolEngine from './ProtocolEngine'; -import StudyMetadata from '../DicomMetadataStore/StudyMetadata'; +import StudyMetadata from '../../types/StudyMetadata'; import IDisplaySet from '../DisplaySetService/IDisplaySet'; const EVENTS = { diff --git a/platform/core/src/types/Consumer.ts b/platform/core/src/types/Consumer.ts new file mode 100644 index 000000000..a761630d4 --- /dev/null +++ b/platform/core/src/types/Consumer.ts @@ -0,0 +1,5 @@ +/** + * Just a function that consumes a single argument, with no return. + */ +type Consumer = (props: Record) => void; +export default Consumer; diff --git a/platform/core/src/types/IPubSub.ts b/platform/core/src/types/IPubSub.ts new file mode 100644 index 000000000..b2cdbd31a --- /dev/null +++ b/platform/core/src/types/IPubSub.ts @@ -0,0 +1,12 @@ +import { Consumer } from './Consumer'; + + +export default interface IPubSub { + subscribe: (eventName: string, callback: Consumer) => void; + _broadcastEvent: ( + eventName: string, + callbackProps: Record + ) => void; + _unsubscribe: (eventName: string, listenerId: string) => void; + _isValidEvent: (eventName: string) => boolean; +} diff --git a/platform/core/src/types/StudyMetadata.ts b/platform/core/src/types/StudyMetadata.ts new file mode 100644 index 000000000..5a0cf8155 --- /dev/null +++ b/platform/core/src/types/StudyMetadata.ts @@ -0,0 +1,23 @@ +/** Defines a typescript type for study metadata */ + +export interface PatientMetadata extends Record { + PatientName?: string; + PatientId?: string; +} + +export interface StudyMetadata extends Record { + readonly StudyInstanceUID?: string; + StudyDescription?: string; +} + +export interface SeriesMetadata extends StudyMetadata { + readonly SeriesInstanceUID?: string; + SeriesDescription?: string; + SeriesNumber?: string | number; +} + +export interface InstanceMetadata extends SeriesMetadata { + readonly SOPInstanceUID: string; + InstanceNumber?: string | number; +} +export default StudyMetadata; diff --git a/platform/core/src/types/index.ts b/platform/core/src/types/index.ts new file mode 100644 index 000000000..896e1ff05 --- /dev/null +++ b/platform/core/src/types/index.ts @@ -0,0 +1,9 @@ +import { + StudyMetadata, + SeriesMetadata, + InstanceMetadata, +} from './StudyMetadata'; + +import Consumer from './Consumer'; + +export { StudyMetadata, SeriesMetadata, InstanceMetadata, Consumer }; diff --git a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx index f2f929732..87dfe5393 100644 --- a/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx +++ b/platform/ui/src/components/StudyBrowser/StudyBrowser.tsx @@ -4,7 +4,7 @@ import classnames from 'classnames'; import { useTranslation } from 'react-i18next'; import { ButtonGroup, Button, StudyItem, ThumbnailList } from '../'; -import { StringNumber } from '../../Types'; +import { StringNumber } from '../../types'; const buttonClasses = 'text-white text-base border-none p-2 min-w-18'; diff --git a/platform/ui/src/components/Thumbnail/Thumbnail.tsx b/platform/ui/src/components/Thumbnail/Thumbnail.tsx index 176ea36a4..73dcc67e4 100644 --- a/platform/ui/src/components/Thumbnail/Thumbnail.tsx +++ b/platform/ui/src/components/Thumbnail/Thumbnail.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { useDrag } from 'react-dnd'; import { Icon } from '../'; -import { StringNumber } from '../../Types'; +import { StringNumber } from '../../types'; /** * diff --git a/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx b/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx index 46ff0ab94..2b477d044 100644 --- a/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx +++ b/platform/ui/src/components/ThumbnailList/ThumbnailList.tsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Thumbnail, ThumbnailNoImage, ThumbnailTracked } from '../'; -import * as Types from '../../Types'; +import * as Types from '../../types'; const ThumbnailList = ({ thumbnails, diff --git a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx index 2e9f5dcf0..782bbe40c 100644 --- a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx +++ b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { Icon, Thumbnail, Tooltip } from '../'; -import { StringNumber } from '../../Types'; +import { StringNumber } from '../../types'; const ThumbnailTracked = ({ displaySetInstanceUID, diff --git a/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx b/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx index 90ad2b34a..3cc554b85 100644 --- a/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx +++ b/platform/ui/src/components/ViewportActionBar/ViewportActionBar.tsx @@ -4,7 +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'; +import { StringNumber } from '../../types'; const classes = { infoHeader: 'text-base text-primary-light', diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js index 4d74012df..12c1a4396 100644 --- a/platform/ui/src/index.js +++ b/platform/ui/src/index.js @@ -4,7 +4,7 @@ /** CONTEXT/HOOKS */ // Export types - need to do as two lines due to a bug in babel -import * as Types from './Types'; +import * as Types from './types'; export { useCine, diff --git a/platform/ui/src/types/ThumbnailType.ts b/platform/ui/src/types/ThumbnailType.ts new file mode 100644 index 000000000..745899f53 --- /dev/null +++ b/platform/ui/src/types/ThumbnailType.ts @@ -0,0 +1,7 @@ +import PropTypes from 'prop-types'; + +export default PropTypes.oneOf([ + 'thumbnail', + 'thumbnailTracked', + 'thumbnailNoImage', +]); diff --git a/platform/ui/src/Types.ts b/platform/ui/src/types/index.ts similarity index 82% rename from platform/ui/src/Types.ts rename to platform/ui/src/types/index.ts index d6c8581e9..6fd59a088 100644 --- a/platform/ui/src/Types.ts +++ b/platform/ui/src/types/index.ts @@ -1,4 +1,7 @@ import PropTypes from 'prop-types'; +import ThumbnailType from './ThumbnailType'; + +// A few miscellaneous types declared inline here. /** * StringNumber often comes back from DICOMweb for integer valued items. @@ -11,10 +14,4 @@ const StringNumber = PropTypes.oneOfType([PropTypes.string, PropTypes.number]); */ const StringArray = PropTypes.oneOfType([PropTypes.string, PropTypes.array]); -const ThumbnailType = PropTypes.oneOf([ - 'thumbnail', - 'thumbnailTracked', - 'thumbnailNoImage', -]); - export { StringNumber, StringArray, ThumbnailType }; diff --git a/platform/viewer/src/routes/DataSourceWrapper.tsx b/platform/viewer/src/routes/DataSourceWrapper.tsx index d48908bdc..60a22eeec 100644 --- a/platform/viewer/src/routes/DataSourceWrapper.tsx +++ b/platform/viewer/src/routes/DataSourceWrapper.tsx @@ -32,11 +32,16 @@ function DataSourceWrapper(props) { return acc.concat(mods); }, []); - // Grabbing first for now - should get active? - const name = webApiDataSources[0].name; + // Grabbing first defined for now - should get active // TODO: Why does this return an array? - const dataSource = extensionManager.getDataSources(name)[0]; - + const dataSource = webApiDataSources + .map(ds => extensionManager.getDataSources(ds.name)?.[0]) + .find(it => it !== undefined); + if (!dataSource) { + throw new Error( + `No data source found for any of ${webApiDataSources.map(it => it.name)}` + ); + } // Route props --> studies.mapParams // mapParams --> studies.search // studies.search --> studies.processResults @@ -168,7 +173,7 @@ function _getQueryFilterValues(query, queryLimit) { return queryFilterValues; function _tryParseInt(str, defaultValue) { - var retValue = defaultValue; + let retValue = defaultValue; if (str !== null) { if (str.length > 0) { if (!isNaN(str)) {