Merge pull request #427 from dannyrb/react

Set and use enabled element
This commit is contained in:
Danny Brown 2019-05-15 15:50:27 -04:00 committed by GitHub
commit be8c243bf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 127 additions and 118 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "ohif-cornerstone-extension", "name": "ohif-cornerstone-extension",
"version": "0.0.28", "version": "0.0.29",
"description": "OHIF extension for Cornerstone", "description": "OHIF extension for Cornerstone",
"author": "OHIF", "author": "OHIF",
"license": "MIT", "license": "MIT",
@ -35,6 +35,12 @@
"react-viewerbase": "^0.2.10", "react-viewerbase": "^0.2.10",
"redux": "^4.0.1" "redux": "^4.0.1"
}, },
"dependencies": {
"@babel/runtime": "^7.2.0",
"classnames": "^2.2.6",
"lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "0.1.26"
},
"devDependencies": { "devDependencies": {
"@babel/core": "^7.2.2", "@babel/core": "^7.2.2",
"@babel/plugin-external-helpers": "^7.2.0", "@babel/plugin-external-helpers": "^7.2.0",
@ -87,11 +93,5 @@
], ],
"files": [ "files": [
"dist" "dist"
], ]
"dependencies": {
"@babel/runtime": "^7.2.0",
"classnames": "^2.2.6",
"lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "^0.1.25"
}
} }

View File

