From 3bdd434488afe2db74e6961acc901e1ebb8a16bd Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Dec 2019 17:29:40 -0300 Subject: [PATCH 1/6] Cleanup LabellingFlow and LabellingManager components --- .../src/components/Labelling/LabellingFlow.js | 76 +++++++++---------- .../components/Labelling/LabellingManager.js | 63 +++------------ 2 files changed, 48 insertions(+), 91 deletions(-) diff --git a/platform/viewer/src/components/Labelling/LabellingFlow.js b/platform/viewer/src/components/Labelling/LabellingFlow.js index 061825c1e..9794e37e9 100644 --- a/platform/viewer/src/components/Labelling/LabellingFlow.js +++ b/platform/viewer/src/components/Labelling/LabellingFlow.js @@ -5,27 +5,14 @@ import cloneDeep from 'lodash.clonedeep'; import LabellingTransition from './LabellingTransition.js'; import OHIFLabellingData from './OHIFLabellingData.js'; +import './LabellingManager.css'; -export default class LabellingFlow extends Component { - static propTypes = { - measurementData: PropTypes.object.isRequired, - labellingDoneCallback: PropTypes.func.isRequired, - updateLabelling: PropTypes.func.isRequired, - initialTopDistance: PropTypes.number, - skipAddLabelButton: PropTypes.bool, - editLocation: PropTypes.bool, - editDescription: PropTypes.bool, - }; - +class LabellingFlow extends Component { constructor(props) { super(props); - const { location, locationLabel, description } = props.measurementData; - this.state = { - location, - locationLabel, - description, + measurementData: props.measurementData, skipAddLabelButton: props.skipAddLabelButton, editDescription: props.editDescription, editLocation: props.editLocation, @@ -33,7 +20,6 @@ export default class LabellingFlow extends Component { displayComponent: true, }; - this.mainElement = React.createRef(); this.descriptionInput = React.createRef(); this.initialItems = OHIFLabellingData; this.currentItems = cloneDeep(this.initialItems); @@ -46,11 +32,6 @@ export default class LabellingFlow extends Component { }; render() { - let mainElementClassName = 'labellingComponent'; - if (this.state.editDescription) { - mainElementClassName += ' editDescription'; - } - return ( <>
@@ -71,12 +52,8 @@ export default class LabellingFlow extends Component { } labellingStateFragment = () => { - const { - skipAddLabelButton, - editLocation, - description, - locationLabel, - } = this.state; + const { skipAddLabelButton, editLocation, measurementData } = this.state; + const { description, locationLabel, location } = measurementData; if (!skipAddLabelButton) { return ( @@ -86,7 +63,7 @@ export default class LabellingFlow extends Component { className="addLabelButton" onClick={this.showLabelling} > - {this.state.location ? 'Edit' : 'Add'} Label + {location ? 'Edit' : 'Add'} Label ); @@ -191,21 +168,24 @@ export default class LabellingFlow extends Component { selectTreeSelectCallback = (event, itemSelected) => { const location = itemSelected.value; + const locationLabel = itemSelected.label; this.props.updateLabelling({ location }); this.setState({ editLocation: false, confirmationState: true, - location: itemSelected.value, - locationLabel: itemSelected.label, + measurementData: { + ...this.state.measurementData, + location, + locationLabel, + }, }); if (this.isTouchScreen) { - this.setTimeout = setTimeout(() => { - this.setState({ - displayComponent: false, - }); - }, 2000); + this.setTimeout = setTimeout( + () => this.setState({ displayComponent: false }), + 2000 + ); } }; @@ -234,3 +214,23 @@ export default class LabellingFlow extends Component { clearTimeout(this.fadeOutTimer); }; } + +LabellingFlow.propTypes = { + measurementData: PropTypes.object.isRequired, + labellingDoneCallback: PropTypes.func.isRequired, + updateLabelling: PropTypes.func.isRequired, + initialTopDistance: PropTypes.number, + skipAddLabelButton: PropTypes.bool, + editLocation: PropTypes.bool, + editDescription: PropTypes.bool, + editDescriptionOnDialog: PropTypes.bool, +}; + +LabellingFlow.defaultProps = { + skipAddLabelButton: false, + editLocation: false, + editDescription: false, + editDescriptionOnDialog: false, +}; + +export default LabellingFlow; diff --git a/platform/viewer/src/components/Labelling/LabellingManager.js b/platform/viewer/src/components/Labelling/LabellingManager.js index 8b0148886..c492bc89d 100644 --- a/platform/viewer/src/components/Labelling/LabellingManager.js +++ b/platform/viewer/src/components/Labelling/LabellingManager.js @@ -1,5 +1,4 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import cloneDeep from 'lodash.clonedeep'; import EditDescriptionDialog from './../EditDescriptionDialog/EditDescriptionDialog.js'; @@ -7,64 +6,27 @@ import LabellingFlow from './LabellingFlow.js'; import './LabellingManager.css'; export default class LabellingManager extends Component { - static propTypes = { - measurementData: PropTypes.object.isRequired, - labellingDoneCallback: PropTypes.func.isRequired, - updateLabelling: PropTypes.func.isRequired, - skipAddLabelButton: PropTypes.bool, - editLocation: PropTypes.bool, - editDescription: PropTypes.bool, - editDescriptionOnDialog: PropTypes.bool, - }; - - static defaultProps = { - skipAddLabelButton: false, - editLocation: false, - editDescription: false, - editDescriptionOnDialog: false, - }; - constructor(props) { super(props); - const measurementData = cloneDeep(props.measurementData); - this.treatMeasurementData(measurementData); + const newMeasurementData = cloneDeep(props.measurementData); + this.treatMeasurementData(newMeasurementData); - let editLocation = props.editLocation; + let newEditLocation = props.editLocation; if (!props.editDescription && !props.editLocation) { - editLocation = true; + newEditLocation = true; } this.state = { - skipAddLabelButton: props.skipAddLabelButton, - editLocation: editLocation, - editDescription: props.editDescription, - editDescriptionOnDialog: props.editDescriptionOnDialog, - measurementData: measurementData, + editLocation: newEditLocation, + measurementData: newMeasurementData, }; } - componentDidMount = () => { - document.addEventListener('touchstart', this.onTouchStart); - }; - - componentWillUnmount = () => { - document.removeEventListener('touchstart', this.onTouchStart); - }; - render() { - return this.getRenderComponent(); - } + const { editLocation, measurementData } = this.state; - getRenderComponent = () => { - const { - editLocation, - editDescription, - editDescriptionOnDialog, - measurementData, - } = this.state; - - if (editDescriptionOnDialog) { + if (this.props.editDescriptionOnDialog) { return ( ; } - }; + } treatMeasurementData = measurementData => { const { editDescription, editLocation } = this.props; @@ -91,11 +53,6 @@ export default class LabellingManager extends Component { } }; - responseDialogUpdate = response => { - this.props.updateLabelling({ response }); - this.props.labellingDoneCallback(); - }; - descriptionDialogUpdate = description => { this.props.updateLabelling({ description }); this.props.labellingDoneCallback(); From d128fd6bf0312cfc50f171d98c4083d3a36e2bc1 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Dec 2019 17:41:43 -0300 Subject: [PATCH 2/6] Remove LabellingManager component --- platform/viewer/src/App.js | 6 +- ...LabellingManager.css => LabellingFlow.css} | 9 +-- .../src/components/Labelling/LabellingFlow.js | 42 ++++++++++++- .../components/Labelling/LabellingManager.js | 60 ------------------- 4 files changed, 45 insertions(+), 72 deletions(-) rename platform/viewer/src/components/Labelling/{LabellingManager.css => LabellingFlow.css} (89%) delete mode 100644 platform/viewer/src/components/Labelling/LabellingManager.js diff --git a/platform/viewer/src/App.js b/platform/viewer/src/App.js index b1cf92739..cde917e54 100644 --- a/platform/viewer/src/App.js +++ b/platform/viewer/src/App.js @@ -9,7 +9,7 @@ import { hot } from 'react-hot-loader/root'; import OHIFCornerstoneExtension from '@ohif/extension-cornerstone'; import ToolContextMenu from './connectedComponents/ToolContextMenu'; -import LabellingManager from './components/Labelling/LabellingManager'; +import LabellingFlow from './components/Labelling/LabellingFlow'; import { SnackbarProvider, @@ -182,7 +182,7 @@ class App extends Component { > { + const { editDescription, editLocation } = this.props; + + if (editDescription) { + measurementData.description = undefined; + } + + if (editLocation) { + measurementData.location = undefined; + } + }; + + descriptionDialogUpdate = description => { + this.props.updateLabelling({ description }); + this.props.labellingDoneCallback(); + }; + render() { + if (this.props.editDescriptionOnDialog) { + return ( + + ); + } + return ( - ); - } - - if (editLocation || this.props.editDescription) { - return ; - } - } - - treatMeasurementData = measurementData => { - const { editDescription, editLocation } = this.props; - - if (editDescription) { - measurementData.description = undefined; - } - - if (editLocation) { - measurementData.location = undefined; - } - }; - - descriptionDialogUpdate = description => { - this.props.updateLabelling({ description }); - this.props.labellingDoneCallback(); - }; -} From ef611e4849ef624479d6ab226b6b69678d5bd8b7 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Dec 2019 18:08:51 -0300 Subject: [PATCH 3/6] Refactoring labellingflow to function component --- .../src/components/Labelling/LabellingFlow.js | 307 +++++++++--------- 1 file changed, 154 insertions(+), 153 deletions(-) diff --git a/platform/viewer/src/components/Labelling/LabellingFlow.js b/platform/viewer/src/components/Labelling/LabellingFlow.js index 877682117..efe54b156 100644 --- a/platform/viewer/src/components/Labelling/LabellingFlow.js +++ b/platform/viewer/src/components/Labelling/LabellingFlow.js @@ -1,5 +1,5 @@ import { Icon, SelectTree } from '@ohif/ui'; -import React, { Component } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import cloneDeep from 'lodash.clonedeep'; @@ -8,87 +8,140 @@ import OHIFLabellingData from './OHIFLabellingData.js'; import EditDescriptionDialog from './../EditDescriptionDialog/EditDescriptionDialog.js'; import './LabellingFlow.css'; -class LabellingFlow extends Component { - constructor(props) { - super(props); +const LabellingFlow = ({ + measurementData, + editLocation, + editDescription, + skipAddLabelButton, + updateLabelling, + labellingDoneCallback, + editDescriptionOnDialog, +}) => { + const [fadeOutTimer, setFadeOutTimer] = useState(); + const [showComponent, setShowComponent] = useState(true); + const descriptionInput = useRef(); + const [state, setState] = useState({ + measurementData, + editLocation, + editDescription, + skipAddLabelButton, + }); - const newMeasurementData = cloneDeep(props.measurementData); - this.treatMeasurementData(newMeasurementData); + const initialItems = OHIFLabellingData; + const currentItems = cloneDeep(initialItems); - let newEditLocation = props.editLocation; - if (!props.editDescription && !props.editLocation) { - newEditLocation = true; - } + useEffect(() => { + const treatMeasurementData = measurementData => { + if (editDescription) { + measurementData.description = undefined; + } - this.state = { - measurementData: newMeasurementData, - skipAddLabelButton: props.skipAddLabelButton, - editDescription: props.editDescription, - editLocation: newEditLocation, - confirmationState: false, - displayComponent: true, + if (editLocation) { + measurementData.location = undefined; + } }; - this.descriptionInput = React.createRef(); - this.initialItems = OHIFLabellingData; - this.currentItems = cloneDeep(this.initialItems); - } + const newMeasurementData = cloneDeep(measurementData); + treatMeasurementData(newMeasurementData); - componentDidUpdate = () => { - if (this.state.editDescription) { - this.descriptionInput.current.focus(); + let newEditLocation = editLocation; + if (!editDescription && !editLocation) { + newEditLocation = true; + } + setState(state => ({ + ...state, + editLocation: newEditLocation, + measurementData: newMeasurementData, + })); + }, [editDescription, editLocation, measurementData]); + + useEffect(() => { + if (descriptionInput.current) { + descriptionInput.current.focus(); + } + }, [state]); + + const relabel = event => + setState(state => ({ ...state, editLocation: true })); + + const setDescriptionUpdateMode = () => { + descriptionInput.current.focus(); + setState(state => ({ ...state, editDescription: true })); + }; + + const descriptionCancel = () => { + const { description = '' } = cloneDeep(state); + descriptionInput.current.value = description; + setState(state => ({ ...state, editDescription: false })); + }; + + const handleKeyPress = e => { + if (e.key === 'Enter') { + descriptionSave(); } }; - treatMeasurementData = measurementData => { - const { editDescription, editLocation } = this.props; + const descriptionSave = () => { + const description = descriptionInput.current.value; + updateLabelling({ description }); - if (editDescription) { - measurementData.description = undefined; - } - - if (editLocation) { - measurementData.location = undefined; - } + setState(state => ({ + ...state, + description, + editDescription: false, + })); }; - descriptionDialogUpdate = description => { - this.props.updateLabelling({ description }); - this.props.labellingDoneCallback(); + const selectTreeSelectCallback = (event, itemSelected) => { + const location = itemSelected.value; + const locationLabel = itemSelected.label; + updateLabelling({ location }); + + setState(state => ({ + ...state, + editLocation: false, + measurementData: { + ...state.measurementData, + location, + locationLabel, + }, + })); }; - render() { - if (this.props.editDescriptionOnDialog) { - return ( - - ); + const showLabelling = () => { + setState(state => ({ + ...state, + skipAddLabelButton: true, + editLocation: false, + })); + }; + + /* + * Waits for 1 sec to dismiss the labelling component. + * + */ + const fadeOutAndLeave = () => { + setFadeOutTimer(setTimeout(() => setShowComponent(false), 1000)); + }; + + const fadeOutAndLeaveFast = () => setShowComponent(false); + + const clearFadeOutTimer = () => { + if (!fadeOutTimer) { + return; } - return ( - - <> -
- {this.labellingStateFragment()} -
- -
- ); - } + clearTimeout(fadeOutTimer); + setFadeOutTimer(null); + }; - labellingStateFragment = () => { - const { skipAddLabelButton, editLocation, measurementData } = this.state; + const descriptionDialogUpdate = description => { + updateLabelling({ description }); + labellingDoneCallback(); + }; + + const labellingStateFragment = () => { + const { skipAddLabelButton, editLocation, measurementData } = state; const { description, locationLabel, location } = measurementData; if (!skipAddLabelButton) { @@ -97,7 +150,7 @@ class LabellingFlow extends Component { @@ -107,19 +160,16 @@ class LabellingFlow extends Component { if (editLocation) { return ( ); } else { return ( <> -
+
@@ -127,10 +177,10 @@ class LabellingFlow extends Component {
@@ -138,14 +188,14 @@ class LabellingFlow extends Component { @@ -173,83 +223,34 @@ class LabellingFlow extends Component { } }; - relabel = event => this.setState({ editLocation: true }); - - setDescriptionUpdateMode = () => { - this.descriptionInput.current.focus(); - this.setState({ editDescription: true }); - }; - - descriptionCancel = () => { - const { description = '' } = cloneDeep(this.state); - this.descriptionInput.current.value = description; - this.setState({ editDescription: false }); - }; - - handleKeyPress = e => { - if (e.key === 'Enter') { - this.descriptionSave(); - } - }; - - descriptionSave = () => { - const description = this.descriptionInput.current.value; - this.props.updateLabelling({ description }); - - this.setState({ - description, - editDescription: false, - }); - }; - - selectTreeSelectCallback = (event, itemSelected) => { - const location = itemSelected.value; - const locationLabel = itemSelected.label; - this.props.updateLabelling({ location }); - - this.setState({ - editLocation: false, - confirmationState: true, - measurementData: { - ...this.state.measurementData, - location, - locationLabel, - }, - }); - - if (this.isTouchScreen) { - this.setTimeout = setTimeout( - () => this.setState({ displayComponent: false }), - 2000 - ); - } - }; - - showLabelling = () => { - this.setState({ - skipAddLabelButton: true, - editLocation: false, - }); - }; - - fadeOutAndLeave = () => { - // Wait for 1 sec to dismiss the labelling component - this.fadeOutTimer = setTimeout( - () => this.setState({ displayComponent: false }), - 1000 + if (editDescriptionOnDialog) { + return ( + ); - }; + } - fadeOutAndLeaveFast = () => this.setState({ displayComponent: false }); - - clearFadeOutTimer = () => { - if (!this.fadeOutTimer) { - return; - } - - clearTimeout(this.fadeOutTimer); - }; -} + return ( + + <> +
+ {labellingStateFragment()} +
+ +
+ ); +}; LabellingFlow.propTypes = { measurementData: PropTypes.object.isRequired, From 68fcaef19adcaaf3dec81f675fe7e70eeac5fe8d Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Dec 2019 18:18:37 -0300 Subject: [PATCH 4/6] Cleanup labelling flow --- .../src/components/Labelling/LabellingFlow.js | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/platform/viewer/src/components/Labelling/LabellingFlow.js b/platform/viewer/src/components/Labelling/LabellingFlow.js index efe54b156..d516b3173 100644 --- a/platform/viewer/src/components/Labelling/LabellingFlow.js +++ b/platform/viewer/src/components/Labelling/LabellingFlow.js @@ -44,13 +44,9 @@ const LabellingFlow = ({ const newMeasurementData = cloneDeep(measurementData); treatMeasurementData(newMeasurementData); - let newEditLocation = editLocation; - if (!editDescription && !editLocation) { - newEditLocation = true; - } setState(state => ({ ...state, - editLocation: newEditLocation, + editLocation: !editDescription && !editLocation, measurementData: newMeasurementData, })); }, [editDescription, editLocation, measurementData]); @@ -75,8 +71,8 @@ const LabellingFlow = ({ setState(state => ({ ...state, editDescription: false })); }; - const handleKeyPress = e => { - if (e.key === 'Enter') { + const handleKeyPress = event => { + if (event.key === 'Enter') { descriptionSave(); } }; @@ -120,19 +116,16 @@ const LabellingFlow = ({ * Waits for 1 sec to dismiss the labelling component. * */ - const fadeOutAndLeave = () => { - setFadeOutTimer(setTimeout(() => setShowComponent(false), 1000)); - }; + const fadeOutAndLeave = () => + setFadeOutTimer(setTimeout(fadeOutAndLeaveFast, 1000)); const fadeOutAndLeaveFast = () => setShowComponent(false); const clearFadeOutTimer = () => { - if (!fadeOutTimer) { - return; + if (fadeOutTimer) { + clearTimeout(fadeOutTimer); + setFadeOutTimer(null); } - - clearTimeout(fadeOutTimer); - setFadeOutTimer(null); }; const descriptionDialogUpdate = description => { @@ -146,15 +139,13 @@ const LabellingFlow = ({ if (!skipAddLabelButton) { return ( - <> - - + ); } else { if (editLocation) { From 92548191e4cfa34179a526b9e15da4583be4baf1 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Dec 2019 18:31:55 -0300 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Remove=20Labelli?= =?UTF-8?q?ngManager=20and=20Clean=20LabellingFlow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate logic from LabellingManager to LabellingFlow and cleanup LabellingFlow component Closes: #1267 --- .../src/components/Labelling/LabellingFlow.js | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/platform/viewer/src/components/Labelling/LabellingFlow.js b/platform/viewer/src/components/Labelling/LabellingFlow.js index d516b3173..c2749431e 100644 --- a/platform/viewer/src/components/Labelling/LabellingFlow.js +++ b/platform/viewer/src/components/Labelling/LabellingFlow.js @@ -27,26 +27,25 @@ const LabellingFlow = ({ skipAddLabelButton, }); - const initialItems = OHIFLabellingData; - const currentItems = cloneDeep(initialItems); - useEffect(() => { - const treatMeasurementData = measurementData => { - if (editDescription) { - measurementData.description = undefined; - } - - if (editLocation) { - measurementData.location = undefined; - } - }; - const newMeasurementData = cloneDeep(measurementData); - treatMeasurementData(newMeasurementData); + + if (editDescription) { + newMeasurementData.description = undefined; + } + + if (editLocation) { + newMeasurementData.location = undefined; + } + + let newEditLocation = editLocation; + if (!editDescription && !editLocation) { + newEditLocation = true; + } setState(state => ({ ...state, - editLocation: !editDescription && !editLocation, + editLocation: newEditLocation, measurementData: newMeasurementData, })); }, [editDescription, editLocation, measurementData]); @@ -151,7 +150,7 @@ const LabellingFlow = ({ if (editLocation) { return ( Date: Wed, 11 Dec 2019 06:54:41 -0300 Subject: [PATCH 6/6] Fix config check in extension init --- extensions/cornerstone/src/init.js | 24 ++++++++++-------------- platform/viewer/public/config/default.js | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/extensions/cornerstone/src/init.js b/extensions/cornerstone/src/init.js index 06ba0a1c5..37d47e5e8 100644 --- a/extensions/cornerstone/src/init.js +++ b/extensions/cornerstone/src/init.js @@ -102,7 +102,7 @@ export default function init({ servicesManager, configuration }) { ]; /* Add extension tools configuration here. */ - const extensionToolsConfiguration = { + const internalToolsConfig = { ArrowAnnotate: { configuration: { getTextCallback: (callback, eventDetails) => @@ -113,19 +113,15 @@ export default function init({ servicesManager, configuration }) { }, }; - const isEmpty = obj => Object.keys(obj).length < 1; - if (!isEmpty(configuration.tools) || !isEmpty(extensionToolsConfiguration)) { - /* Add tools with its custom props through extension configuration. */ - tools.forEach(tool => { - const toolName = tool.name.replace('Tool', ''); - const configurationToolProps = configuration.tools[toolName] || {}; - const extensionToolProps = extensionToolsConfiguration[toolName]; - let props = merge(extensionToolProps, configurationToolProps); - csTools.addTool(tool, props); - }); - } else { - tools.forEach(tool => csTools.addTool(tool)); - } + /* Add tools with its custom props through extension configuration. */ + tools.forEach(tool => { + const toolName = tool.name.replace('Tool', ''); + const externalToolsConfig = configuration.tools || {}; + const externalToolProps = externalToolsConfig[toolName] || {}; + const internalToolProps = internalToolsConfig[toolName] || {}; + const props = merge(internalToolProps, externalToolProps); + csTools.addTool(tool, props); + }); csTools.setToolActive('Pan', { mouseButtonMask: 4 }); csTools.setToolActive('Zoom', { mouseButtonMask: 2 }); diff --git a/platform/viewer/public/config/default.js b/platform/viewer/public/config/default.js index a8d44e7ef..492294bf7 100644 --- a/platform/viewer/public/config/default.js +++ b/platform/viewer/public/config/default.js @@ -70,5 +70,5 @@ window.config = { // ~ Cornerstone Tools { commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] }, ], - cornerstoneExtensionConfig: { tools: {} }, + cornerstoneExtensionConfig: {}, };