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:
Igor Octaviano 2020-01-24 07:31:22 -03:00 committed by Erik Ziegler
parent 9e3afda2f1
commit a7e612eb88
6 changed files with 136 additions and 76 deletions

View File

@ -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 };

View File

@ -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;

View File

@ -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());
} },
}; };
}; };

View File

@ -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>
); );

View File

@ -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;

View File

@ -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(