Merge branch 'master' of github.com:OHIF/Viewers

This commit is contained in:
dannyrb 2019-05-28 13:03:41 -04:00
commit b3f54b4500
11 changed files with 156 additions and 125 deletions

View File

@ -24,8 +24,7 @@ add a powerful medical imaging viewer to an existing web page using only a few
include tags. include tags.
- Read more about it here: [Embedded Viewer](./recipes/embedded-viewer.md) - Read more about it here: [Embedded Viewer](./recipes/embedded-viewer.md)
- And check out our - And check out our [live demo on CodeSandbox][code-sandbox]
[live demo on CodeSandbox](https://codesandbox.io/s/lrjoo3znxm)
{% include "./_embedded-viewer-diagram.md" %} {% include "./_embedded-viewer-diagram.md" %}
@ -207,4 +206,5 @@ Please feel free to suggest or contribute your own recipes.
[host-static-assets]: https://www.netlify.com/blog/2016/05/18/9-reasons-your-site-should-be-static/ [host-static-assets]: https://www.netlify.com/blog/2016/05/18/9-reasons-your-site-should-be-static/
[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS [cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
[code-flows]: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660 [code-flows]: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660
[code-sandbox]: https://codesandbox.io/s/ohif-viewer-script-tag-usage-b3st9
<!-- prettier-ignore-end --> <!-- prettier-ignore-end -->

View File

@ -92,10 +92,9 @@ ReactDOM.render(app, document.getElementById('ohif-viewer-target'))
> I'm having trouble getting this to work. Where can I go for help? > I'm having trouble getting this to work. Where can I go for help?
First, check out this fully functional First, check out this fully functional [CodeSandbox][code-sandbox] example. If
[CodeSandbox](https://codesandbox.io/s/ohif-viewer-script-tag-usage-b3st9) you're still having trouble, feel free to search or GitHub issues. Can't find
example. If you're still having trouble, feel free to search or GitHub issues. anything related your problem? Create a new one.
Can't find anything related your problem? Create a new one.
> When I include bootstrap, other styles on my page no longer work correctly. > When I include bootstrap, other styles on my page no longer work correctly.
> What can I do? > What can I do?
@ -108,3 +107,5 @@ Have that working? Good. Now `embed` that new page using an
This should produce the expected result while also protecting your page from any This should produce the expected result while also protecting your page from any
globally defined styles/scripts. globally defined styles/scripts.
[code-sandbox]: https://codesandbox.io/s/ohif-viewer-script-tag-usage-b3st9

View File

@ -1,6 +1,6 @@
{ {
"name": "ohif-cornerstone-extension", "name": "ohif-cornerstone-extension",
"version": "0.0.30", "version": "0.0.31",
"description": "OHIF extension for Cornerstone", "description": "OHIF extension for Cornerstone",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@ -39,7 +39,7 @@
"@babel/runtime": "^7.2.0", "@babel/runtime": "^7.2.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "0.1.27" "react-cornerstone-viewport": "0.1.28"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.2.2", "@babel/core": "^7.2.2",

View File

@ -30,7 +30,8 @@ const mapStateToProps = (state, ownProps) => {
...dataFromStore, ...dataFromStore,
enableStackPrefetch: isActive, enableStackPrefetch: isActive,
//stack: viewportSpecificData.stack, //stack: viewportSpecificData.stack,
cineToolData: viewportSpecificData.cine cineToolData: viewportSpecificData.cine,
viewport: viewportSpecificData.viewport
}; };
}; };

View File

@ -4418,10 +4418,10 @@ randomfill@^1.0.3:
randombytes "^2.0.5" randombytes "^2.0.5"
safe-buffer "^5.1.0" safe-buffer "^5.1.0"
react-cornerstone-viewport@0.1.27: react-cornerstone-viewport@0.1.28:
version "0.1.27" version "0.1.28"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.27.tgz#6e00be845c1684aadaf31d0f0ee3933fd44e33f3" resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.28.tgz#ca1b0062c9f08868c653c11d6cdef8f5d519f90a"
integrity sha512-pPIy7snnIXjxyZcghAKmyxvrim8xzQxhml7TxGZ/fv2L+rAsF2ZhsB7LLEUCXIZXL3F8A30VTHWLK3lV92TBDQ== integrity sha512-lGXFB1pxUJE+tozAHjQD8KcmnGuGG/nD3CGrK44cFqx8e3W/CKU9/bZM6qomy/X1fK5TlnJUaZ9NOCaDLhzJrQ==
dependencies: dependencies:
lodash.debounce "^4.0.8" lodash.debounce "^4.0.8"
moment "^2.23.0" moment "^2.23.0"

View File

@ -69,7 +69,7 @@
"classnames": "^2.2.6", "classnames": "^2.2.6",
"cornerstone-core": "^2.2.8", "cornerstone-core": "^2.2.8",
"cornerstone-math": "^0.1.8", "cornerstone-math": "^0.1.8",
"cornerstone-tools": "^3.9.0", "cornerstone-tools": "^3.11.0",
"cornerstone-wado-image-loader": "^2.2.3", "cornerstone-wado-image-loader": "^2.2.3",
"dcmjs": "^0.3.8", "dcmjs": "^0.3.8",
"dicom-parser": "^1.8.3", "dicom-parser": "^1.8.3",
@ -77,8 +77,8 @@
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"lodash.isequal": "4.5.0", "lodash.isequal": "4.5.0",
"moment": "^2.24.0", "moment": "^2.24.0",
"ohif-core": "0.5.3", "ohif-core": "0.5.5",
"ohif-cornerstone-extension": "0.0.30", "ohif-cornerstone-extension": "0.0.31",
"ohif-dicom-html-extension": "^0.0.2", "ohif-dicom-html-extension": "^0.0.2",
"ohif-dicom-microscopy-extension": "^0.0.5", "ohif-dicom-microscopy-extension": "^0.0.5",
"ohif-dicom-pdf-extension": "^0.0.6", "ohif-dicom-pdf-extension": "^0.0.6",

View File

@ -1,33 +1,44 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux'
import ViewerMain from './ViewerMain'; import ViewerMain from './ViewerMain'
import OHIF from 'ohif-core'; import OHIF from 'ohif-core'
const { setViewportSpecificData, clearViewportSpecificData } = OHIF.redux.actions; const {
setViewportSpecificData,
clearViewportSpecificData,
setToolActive,
setActiveViewportSpecificData,
} = OHIF.redux.actions
const mapStateToProps = state => { const mapStateToProps = state => {
const { activeViewportIndex, layout, viewportSpecificData } = state.viewports; const { activeViewportIndex, layout, viewportSpecificData } = state.viewports
return { return {
activeViewportIndex, activeViewportIndex,
layout, layout,
viewportSpecificData viewportSpecificData,
} }
}; }
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
setViewportSpecificData: (viewportIndex, data) => { setViewportSpecificData: (viewportIndex, data) => {
dispatch(setViewportSpecificData(viewportIndex, data)); dispatch(setViewportSpecificData(viewportIndex, data))
}, },
clearViewportSpecificData: () => { clearViewportSpecificData: () => {
dispatch(clearViewportSpecificData()); dispatch(clearViewportSpecificData())
} },
}; setToolActive: tool => {
}; dispatch(setToolActive(tool))
},
setActiveViewportSpecificData: viewport => {
dispatch(setActiveViewportSpecificData(viewport))
},
}
}
const ConnectedViewerMain = connect( const ConnectedViewerMain = connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(ViewerMain); )(ViewerMain)
export default ConnectedViewerMain; export default ConnectedViewerMain

