Update viewer with Study List and routing to Viewer
This commit is contained in:
parent
4fbc208b41
commit
5d6aad488e
@ -13,7 +13,7 @@
|
||||
"hammerjs": "^2.0.8",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"moment": "^2.22.2",
|
||||
"ohif-core": "^0.1.1",
|
||||
"ohif-core": "^0.1.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"query-string": "^6.2.0",
|
||||
"react": "^16.4.1",
|
||||
@ -23,7 +23,7 @@
|
||||
"react-router": "^4.3.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-scripts": "^2.1.1",
|
||||
"react-viewerbase": "^0.1.5",
|
||||
"react-viewerbase": "^0.1.6",
|
||||
"redux": "^4.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -2,13 +2,13 @@ import React, { Component } from 'react';
|
||||
import { withRouter } from 'react-router';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import ViewerRouting from "./ViewerRouting.js";
|
||||
import StudyListRouting from './StudyListRouting.js';
|
||||
import StandaloneRouting from './StandaloneRouting.js';
|
||||
import IHEInvokeImageDisplay from './IHEInvokeImageDisplay.js';
|
||||
import './App.css';
|
||||
import './variables.css';
|
||||
// TODO: figure out how to change themes dynamically
|
||||
import './theme-tide.css';
|
||||
import { StudyList } from 'react-viewerbase';
|
||||
|
||||
const reload = () => window.location.reload();
|
||||
|
||||
@ -43,14 +43,14 @@ class App extends Component {
|
||||
<Route
|
||||
exact
|
||||
path="/studylist"
|
||||
component={StudyList}
|
||||
component={StudyListRouting}
|
||||
/*auth={this.props.auth}*/
|
||||
store={this.props.store}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
component={StudyList}
|
||||
component={StudyListRouting}
|
||||
/*auth={this.props.auth}*/
|
||||
store={this.props.store}
|
||||
/>
|
||||
|
||||
21
OHIFViewer-react/src/ConnectedStudyList.js
Normal file
21
OHIFViewer-react/src/ConnectedStudyList.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import StudyListWithData from './StudyListWithData.js';
|
||||
|
||||
const isActive = (a) => a.active === true;
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const activeServer = state.servers.servers.find(isActive);
|
||||
|
||||
return {
|
||||
server: activeServer,
|
||||
...ownProps
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedStudyList = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(StudyListWithData);
|
||||
|
||||
export default ConnectedStudyList;
|
||||
16
OHIFViewer-react/src/FlexboxLayout/ConnectedFlexboxLayout.js
Normal file
16
OHIFViewer-react/src/FlexboxLayout/ConnectedFlexboxLayout.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { connect } from 'react-redux';
|
||||
import FlexboxLayout from './FlexboxLayout';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
leftSidebarOpen: state.ui.leftSidebarOpen,
|
||||
rightSidebarOpen: state.ui.rightSidebarOpen
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedFlexboxLayout = connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(FlexboxLayout);
|
||||
|
||||
export default ConnectedFlexboxLayout;
|
||||
29
OHIFViewer-react/src/FlexboxLayout/ConnectedToolbarRow.js
Normal file
29
OHIFViewer-react/src/FlexboxLayout/ConnectedToolbarRow.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ToolbarRow from './ToolbarRow';
|
||||
import { setLeftSidebarOpen, setRightSidebarOpen } from '../redux/actions.js';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
leftSidebarOpen: state.ui.leftSidebarOpen,
|
||||
rightSidebarOpen: state.ui.rightSidebarOpen
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
setLeftSidebarOpen: state => {
|
||||
dispatch(setLeftSidebarOpen(state))
|
||||
},
|
||||
setRightSidebarOpen: state => {
|
||||
dispatch(setRightSidebarOpen(state))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ConnectedToolbarRow = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ToolbarRow);
|
||||
|
||||
export default ConnectedToolbarRow;
|
||||
@ -1,6 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import OHIF from 'ohif-core';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import { StudyBrowser } from 'react-viewerbase';
|
||||
import ViewerMain from './ViewerMain.js';
|
||||
@ -81,12 +80,12 @@ class FlexboxLayout extends Component {
|
||||
}
|
||||
|
||||
getThumbnailsFromImageIds() {
|
||||
const studyThumbnails = this.state.studiesForBrowser.forEach(function (study) {
|
||||
this.state.studiesForBrowser.forEach(function (study) {
|
||||
const { studyInstanceUid } = study;
|
||||
|
||||
study.thumbnails.forEach(function (displaySet) {
|
||||
const imageId = displaySet.imageId;
|
||||
const {displaySetInstanceUid, seriesDescription, seriesNumber, instanceNumber, numImageFrames} = displaySet;
|
||||
const { displaySetInstanceUid } = displaySet;
|
||||
|
||||
cornerstone.loadAndCacheImage(imageId).then((image) => {
|
||||
loadSuccess.call(this, image, studyInstanceUid, displaySetInstanceUid);
|
||||
|
||||
@ -5,7 +5,7 @@ import ViewerFromStudyData from "./ViewerFromStudyData.js";
|
||||
function IHEInvokeImageDisplay({ match }) {
|
||||
const requestType = match.params.query.requestType;
|
||||
let studyInstanceUids;
|
||||
let patientUids;
|
||||
//let patientUids;
|
||||
let displayStudyList = false;
|
||||
|
||||
if (requestType === "STUDY") {
|
||||
@ -15,7 +15,7 @@ function IHEInvokeImageDisplay({ match }) {
|
||||
const decodedData = window.atob(uids);
|
||||
studyInstanceUids = decodedData.split(';');
|
||||
} else if (requestType === "PATIENT") {
|
||||
patientUids = this.params.query.patientID.split(';');
|
||||
//patientUidspatientUids = this.params.query.patientID.split(';');
|
||||
displayStudyList = true
|
||||
} else {
|
||||
displayStudyList = true
|
||||
|
||||
24
OHIFViewer-react/src/StudyListRouting.js
Normal file
24
OHIFViewer-react/src/StudyListRouting.js
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ConnectedStudyList from "./ConnectedStudyList";
|
||||
|
||||
// TODO: Move to react-viewerbase
|
||||
|
||||
function StudyListRouting({ match }) {
|
||||
// TODO: Figure out which filters we want to pass in via a URL
|
||||
//const { patientId } = match.params;
|
||||
|
||||
return (
|
||||
<ConnectedStudyList/>
|
||||
);
|
||||
}
|
||||
|
||||
StudyListRouting.propTypes = {
|
||||
match: PropTypes.shape({
|
||||
params: PropTypes.shape({
|
||||
patientIds: PropTypes.string,
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
export default StudyListRouting;
|
||||
120
OHIFViewer-react/src/StudyListWithData.js
Normal file
120
OHIFViewer-react/src/StudyListWithData.js
Normal file
@ -0,0 +1,120 @@
|
||||
import React, {Component} from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OHIF from 'ohif-core';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { StudyList } from "react-viewerbase";
|
||||
import Header from "./Header";
|
||||
|
||||
class StudyListWithData extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
searchData: {},
|
||||
studies: null,
|
||||
error: null
|
||||
};
|
||||
|
||||
this.pageSize = 5;
|
||||
this.defaultSort = { field: 'patientName', order: 'desc' };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// TODO: Avoid using timepoints here
|
||||
//const params = { studyInstanceUids, seriesInstanceUids, timepointId, timepointsFilter={} };
|
||||
|
||||
this.searchForStudies();
|
||||
}
|
||||
|
||||
searchForStudies = (searchData = {
|
||||
currentPage: 0,
|
||||
pageSize: 5
|
||||
}) => {
|
||||
const { server } = this.props;
|
||||
console.log(searchData);
|
||||
const filter = {
|
||||
patientId: searchData.patientId,
|
||||
patientName: searchData.patientName,
|
||||
accessionNumber: searchData.accessionNumber,
|
||||
studyDescription: searchData.studyDescription,
|
||||
modalitiesInStudy: searchData.modalitiesInStudy,
|
||||
limit: searchData.currentPage * searchData.pageSize + searchData.pageSize,
|
||||
offset: searchData.currentPage * searchData.pageSize
|
||||
};
|
||||
|
||||
// TODO: add sorting
|
||||
const promise = OHIF.studies.searchStudies(server, filter)
|
||||
|
||||
// Render the viewer when the data is ready
|
||||
promise.then(studies => {
|
||||
if (!studies) {
|
||||
studies = [];
|
||||
}
|
||||
|
||||
// TODO: Fix casing of this property!
|
||||
const fixedStudies = studies.map(study => {
|
||||
const fixedStudy = study;
|
||||
fixedStudy.studyInstanceUID = study.studyInstanceUid;
|
||||
|
||||
return fixedStudy;
|
||||
})
|
||||
|
||||
this.setState({
|
||||
studies: fixedStudies,
|
||||
});
|
||||
}).catch(error => {
|
||||
this.setState({
|
||||
error: true,
|
||||
});
|
||||
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
onImport = () => {
|
||||
console.log('onImport');
|
||||
}
|
||||
|
||||
onSelectItem = (studyInstanceUID) => {
|
||||
console.log('onSelectItem');
|
||||
|
||||
console.log('studyInstanceUID');
|
||||
|
||||
this.props.history.push(`/viewer/${studyInstanceUID}`);
|
||||
}
|
||||
|
||||
onSearch = (searchData) => {
|
||||
// TODO: Update search filters
|
||||
this.searchForStudies(searchData);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return (<div>Error: {JSON.stringify(this.state.error)}</div>);
|
||||
} else if (this.state.studies === null) {
|
||||
return (<div>Loading...</div>);
|
||||
}
|
||||
|
||||
const studyCount = this.state.studies ? this.state.studies.length : 0;
|
||||
|
||||
return (<>
|
||||
<Header />
|
||||
<StudyList studies={this.state.studies}
|
||||
studyCount={studyCount}
|
||||
studyListFunctionsEnabled={false}
|
||||
onImport={this.onImport}
|
||||
onSelectItem={this.onSelectItem}
|
||||
pageSize={this.pageSize}
|
||||
defaultSort={this.defaultSort}
|
||||
onSearch={this.onSearch} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
StudyListWithData.propTypes = {
|
||||
patientId: PropTypes.string,
|
||||
server: PropTypes.object
|
||||
};
|
||||
|
||||
export default withRouter(StudyListWithData);
|
||||
@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import cornerstoneTools from 'cornerstone-tools';
|
||||
import OHIF from 'ohif-core';
|
||||
import { CineDialog } from 'react-viewerbase';
|
||||
//import { CineDialog } from 'react-viewerbase';
|
||||
|
||||
import Header from '../Header'
|
||||
import ConnectedFlexboxLayout from '../FlexboxLayout/ConnectedFlexboxLayout.js';
|
||||
|
||||
@ -8,7 +8,7 @@ class Dropdown extends Component {
|
||||
}
|
||||
|
||||
renderList = () => {
|
||||
const { list, link, align } = this.props
|
||||
const { list, align } = this.props
|
||||
|
||||
if (!this.state.open) {
|
||||
return null
|
||||
@ -80,8 +80,6 @@ class Dropdown extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { open } = this.state
|
||||
|
||||
return (
|
||||
<div className='dd-menu' ref={node => this.node = node}>
|
||||
<div className="dd-menu-toggle" onClick={this.toggleList}>
|
||||
|
||||
@ -18,9 +18,12 @@ const servers = {
|
||||
dicomWeb: [
|
||||
{
|
||||
"name": "DCM4CHEE",
|
||||
"wadoUriRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
"qidoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"wadoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
//"wadoUriRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
//"qidoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
//"wadoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"wadoUriRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||
"qidoRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"wadoRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||
"qidoSupportsIncludeField": true,
|
||||
"imageRendering": "wadors",
|
||||
"thumbnailRendering": "wadors",
|
||||
@ -29,7 +32,8 @@ const servers = {
|
||||
"logRequests": true,
|
||||
"logResponses": false,
|
||||
"logTiming": true,
|
||||
"auth": "admin:admin"
|
||||
//"auth": "admin:admin"
|
||||
"auth": "cloud:healthcare"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
16
OHIFViewer-react/src/redux/actions.js
Normal file
16
OHIFViewer-react/src/redux/actions.js
Normal file
@ -0,0 +1,16 @@
|
||||
export const setLeftSidebarOpen = state => ({
|
||||
type: 'SET_LEFT_SIDEBAR_OPEN',
|
||||
state
|
||||
});
|
||||
|
||||
export const setRightSidebarOpen = state => ({
|
||||
type: 'SET_RIGHT_SIDEBAR_OPEN',
|
||||
state
|
||||
});
|
||||
|
||||
const actions = {
|
||||
setLeftSidebarOpen,
|
||||
setRightSidebarOpen
|
||||
};
|
||||
|
||||
export default actions;
|
||||
@ -1 +1 @@
|
||||
export default 'c08d12cb36ad7b1ff310b4970a84bc7e6a14e6ed';
|
||||
export default '4fbc208b41fcaa0f957a49409cb55e91c6397d03';
|
||||
|
||||
@ -6832,10 +6832,10 @@ obuf@^1.0.0, obuf@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
|
||||
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
|
||||
|
||||
ohif-core@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.1.1.tgz#594b5a7969c11e5d5eaa3890a384f39409543d3b"
|
||||
integrity sha512-Ib/lI9fioMiqt5DXmZ8iXtiSne8Z2ubQoh/ePAwgZPljXfMvSY1cUpQK+O90pZqBh444KDolYX00OrJIIbSRgg==
|
||||
ohif-core@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.1.2.tgz#897c63b73de7a139567d0a6cfe98426aa25e1cb9"
|
||||
integrity sha512-KkiN14ctO3Dp4fJkjndSyUH5suBVcMVxetZdOVGrSlxWbnpCg6Hd2FPZpP6PcYPE4yhWNvUyV5dfP4Qhg14oxw==
|
||||
dependencies:
|
||||
cornerstone-math "^0.1.7"
|
||||
isomorphic-base64 "^1.0.2"
|
||||
@ -8288,10 +8288,10 @@ react-scripts@^2.1.1:
|
||||
optionalDependencies:
|
||||
fsevents "1.2.4"
|
||||
|
||||
react-viewerbase@^0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.1.5.tgz#a5ef7fd852ead91c74fb0068a7cb97c922a9c17a"
|
||||
integrity sha512-196Req5szlhpvQWivxZmQzF3dMj2vCJtjnyusullRd8isTdaK+cLaCuKBRiJ5Eo6zwM69uTXj7ar8BHQARRzeQ==
|
||||
react-viewerbase@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.1.6.tgz#09c775aed103d4382e7f24e5e0850c45327fa481"
|
||||
integrity sha512-msFND25X0uooifaPf8y/VA/2yHrz+M/6yiJwh/rJD8HiM2Bel4JExDOJw9hJmmOS4l7dHpooxAI9ackibvwFAQ==
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user