@ -1,49 +1,32 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { CineDialog } from 'react-viewerbase'; import { CineDialog } from 'react-viewerbase';
import OHIF from 'ohif-core'; import OHIF from 'ohif-core';
import csTools from 'cornerstone-tools';
// Our target output kills the `as` and "import" throws a keyword error
// import { import as toolImport, getToolState } from 'cornerstone-tools';
import cloneDeep from 'lodash.clonedeep'; import cloneDeep from 'lodash.clonedeep';
const toolImport = csTools.import;
const scrollToIndex = toolImport('util/scrollToIndex');
const { setViewportSpecificData } = OHIF.redux.actions; const { setViewportSpecificData } = OHIF.redux.actions;
// TODO: I'm guessing this function will be used in other connect locations // Why do I need or care about any of this info?
// so we might want to put it somewhere shared // A dispatch action should be able to pull this at the time of an event?
function getActiveViewportSpecificData(state) { // `isPlaying` and `cineFrameRate` might matter, but I think we can prop pass for those.
const { viewportSpecificData, activeViewportIndex } = state.viewports;
return viewportSpecificData[activeViewportIndex];
}
const mapStateToProps = state => { const mapStateToProps = state => {
// TODO: // Get activeViewport's `cine` and `stack`
// - Test if including CineDialog in the toolbarRow will prevent it const { viewportSpecificData, activeViewportIndex } = state.viewports;
// from hovering over the rest of the UI when visible. const { cine, dom } = viewportSpecificData[activeViewportIndex] || {};
//
// - Create custom ToolbarButton which just shows Play state
// - Connect this ToolbarButton to Redux
const activeViewportSpecificData = getActiveViewportSpecificData(state);
let stack = { const cineData = cine || {
imageIds: [],
currentImageIdIndex: 0
};
if (activeViewportSpecificData && activeViewportSpecificData.stack) {
stack = activeViewportSpecificData.stack
}
let cine = {
isPlaying: false, isPlaying: false,
cineFrameRate: 24 cineFrameRate: 24
}; };
if (activeViewportSpecificData && activeViewportSpecificData.cine) {
cine = activeViewportSpecificData.cine
}
// New props we're creating?
// TODO: activeViewportStackData won't currently change anything on
// CornerstoneViewport. The updates are too frequent and it's killing
// performance. Need to revisit how we can do this.
return { return {
activeViewportStackData: stack, activeEnabledElement: dom,
activeViewportCineData: cine, activeViewportCineData: cineData,
activeViewportIndex: state.viewports.activeViewportIndex activeViewportIndex: state.viewports.activeViewportIndex
}; };
}; };
@ -52,12 +35,16 @@ const mapDispatchToProps = dispatch => {
return { return {
dispatchSetViewportSpecificData: (viewportIndex, data) => { dispatchSetViewportSpecificData: (viewportIndex, data) => {
dispatch(setViewportSpecificData(viewportIndex, data)); dispatch(setViewportSpecificData(viewportIndex, data));
}, }
}; };
}; };
const mergeProps = (propsFromState, propsFromDispatch, ownProps) => { const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
const { activeViewportStackData, activeViewportCineData, activeViewportIndex } = propsFromState; const {
activeEnabledElement,
activeViewportCineData,
activeViewportIndex
} = propsFromState;
return { return {
cineFrameRate: activeViewportCineData.cineFrameRate, cineFrameRate: activeViewportCineData.cineFrameRate,
@ -66,38 +53,42 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => {
const cine = cloneDeep(activeViewportCineData); const cine = cloneDeep(activeViewportCineData);
cine.isPlaying = !cine.isPlaying; cine.isPlaying = !cine.isPlaying;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { cine }); propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, {
cine
});
}, },
onFrameRateChanged: frameRate => { onFrameRateChanged: frameRate => {
const cine = cloneDeep(activeViewportCineData); const cine = cloneDeep(activeViewportCineData);
cine.cineFrameRate = frameRate; cine.cineFrameRate = frameRate;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { cine }); propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, {
cine
});
}, },
onClickNextButton: () => { onClickNextButton: () => {
const stack = cloneDeep(activeViewportStackData); const stackData = csTools.getToolState(activeEnabledElement, 'stack');
const largestPossibleIndex = stack.imageIds.length - 1; if (!stackData || !stackData.data || !stackData.data.length) return;
stack.currentImageIdIndex = Math.min(stack.currentImageIdIndex + 1, largestPossibleIndex) const { currentImageIdIndex, imageIds } = stackData.data[0];
if (currentImageIdIndex >= imageIds.length - 1) return;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack }); scrollToIndex(activeEnabledElement, currentImageIdIndex + 1);
}, },
onClickBackButton: () => { onClickBackButton: () => {
const stack = cloneDeep(activeViewportStackData); const stackData = csTools.getToolState(activeEnabledElement, 'stack');
stack.currentImageIdIndex = Math.max(stack.currentImageIdIndex - 1, 0); if (!stackData || !stackData.data || !stackData.data.length) return;
const { currentImageIdIndex } = stackData.data[0];
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack }); if (currentImageIdIndex === 0) return;
scrollToIndex(activeEnabledElement, currentImageIdIndex - 1);
}, },
onClickSkipToStart: () => { onClickSkipToStart: () => {
const stack = cloneDeep(activeViewportStackData); const stackData = csTools.getToolState(activeEnabledElement, 'stack');
stack.currentImageIdIndex = 0; if (!stackData || !stackData.data || !stackData.data.length) return;
scrollToIndex(activeEnabledElement, 0);
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack });
}, },
onClickSkipToEnd: () => { onClickSkipToEnd: () => {
const stack = cloneDeep(activeViewportStackData); const stackData = csTools.getToolState(activeEnabledElement, 'stack');
stack.currentImageIdIndex = stack.imageIds.length; if (!stackData || !stackData.data || !stackData.data.length) return;
const lastIndex = stackData.data[0].imageIds.length - 1;
propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, { stack }); scrollToIndex(activeEnabledElement, lastIndex);
} }
}; };
}; };

View File