View File

@ -1,19 +1,19 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux'
import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js'; import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js'
const isActive = (a) => a.active === true; const isActive = a => a.active === true
const mapStateToProps = state => { const mapStateToProps = state => {
const activeServer = state.servers.servers.find(isActive); const activeServer = state.servers.servers.find(isActive)
return { return {
server: activeServer, server: activeServer,
}; }
}; }
const ConnectedViewerRetrieveStudyData = connect( const ConnectedViewerRetrieveStudyData = connect(
mapStateToProps, mapStateToProps,
null null
)(ViewerRetrieveStudyData); )(ViewerRetrieveStudyData)
export default ConnectedViewerRetrieveStudyData; export default ConnectedViewerRetrieveStudyData

View File

@ -1,52 +1,61 @@
import { Component } from 'react'; import { Component } from 'react'
import React from 'react'; import React from 'react'
import PropTypes from 'prop-types'; import PropTypes from 'prop-types'
import { OHIF } from 'ohif-core'; import { OHIF } from 'ohif-core'
import ConnectedLayoutManager from './ConnectedLayoutManager.js'; import ConnectedLayoutManager from './ConnectedLayoutManager.js'
import './ViewerMain.css'; import './ViewerMain.css'
class ViewerMain extends Component { class ViewerMain extends Component {
static propTypes = { static propTypes = {
studies: PropTypes.array.isRequired, studies: PropTypes.array.isRequired,
setViewportSpecificData: PropTypes.func.isRequired, setViewportSpecificData: PropTypes.func.isRequired,
clearViewportSpecificData: PropTypes.func.isRequired clearViewportSpecificData: PropTypes.func.isRequired,
}; setToolActive: PropTypes.func.isRequired,
setActiveViewportSpecificData: PropTypes.func.isRequired,
}
constructor(props) { constructor(props) {
super(props); super(props)
OHIF.hotkeysUtil.setup('viewer');
// Initialize hotkeys
new OHIF.HotkeysUtil('viewer', {
setViewportSpecificData: props.setViewportSpecificData,
clearViewportSpecificData: props.clearViewportSpecificData,
setToolActive: props.setToolActive,
setActiveViewportSpecificData: props.setActiveViewportSpecificData,
})
this.state = { this.state = {
displaySets: [] displaySets: [],
} }
} }
getDisplaySets(studies) { getDisplaySets(studies) {
const displaySets = []; const displaySets = []
studies.forEach(study => { studies.forEach(study => {
study.displaySets.forEach(dSet => { study.displaySets.forEach(dSet => {
if (!dSet.plugin) { if (!dSet.plugin) {
dSet.plugin = 'cornerstone'; dSet.plugin = 'cornerstone'
} }
displaySets.push(dSet); displaySets.push(dSet)
}); })
}); })
return displaySets; return displaySets
} }
findDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) { findDisplaySet(studies, studyInstanceUid, displaySetInstanceUid) {
const study = studies.find(study => { const study = studies.find(study => {
return study.studyInstanceUid === studyInstanceUid; return study.studyInstanceUid === studyInstanceUid
}); })
if (!study) { if (!study) {
return; return
} }
return study.displaySets.find(displaySet => { return study.displaySets.find(displaySet => {
return displaySet.displaySetInstanceUid === displaySetInstanceUid; return displaySet.displaySetInstanceUid === displaySetInstanceUid
}); })
} }
componentDidMount() { componentDidMount() {
@ -54,41 +63,50 @@ class ViewerMain extends Component {
//window.addEventListener('beforeunload', unloadHandlers.beforeUnload); //window.addEventListener('beforeunload', unloadHandlers.beforeUnload);
// Get all the display sets for the viewer studies // Get all the display sets for the viewer studies
const displaySets = this.getDisplaySets(this.props.studies); const displaySets = this.getDisplaySets(this.props.studies)
this.setState({ this.setState({
displaySets displaySets,
}); })
} }
getViewportData = () => { getViewportData = () => {
const viewportData = []; const viewportData = []
const { layout, viewportSpecificData } = this.props; const { layout, viewportSpecificData } = this.props
for (let viewportIndex = 0; viewportIndex < layout.viewports.length; viewportIndex++) { for (
let displaySet = viewportSpecificData[viewportIndex]; let viewportIndex = 0;
viewportIndex < layout.viewports.length;
viewportIndex++
) {
let displaySet = viewportSpecificData[viewportIndex]
// If the viewport is empty, get one available in study // If the viewport is empty, get one available in study
if (!displaySet || !displaySet.displaySetInstanceUid) { if (!displaySet || !displaySet.displaySetInstanceUid) {
const { displaySets } = this.state; const { displaySets } = this.state
displaySet = displaySets.find(ds => !viewportData.some(v => v.displaySetInstanceUid === ds.displaySetInstanceUid)); displaySet = displaySets.find(
ds =>
!viewportData.some(
v => v.displaySetInstanceUid === ds.displaySetInstanceUid
)
)
} }
viewportData.push(displaySet); viewportData.push(displaySet)
} }
return viewportData; return viewportData
}; }
setViewportData = ({ viewportIndex, item }) => { setViewportData = ({ viewportIndex, item }) => {
const displaySet = this.findDisplaySet( const displaySet = this.findDisplaySet(
this.props.studies, this.props.studies,
item.studyInstanceUid, item.studyInstanceUid,
item.displaySetInstanceUid item.displaySetInstanceUid
); )
this.props.setViewportSpecificData(viewportIndex, displaySet); this.props.setViewportSpecificData(viewportIndex, displaySet)
}; }
render() { render() {
return ( return (
@ -99,15 +117,15 @@ class ViewerMain extends Component {
setViewportData={this.setViewportData} setViewportData={this.setViewportData}
/> />
</div> </div>
); )
} }
componentWillUnmount() { componentWillUnmount() {
// Clear the entire viewport specific data // Clear the entire viewport specific data
const { viewportSpecificData } = this.props; const { viewportSpecificData } = this.props
Object.keys(viewportSpecificData).forEach((viewportIndex) => { Object.keys(viewportSpecificData).forEach(viewportIndex => {
this.props.clearViewportSpecificData(viewportIndex); this.props.clearViewportSpecificData(viewportIndex)
}); })
// Remove beforeUnload event handler... // Remove beforeUnload event handler...
//window.removeEventListener('beforeunload', unloadHandlers.beforeUnload); //window.removeEventListener('beforeunload', unloadHandlers.beforeUnload);
@ -126,4 +144,4 @@ class ViewerMain extends Component {
} }
} }
export default ViewerMain; export default ViewerMain

View File

@ -1,21 +1,21 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux'
import StudyListWithData from './StudyListWithData.js'; import StudyListWithData from './StudyListWithData.js'
const isActive = (a) => a.active === true; const isActive = a => a.active === true
const mapStateToProps = state => { const mapStateToProps = state => {
const activeServer = state.servers.servers.find(isActive); const activeServer = state.servers.servers.find(isActive)
return { return {
server: activeServer, server: activeServer,
user: state.oidc.user, user: state.oidc.user,
}; }
}; }
const ConnectedStudyList = connect( const ConnectedStudyList = connect(
mapStateToProps, mapStateToProps,
null null
)(StudyListWithData); )(StudyListWithData)
export default ConnectedStudyList; export default ConnectedStudyList

View File

@ -3477,10 +3477,10 @@ cornerstone-math@^0.1.8:
resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5" resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5"
integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw== integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw==
cornerstone-tools@^3.9.0: cornerstone-tools@^3.11.0:
version "3.9.0" version "3.11.0"
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-3.9.0.tgz#6e5a2865fe2ba6d80bf907b1b9734848b83132a0" resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-3.11.0.tgz#8d14537548ef4f0cc2f38fd55b343bc28d73f5a7"
integrity sha512-gi+KhxYx3OEr4E0vt7Rp+MiQ5SRf1Qf/qf/D12i/VywDg3mPTLpe588nZZoUxeBJc0wF2s+Zybyv15NrbkoP2Q== integrity sha512-n1zeYr7rJ4wNCE3a9IJvb7wWnvYfMWOiiaKL0IN093VrYiJU2DBvjC+97gbQE+AboQyp02JbUV2ac4fhdyzMQg==
dependencies: dependencies:
"@babel/runtime" "7.1.2" "@babel/runtime" "7.1.2"
cornerstone-math "0.1.7" cornerstone-math "0.1.7"
@ -9674,10 +9674,10 @@ octokit-pagination-methods@^1.1.0:
resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"
integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==
ohif-core@0.5.3: ohif-core@0.5.5:
version "0.5.3" version "0.5.5"
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.5.3.tgz#cf78f0e4b28ed5a602b032483cdd44f3baea34f2" resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.5.5.tgz#78ace87fa06b3b23a004414a702cc23cb00edf9d"
integrity sha512-pdzVz9WkdXVm99TuBSx1JYEed9aPaD9/CKd/+YM4R3lgchDNLxuz0l76HBPHpFV2XDIKmu1q5EyETyMiOxhZsw== integrity sha512-BORJCxOWuVAx2CE6+LSdL5+1+PG6gkYgl6tyAZhHhAgT46DWAfbq8nkAIX7Rhwot0BWpAcHkkBWIavGOBOH24Q==
dependencies: dependencies:
"@babel/runtime" "^7.2.0" "@babel/runtime" "^7.2.0"
ajv "^6.10.0" ajv "^6.10.0"
@ -9688,15 +9688,15 @@ ohif-core@0.5.3:
lodash.merge "^4.6.1" lodash.merge "^4.6.1"
validate.js "^0.12.0" validate.js "^0.12.0"
ohif-cornerstone-extension@0.0.30: ohif-cornerstone-extension@0.0.31:
version "0.0.30" version "0.0.31"
resolved "https://registry.yarnpkg.com/ohif-cornerstone-extension/-/ohif-cornerstone-extension-0.0.30.tgz#b5c87d83f2215d7648f3324f1d2655955123afb5" resolved "https://registry.yarnpkg.com/ohif-cornerstone-extension/-/ohif-cornerstone-extension-0.0.31.tgz#39669e5d8a5e39a4e84f0bdae02b39e222c222aa"
integrity sha512-UAaeiCB50FOv+YnK/Nl9ASEwJOE5OsVODDkMz4SNmWznLxS0luYZNZC8cDZl2dPLvWkVGRgyjY8WHfBqMdWPfw== integrity sha512-7skySEBTkQ2cVOvHXI1Q4rPsjynD1xQ9xQTnPskNNvMEiH4/XJbBXsmbg37D3hocXL16CKIztHoYpNqF0cruYQ==
dependencies: dependencies:
"@babel/runtime" "^7.2.0" "@babel/runtime" "^7.2.0"
classnames "^2.2.6" classnames "^2.2.6"
lodash.throttle "^4.1.1" lodash.throttle "^4.1.1"
react-cornerstone-viewport "0.1.27" react-cornerstone-viewport "0.1.28"
ohif-dicom-html-extension@^0.0.2: ohif-dicom-html-extension@^0.0.2:
version "0.0.2" version "0.0.2"
@ -11480,10 +11480,10 @@ react-bootstrap-modal@4.2.0, react-bootstrap-modal@^4.2.0:
react-overlays "^0.8.0" react-overlays "^0.8.0"
react-transition-group "^2.0.0" react-transition-group "^2.0.0"
react-cornerstone-viewport@0.1.27: react-cornerstone-viewport@0.1.28:
version "0.1.27" version "0.1.28"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.27.tgz#6e00be845c1684aadaf31d0f0ee3933fd44e33f3" resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.28.tgz#ca1b0062c9f08868c653c11d6cdef8f5d519f90a"
integrity sha512-pPIy7snnIXjxyZcghAKmyxvrim8xzQxhml7TxGZ/fv2L+rAsF2ZhsB7LLEUCXIZXL3F8A30VTHWLK3lV92TBDQ== integrity sha512-lGXFB1pxUJE+tozAHjQD8KcmnGuGG/nD3CGrK44cFqx8e3W/CKU9/bZM6qomy/X1fK5TlnJUaZ9NOCaDLhzJrQ==
dependencies: dependencies:
lodash.debounce "^4.0.8" lodash.debounce "^4.0.8"
moment "^2.23.0" moment "^2.23.0"