Files
ohif-viewer/platform/viewer/src/components/Labelling/LabellingFlow.js
T

272 lines
7.2 KiB
JavaScript
Raw Normal View History

2019-08-13 15:36:46 -04:00
import { Icon, SelectTree } from '@ohif/ui';
2019-05-30 00:46:45 -04:00
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cloneDeep from 'lodash.clonedeep';
2019-05-02 17:12:06 -04:00
2019-05-30 00:46:45 -04:00
import LabellingTransition from './LabellingTransition.js';
import OHIFLabellingData from './OHIFLabellingData.js';
2019-12-10 17:41:43 -03:00
import EditDescriptionDialog from './../EditDescriptionDialog/EditDescriptionDialog.js';
import './LabellingFlow.css';
2019-05-02 17:12:06 -04:00
class LabellingFlow extends Component {
2019-05-02 17:12:06 -04:00
constructor(props) {
2019-05-30 00:46:45 -04:00
super(props);
2019-05-02 17:12:06 -04:00
2019-12-10 17:41:43 -03:00
const newMeasurementData = cloneDeep(props.measurementData);
this.treatMeasurementData(newMeasurementData);
let newEditLocation = props.editLocation;
if (!props.editDescription && !props.editLocation) {
newEditLocation = true;
}
2019-05-02 17:12:06 -04:00
this.state = {
2019-12-10 17:41:43 -03:00
measurementData: newMeasurementData,
2019-05-02 17:12:06 -04:00
skipAddLabelButton: props.skipAddLabelButton,
editDescription: props.editDescription,
2019-12-10 17:41:43 -03:00
editLocation: newEditLocation,
2019-05-02 17:12:06 -04:00
confirmationState: false,
displayComponent: true,
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
2019-05-30 00:46:45 -04:00
this.descriptionInput = React.createRef();
this.initialItems = OHIFLabellingData;
this.currentItems = cloneDeep(this.initialItems);
2019-05-02 17:12:06 -04:00
}
componentDidUpdate = () => {
if (this.state.editDescription) {
this.descriptionInput.current.focus();
}
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
2019-12-10 17:41:43 -03:00
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();
};
2019-05-02 17:12:06 -04:00
render() {
2019-12-10 17:41:43 -03:00
if (this.props.editDescriptionOnDialog) {
return (
<EditDescriptionDialog
onCancel={this.props.labellingDoneCallback}
onUpdate={this.descriptionDialogUpdate}
measurementData={this.state.measurementData}
/>
);
}
2019-05-02 17:12:06 -04:00
return (
<LabellingTransition
displayComponent={this.state.displayComponent}
onTransitionExit={this.props.labellingDoneCallback}
>
<>
<div
className={`labellingComponent ${this.state.editDescription &&
'editDescription'}`}
onMouseLeave={this.fadeOutAndLeave}
onMouseEnter={this.clearFadeOutTimer}
>
{this.labellingStateFragment()}
</div>
</>
2019-05-02 17:12:06 -04:00
</LabellingTransition>
2019-05-30 00:46:45 -04:00
);
2019-05-02 17:12:06 -04:00
}
labellingStateFragment = () => {
const { skipAddLabelButton, editLocation, measurementData } = this.state;
const { description, locationLabel, location } = measurementData;
2019-05-02 17:12:06 -04:00
if (!skipAddLabelButton) {
return (
<>
<button
type="button"
className="addLabelButton"
onClick={this.showLabelling}
>
{location ? 'Edit' : 'Add'} Label
2019-05-02 17:12:06 -04:00
</button>
</>
2019-05-30 00:46:45 -04:00
);
2019-05-02 17:12:06 -04:00
} else {
if (editLocation) {
return (
<SelectTree
items={this.currentItems}
columns={1}
onSelected={this.selectTreeSelectCallback}
2019-05-02 17:12:06 -04:00
selectTreeFirstTitle="Assign Label"
/>
2019-05-30 00:46:45 -04:00
);
2019-05-02 17:12:06 -04:00
} else {
return (
<>
<div
className="checkIconWrapper"
onClick={this.fadeOutAndLeaveFast}
>
2019-05-30 12:08:46 -04:00
<Icon name="check" className="checkIcon" />
2019-05-02 17:12:06 -04:00
</div>
<div className="locationDescriptionWrapper">
<div className="location">{locationLabel}</div>
<div className="description">
<input
id="descriptionInput"
ref={this.descriptionInput}
defaultValue={description || ''}
autoComplete="off"
onKeyPress={this.handleKeyPress}
2019-05-02 17:12:06 -04:00
/>
</div>
</div>
<div className="commonButtons">
<button
type="button"
className="commonButton left"
onClick={this.relabel}
>
Relabel
</button>
<button
type="button"
className="commonButton right"
onClick={this.setDescriptionUpdateMode}
>
{description ? 'Edit ' : 'Add '}
Description
</button>
</div>
<div className="editDescriptionButtons">
<button
type="button"
className="commonButton left"
onClick={this.descriptionCancel}
>
Cancel
</button>
<button
type="button"
className="commonButton right"
onClick={this.descriptionSave}
>
Save
</button>
</div>
</>
2019-05-30 00:46:45 -04:00
);
2019-05-02 17:12:06 -04:00
}
}
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
relabel = event => this.setState({ editLocation: true });
2019-05-02 17:12:06 -04:00
setDescriptionUpdateMode = () => {
2019-05-30 00:46:45 -04:00
this.descriptionInput.current.focus();
this.setState({ editDescription: true });
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
descriptionCancel = () => {
2019-05-30 00:46:45 -04:00
const { description = '' } = cloneDeep(this.state);
this.descriptionInput.current.value = description;
this.setState({ editDescription: false });
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
handleKeyPress = e => {
if (e.key === 'Enter') {
this.descriptionSave();
}
};
2019-05-02 17:12:06 -04:00
descriptionSave = () => {
2019-05-30 00:46:45 -04:00
const description = this.descriptionInput.current.value;
this.props.updateLabelling({ description });
2019-05-02 17:12:06 -04:00
this.setState({
description,
editDescription: false,
2019-05-30 00:46:45 -04:00
});
};
2019-05-02 17:12:06 -04:00
selectTreeSelectCallback = (event, itemSelected) => {
2019-05-30 00:46:45 -04:00
const location = itemSelected.value;
const locationLabel = itemSelected.label;
2019-05-30 00:46:45 -04:00
this.props.updateLabelling({ location });
2019-05-02 17:12:06 -04:00
this.setState({
editLocation: false,
confirmationState: true,
measurementData: {
...this.state.measurementData,
location,
locationLabel,
},
2019-05-30 00:46:45 -04:00
});
2019-05-02 17:12:06 -04:00
if (this.isTouchScreen) {
this.setTimeout = setTimeout(
() => this.setState({ displayComponent: false }),
2000
);
2019-05-02 17:12:06 -04:00
}
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
showLabelling = () => {
this.setState({
skipAddLabelButton: true,
editLocation: false,
2019-05-30 00:46:45 -04:00
});
};
2019-05-02 17:12:06 -04:00
fadeOutAndLeave = () => {
// Wait for 1 sec to dismiss the labelling component
this.fadeOutTimer = setTimeout(
() => this.setState({ displayComponent: false }),
1000
);
2019-05-30 00:46:45 -04:00
};
2019-05-02 17:12:06 -04:00
fadeOutAndLeaveFast = () => this.setState({ displayComponent: false });
2019-05-02 17:12:06 -04:00
clearFadeOutTimer = () => {
if (!this.fadeOutTimer) {
2019-05-30 00:46:45 -04:00
return;
2019-05-02 17:12:06 -04:00
}
2019-05-30 00:46:45 -04:00
clearTimeout(this.fadeOutTimer);
};
2019-05-02 17:12:06 -04:00
}
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;