feat(datasourcename):Allow specifying the datasourcename as a parameter (#3029)

This commit is contained in:
Bill Wallace 2022-11-22 09:09:24 -05:00 committed by GitHub
parent bbfdda7fe7
commit abd75b0ba1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 237 additions and 27 deletions

View File

@ -2,6 +2,8 @@ import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router';
import { import {
SidePanel, SidePanel,
ErrorBoundary, ErrorBoundary,
@ -11,7 +13,6 @@ import {
useModal, useModal,
LoadingIndicatorProgress, LoadingIndicatorProgress,
} from '@ohif/ui'; } from '@ohif/ui';
import i18n from '@ohif/i18n'; import i18n from '@ohif/i18n';
import { hotkeys } from '@ohif/core'; import { hotkeys } from '@ohif/core';
import { useAppConfig } from '@state'; import { useAppConfig } from '@state';
@ -35,9 +36,19 @@ function ViewerLayout({
}) { }) {
const [appConfig] = useAppConfig(); const [appConfig] = useAppConfig();
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation();
const onClickReturnButton = () => { const onClickReturnButton = () => {
navigate('/'); const { pathname } = location;
const dataSourceIdx = pathname.indexOf('/', 1);
const search =
dataSourceIdx === -1
? undefined
: `datasourcename=${pathname.substring(dataSourceIdx + 1)}`;
navigate({
pathname: '/',
search,
});
}; };
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -143,6 +143,9 @@ module.exports = (env, argv) => {
client: { client: {
overlay: { errors: true, warnings: false }, overlay: { errors: true, warnings: false },
}, },
proxy: {
'/dicomweb': 'http://localhost:5000',
},
'static': [ 'static': [
{ {
directory: '../../testdata', directory: '../../testdata',

View File

@ -16,9 +16,8 @@ window.config = {
sourceName: 'dicomweb', sourceName: 'dicomweb',
configuration: { configuration: {
name: 'DCM4CHEE', name: 'DCM4CHEE',
wadoUriRoot: 'http://localhost:5000/dicomweb', qidoRoot: '/dicomweb',
qidoRoot: 'http://localhost:5000/dicomweb', wadoRoot: '/dicomweb',
wadoRoot: 'http://localhost:5000/dicomweb',
qidoSupportsIncludeField: false, qidoSupportsIncludeField: false,
supportsReject: false, supportsReject: false,
imageRendering: 'wadors', imageRendering: 'wadors',

View File

@ -0,0 +1,183 @@
window.config = {
routerBasename: '/',
customizationService: [
],
extensions: [],
modes: [],
showStudyList: true,
maxNumberOfWebWorkers: 4,
// below flag is for performance reasons, but it might not work for all servers
omitQuotationForMultipartRequest: true,
showLoadingIndicator: true,
// filterQueryParam: false,
dataSources: [
{
friendlyName: 'Static WADO Local Data',
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'default',
configuration: {
name: 'DCM4CHEE',
qidoRoot: '/dicomweb',
wadoRoot: '/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
},
},
{
friendlyName: 'AWS S3 OHIF',
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'aws',
configuration: {
name: 'aws',
qidoRoot: 'https://viewer.flexview.ai/dicomweb',
wadoRoot: 'https://viewer.flexview.ai/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: 'bulkdata,video,pdf',
},
},
{
friendlyName: 'E2E Test Data',
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'e2e',
configuration: {
name: 'DCM4CHEE',
wadoUriRoot: '/viewer-testdata',
qidoRoot: '/viewer-testdata',
wadoRoot: '/viewer-testdata',
qidoSupportsIncludeField: false,
supportsReject: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: true,
staticWado: true,
singlepart: 'video,thumbnail,pdf',
},
},
{
friendlyName: 'dicom json',
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',
sourceName: 'dicomjson',
configuration: {
name: 'json',
},
},
{
friendlyName: 'dicom local',
namespace: '@ohif/extension-default.dataSourcesModule.dicomlocal',
sourceName: 'dicomlocal',
configuration: {},
},
],
httpErrorHandler: error => {
// This is 429 when rejected from the public idc sandbox too often.
console.warn(error.status);
// Could use services manager here to bring up a dialog/modal if needed.
console.warn('test, navigate to https://ohif.org/');
},
defaultDataSourceName: 'default',
hotkeys: [
{
commandName: 'incrementActiveViewport',
label: 'Next Viewport',
keys: ['right'],
},
{
commandName: 'decrementActiveViewport',
label: 'Previous Viewport',
keys: ['left'],
},
{ commandName: 'rotateViewportCW', label: 'Rotate Right', keys: ['r'] },
{ commandName: 'rotateViewportCCW', label: 'Rotate Left', keys: ['l'] },
{ commandName: 'invertViewport', label: 'Invert', keys: ['i'] },
{
commandName: 'flipViewportHorizontal',
label: 'Flip Horizontally',
keys: ['h'],
},
{
commandName: 'flipViewportVertical',
label: 'Flip Vertically',
keys: ['v'],
},
{ commandName: 'scaleUpViewport', label: 'Zoom In', keys: ['+'] },
{ commandName: 'scaleDownViewport', label: 'Zoom Out', keys: ['-'] },
{ commandName: 'fitViewportToWindow', label: 'Zoom to Fit', keys: ['='] },
{ commandName: 'resetViewport', label: 'Reset', keys: ['space'] },
{ commandName: 'nextImage', label: 'Next Image', keys: ['down'] },
{ commandName: 'previousImage', label: 'Previous Image', keys: ['up'] },
// {
// commandName: 'previousViewportDisplaySet',
// label: 'Previous Series',
// keys: ['pagedown'],
// },
// {
// commandName: 'nextViewportDisplaySet',
// label: 'Next Series',
// keys: ['pageup'],
// },
{ commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] },
// ~ Window level presets
{
commandName: 'windowLevelPreset1',
label: 'W/L Preset 1',
keys: ['1'],
},
{
commandName: 'windowLevelPreset2',
label: 'W/L Preset 2',
keys: ['2'],
},
{
commandName: 'windowLevelPreset3',
label: 'W/L Preset 3',
keys: ['3'],
},
{
commandName: 'windowLevelPreset4',
label: 'W/L Preset 4',
keys: ['4'],
},
{
commandName: 'windowLevelPreset5',
label: 'W/L Preset 5',
keys: ['5'],
},
{
commandName: 'windowLevelPreset6',
label: 'W/L Preset 6',
keys: ['6'],
},
{
commandName: 'windowLevelPreset7',
label: 'W/L Preset 7',
keys: ['7'],
},
{
commandName: 'windowLevelPreset8',
label: 'W/L Preset 8',
keys: ['8'],
},
{
commandName: 'windowLevelPreset9',
label: 'W/L Preset 9',
keys: ['9'],
},
],
};

View File

@ -19,29 +19,38 @@ function DataSourceWrapper(props) {
const params = useParams(); const params = useParams();
const location = useLocation(); const location = useLocation();
// TODO: Fetch by type, name, etc? // TODO - get the variable from the props all the time...
const dataSourceModules = extensionManager.modules[MODULE_TYPES.DATA_SOURCE]; let dataSourceName = new URLSearchParams(location.search).get(
// TODO: Good usecase for flatmap? 'datasourcename'
const webApiDataSources = dataSourceModules.reduce((acc, curr) => { );
const mods = []; const dataPath = dataSourceName ? `/${dataSourceName}` : '';
curr.module.forEach(mod => {
if (mod.type === 'webApi') {
mods.push(mod);
}
});
return acc.concat(mods);
}, []);
// Grabbing first defined for now - should get active if (!dataSourceName && window.config.defaultDataSourceName) {
// TODO: Why does this return an array? dataSourceName = window.config.defaultDataSourceName;
const dataSource = webApiDataSources } else if (!dataSourceName) {
.map(ds => extensionManager.getDataSources(ds.name)?.[0]) // Gets the first defined datasource with the right name
.find(it => it !== undefined); // Mostly for historical reasons - new configs should use the defaultDataSourceName
if (!dataSource) { const dataSourceModules =
throw new Error( extensionManager.modules[MODULE_TYPES.DATA_SOURCE];
`No data source found for any of ${webApiDataSources.map(it => it.name)}` // TODO: Good usecase for flatmap?
); const webApiDataSources = dataSourceModules.reduce((acc, curr) => {
const mods = [];
curr.module.forEach(mod => {
if (mod.type === 'webApi') {
mods.push(mod);
}
});
return acc.concat(mods);
}, []);
dataSourceName = webApiDataSources
.map(ds => ds.name)
.find(it => extensionManager.getDataSources(it)?.[0] !== undefined);
} }
const dataSource = extensionManager.getDataSources(dataSourceName)?.[0];
if (!dataSource) {
throw new Error(`No data source found for ${dataSourceName}`);
}
// Route props --> studies.mapParams // Route props --> studies.mapParams
// mapParams --> studies.search // mapParams --> studies.search
// studies.search --> studies.processResults // studies.search --> studies.processResults
@ -114,6 +123,7 @@ function DataSourceWrapper(props) {
<LayoutTemplate <LayoutTemplate
{...rest} {...rest}
data={data.studies} data={data.studies}
dataPath={dataPath}
dataTotal={data.total} dataTotal={data.total}
dataSource={dataSource} dataSource={dataSource}
isLoadingData={isLoading} isLoadingData={isLoading}

View File

@ -46,6 +46,7 @@ function WorkList({
isLoadingData, isLoadingData,
dataSource, dataSource,
hotkeysManager, hotkeysManager,
dataPath,
}) { }) {
const { hotkeyDefinitions, hotkeyDefaults } = hotkeysManager; const { hotkeyDefinitions, hotkeyDefaults } = hotkeysManager;
const { show, hide } = useModal(); const { show, hide } = useModal();
@ -346,7 +347,8 @@ function WorkList({
return ( return (
<Link <Link
key={i} key={i}
to={`${mode.routeName}?StudyInstanceUIDs=${studyInstanceUid}`} to={`${dataPath ? '../../' : ''}${mode.routeName}${dataPath ||
''}?StudyInstanceUIDs=${studyInstanceUid}`}
// to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`} // to={`${mode.routeName}/dicomweb?StudyInstanceUIDs=${studyInstanceUid}`}
> >
<Button <Button
@ -496,6 +498,7 @@ const defaultFilterValues = {
sortDirection: 'none', sortDirection: 'none',
pageNumber: 1, pageNumber: 1,
resultsPerPage: 25, resultsPerPage: 25,
datasourcename: '',
}; };
function _tryParseInt(str, defaultValue) { function _tryParseInt(str, defaultValue) {
@ -527,6 +530,7 @@ function _getQueryFilterValues(query) {
sortDirection: query.get('sortDirection'), sortDirection: query.get('sortDirection'),
pageNumber: _tryParseInt(query.get('pageNumber'), undefined), pageNumber: _tryParseInt(query.get('pageNumber'), undefined),
resultsPerPage: _tryParseInt(query.get('resultsPerPage'), undefined), resultsPerPage: _tryParseInt(query.get('resultsPerPage'), undefined),
datasourcename: query.get('datasourcename'),
}; };
// Delete null/undefined keys // Delete null/undefined keys