fix(datasource): configurability of additional data source extensions (#2931)

* feat(dataSource):Support more than one data source type.

* Add consumer type
This commit is contained in:
Bill Wallace 2022-09-20 11:05:26 -04:00 committed by GitHub
parent 55a1704e4a
commit 3900e62641
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 83 additions and 29 deletions

View File

@ -6,7 +6,7 @@
"license": "MIT", "license": "MIT",
"repository": "OHIF/Viewers", "repository": "OHIF/Viewers",
"main": "dist/index.umd.js", "main": "dist/index.umd.js",
"module": "src/index.js", "module": "src/index.ts",
"sideEffects": "false", "sideEffects": "false",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"

View File

@ -1,4 +1,4 @@
import * as OHIF from './index.js'; import * as OHIF from './index';
describe('Top level exports', () => { describe('Top level exports', () => {
test('have not changed', () => { test('have not changed', () => {
@ -31,6 +31,7 @@ describe('Top level exports', () => {
'DisplaySetService', 'DisplaySetService',
'MeasurementService', 'MeasurementService',
'ToolBarService', 'ToolBarService',
'Types',
'ViewportGridService', 'ViewportGridService',
'SegmentationService', 'SegmentationService',
'HangingProtocolService', 'HangingProtocolService',

View File

@ -1,6 +1,6 @@
import { ExtensionManager, MODULE_TYPES } from './extensions'; import { ExtensionManager, MODULE_TYPES } from './extensions';
import { ServicesManager } from './services'; import { ServicesManager } from './services';
import classes, { CommandsManager, HotkeysManager } from './classes/'; import classes, { CommandsManager, HotkeysManager } from './classes';
import DICOMWeb from './DICOMWeb'; import DICOMWeb from './DICOMWeb';
import errorHandler from './errorHandler.js'; import errorHandler from './errorHandler.js';
@ -8,8 +8,9 @@ import log from './log.js';
import object from './object.js'; import object from './object.js';
import string from './string.js'; import string from './string.js';
import user from './user.js'; import user from './user.js';
import utils from './utils/'; import utils from './utils';
import defaults from './defaults'; import defaults from './defaults';
import * as Types from './types';
import { import {
CineService, CineService,
@ -107,6 +108,7 @@ export {
IWebApiDataSource, IWebApiDataSource,
DicomMetadataStore, DicomMetadataStore,
pubSubServiceInterface, pubSubServiceInterface,
Types,
}; };
export { OHIF }; export { OHIF };

View File

@ -1,7 +0,0 @@
/** Defines a typescript type for study metadata */
interface StudyMetadata {
readonly StudyInstanceUID: string;
StudyDescription?: string;
}
export default StudyMetadata;

View File

@ -1,7 +1,7 @@
import pubSubServiceInterface from '../_shared/pubSubServiceInterface'; import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
import sortBy from '../../utils/sortBy'; import sortBy from '../../utils/sortBy';
import ProtocolEngine from './ProtocolEngine'; import ProtocolEngine from './ProtocolEngine';
import StudyMetadata from '../DicomMetadataStore/StudyMetadata'; import StudyMetadata from '../../types/StudyMetadata';
import IDisplaySet from '../DisplaySetService/IDisplaySet'; import IDisplaySet from '../DisplaySetService/IDisplaySet';
const EVENTS = { const EVENTS = {

View File

@ -0,0 +1,5 @@
/**
* Just a function that consumes a single argument, with no return.
*/
type Consumer = (props: Record<string, unknown>) => void;
export default Consumer;

View File

@ -0,0 +1,12 @@
import { Consumer } from './Consumer';
export default interface IPubSub {
subscribe: (eventName: string, callback: Consumer) => void;
_broadcastEvent: (
eventName: string,
callbackProps: Record<string, unknown>
) => void;
_unsubscribe: (eventName: string, listenerId: string) => void;
_isValidEvent: (eventName: string) => boolean;
}

View File

@ -0,0 +1,23 @@
/** Defines a typescript type for study metadata */
export interface PatientMetadata extends Record<string, unknown> {
PatientName?: string;
PatientId?: string;
}
export interface StudyMetadata extends Record<string, unknown> {
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;

View File

@ -0,0 +1,9 @@
import {
StudyMetadata,
SeriesMetadata,
InstanceMetadata,
} from './StudyMetadata';
import Consumer from './Consumer';
export { StudyMetadata, SeriesMetadata, InstanceMetadata, Consumer };

View File

@ -4,7 +4,7 @@ import classnames from 'classnames';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ButtonGroup, Button, StudyItem, ThumbnailList } from '../'; 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'; const buttonClasses = 'text-white text-base border-none p-2 min-w-18';

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import { useDrag } from 'react-dnd'; import { useDrag } from 'react-dnd';
import { Icon } from '../'; import { Icon } from '../';
import { StringNumber } from '../../Types'; import { StringNumber } from '../../types';
/** /**
* *

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Thumbnail, ThumbnailNoImage, ThumbnailTracked } from '../'; import { Thumbnail, ThumbnailNoImage, ThumbnailTracked } from '../';
import * as Types from '../../Types'; import * as Types from '../../types';
const ThumbnailList = ({ const ThumbnailList = ({
thumbnails, thumbnails,

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import { Icon, Thumbnail, Tooltip } from '../'; import { Icon, Thumbnail, Tooltip } from '../';
import { StringNumber } from '../../Types'; import { StringNumber } from '../../types';
const ThumbnailTracked = ({ const ThumbnailTracked = ({
displaySetInstanceUID, displaySetInstanceUID,

View File

@ -4,7 +4,7 @@ import classnames from 'classnames';
import { Icon, ButtonGroup, Button, Tooltip, CinePlayer } from '../'; import { Icon, ButtonGroup, Button, Tooltip, CinePlayer } from '../';
import useOnClickOutside from '../../utils/useOnClickOutside'; import useOnClickOutside from '../../utils/useOnClickOutside';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { StringNumber } from '../../Types'; import { StringNumber } from '../../types';
const classes = { const classes = {
infoHeader: 'text-base text-primary-light', infoHeader: 'text-base text-primary-light',

View File

@ -4,7 +4,7 @@
/** CONTEXT/HOOKS */ /** CONTEXT/HOOKS */
// Export types - need to do as two lines due to a bug in babel // 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 { export {
useCine, useCine,

View File

@ -0,0 +1,7 @@
import PropTypes from 'prop-types';
export default PropTypes.oneOf([
'thumbnail',
'thumbnailTracked',
'thumbnailNoImage',
]);

View File

@ -1,4 +1,7 @@
import PropTypes from 'prop-types'; 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. * 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 StringArray = PropTypes.oneOfType([PropTypes.string, PropTypes.array]);
const ThumbnailType = PropTypes.oneOf([
'thumbnail',
'thumbnailTracked',
'thumbnailNoImage',
]);
export { StringNumber, StringArray, ThumbnailType }; export { StringNumber, StringArray, ThumbnailType };

View File

@ -32,11 +32,16 @@ function DataSourceWrapper(props) {
return acc.concat(mods); return acc.concat(mods);
}, []); }, []);
// Grabbing first for now - should get active? // Grabbing first defined for now - should get active
const name = webApiDataSources[0].name;
// TODO: Why does this return an array? // 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 // Route props --> studies.mapParams
// mapParams --> studies.search // mapParams --> studies.search
// studies.search --> studies.processResults // studies.search --> studies.processResults
@ -168,7 +173,7 @@ function _getQueryFilterValues(query, queryLimit) {
return queryFilterValues; return queryFilterValues;
function _tryParseInt(str, defaultValue) { function _tryParseInt(str, defaultValue) {
var retValue = defaultValue; let retValue = defaultValue;
if (str !== null) { if (str !== null) {
if (str.length > 0) { if (str.length > 0) {
if (!isNaN(str)) { if (!isNaN(str)) {