ohif-viewer/platform/viewer/src/routes/DataSourceWrapper.jsx

142 lines
4.1 KiB
JavaScript

/* eslint-disable react/jsx-props-no-spreading */
import React, { useContext, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { MODULE_TYPES } from '@ohif/core';
//
import { appConfigContext } from '../state/appConfig.context';
import { extensionManager } from '../App.jsx';
/**
* Uses route properties to determine the data source that should be passed
* to the child layout template. In some instances, initiates requests and
* passes data as props.
*
* @param {object} props
* @param {function} props.children - Layout Template React Component
*/
function DataSourceWrapper(props) {
const { appConfig } = useContext(appConfigContext);
const { children: LayoutTemplate, history, ...rest } = props;
const queryFilterValues = _getQueryFilterValues(history.location.search);
// 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);
}, []);
// Grabbing first for now. This isn't hydrated yet, but we should
// hydrate it somewhere based on config...
// ~ default.js
const firstAppConfigDataSource = appConfig.dataSources[0];
const dataSourceConfig = firstAppConfigDataSource.configuration;
const firstWebApiDataSource = webApiDataSources[0];
debugger;
const dataSource = firstWebApiDataSource.createDataSource(dataSourceConfig);
// Route props --> studies.mapParams
// mapParams --> studies.search
// studies.search --> studies.processResults
// studies.processResults --> <LayoutTemplate studies={} />
// But only for LayoutTemplate type of 'list'?
// Or no data fetching here, and just hand down my source
const [data, setData] = useState();
useEffect(() => {
// 204: no content
async function getData() {
const searchResults = await dataSource.query.studies.search(
queryFilterValues
);
setData(searchResults);
}
try {
getData();
} catch (ex) {
console.warn(ex);
}
console.log('DataSourceWrapper: useEffect');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [history.location.search]);
// queryFilterValues
// TODO: Better way to pass DataSource?
return (
<React.Fragment>
{data && (
<LayoutTemplate
{...rest}
history={history}
data={data}
dataSource={dataSource}
/>
)}
</React.Fragment>
);
}
DataSourceWrapper.propTypes = {
/** Layout Component to wrap with a Data Source */
children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
};
export default DataSourceWrapper;
/**
* Duplicated in `workList`
* Need generic that can be shared? Isn't this what qs is for?
* @param {*} query
*/
function _getQueryFilterValues(query) {
query = new URLSearchParams(query);
const queryFilterValues = {
// DCM
patientId: query.get('mrn'),
patientName: query.get('patientName'),
studyDescription: query.get('description'),
modalitiesInStudy: query.get('modalities')
? query.get('modalities').split(',')
: [],
accessionNumber: query.get('accession'),
//
startDate: query.get('startDate'),
endDate: query.get('endDate'),
page: _tryParseInt(query.get('page'), undefined),
resultsPerPage: _tryParseInt(query.get('resultsPerPage'), undefined),
// Rarely supported server-side
sortBy: query.get('sortBy'),
sortDirection: query.get('sortDirection'),
};
// patientName: good
// studyDescription: good
// accessionNumber: good
// Delete null/undefined keys
Object.keys(queryFilterValues).forEach(
key => queryFilterValues[key] == null && delete queryFilterValues[key]
);
return queryFilterValues;
function _tryParseInt(str, defaultValue) {
var retValue = defaultValue;
if (str !== null) {
if (str.length > 0) {
if (!isNaN(str)) {
retValue = parseInt(str);
}
}
}
return retValue;
}
}