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 { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router';
import {
SidePanel,
ErrorBoundary,
@ -11,7 +13,6 @@ import {
useModal,
LoadingIndicatorProgress,
} from '@ohif/ui';
import i18n from '@ohif/i18n';
import { hotkeys } from '@ohif/core';
import { useAppConfig } from '@state';
@ -35,9 +36,19 @@ function ViewerLayout({
}) {
const [appConfig] = useAppConfig();
const navigate = useNavigate();
const location = useLocation();
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();

View File

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

View File

@ -16,9 +16,8 @@ window.config = {
sourceName: 'dicomweb',
configuration: {
name: 'DCM4CHEE',
wadoUriRoot: 'http://localhost:5000/dicomweb',
qidoRoot: 'http://localhost:5000/dicomweb',
wadoRoot: 'http://localhost:5000/dicomweb',
qidoRoot: '/dicomweb',
wadoRoot: '/dicomweb',
qidoSupportsIncludeField: false,
supportsReject: false,
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 location = useLocation();
// TODO: Fetch by type, name, etc?
const dataSourceModules = extensionManager.modules[MODULE_TYPES.DATA_SOURCE];
// 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);
}, []);
// TODO - get the variable from the props all the time...
let dataSourceName = new URLSearchParams(location.search).get(
'datasourcename'
);
const dataPath = dataSourceName ? `/${dataSourceName}` : '';
// Grabbing first defined for now - should get active
// TODO: Why does this return an array?
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)}`
);
if (!dataSourceName && window.config.defaultDataSourceName) {
dataSourceName = window.config.defaultDataSourceName;
} else if (!dataSourceName) {
// Gets the first defined datasource with the right name
// Mostly for historical reasons - new configs should use the defaultDataSourceName
const dataSourceModules =
extensionManager.modules[MODULE_TYPES.DATA_SOURCE];
// 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
// mapParams --> studies.search
// studies.search --> studies.processResults
@ -114,6 +123,7 @@ function DataSourceWrapper(props) {
<LayoutTemplate
{...rest}
data={data.studies}
dataPath={dataPath}
dataTotal={data.total}
dataSource={dataSource}
isLoadingData={isLoading}

View File

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