remove unused files
This commit is contained in:
parent
a99badd011
commit
c2853f719a
@ -1,37 +0,0 @@
|
|||||||
import React, { useContext } from 'react';
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { getActiveContexts } from '../store/layout/selectors.js';
|
|
||||||
|
|
||||||
let AppContext = React.createContext({});
|
|
||||||
|
|
||||||
export const CONTEXTS = {
|
|
||||||
CORNERSTONE: 'ACTIVE_VIEWPORT::CORNERSTONE',
|
|
||||||
VTK: 'ACTIVE_VIEWPORT::VTK',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useAppContext = () => useContext(AppContext);
|
|
||||||
|
|
||||||
export const AppProvider = ({ children, config }) => {
|
|
||||||
const activeContexts = useSelector(state => getActiveContexts(state));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppContext.Provider value={{ appConfig: config, activeContexts }}>
|
|
||||||
{children}
|
|
||||||
</AppContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const withAppContext = Component => {
|
|
||||||
return function WrappedComponent(props) {
|
|
||||||
const { appConfig, activeContexts } = useAppContext();
|
|
||||||
return (
|
|
||||||
<Component
|
|
||||||
{...props}
|
|
||||||
appConfig={appConfig}
|
|
||||||
activeContexts={activeContexts}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AppContext;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import OHIFLogo from '../components/OHIFLogo/OHIFLogo.js';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const defaultContextValues = {
|
|
||||||
createLogoComponentFn: React => OHIFLogo(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const WhiteLabelingContext = React.createContext(defaultContextValues);
|
|
||||||
|
|
||||||
export default WhiteLabelingContext;
|
|
||||||
@ -1,578 +0,0 @@
|
|||||||
import React, { useState, useEffect, useContext } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import OHIF from '@ohif/core';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import {
|
|
||||||
StudyList,
|
|
||||||
PageToolbar,
|
|
||||||
TablePagination,
|
|
||||||
useDebounce,
|
|
||||||
useMedia,
|
|
||||||
} from '@ohif/ui';
|
|
||||||
import ConnectedHeader from '../connectedComponents/ConnectedHeader.js';
|
|
||||||
import * as RoutesUtil from '../routes/routesUtil';
|
|
||||||
import moment from 'moment';
|
|
||||||
import ConnectedDicomFilesUploader from '../googleCloud/ConnectedDicomFilesUploader';
|
|
||||||
import ConnectedDicomStorePicker from '../googleCloud/ConnectedDicomStorePicker';
|
|
||||||
import filesToStudies from '../lib/filesToStudies.js';
|
|
||||||
|
|
||||||
// Contexts
|
|
||||||
import UserManagerContext from '../context/UserManagerContext';
|
|
||||||
import WhiteLabelingContext from '../context/WhiteLabelingContext';
|
|
||||||
import AppContext from '../context/AppContext';
|
|
||||||
|
|
||||||
const { urlUtil: UrlUtil } = OHIF.utils;
|
|
||||||
|
|
||||||
function StudyListRoute(props) {
|
|
||||||
const { history, server, user, studyListFunctionsEnabled } = props;
|
|
||||||
const [t] = useTranslation('Common');
|
|
||||||
// ~~ STATE
|
|
||||||
const [sort, setSort] = useState({
|
|
||||||
fieldName: 'PatientName',
|
|
||||||
direction: 'desc',
|
|
||||||
});
|
|
||||||
const [filterValues, setFilterValues] = useState({
|
|
||||||
studyDateTo: null,
|
|
||||||
studyDateFrom: null,
|
|
||||||
PatientName: '',
|
|
||||||
PatientID: '',
|
|
||||||
AccessionNumber: '',
|
|
||||||
StudyDate: '',
|
|
||||||
modalities: '',
|
|
||||||
StudyDescription: '',
|
|
||||||
//
|
|
||||||
patientNameOrId: '',
|
|
||||||
accessionOrModalityOrDescription: '',
|
|
||||||
//
|
|
||||||
allFields: '',
|
|
||||||
});
|
|
||||||
const [studies, setStudies] = useState([]);
|
|
||||||
const [searchStatus, setSearchStatus] = useState({
|
|
||||||
isSearchingForStudies: false,
|
|
||||||
error: null,
|
|
||||||
});
|
|
||||||
const [activeModalId, setActiveModalId] = useState(null);
|
|
||||||
const [rowsPerPage, setRowsPerPage] = useState(25);
|
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
|
||||||
const appContext = useContext(AppContext);
|
|
||||||
// ~~ RESPONSIVE
|
|
||||||
const displaySize = useMedia(
|
|
||||||
[
|
|
||||||
'(min-width: 1750px)',
|
|
||||||
'(min-width: 1000px) and (max-width: 1749px)',
|
|
||||||
'(max-width: 999px)',
|
|
||||||
],
|
|
||||||
['large', 'medium', 'small'],
|
|
||||||
'small'
|
|
||||||
);
|
|
||||||
// ~~ DEBOUNCED INPUT
|
|
||||||
const debouncedSort = useDebounce(sort, 200);
|
|
||||||
const debouncedFilters = useDebounce(filterValues, 250);
|
|
||||||
|
|
||||||
// Google Cloud Adapter for DICOM Store Picking
|
|
||||||
const { appConfig = {} } = appContext;
|
|
||||||
const isGoogleCHAIntegrationEnabled =
|
|
||||||
!server && appConfig.enableGoogleCloudAdapter;
|
|
||||||
if (isGoogleCHAIntegrationEnabled && activeModalId !== 'DicomStorePicker') {
|
|
||||||
setActiveModalId('DicomStorePicker');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when relevant state/props are updated
|
|
||||||
// Watches filters and sort, debounced
|
|
||||||
useEffect(
|
|
||||||
() => {
|
|
||||||
const fetchStudies = async () => {
|
|
||||||
try {
|
|
||||||
setSearchStatus({ error: null, isSearchingForStudies: true });
|
|
||||||
|
|
||||||
const response = await getStudyList(
|
|
||||||
server,
|
|
||||||
debouncedFilters,
|
|
||||||
debouncedSort,
|
|
||||||
rowsPerPage,
|
|
||||||
pageNumber,
|
|
||||||
displaySize
|
|
||||||
);
|
|
||||||
|
|
||||||
setStudies(response);
|
|
||||||
setSearchStatus({ error: null, isSearchingForStudies: false });
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(error);
|
|
||||||
setSearchStatus({ error: true, isFetching: false });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (server) {
|
|
||||||
fetchStudies();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// TODO: Can we update studies directly?
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
[
|
|
||||||
debouncedFilters,
|
|
||||||
debouncedSort,
|
|
||||||
rowsPerPage,
|
|
||||||
pageNumber,
|
|
||||||
displaySize,
|
|
||||||
server,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: Update Server
|
|
||||||
// if (this.props.server !== prevProps.server) {
|
|
||||||
// this.setState({
|
|
||||||
// modalComponentId: null,
|
|
||||||
// searchData: null,
|
|
||||||
// studies: null,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
const onDrop = async acceptedFiles => {
|
|
||||||
try {
|
|
||||||
const studiesFromFiles = await filesToStudies(acceptedFiles);
|
|
||||||
setStudies(studiesFromFiles);
|
|
||||||
} catch (error) {
|
|
||||||
setSearchStatus({ isSearchingForStudies: false, error });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (searchStatus.error) {
|
|
||||||
return <div>Error: {JSON.stringify(searchStatus.error)}</div>;
|
|
||||||
} else if (studies === [] && !activeModalId) {
|
|
||||||
return <div>Loading...</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let healthCareApiButtons = null;
|
|
||||||
let healthCareApiWindows = null;
|
|
||||||
|
|
||||||
if (appConfig.enableGoogleCloudAdapter) {
|
|
||||||
const isModalOpen = activeModalId === 'DicomStorePicker';
|
|
||||||
updateURL(isModalOpen, appConfig, server, history);
|
|
||||||
|
|
||||||
healthCareApiWindows = (
|
|
||||||
<ConnectedDicomStorePicker
|
|
||||||
isOpen={activeModalId === 'DicomStorePicker'}
|
|
||||||
onClose={() => setActiveModalId(null)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
healthCareApiButtons = (
|
|
||||||
<div
|
|
||||||
className="form-inline btn-group pull-right"
|
|
||||||
style={{ padding: '20px' }}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="btn btn-primary"
|
|
||||||
onClick={() => setActiveModalId('DicomStorePicker')}
|
|
||||||
>
|
|
||||||
{t('Change DICOM Store')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSort(fieldName) {
|
|
||||||
let sortFieldName = fieldName;
|
|
||||||
let sortDirection = 'asc';
|
|
||||||
|
|
||||||
if (fieldName === sort.fieldName) {
|
|
||||||
if (sort.direction === 'asc') {
|
|
||||||
sortDirection = 'desc';
|
|
||||||
} else {
|
|
||||||
sortFieldName = null;
|
|
||||||
sortDirection = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setSort({
|
|
||||||
fieldName: sortFieldName,
|
|
||||||
direction: sortDirection,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleFilterChange(fieldName, value) {
|
|
||||||
setFilterValues(state => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
[fieldName]: value,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{studyListFunctionsEnabled ? (
|
|
||||||
<ConnectedDicomFilesUploader
|
|
||||||
isOpen={activeModalId === 'DicomFilesUploader'}
|
|
||||||
onClose={() => setActiveModalId(null)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{healthCareApiWindows}
|
|
||||||
<WhiteLabelingContext.Consumer>
|
|
||||||
{whiteLabeling => (
|
|
||||||
<UserManagerContext.Consumer>
|
|
||||||
{userManager => (
|
|
||||||
<ConnectedHeader
|
|
||||||
useLargeLogo={true}
|
|
||||||
user={user}
|
|
||||||
userManager={userManager}
|
|
||||||
>
|
|
||||||
{whiteLabeling &&
|
|
||||||
whiteLabeling.createLogoComponentFn &&
|
|
||||||
whiteLabeling.createLogoComponentFn(React)}
|
|
||||||
</ConnectedHeader>
|
|
||||||
)}
|
|
||||||
</UserManagerContext.Consumer>
|
|
||||||
)}
|
|
||||||
</WhiteLabelingContext.Consumer>
|
|
||||||
<div className="study-list-header">
|
|
||||||
<div className="header">
|
|
||||||
<h1 style={{ fontWeight: 300, fontSize: '22px' }}>
|
|
||||||
{t('StudyList')}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div className="actions">
|
|
||||||
{studyListFunctionsEnabled && healthCareApiButtons}
|
|
||||||
{studyListFunctionsEnabled && (
|
|
||||||
<PageToolbar
|
|
||||||
onImport={() => setActiveModalId('DicomFilesUploader')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<span className="study-count">{studies.length}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="table-head-background" />
|
|
||||||
<div className="study-list-container">
|
|
||||||
{/* STUDY LIST OR DROP ZONE? */}
|
|
||||||
<StudyList
|
|
||||||
isLoading={searchStatus.isSearchingForStudies}
|
|
||||||
hasError={searchStatus.error === true}
|
|
||||||
// Rows
|
|
||||||
studies={studies}
|
|
||||||
onSelectItem={studyInstanceUID => {
|
|
||||||
const viewerPath = RoutesUtil.parseViewerPath(appConfig, server, {
|
|
||||||
studyInstanceUIDs: studyInstanceUID,
|
|
||||||
});
|
|
||||||
history.push(viewerPath);
|
|
||||||
}}
|
|
||||||
// Table Header
|
|
||||||
sort={sort}
|
|
||||||
onSort={handleSort}
|
|
||||||
filterValues={filterValues}
|
|
||||||
onFilterChange={handleFilterChange}
|
|
||||||
studyListDateFilterNumDays={appConfig.studyListDateFilterNumDays}
|
|
||||||
displaySize={displaySize}
|
|
||||||
/>
|
|
||||||
{/* PAGINATION FOOTER */}
|
|
||||||
<TablePagination
|
|
||||||
currentPage={pageNumber}
|
|
||||||
nextPageFunc={() => setPageNumber(pageNumber + 1)}
|
|
||||||
prevPageFunc={() => setPageNumber(pageNumber - 1)}
|
|
||||||
onRowsPerPageChange={Rows => setRowsPerPage(Rows)}
|
|
||||||
rowsPerPage={rowsPerPage}
|
|
||||||
recordCount={studies.length}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
StudyListRoute.propTypes = {
|
|
||||||
filters: PropTypes.object,
|
|
||||||
PatientID: PropTypes.string,
|
|
||||||
server: PropTypes.object,
|
|
||||||
user: PropTypes.object,
|
|
||||||
history: PropTypes.object,
|
|
||||||
studyListFunctionsEnabled: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
StudyListRoute.defaultProps = {
|
|
||||||
studyListFunctionsEnabled: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
function updateURL(isModalOpen, appConfig, server, history) {
|
|
||||||
if (isModalOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const listPath = RoutesUtil.parseStudyListPath(appConfig, server);
|
|
||||||
|
|
||||||
if (UrlUtil.paramString.isValidPath(listPath)) {
|
|
||||||
const { location = {} } = history;
|
|
||||||
if (location.pathname !== listPath) {
|
|
||||||
history.replace(listPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not ideal, but we use displaySize to determine how the filters should be used
|
|
||||||
* to build the collection of promises we need to fetch a result set.
|
|
||||||
*
|
|
||||||
* @param {*} server
|
|
||||||
* @param {*} filters
|
|
||||||
* @param {object} sort
|
|
||||||
* @param {string} sort.fieldName - field to sort by
|
|
||||||
* @param {string} sort.direction - direction to sort
|
|
||||||
* @param {number} rowsPerPage - Number of results to return
|
|
||||||
* @param {number} pageNumber - Used to determine results offset
|
|
||||||
* @param {string} displaySize - small, medium, large
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
async function getStudyList(
|
|
||||||
server,
|
|
||||||
filters,
|
|
||||||
sort,
|
|
||||||
rowsPerPage,
|
|
||||||
pageNumber,
|
|
||||||
displaySize
|
|
||||||
) {
|
|
||||||
const {
|
|
||||||
allFields,
|
|
||||||
patientNameOrId,
|
|
||||||
accessionOrModalityOrDescription,
|
|
||||||
} = filters;
|
|
||||||
const sortFieldName = sort.fieldName || 'PatientName';
|
|
||||||
const sortDirection = sort.direction || 'desc';
|
|
||||||
const studyDateFrom =
|
|
||||||
filters.studyDateFrom ||
|
|
||||||
moment()
|
|
||||||
.subtract(25000, 'days')
|
|
||||||
.toDate();
|
|
||||||
const studyDateTo = filters.studyDateTo || new Date();
|
|
||||||
|
|
||||||
const mappedFilters = {
|
|
||||||
PatientID: filters.PatientID,
|
|
||||||
PatientName: filters.PatientName,
|
|
||||||
AccessionNumber: filters.AccessionNumber,
|
|
||||||
StudyDescription: filters.StudyDescription,
|
|
||||||
ModalitiesInStudy: filters.modalities,
|
|
||||||
// NEVER CHANGE
|
|
||||||
studyDateFrom,
|
|
||||||
studyDateTo,
|
|
||||||
limit: rowsPerPage,
|
|
||||||
offset: pageNumber * rowsPerPage,
|
|
||||||
fuzzymatching: server.supportsFuzzyMatching === true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const studies = await _fetchStudies(server, mappedFilters, displaySize, {
|
|
||||||
allFields,
|
|
||||||
patientNameOrId,
|
|
||||||
accessionOrModalityOrDescription,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Only the fields we use
|
|
||||||
const mappedStudies = studies.map(study => {
|
|
||||||
const PatientName =
|
|
||||||
typeof study.PatientName === 'string' ? study.PatientName : undefined;
|
|
||||||
|
|
||||||
return {
|
|
||||||
AccessionNumber: study.AccessionNumber, // "1"
|
|
||||||
modalities: study.modalities, // "SEG\\MR"
|
|
||||||
// numberOfStudyRelatedInstances: "3"
|
|
||||||
// numberOfStudyRelatedSeries: "3"
|
|
||||||
// PatientBirthdate: undefined
|
|
||||||
PatientID: study.PatientID, // "NOID"
|
|
||||||
PatientName, // "NAME^NONE"
|
|
||||||
// PatientSex: "M"
|
|
||||||
// referringPhysicianName: undefined
|
|
||||||
StudyDate: study.StudyDate, // "Jun 28, 2002"
|
|
||||||
StudyDescription: study.StudyDescription, // "BRAIN"
|
|
||||||
// studyId: "No Study ID"
|
|
||||||
StudyInstanceUID: study.StudyInstanceUID, // "1.3.6.1.4.1.5962.99.1.3814087073.479799962.1489872804257.3.0"
|
|
||||||
// StudyTime: "160956.0"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// For our smaller displays, map our field name to a single
|
|
||||||
// field we can actually sort by.
|
|
||||||
const sortFieldNameMapping = {
|
|
||||||
allFields: 'PatientName',
|
|
||||||
patientNameOrId: 'PatientName',
|
|
||||||
accessionOrModalityOrDescription: 'modalities',
|
|
||||||
};
|
|
||||||
const mappedSortFieldName =
|
|
||||||
sortFieldNameMapping[sortFieldName] || sortFieldName;
|
|
||||||
|
|
||||||
const sortedStudies = _sortStudies(
|
|
||||||
mappedStudies,
|
|
||||||
mappedSortFieldName,
|
|
||||||
sortDirection
|
|
||||||
);
|
|
||||||
|
|
||||||
// Because we've merged multiple requests, we may have more than
|
|
||||||
// our Rows per page. Let's `take` that number from our sorted array.
|
|
||||||
// This "might" cause paging issues.
|
|
||||||
const numToTake =
|
|
||||||
sortedStudies.length < rowsPerPage ? sortedStudies.length : rowsPerPage;
|
|
||||||
const result = sortedStudies.slice(0, numToTake);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param {object[]} studies - Array of studies to sort
|
|
||||||
* @param {string} studies.StudyDate - Date in 'MMM DD, YYYY' format
|
|
||||||
* @param {string} field - name of properties on study to sort by
|
|
||||||
* @param {string} order - 'asc' or 'desc'
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function _sortStudies(studies, field, order) {
|
|
||||||
// Make sure our StudyDate is in a valid format and create copy of studies array
|
|
||||||
const sortedStudies = studies.map(study => {
|
|
||||||
if (!moment(study.StudyDate, 'MMM DD, YYYY', true).isValid()) {
|
|
||||||
study.StudyDate = moment(study.StudyDate, 'YYYYMMDD').format(
|
|
||||||
'MMM DD, YYYY'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return study;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort by field
|
|
||||||
sortedStudies.sort(function(a, b) {
|
|
||||||
let fieldA = a[field];
|
|
||||||
let fieldB = b[field];
|
|
||||||
if (field === 'StudyDate') {
|
|
||||||
fieldA = moment(fieldA).toISOString();
|
|
||||||
fieldB = moment(fieldB).toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Order
|
|
||||||
if (order === 'desc') {
|
|
||||||
if (fieldA < fieldB) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (fieldA > fieldB) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
if (fieldA > fieldB) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (fieldA < fieldB) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return sortedStudies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We're forced to do this because DICOMWeb does not support "AND|OR" searches
|
|
||||||
* across multiple fields. This allows us to make multiple requests, remove
|
|
||||||
* duplicates, and return the result set as if it were supported
|
|
||||||
*
|
|
||||||
* @param {object} server
|
|
||||||
* @param {Object} filters
|
|
||||||
* @param {string} displaySize - small, medium, or large
|
|
||||||
* @param {string} multi.allFields
|
|
||||||
* @param {string} multi.patientNameOrId
|
|
||||||
* @param {string} multi.accessionOrModalityOrDescription
|
|
||||||
*/
|
|
||||||
async function _fetchStudies(
|
|
||||||
server,
|
|
||||||
filters,
|
|
||||||
displaySize,
|
|
||||||
{ allFields, patientNameOrId, accessionOrModalityOrDescription }
|
|
||||||
) {
|
|
||||||
let queryFiltersArray = [filters];
|
|
||||||
|
|
||||||
if (displaySize === 'small') {
|
|
||||||
const firstSet = _getQueryFiltersForValue(
|
|
||||||
filters,
|
|
||||||
[
|
|
||||||
'PatientID',
|
|
||||||
'PatientName',
|
|
||||||
'AccessionNumber',
|
|
||||||
'StudyDescription',
|
|
||||||
'ModalitiesInStudy',
|
|
||||||
],
|
|
||||||
allFields
|
|
||||||
);
|
|
||||||
|
|
||||||
if (firstSet.length) {
|
|
||||||
queryFiltersArray = firstSet;
|
|
||||||
}
|
|
||||||
} else if (displaySize === 'medium') {
|
|
||||||
const firstSet = _getQueryFiltersForValue(
|
|
||||||
filters,
|
|
||||||
['PatientID', 'PatientName'],
|
|
||||||
patientNameOrId
|
|
||||||
);
|
|
||||||
|
|
||||||
const secondSet = _getQueryFiltersForValue(
|
|
||||||
filters,
|
|
||||||
['AccessionNumber', 'StudyDescription', 'ModalitiesInStudy'],
|
|
||||||
accessionOrModalityOrDescription
|
|
||||||
);
|
|
||||||
|
|
||||||
if (firstSet.length || secondSet.length) {
|
|
||||||
queryFiltersArray = firstSet.concat(secondSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryPromises = [];
|
|
||||||
|
|
||||||
queryFiltersArray.forEach(filter => {
|
|
||||||
const searchStudiesPromise = OHIF.studies.searchStudies(server, filter);
|
|
||||||
queryPromises.push(searchStudiesPromise);
|
|
||||||
});
|
|
||||||
|
|
||||||
const lotsOfStudies = await Promise.all(queryPromises);
|
|
||||||
const studies = [];
|
|
||||||
|
|
||||||
// Flatten and dedupe
|
|
||||||
lotsOfStudies.forEach(arrayOfStudies => {
|
|
||||||
if (arrayOfStudies) {
|
|
||||||
arrayOfStudies.forEach(study => {
|
|
||||||
if (!studies.some(s => s.StudyInstanceUID === study.StudyInstanceUID)) {
|
|
||||||
studies.push(study);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return studies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param {*} filters
|
|
||||||
* @param {*} fields - Array of string fields
|
|
||||||
* @param {*} value
|
|
||||||
*/
|
|
||||||
function _getQueryFiltersForValue(filters, fields, value) {
|
|
||||||
const queryFilters = [];
|
|
||||||
|
|
||||||
if (value === '' || !value) {
|
|
||||||
return queryFilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.forEach(field => {
|
|
||||||
const filter = Object.assign(
|
|
||||||
{
|
|
||||||
PatientID: '',
|
|
||||||
PatientName: '',
|
|
||||||
AccessionNumber: '',
|
|
||||||
StudyDescription: '',
|
|
||||||
ModalitiesInStudy: '',
|
|
||||||
},
|
|
||||||
filters
|
|
||||||
);
|
|
||||||
|
|
||||||
filter[field] = value;
|
|
||||||
queryFilters.push(filter);
|
|
||||||
});
|
|
||||||
|
|
||||||
return queryFilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withRouter(StudyListRoute);
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
import React, { useContext } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
import ConnectedStudyList from './ConnectedStudyList';
|
|
||||||
import useServer from '../customHooks/useServer';
|
|
||||||
import OHIF from '@ohif/core';
|
|
||||||
const { urlUtil: UrlUtil } = OHIF.utils;
|
|
||||||
|
|
||||||
// Contexts
|
|
||||||
import AppContext from '../context/AppContext';
|
|
||||||
|
|
||||||
function StudyListRouting({ match: routeMatch, location: routeLocation }) {
|
|
||||||
const {
|
|
||||||
project,
|
|
||||||
location,
|
|
||||||
dataset,
|
|
||||||
dicomStore,
|
|
||||||
studyInstanceUIDs,
|
|
||||||
seriesInstanceUIDs,
|
|
||||||
} = routeMatch.params;
|
|
||||||
const server = useServer({ project, location, dataset, dicomStore });
|
|
||||||
const { appConfig = {} } = useContext(AppContext);
|
|
||||||
|
|
||||||
const filters = UrlUtil.queryString.getQueryFilters(routeLocation);
|
|
||||||
|
|
||||||
let studyListFunctionsEnabled = false;
|
|
||||||
if (appConfig.studyListFunctionsEnabled) {
|
|
||||||
studyListFunctionsEnabled = appConfig.studyListFunctionsEnabled;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<ConnectedStudyList
|
|
||||||
filters={filters}
|
|
||||||
studyListFunctionsEnabled={studyListFunctionsEnabled}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
StudyListRouting.propTypes = {
|
|
||||||
location: PropTypes.shape({
|
|
||||||
search: PropTypes.string,
|
|
||||||
}).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withRouter(StudyListRouting);
|
|
||||||
Loading…
Reference in New Issue
Block a user