refactor: 💡 Clean up JSON launch with DICOMWeb server (#1388)
* refactor: 💡 Clean up JSON launch with DICOMWeb server Clean up JSON launch with DICOMWeb server ✅ Closes: #1387 * Remove test file * parse seriesinstanceuids in query * Add default studies * Remove test file * Cleanup retrievedata changes * Set active server
This commit is contained in:
parent
9e3afda2f1
commit
a7e612eb88
@ -11,6 +11,16 @@ const servers = (state = defaultState, action) => {
|
|||||||
servers.forEach(s => (s.active = true));
|
servers.forEach(s => (s.active = true));
|
||||||
return { ...state, servers };
|
return { ...state, servers };
|
||||||
|
|
||||||
|
case 'ACTIVATE_SERVER': {
|
||||||
|
const newServer = { ...action.server, active: true };
|
||||||
|
const newServers = state.servers;
|
||||||
|
newServers.forEach(s => (s.active = false));
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
servers: uniqBy([...newServers, newServer], 'wadoRoot'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'SET_SERVERS':
|
case 'SET_SERVERS':
|
||||||
return { ...state, servers: action.servers };
|
return { ...state, servers: action.servers };
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import StandaloneRouting from '../routes/StandaloneRouting';
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
activateServer: server => {
|
||||||
|
const action = {
|
||||||
|
type: 'ACTIVATE_SERVER',
|
||||||
|
server,
|
||||||
|
};
|
||||||
|
dispatch(action);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConnectedStandaloneRouting = connect(
|
||||||
|
null,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(StandaloneRouting);
|
||||||
|
|
||||||
|
export default ConnectedStandaloneRouting;
|
||||||
@ -2,23 +2,21 @@ import { connect } from 'react-redux';
|
|||||||
import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js';
|
import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js';
|
||||||
import OHIF from "@ohif/core";
|
import OHIF from "@ohif/core";
|
||||||
|
|
||||||
const {
|
const { clearViewportSpecificData } = OHIF.redux.actions;
|
||||||
clearViewportSpecificData
|
|
||||||
} = OHIF.redux.actions;
|
|
||||||
const isActive = a => a.active === true;
|
const isActive = a => a.active === true;
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state, ownProps) => {
|
||||||
const activeServer = state.servers.servers.find(isActive);
|
const activeServer = state.servers.servers.find(isActive);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
server: activeServer,
|
server: ownProps.server || activeServer,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
clearViewportSpecificData: () => {
|
clearViewportSpecificData: () => {
|
||||||
dispatch(clearViewportSpecificData());
|
dispatch(clearViewportSpecificData());
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,16 @@ import React from 'react';
|
|||||||
import './NotFound.css';
|
import './NotFound.css';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
export default function NotFound() {
|
export default function NotFound({ message = 'Sorry, this page does not exist.', showGoBackButton = true }) {
|
||||||
return (
|
return (
|
||||||
<div className={'not-found'}>
|
<div className={'not-found'}>
|
||||||
<div>
|
<div>
|
||||||
<h4>Sorry, this page does not exist.</h4>
|
<h4>{message}</h4>
|
||||||
<h5>
|
{showGoBackButton && (
|
||||||
<Link to={'/'}>Go back to the Study List</Link>
|
<h5>
|
||||||
</h5>
|
<Link to={'/'}>Go back to the Study List</Link>
|
||||||
|
</h5>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,29 +1,33 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { log, metadata, studies, utils } from '@ohif/core';
|
import { log, metadata, utils } from '@ohif/core';
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ConnectedViewer from '../connectedComponents/ConnectedViewer';
|
|
||||||
import { extensionManager } from './../App.js';
|
|
||||||
import qs from 'querystring';
|
import qs from 'querystring';
|
||||||
|
|
||||||
const { OHIFStudyMetadata } = metadata;
|
import { extensionManager } from './../App.js';
|
||||||
const { retrieveStudiesMetadata } = studies;
|
import ConnectedViewer from '../connectedComponents/ConnectedViewer';
|
||||||
|
import ConnectedViewerRetrieveStudyData from '../connectedComponents/ConnectedViewerRetrieveStudyData';
|
||||||
|
import NotFound from '../routes/NotFound';
|
||||||
|
|
||||||
const { studyMetadataManager, updateMetaDataManager } = utils;
|
const { studyMetadataManager, updateMetaDataManager } = utils;
|
||||||
|
const { OHIFStudyMetadata } = metadata;
|
||||||
|
|
||||||
class StandaloneRouting extends Component {
|
class StandaloneRouting extends Component {
|
||||||
state = {
|
state = {
|
||||||
studies: null,
|
studies: null,
|
||||||
|
server: null,
|
||||||
|
studyInstanceUids: null,
|
||||||
|
seriesInstanceUids: null,
|
||||||
error: null,
|
error: null,
|
||||||
|
loading: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
studyInstanceUids = [];
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
location: PropTypes.object,
|
location: PropTypes.object,
|
||||||
store: PropTypes.object,
|
store: PropTypes.object,
|
||||||
|
setServers: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static parseQueryAndFetchStudies(query) {
|
parseQueryAndRetrieveDICOMWebData(query) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const url = query.url;
|
const url = query.url;
|
||||||
|
|
||||||
@ -43,7 +47,11 @@ class StandaloneRouting extends Component {
|
|||||||
|
|
||||||
// When the JSON has been returned, parse it into a JavaScript Object
|
// When the JSON has been returned, parse it into a JavaScript Object
|
||||||
// and render the OHIF Viewer with this data
|
// and render the OHIF Viewer with this data
|
||||||
oReq.addEventListener('load', () => {
|
oReq.addEventListener('load', event => {
|
||||||
|
if (event.target.status === 404) {
|
||||||
|
reject(new Error('No JSON data found'));
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the response content
|
// Parse the response content
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText
|
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText
|
||||||
if (!oReq.responseText) {
|
if (!oReq.responseText) {
|
||||||
@ -54,27 +62,24 @@ class StandaloneRouting extends Component {
|
|||||||
log.info(JSON.stringify(oReq.responseText, null, 2));
|
log.info(JSON.stringify(oReq.responseText, null, 2));
|
||||||
|
|
||||||
const data = JSON.parse(oReq.responseText);
|
const data = JSON.parse(oReq.responseText);
|
||||||
if (data.servers && query.studyInstanceUids) {
|
if (data.servers) {
|
||||||
|
if (!query.studyInstanceUids) {
|
||||||
|
log.warn('No study instance uids specified');
|
||||||
|
reject(new Error('No study instance uids specified'));
|
||||||
|
}
|
||||||
|
|
||||||
const server = data.servers.dicomWeb[0];
|
const server = data.servers.dicomWeb[0];
|
||||||
server.type = 'dicomWeb';
|
server.type = 'dicomWeb';
|
||||||
|
|
||||||
const studyInstanceUids = query.studyInstanceUids.split(';');
|
log.warn('Activating server', server);
|
||||||
const seriesInstanceUids = [];
|
this.props.activateServer(server);
|
||||||
|
|
||||||
retrieveStudiesMetadata(
|
const studyInstanceUids = query.studyInstanceUids.split(';');
|
||||||
server,
|
const seriesInstanceUids = query.seriesInstanceUids ? query.seriesInstanceUids.split(';') : [];
|
||||||
studyInstanceUids,
|
|
||||||
seriesInstanceUids
|
resolve({ server, studyInstanceUids, seriesInstanceUids });
|
||||||
).then(
|
|
||||||
studies => {
|
|
||||||
resolve(studies);
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
resolve(data.studies);
|
resolve({ studies: data.studies, studyInstanceUids: [] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -96,56 +101,80 @@ class StandaloneRouting extends Component {
|
|||||||
|
|
||||||
// Remove ? prefix which is included for some reason
|
// Remove ? prefix which is included for some reason
|
||||||
search = search.slice(1, search.length);
|
search = search.slice(1, search.length);
|
||||||
|
|
||||||
const query = qs.parse(search);
|
const query = qs.parse(search);
|
||||||
const studies = await StandaloneRouting.parseQueryAndFetchStudies(query);
|
|
||||||
|
|
||||||
studyMetadataManager.purge();
|
let {
|
||||||
|
server,
|
||||||
|
studies,
|
||||||
|
studyInstanceUids,
|
||||||
|
seriesInstanceUids,
|
||||||
|
} = await this.parseQueryAndRetrieveDICOMWebData(query);
|
||||||
|
|
||||||
// Map studies to new format, update metadata manager?
|
if (studies) {
|
||||||
const uniqueStudyUids = new Set();
|
const {
|
||||||
const updatedStudies = studies.map(study => {
|
studies: updatedStudies,
|
||||||
const studyMetadata = new OHIFStudyMetadata(
|
studyInstanceUids: updatedStudiesInstanceUids,
|
||||||
study,
|
} = _mapStudiesToNewFormat(studies);
|
||||||
study.studyInstanceUid
|
studies = updatedStudies;
|
||||||
);
|
studyInstanceUids = updatedStudiesInstanceUids;
|
||||||
const sopClassHandlerModules =
|
}
|
||||||
extensionManager.modules['sopClassHandlerModule'];
|
|
||||||
|
|
||||||
study.displaySets =
|
this.setState({
|
||||||
study.displaySets ||
|
studies,
|
||||||
studyMetadata.createDisplaySets(sopClassHandlerModules);
|
server,
|
||||||
studyMetadata.setDisplaySets(study.displaySets);
|
studyInstanceUids,
|
||||||
|
seriesInstanceUids,
|
||||||
// Updates WADO-RS metaDataManager
|
loading: false,
|
||||||
updateMetaDataManager(study);
|
|
||||||
|
|
||||||
studyMetadataManager.add(studyMetadata);
|
|
||||||
uniqueStudyUids.add(study.studyInstanceUid);
|
|
||||||
|
|
||||||
return study;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.studyInstanceUids = Array.from(uniqueStudyUids);
|
|
||||||
this.setState({ studies: updatedStudies });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setState({ error });
|
this.setState({ error: error.message, loading: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.error) {
|
const message = this.state.error ? `Error: ${JSON.stringify(this.state.error)}` : 'Loading...';
|
||||||
return <div>Error: {JSON.stringify(this.state.error)}</div>;
|
if (this.state.error || this.state.loading) {
|
||||||
} else if (!this.state.studies) {
|
return <NotFound message={message} showGoBackButton={this.state.error} />;
|
||||||
return <div>Loading...</div>;
|
|
||||||
}
|
}
|
||||||
return (
|
|
||||||
<ConnectedViewer
|
return this.state.studies ? (
|
||||||
studies={this.state.studies}
|
<ConnectedViewer studies={this.state.studies} />
|
||||||
studyInstanceUids={this.studyInstanceUids}
|
) : (
|
||||||
/>
|
<ConnectedViewerRetrieveStudyData
|
||||||
);
|
studyInstanceUids={this.state.studyInstanceUids}
|
||||||
|
seriesInstanceUids={this.state.seriesInstanceUids}
|
||||||
|
server={this.state.server}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _mapStudiesToNewFormat = studies => {
|
||||||
|
studyMetadataManager.purge();
|
||||||
|
|
||||||
|
/* Map studies to new format, update metadata manager? */
|
||||||
|
const uniqueStudyUids = new Set();
|
||||||
|
const updatedStudies = studies.map(study => {
|
||||||
|
const studyMetadata = new OHIFStudyMetadata(study, study.studyInstanceUid);
|
||||||
|
|
||||||
|
const sopClassHandlerModules = extensionManager.modules['sopClassHandlerModule'];
|
||||||
|
study.displaySets = study.displaySets ||
|
||||||
|
studyMetadata.createDisplaySets(sopClassHandlerModules);
|
||||||
|
studyMetadata.setDisplaySets(study.displaySets);
|
||||||
|
|
||||||
|
/* Updates WADO-RS metaDataManager */
|
||||||
|
updateMetaDataManager(study);
|
||||||
|
|
||||||
|
studyMetadataManager.add(studyMetadata);
|
||||||
|
uniqueStudyUids.add(study.studyInstanceUid);
|
||||||
|
|
||||||
|
return study;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
studies: updatedStudies,
|
||||||
|
studyInstanceUids: Array.from(uniqueStudyUids),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default StandaloneRouting;
|
export default StandaloneRouting;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const StudyListRouting = asyncComponent(() =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
const StandaloneRouting = asyncComponent(() =>
|
const StandaloneRouting = asyncComponent(() =>
|
||||||
import(/* webpackChunkName: "StandaloneRouting" */ './StandaloneRouting.js')
|
import(/* webpackChunkName: "ConnectedStandaloneRouting" */ '../connectedComponents/ConnectedStandaloneRouting.js')
|
||||||
);
|
);
|
||||||
const ViewerLocalFileData = asyncComponent(() =>
|
const ViewerLocalFileData = asyncComponent(() =>
|
||||||
import(
|
import(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user