feat: New dialog service (#1202)

* Add dialog provider boilerplate and improve provider imports

* Add react-draggable dependency

* Add dialog service boilerplate

* Refactor modal to use react-modal and remove dependency on modal themed styles

* Update cinedialog to use new dialog provider

* Add multiple dialogs and refactor provider (dialogs)

* Set app root (modal)

* Add modal zindex bigger than tooltip

* Block drag on buttons/svgs/paths/input and improve jsdoc

* Use guid util to generate dialog ids

* Explicit props in dialog provider

* Improve jsdocs

* Fix tests broken

* Fix boundaries calculation

* Remember last dialog position

* Update providers location

* Add scroll to modal

* Add toggable button toolbar and fix css modal
This commit is contained in:
Igor Octaviano authored and Danny Brown committed 2019-11-19 14:17:33 -05:00
1 parent cdd75bda2a
commit f65639c2b0
39 files changed
+741 -193

No files matched your search

@@ -7,6 +7,7 @@ import {
RoundedButtonGroup,
ToolbarButton,
withModal,
withDialog,
} from '@ohif/ui';
import './ToolbarRow.css';
@@ -45,7 +46,6 @@ class ToolbarRow extends Component {
this.state = {
toolbarButtons: toolbarButtonDefinitions,
activeButtons: [],
isCineDialogOpen: false,
};
this._handleBuiltIn = _handleBuiltIn.bind(this);
@@ -106,13 +106,6 @@ class ToolbarRow extends Component {
this.state.activeButtons
);
const cineDialogContainerStyle = {
display: this.state.isCineDialogOpen ? 'block' : 'none',
position: 'absolute',
top: '82px',
zIndex: 999,
};
const onPress = (side, value) => {
this.props.handleSidePanelChange(side, value);
};
@@ -145,9 +138,6 @@ class ToolbarRow extends Component {
)}
</div>
</div>
<div className="CineDialogContainer" style={cineDialogContainerStyle}>
<ConnectedCineDialog />
</div>
</>
);
}
@@ -160,7 +150,8 @@ function _getCustomButtonComponent(button, activeButtons) {
// Check if its a valid customComponent. Later on an CustomToolbarComponent interface could be implemented.
if (isValidComponent) {
const parentContext = this;
const isActive = activeButtons.includes(button.id);
const activeButtonsIds = activeButtons.map(button => button.id);
const isActive = activeButtonsIds.includes(button.id);
return (
<CustomComponent
@@ -168,7 +159,7 @@ function _getCustomButtonComponent(button, activeButtons) {
toolbarClickCallback={_handleToolbarButtonClick.bind(this)}
button={button}
key={button.id}
activeButtons={activeButtons}
activeButtons={activeButtonsIds}
isActive={isActive}
/>
);
@@ -181,7 +172,7 @@ function _getExpandableButtonComponent(button, activeButtons) {
const childButtons = button.buttons.map(childButton => {
childButton.onClick = _handleToolbarButtonClick.bind(this, childButton);
if (activeButtons.indexOf(childButton.id) > -1) {
if (activeButtons.map(button => button.id).indexOf(childButton.id) > -1) {
activeCommand = childButton.id;
}
@@ -206,7 +197,7 @@ function _getDefaultButtonComponent(button, activeButtons) {
label={button.label}
icon={button.icon}
onClick={_handleToolbarButtonClick.bind(this, button)}
isActive={activeButtons.includes(button.id)}
isActive={activeButtons.map(button => button.id).includes(button.id)}
/>
);
}
@@ -241,6 +232,8 @@ function _getButtonComponents(toolbarButtons, activeButtons) {
* @param {*} props
*/
function _handleToolbarButtonClick(button, evt, props) {
const { activeButtons } = this.state;
if (button.commandName) {
const options = Object.assign({ evt }, button.commandOptions);
commandsManager.runCommand(button.commandName, options);
@@ -250,11 +243,12 @@ function _handleToolbarButtonClick(button, evt, props) {
// TODO: We can update this to be a `getter` on the extension to query
// For the active tools after we apply our updates?
if (button.type === 'setToolActive') {
this.setState({
activeButtons: [button.id],
});
const toggables = activeButtons.filter(
({ options }) => options && !options.togglable
);
this.setState({ activeButtons: [...toggables, button] });
} else if (button.type === 'builtIn') {
this._handleBuiltIn(button.options);
this._handleBuiltIn(button);
}
}
@@ -279,21 +273,47 @@ function _getVisibleToolbarButtons() {
return toolbarButtonDefinitions;
}
function _handleBuiltIn({ behavior } = {}) {
if (behavior === 'CINE') {
this.setState({
isCineDialogOpen: !this.state.isCineDialogOpen,
});
function _handleBuiltIn(button) {
/* TODO: Keep cine button active until its unselected. */
const { dialog, modal, t } = this.props;
const { dialogId } = this.state;
const { id, options } = button;
if (options.behavior === 'CINE') {
if (dialogId) {
dialog.dismiss({ id: dialogId });
this.setState(state => ({
dialogId: null,
activeButtons: [
...state.activeButtons.filter(button => button.id !== id),
],
}));
} else {
const spacing = 20;
const { x, y } = document
.querySelector(`.ViewerMain`)
.getBoundingClientRect();
const newDialogId = dialog.create({
content: ConnectedCineDialog,
defaultPosition: {
x: x + spacing || 0,
y: y + spacing || 0,
},
});
this.setState(state => ({
dialogId: newDialogId,
activeButtons: [...state.activeButtons, button],
}));
}
}
if (behavior === 'DOWNLOAD_SCREEN_SHOT') {
this.props.modal.show(ConnectedViewportDownloadForm, {
title: this.props.t('Download High Quality Image'),
customClassName: 'ViewportDownloadForm',
if (options.behavior === 'DOWNLOAD_SCREEN_SHOT') {
modal.show(ConnectedViewportDownloadForm, {
title: t('Download High Quality Image'),
});
}
}
export default withTranslation(['Common', 'ViewportDownloadForm'])(
withModal(ToolbarRow)
withModal(withDialog(ToolbarRow))
);