From 9104e7be509b702c8131deffc66223d68656fb0d Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 10:19:33 -0300 Subject: [PATCH 01/11] Add new modal service --- platform/core/src/index.js | 8 +- platform/core/src/index.test.js | 3 +- .../core/src/services/UIModalService/index.js | 89 +++++++++++++++++++ .../services/UINotificationService/index.js | 4 +- platform/core/src/services/index.js | 5 +- platform/ui/src/utils/ModalProvider.js | 28 +++++- platform/ui/src/utils/SnackbarProvider.js | 5 ++ platform/viewer/src/App.js | 15 ++-- 8 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 platform/core/src/services/UIModalService/index.js diff --git a/platform/core/src/index.js b/platform/core/src/index.js index 6cec02db8..cb482e505 100644 --- a/platform/core/src/index.js +++ b/platform/core/src/index.js @@ -19,7 +19,7 @@ import ui from './ui'; import user from './user.js'; import utils from './utils/'; -import { createUiNotificationService } from './services'; +import { createUINotificationService, createUIModalService } from './services'; const OHIF = { MODULE_TYPES, @@ -46,7 +46,8 @@ const OHIF = { measurements, hangingProtocols, // - createUiNotificationService, + createUINotificationService, + createUIModalService, }; export { @@ -73,7 +74,8 @@ export { measurements, hangingProtocols, // - createUiNotificationService, + createUINotificationService, + createUIModalService, }; export { OHIF }; diff --git a/platform/core/src/index.test.js b/platform/core/src/index.test.js index a017a8a39..b06073e12 100644 --- a/platform/core/src/index.test.js +++ b/platform/core/src/index.test.js @@ -10,7 +10,8 @@ describe('Top level exports', () => { 'HotkeysManager', 'ServicesManager', // - 'createUiNotificationService', + 'createUINotificationService', + 'createUIModalService', // 'utils', 'studies', diff --git a/platform/core/src/services/UIModalService/index.js b/platform/core/src/services/UIModalService/index.js new file mode 100644 index 000000000..b8901e013 --- /dev/null +++ b/platform/core/src/services/UIModalService/index.js @@ -0,0 +1,89 @@ +/** + * A UI Element + * + * @typedef {HTMLElement} Modal + */ + +/** + * UI Modal + * + * @typedef {Object} ModalProps + * @property {string} [backdrop=false] - + * @property {string} [keyboard=false] - + * @property {number} [show=true] - + * @property {string} [closeButton=true] - + * @property {string} [title=null] - 'Modal Title' + * @property {boolean} [customClassName=null] - '.ModalClass' + */ + +const uiModalServicePublicApi = { + name: 'UIModalService', + hide, + show, + setServiceImplementation, +}; + +const uiModalServiceImplementation = { + _hide: () => console.warn('hide() NOT IMPLEMENTED'), + _show: () => console.warn('show() NOT IMPLEMENTED'), +}; + +function createUiModalService() { + return uiModalServicePublicApi; +} + +/** + * Show a new UI modal; + * + * @param {Modal} component + * @param {ModalProps} props { backdrop, keyboard, show, closeButton, title, customClassName } + */ +function show(component, props) { + const { + backdrop = false, + keyboard = false, + show = true, + closeButton = true, + title = null, + customClassName = null, + } = props; + return uiModalServiceImplementation._show(component, { + backdrop, + keyboard, + show, + closeButton, + title, + customClassName, + }); +} + +/** + * Hides/dismisses the modal, if currently shown + * + * @returns void + */ +function hide() { + return uiModalServiceImplementation._hide(); +} + +/** + * + * + * @param {*} { + * hide: hideImplementation, + * show: showImplementation, + * } + */ +function setServiceImplementation({ + hide: hideImplementation, + show: showImplementation, +}) { + if (hideImplementation) { + uiModalServiceImplementation._hide = hideImplementation; + } + if (showImplementation) { + uiModalServiceImplementation._show = showImplementation; + } +} + +export default createUiModalService; diff --git a/platform/core/src/services/UINotificationService/index.js b/platform/core/src/services/UINotificationService/index.js index 97db61040..86e6e1f56 100644 --- a/platform/core/src/services/UINotificationService/index.js +++ b/platform/core/src/services/UINotificationService/index.js @@ -22,7 +22,7 @@ const uiNotificationServiceImplementation = { _show: () => console.warn('show() NOT IMPLEMENTED'), }; -function createUiNotificationService() { +function createUINotificationService() { return uiNotificationServicePublicApi; } @@ -81,4 +81,4 @@ function setServiceImplementation({ } } -export default createUiNotificationService; +export default createUINotificationService; diff --git a/platform/core/src/services/index.js b/platform/core/src/services/index.js index ded69e822..033dee202 100644 --- a/platform/core/src/services/index.js +++ b/platform/core/src/services/index.js @@ -1,4 +1,5 @@ import ServicesManager from './ServicesManager.js'; -import createUiNotificationService from './UINotificationService'; +import createUINotificationService from './UINotificationService'; +import createUIModalService from './UIModalService'; -export { createUiNotificationService, ServicesManager }; +export { createUINotificationService, createUIModalService, ServicesManager }; diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index c1734cfb1..cbf07c220 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -1,4 +1,10 @@ -import React, { useState, createContext, useContext } from 'react'; +import React, { + useState, + createContext, + useContext, + useCallback, + useEffect, +} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; @@ -7,7 +13,7 @@ const { Provider, Consumer } = ModalContext; export const useModal = () => useContext(ModalContext); -const ModalProvider = ({ children, modal: Modal }) => { +const ModalProvider = ({ children, modal: Modal, service }) => { const DEFAULT_OPTIONS = { component: null /* The component instance inside the modal. */, backdrop: false /* Should the modal render a backdrop overlay. */, @@ -20,20 +26,31 @@ const ModalProvider = ({ children, modal: Modal }) => { const [options, setOptions] = useState(DEFAULT_OPTIONS); + /** + * Sets the implementation of a modal service that can be used by extensions. + * + * @returns void + */ + useEffect(() => { + service.setServiceImplementation({ hide, show }); + }, [hide, service, show]); + /** * Show the modal and override its configuration props. * * @returns void */ - const show = (component, props = {}) => + const show = useCallback((component, props = {}) => { setOptions(Object.assign({}, options, props, { component })); + console.log(component, props); + }); /** * Hide the modal and set its properties to default. * * @returns void */ - const hide = () => setOptions(DEFAULT_OPTIONS); + const hide = useCallback(() => setOptions(DEFAULT_OPTIONS)); return ( @@ -65,6 +82,9 @@ const ModalProvider = ({ children, modal: Modal }) => { ModalProvider.propTypes = { children: PropTypes.node, modal: PropTypes.node, + service: PropTypes.shape({ + setServiceImplementation: PropTypes.func, + }), }; /** diff --git a/platform/ui/src/utils/SnackbarProvider.js b/platform/ui/src/utils/SnackbarProvider.js index 4151aec53..ed603003c 100644 --- a/platform/ui/src/utils/SnackbarProvider.js +++ b/platform/ui/src/utils/SnackbarProvider.js @@ -25,6 +25,11 @@ const SnackbarProvider = ({ children, service }) => { const [count, setCount] = useState(1); const [snackbarItems, setSnackbarItems] = useState([]); + /** + * Sets the implementation of a notification service that can be used by extensions. + * + * @returns void + */ useEffect(() => { service.setServiceImplementation({ hide, show }); }, [service, hide, show]); diff --git a/platform/viewer/src/App.js b/platform/viewer/src/App.js index 862a2c2ba..c496b5428 100644 --- a/platform/viewer/src/App.js +++ b/platform/viewer/src/App.js @@ -8,7 +8,8 @@ import { ExtensionManager, ServicesManager, HotkeysManager, - createUiNotificationService, + createUINotificationService, + createUIModalService, utils, } from '@ohif/core'; import React, { Component } from 'react'; @@ -44,7 +45,8 @@ const commandsManagerConfig = { }; // Services -const UINotificationService = createUiNotificationService(); +const UINotificationService = createUINotificationService(); +const UIModalService = createUIModalService(); const commandsManager = new CommandsManager(commandsManagerConfig); const hotkeysManager = new HotkeysManager(commandsManager); @@ -89,7 +91,7 @@ class App extends Component { const { servers, extensions, hotkeys, oidc } = props; this.initUserManager(oidc); - _initServices([UINotificationService]); + _initServices([UINotificationService, UIModalService]); _initExtensions(extensions, hotkeys); _initServers(servers); initWebWorkers(); @@ -112,7 +114,10 @@ class App extends Component { - + @@ -133,7 +138,7 @@ class App extends Component { - + From e6845587837378058b3d80ff1146dd7e190fbbc4 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 10:32:24 -0300 Subject: [PATCH 02/11] Change serviceManager prop to servicesManager --- extensions/_example/src/index.js | 5 ++++- extensions/cornerstone/src/index.js | 4 ++-- extensions/cornerstone/src/init.js | 2 +- platform/viewer/src/appExtensions/MeasurementsPanel/index.js | 4 ++-- platform/viewer/src/appExtensions/MeasurementsPanel/init.js | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/extensions/_example/src/index.js b/extensions/_example/src/index.js index 6d1e82bac..c061a44af 100644 --- a/extensions/_example/src/index.js +++ b/extensions/_example/src/index.js @@ -11,7 +11,10 @@ export default { * LIFECYCLE HOOKS */ - preRegistration({ serviceManager, configuration: extensionConfiguration }) {}, + preRegistration({ + servicesManager, + configuration: extensionConfiguration, + }) {}, /** * MODULE GETTERS diff --git a/extensions/cornerstone/src/index.js b/extensions/cornerstone/src/index.js index 5451f4041..6470382c9 100644 --- a/extensions/cornerstone/src/index.js +++ b/extensions/cornerstone/src/index.js @@ -24,8 +24,8 @@ export default { * @param {object} [configuration={}] * @param {object|array} [configuration.csToolsConfig] - Passed directly to `initCornerstoneTools` */ - preRegistration({ serviceManager, configuration = {} }) { - init({ serviceManager, configuration }); + preRegistration({ servicesManager, configuration = {} }) { + init({ servicesManager, configuration }); }, getViewportModule() { return OHIFCornerstoneViewport; diff --git a/extensions/cornerstone/src/init.js b/extensions/cornerstone/src/init.js index 0795e2034..aee850564 100644 --- a/extensions/cornerstone/src/init.js +++ b/extensions/cornerstone/src/init.js @@ -28,7 +28,7 @@ cornerstone.metaData.addProvider(fallbackMetaDataProvider, -1); * @param {object} configuration * @param {Object|Array} configuration.csToolsConfig */ -export default function init({ serviceManager, configuration = {} }) { +export default function init({ servicesManager, configuration = {} }) { const { csToolsConfig } = configuration; const { StackManager } = OHIF.utils; const metadataProvider = new OHIF.cornerstone.MetadataProvider(); diff --git a/platform/viewer/src/appExtensions/MeasurementsPanel/index.js b/platform/viewer/src/appExtensions/MeasurementsPanel/index.js index 52a89b961..3ce151015 100644 --- a/platform/viewer/src/appExtensions/MeasurementsPanel/index.js +++ b/platform/viewer/src/appExtensions/MeasurementsPanel/index.js @@ -7,8 +7,8 @@ export default { */ id: 'measurements-table', - preRegistration({ serviceManager, configuration = {} }) { - init({ serviceManager, configuration }); + preRegistration({ servicesManager, configuration = {} }) { + init({ servicesManager, configuration }); }, getPanelModule() { return { diff --git a/platform/viewer/src/appExtensions/MeasurementsPanel/init.js b/platform/viewer/src/appExtensions/MeasurementsPanel/init.js index e957c6d28..0b1067ee0 100644 --- a/platform/viewer/src/appExtensions/MeasurementsPanel/init.js +++ b/platform/viewer/src/appExtensions/MeasurementsPanel/init.js @@ -34,7 +34,7 @@ const MEASUREMENT_ACTION_MAP = { * @export * @param {*} configuration */ -export default function init({ serviceManager, configuration = {} }) { +export default function init({ servicesManager, configuration = {} }) { // If these tools were already added by a different extension, we want to replace // them with the same tools that have an alternative configuration. By passing in // our custom `getMeasurementLocationCallback`, we can... From 95c18b498616322acaf5277ce3a13bcbfccee43a Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 11:16:35 -0300 Subject: [PATCH 03/11] CR Update: fix casing and add required proptypes to providers --- platform/core/src/services/UIModalService/index.js | 12 ++++++------ .../core/src/services/UINotificationService/index.js | 4 ++-- platform/ui/src/utils/ModalProvider.js | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/platform/core/src/services/UIModalService/index.js b/platform/core/src/services/UIModalService/index.js index b8901e013..1909804dd 100644 --- a/platform/core/src/services/UIModalService/index.js +++ b/platform/core/src/services/UIModalService/index.js @@ -1,7 +1,7 @@ /** * A UI Element * - * @typedef {HTMLElement} Modal + * @typedef {ReactElement|HTMLElement} Modal */ /** @@ -16,7 +16,7 @@ * @property {boolean} [customClassName=null] - '.ModalClass' */ -const uiModalServicePublicApi = { +const uiModalServicePublicAPI = { name: 'UIModalService', hide, show, @@ -28,14 +28,14 @@ const uiModalServiceImplementation = { _show: () => console.warn('show() NOT IMPLEMENTED'), }; -function createUiModalService() { - return uiModalServicePublicApi; +function createUIModalService() { + return uiModalServicePublicAPI; } /** * Show a new UI modal; * - * @param {Modal} component + * @param {Modal} component React component * @param {ModalProps} props { backdrop, keyboard, show, closeButton, title, customClassName } */ function show(component, props) { @@ -86,4 +86,4 @@ function setServiceImplementation({ } } -export default createUiModalService; +export default createUIModalService; diff --git a/platform/core/src/services/UINotificationService/index.js b/platform/core/src/services/UINotificationService/index.js index 86e6e1f56..7538a6280 100644 --- a/platform/core/src/services/UINotificationService/index.js +++ b/platform/core/src/services/UINotificationService/index.js @@ -10,7 +10,7 @@ * @property {boolean} [autoClose=true] */ -const uiNotificationServicePublicApi = { +const uiNotificationServicePublicAPI = { name: 'UINotificationService', hide, show, @@ -23,7 +23,7 @@ const uiNotificationServiceImplementation = { }; function createUINotificationService() { - return uiNotificationServicePublicApi; + return uiNotificationServicePublicAPI; } /** diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index cbf07c220..2f66692e9 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -80,11 +80,11 @@ const ModalProvider = ({ children, modal: Modal, service }) => { }; ModalProvider.propTypes = { - children: PropTypes.node, - modal: PropTypes.node, + children: PropTypes.node.isRequired, + modal: PropTypes.node.isRequired, service: PropTypes.shape({ setServiceImplementation: PropTypes.func, - }), + }).isRequired, }; /** From 08fdb10f6d128ee970803f6a46511a568d703409 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 11:42:25 -0300 Subject: [PATCH 04/11] CR Update: Improve ohifmodal proptypes --- .../ui/src/components/ohifModal/OHIFModal.js | 7 ++++++- platform/ui/src/utils/ModalProvider.js | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/platform/ui/src/components/ohifModal/OHIFModal.js b/platform/ui/src/components/ohifModal/OHIFModal.js index f69c9376e..caad4ec08 100644 --- a/platform/ui/src/components/ohifModal/OHIFModal.js +++ b/platform/ui/src/components/ohifModal/OHIFModal.js @@ -54,7 +54,12 @@ OHIFModal.propTypes = { onHide: PropTypes.func, footer: PropTypes.node, header: PropTypes.node, - children: PropTypes.node, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + PropTypes.object, + PropTypes.func, + ]).isRequired, }; export default OHIFModal; diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index 2f66692e9..0378faa75 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -40,10 +40,9 @@ const ModalProvider = ({ children, modal: Modal, service }) => { * * @returns void */ - const show = useCallback((component, props = {}) => { - setOptions(Object.assign({}, options, props, { component })); - console.log(component, props); - }); + const show = useCallback((component, props = {}) => + setOptions(Object.assign({}, options, props, { component })) + ); /** * Hide the modal and set its properties to default. @@ -80,8 +79,16 @@ const ModalProvider = ({ children, modal: Modal, service }) => { }; ModalProvider.propTypes = { - children: PropTypes.node.isRequired, - modal: PropTypes.node.isRequired, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + PropTypes.func, + ]).isRequired, + modal: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + PropTypes.func, + ]).isRequired, service: PropTypes.shape({ setServiceImplementation: PropTypes.func, }).isRequired, From db0f751a68203d7763cb843b0526217c14fd7660 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 11:50:37 -0300 Subject: [PATCH 05/11] CR Update: Fix typo in extensionmanager --- platform/core/src/extensions/ExtensionManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core/src/extensions/ExtensionManager.js b/platform/core/src/extensions/ExtensionManager.js index ddb702485..a6ceb7c36 100644 --- a/platform/core/src/extensions/ExtensionManager.js +++ b/platform/core/src/extensions/ExtensionManager.js @@ -68,7 +68,7 @@ export default class ExtensionManager { // preRegistrationHook if (extension.preRegistration) { extension.preRegistration({ - serviceManager: this._servicesManager, + servicesManager: this._servicesManager, configuration, }); } From bdb9af5c4bc8163b63cabdcea9b5416cf0063d99 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 12:43:25 -0300 Subject: [PATCH 06/11] CR Update: add default props to service and check service in provider --- platform/ui/src/utils/ModalProvider.js | 10 ++++++++-- platform/ui/src/utils/SnackbarProvider.js | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index 0378faa75..13185dae2 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -32,7 +32,9 @@ const ModalProvider = ({ children, modal: Modal, service }) => { * @returns void */ useEffect(() => { - service.setServiceImplementation({ hide, show }); + if (service) { + service.setServiceImplementation({ hide, show }); + } }, [hide, service, show]); /** @@ -78,6 +80,10 @@ const ModalProvider = ({ children, modal: Modal, service }) => { ); }; +ModalProvider.defaultProps = { + service: null, +}; + ModalProvider.propTypes = { children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), @@ -91,7 +97,7 @@ ModalProvider.propTypes = { ]).isRequired, service: PropTypes.shape({ setServiceImplementation: PropTypes.func, - }).isRequired, + }), }; /** diff --git a/platform/ui/src/utils/SnackbarProvider.js b/platform/ui/src/utils/SnackbarProvider.js index ed603003c..2ce39dc37 100644 --- a/platform/ui/src/utils/SnackbarProvider.js +++ b/platform/ui/src/utils/SnackbarProvider.js @@ -5,6 +5,8 @@ import React, { useCallback, useEffect, } from 'react'; +import PropTypes from 'prop-types'; + import SnackbarContainer from '../components/snackbar/SnackbarContainer'; import SnackbarTypes from '../components/snackbar/SnackbarTypes'; @@ -31,7 +33,9 @@ const SnackbarProvider = ({ children, service }) => { * @returns void */ useEffect(() => { - service.setServiceImplementation({ hide, show }); + if (service) { + service.setServiceImplementation({ hide, show }); + } }, [service, hide, show]); const show = useCallback(options => { @@ -100,6 +104,21 @@ const SnackbarProvider = ({ children, service }) => { ); }; +SnackbarProvider.defaultProps = { + service: null, +}; + +SnackbarProvider.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + PropTypes.func, + ]).isRequired, + service: PropTypes.shape({ + setServiceImplementation: PropTypes.func, + }), +}; + /** * * High Order Component to use the snackbar methods through a Class Component From fe687cd2f908433288bc8a176538565650dd448b Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 14:56:01 -0300 Subject: [PATCH 07/11] Refactor modal provider to better use its own state --- .../core/src/services/UIModalService/index.js | 8 ++- platform/ui/src/utils/ModalProvider.js | 56 ++++++++------- platform/ui/src/utils/SnackbarProvider.js | 68 ++++++++++--------- 3 files changed, 74 insertions(+), 58 deletions(-) diff --git a/platform/core/src/services/UIModalService/index.js b/platform/core/src/services/UIModalService/index.js index 1909804dd..ce809055e 100644 --- a/platform/core/src/services/UIModalService/index.js +++ b/platform/core/src/services/UIModalService/index.js @@ -8,6 +8,8 @@ * UI Modal * * @typedef {Object} ModalProps + * @property {string} [header=null] - + * @property {string} [footer=null] - * @property {string} [backdrop=false] - * @property {string} [keyboard=false] - * @property {number} [show=true] - @@ -36,10 +38,12 @@ function createUIModalService() { * Show a new UI modal; * * @param {Modal} component React component - * @param {ModalProps} props { backdrop, keyboard, show, closeButton, title, customClassName } + * @param {ModalProps} props { header, footer, backdrop, keyboard, show, closeButton, title, customClassName } */ function show(component, props) { const { + header = null, + footer = null, backdrop = false, keyboard = false, show = true, @@ -48,6 +52,8 @@ function show(component, props) { customClassName = null, } = props; return uiModalServiceImplementation._show(component, { + header, + footer, backdrop, keyboard, show, diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index 13185dae2..4ef1c4bf4 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -2,20 +2,22 @@ import React, { useState, createContext, useContext, - useCallback, useEffect, + useCallback, } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; const ModalContext = createContext(null); -const { Provider, Consumer } = ModalContext; +const { Provider } = ModalContext; export const useModal = () => useContext(ModalContext); const ModalProvider = ({ children, modal: Modal, service }) => { const DEFAULT_OPTIONS = { component: null /* The component instance inside the modal. */, + header: null /* The content inside the modal header. */, + footer: null /* The content inside the modal footer. */, backdrop: false /* Should the modal render a backdrop overlay. */, keyboard: false /* Modal is dismissible via the esc key. */, show: true /* Make the Modal visible or hidden. */, @@ -42,8 +44,10 @@ const ModalProvider = ({ children, modal: Modal, service }) => { * * @returns void */ - const show = useCallback((component, props = {}) => - setOptions(Object.assign({}, options, props, { component })) + const show = useCallback( + (component, props = {}) => + setOptions(Object.assign({}, options, props, { component })), + [options] ); /** @@ -51,30 +55,30 @@ const ModalProvider = ({ children, modal: Modal, service }) => { * * @returns void */ - const hide = useCallback(() => setOptions(DEFAULT_OPTIONS)); + const hide = useCallback(() => setOptions(DEFAULT_OPTIONS), [ + DEFAULT_OPTIONS, + ]); return ( - - - {props => { - const { component, footer, header, customClassName } = props; - return component ? ( - - {component} - - ) : null; - }} - + + {options.component && ( + + {options.component} + + )} {children} ); diff --git a/platform/ui/src/utils/SnackbarProvider.js b/platform/ui/src/utils/SnackbarProvider.js index 2ce39dc37..cd8f3b1e0 100644 --- a/platform/ui/src/utils/SnackbarProvider.js +++ b/platform/ui/src/utils/SnackbarProvider.js @@ -38,45 +38,51 @@ const SnackbarProvider = ({ children, service }) => { } }, [service, hide, show]); - const show = useCallback(options => { - if (!options || (!options.title && !options.message)) { - console.warn( - 'Snackbar cannot be rendered without required parameters: title | message' - ); + const show = useCallback( + options => { + if (!options || (!options.title && !options.message)) { + console.warn( + 'Snackbar cannot be rendered without required parameters: title | message' + ); - return null; - } + return null; + } - const newItem = { - ...DEFAULT_OPTIONS, - ...options, - id: count, - visible: true, - }; + const newItem = { + ...DEFAULT_OPTIONS, + ...options, + id: count, + visible: true, + }; - setSnackbarItems(state => [...state, newItem]); - setCount(count + 1); - }); + setSnackbarItems(state => [...state, newItem]); + setCount(count + 1); + }, + [count, DEFAULT_OPTIONS] + ); - const hide = useCallback(id => { - const hideItem = items => { - const newItems = items.map(item => { - if (item.id === id) { - item.visible = false; - } + const hide = useCallback( + id => { + const hideItem = items => { + const newItems = items.map(item => { + if (item.id === id) { + item.visible = false; + } - return item; - }); + return item; + }); - return newItems; - }; + return newItems; + }; - setSnackbarItems(state => hideItem(state)); + setSnackbarItems(state => hideItem(state)); - setTimeout(() => { - setSnackbarItems(state => [...state.filter(item => item.id !== id)]); - }, 1000); - }); + setTimeout(() => { + setSnackbarItems(state => [...state.filter(item => item.id !== id)]); + }, 1000); + }, + [setSnackbarItems] + ); const hideAll = () => { // reset count From ec7337e8017d07a8cd618d761fa72f85ceaaf9f9 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 17:25:09 -0300 Subject: [PATCH 08/11] Use modal instead of modal context --- platform/ui/src/utils/ModalProvider.js | 3 ++- platform/viewer/src/components/Header/Header.js | 4 ++-- platform/viewer/src/connectedComponents/ToolbarRow.js | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index 4ef1c4bf4..e962b2060 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -111,7 +111,8 @@ ModalProvider.propTypes = { */ export const withModal = Component => { return function WrappedComponent(props) { - return ; + const { show, hide } = useModal(); + return ; }; }; diff --git a/platform/viewer/src/components/Header/Header.js b/platform/viewer/src/components/Header/Header.js index 882c065d5..9da9f401f 100644 --- a/platform/viewer/src/components/Header/Header.js +++ b/platform/viewer/src/components/Header/Header.js @@ -20,7 +20,7 @@ class Header extends Component { t: PropTypes.func.isRequired, userManager: PropTypes.object, user: PropTypes.object, - modalContext: PropTypes.object, + modal: PropTypes.object, }; static defaultProps = { @@ -40,7 +40,7 @@ class Header extends Component { t, user, userManager, - modalContext: { show }, + modal: { show }, } = this.props; this.options = [ { diff --git a/platform/viewer/src/connectedComponents/ToolbarRow.js b/platform/viewer/src/connectedComponents/ToolbarRow.js index fe13d3919..007da4335 100644 --- a/platform/viewer/src/connectedComponents/ToolbarRow.js +++ b/platform/viewer/src/connectedComponents/ToolbarRow.js @@ -287,7 +287,7 @@ function _handleBuiltIn({ behavior } = {}) { } if (behavior === 'DOWNLOAD_SCREEN_SHOT') { - this.props.modalContext.show(ConnectedViewportDownloadForm, { + this.props.modal.show(ConnectedViewportDownloadForm, { title: this.props.t('Download High Quality Image'), customClassName: 'ViewportDownloadForm', }); From e895bfb1aa2257a6d4cc78e2df6f8666b10ce442 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 17:40:37 -0300 Subject: [PATCH 09/11] Change modal children order --- platform/ui/src/components/ohifModal/OHIFModal.js | 8 ++------ platform/ui/src/utils/ModalProvider.js | 5 +++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/platform/ui/src/components/ohifModal/OHIFModal.js b/platform/ui/src/components/ohifModal/OHIFModal.js index caad4ec08..1bdf5e45e 100644 --- a/platform/ui/src/components/ohifModal/OHIFModal.js +++ b/platform/ui/src/components/ohifModal/OHIFModal.js @@ -13,7 +13,7 @@ const OHIFModal = ({ onHide, footer: Footer, header: Header, - children: Component, + children, }) => ( } )} - - {Component && } - + {children} {Footer && ( {' '} @@ -57,8 +55,6 @@ OHIFModal.propTypes = { children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node, - PropTypes.object, - PropTypes.func, ]).isRequired, }; diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js index e962b2060..16eb7ee71 100644 --- a/platform/ui/src/utils/ModalProvider.js +++ b/platform/ui/src/utils/ModalProvider.js @@ -59,6 +59,8 @@ const ModalProvider = ({ children, modal: Modal, service }) => { DEFAULT_OPTIONS, ]); + const { component: Component } = options; + return ( {options.component && ( @@ -76,7 +78,7 @@ const ModalProvider = ({ children, modal: Modal, service }) => { footer={options.footer} header={options.header} > - {options.component} + )} {children} @@ -92,7 +94,6 @@ ModalProvider.propTypes = { children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node, - PropTypes.func, ]).isRequired, modal: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), From b6119f8e29d828694023bf4d479aec75f3c9b3b9 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 14 Nov 2019 17:57:44 -0300 Subject: [PATCH 10/11] Fix OHIFModal proptypes --- platform/ui/src/components/ohifModal/OHIFModal.js | 13 ++++++++++--- platform/ui/src/utils/ModalProvider.js | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/platform/ui/src/components/ohifModal/OHIFModal.js b/platform/ui/src/components/ohifModal/OHIFModal.js index 1bdf5e45e..483c650f9 100644 --- a/platform/ui/src/components/ohifModal/OHIFModal.js +++ b/platform/ui/src/components/ohifModal/OHIFModal.js @@ -35,7 +35,6 @@ const OHIFModal = ({ {children} {Footer && ( - {' '}