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

This commit is contained in:
dannyrb committed 2019-05-28 13:03:41 -04:00
commit b3f54b4500
11 files changed
+156 -125

No files matched your search

+2 -2
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 -->
@@ -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
@@ -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",
@@ -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
}; };
}; };
@@ -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"
+3 -3
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",
+35 -24
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
@@ -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
+61 -43
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
+13 -13
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
+17 -17
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"