@ -50,6 +50,21 @@ const mapDispatchToProps = (dispatch, ownProps) => {
dispatch(clearViewportSpecificData(viewportIndex)); dispatch(clearViewportSpecificData(viewportIndex));
}, },
/**
* Our component "enables" the underlying dom element on "componentDidMount"
* It listens for that event, and then emits the enabledElement. We can grab
* a reference to it here, to make playing with cornerstone's native methods
* easier.
*/
onElementEnabled: event => {
const enabledElement = event.detail.element;
dispatch(
setViewportSpecificData(viewportIndex, {
dom: enabledElement
})
);
},
onMeasurementsChanged: (event, action) => { onMeasurementsChanged: (event, action) => {
const { const {
onAdded, onAdded,

View File

@ -6,7 +6,7 @@ import ConnectedCineDialog from './ConnectedCineDialog';
class ToolbarModule extends Component { class ToolbarModule extends Component {
state = { state = {
cineDialogOpen: false cineDialogOpen: false
} };
onClickCineToolbarButton = () => { onClickCineToolbarButton = () => {
this.setState({ this.setState({
@ -16,10 +16,14 @@ class ToolbarModule extends Component {
render() { render() {
const cineDialogContainerStyle = { const cineDialogContainerStyle = {
display: this.state.cineDialogOpen ? 'inline-block' : 'none' display: this.state.cineDialogOpen ? 'block' : 'none',
position: 'absolute',
top: '82px',
zIndex: 999
}; };
return (<div className="ToolbarModule"> return (
<div className="ToolbarModule">
<ConnectedToolbarSection /> <ConnectedToolbarSection />
<ToolbarButton <ToolbarButton
active={this.state.cineDialogOpen} active={this.state.cineDialogOpen}

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.23: react-cornerstone-viewport@0.1.26:
version "0.1.23" version "0.1.26"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.23.tgz#4f065c4d1a5e721a45b819d1b7e94489af69b5c1" resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.26.tgz#eb09ae7c5d0f24e20a852fdc3ce648935d182370"
integrity sha512-uukvBIrtvExY0oOo6d/79CZRrALtU2Pq8NBovYVvD02Hg40yYtGYLZ2AnbjbQEtsf0LjpLhcfT/QU6ZOB2v8rw== integrity sha512-t4onVJeib+FHWNHZNVrJyndLw8dCf7cI/69r5pNE4Sefjxw7pDuPdXfmZdcT8VWpl9cLairTqtqaLW+gXxTxIA==
dependencies: dependencies:
lodash.debounce "^4.0.8" lodash.debounce "^4.0.8"
moment "^2.23.0" moment "^2.23.0"

View File

@ -77,7 +77,7 @@
"lodash.isequal": "4.5.0", "lodash.isequal": "4.5.0",
"moment": "^2.24.0", "moment": "^2.24.0",
"ohif-core": "0.5.2", "ohif-core": "0.5.2",
"ohif-cornerstone-extension": "^0.0.28", "ohif-cornerstone-extension": "0.0.29",
"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

@ -20,7 +20,6 @@ OHIF.user.getAccessToken = () => {
// TODO: Get the Redux store from somewhere else // TODO: Get the Redux store from somewhere else
const state = window.store.getState() const state = window.store.getState()
if (!state.oidc || !state.oidc.user) { if (!state.oidc || !state.oidc.user) {
console.warn('failed to grab access token')
return return
} }

View File

@ -9617,15 +9617,15 @@ ohif-core@0.5.2:
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.28: ohif-cornerstone-extension@0.0.29:
version "0.0.28" version "0.0.29"
resolved "https://registry.yarnpkg.com/ohif-cornerstone-extension/-/ohif-cornerstone-extension-0.0.28.tgz#79e07133e0b08f2c38f4bdb77032c4c7182266c4" resolved "https://registry.yarnpkg.com/ohif-cornerstone-extension/-/ohif-cornerstone-extension-0.0.29.tgz#288f3acb9b85b2434e39cae728ffd6dd2d67e0c2"
integrity sha512-GPXMqrmB+kmRAEOlSD0nBO4vwOvYLyn4gt9AtP016JMCLADpAsEDymUzE8Psr0NPLSvk6QrPL0/bKglfsGl7sA== integrity sha512-1tFQokdYhW6Z5bhABvU84vLo4u7SHkFqgNpqwyw4mz3UlsbUBB30P9K88a68Txu8/wsMxTa9h8cAEZa1WfJo+g==
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.25" react-cornerstone-viewport "0.1.26"
ohif-dicom-html-extension@^0.0.2: ohif-dicom-html-extension@^0.0.2:
version "0.0.2" version "0.0.2"
@ -11401,10 +11401,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.25: react-cornerstone-viewport@0.1.26:
version "0.1.25" version "0.1.26"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.25.tgz#8d55d35db76f56c4844770ad14b21aeb20640724" resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-0.1.26.tgz#eb09ae7c5d0f24e20a852fdc3ce648935d182370"
integrity sha512-h+00YdJubWiPylVAeRLhbOA3908ST3aB+ideoMsnDzNH3PGhL0KIgey5e8caAhWXkmFOS+SRJbXjpLCD8aGcLw== integrity sha512-t4onVJeib+FHWNHZNVrJyndLw8dCf7cI/69r5pNE4Sefjxw7pDuPdXfmZdcT8VWpl9cLairTqtqaLW+gXxTxIA==
dependencies: dependencies:
lodash.debounce "^4.0.8" lodash.debounce "^4.0.8"
moment "^2.23.0" moment "^2.23.0"