diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js index 99d573cdd..11e21e9f1 100644 --- a/platform/ui/src/components/index.js +++ b/platform/ui/src/components/index.js @@ -16,6 +16,7 @@ import { QuickSwitch } from './quickSwitch'; import { RoundedButtonGroup } from './roundedButtonGroup'; import { SelectTree } from './selectTree'; import { SimpleDialog } from './simpleDialog'; +import { OHIFModal } from './ohifModal'; import { PageToolbar, StudyList, @@ -52,4 +53,5 @@ export { AboutModal, UserPreferences, UserPreferencesModal, + OHIFModal, }; diff --git a/platform/ui/src/components/ohifModal/OHIFModal.js b/platform/ui/src/components/ohifModal/OHIFModal.js new file mode 100644 index 000000000..f69c9376e --- /dev/null +++ b/platform/ui/src/components/ohifModal/OHIFModal.js @@ -0,0 +1,60 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ReactBootstrapModal from 'react-bootstrap-modal'; +import classNames from 'classnames'; + +const OHIFModal = ({ + className, + closeButton, + backdrop, + keyboard, + show, + title, + onHide, + footer: Footer, + header: Header, + children: Component, +}) => ( + + {(Header || title) && ( + + {title && ( + {title} + )} + {Header && } + + )} + + {Component && } + + {Footer && ( + + {' '} + + + )} + +); + +OHIFModal.propTypes = { + className: PropTypes.string, + closeButton: PropTypes.bool, + backdrop: PropTypes.bool, + keyboard: PropTypes.bool, + show: PropTypes.bool, + title: PropTypes.string, + onHide: PropTypes.func, + footer: PropTypes.node, + header: PropTypes.node, + children: PropTypes.node, +}; + +export default OHIFModal; diff --git a/platform/ui/src/components/ohifModal/__docs__/ohifModal.mdx b/platform/ui/src/components/ohifModal/__docs__/ohifModal.mdx new file mode 100644 index 000000000..67bb3f054 --- /dev/null +++ b/platform/ui/src/components/ohifModal/__docs__/ohifModal.mdx @@ -0,0 +1,39 @@ +--- +name: OHIFModal +menu: Components +route: /components/ohif-modal +--- + +import { Playground, Props } from 'docz' +import { State } from 'react-powerplug' +import { OHIFModal } from './../index' +import NameSpace from '../../../__docs__/NameSpace' + +# OHIF Modal + +## Basic usage + + + + {({ state, setState }) => ( + + + {JSON.stringify(state, null, 2)} + + + + + + )} + + + +## API + + + +## Translation Namespace + + diff --git a/platform/ui/src/components/ohifModal/index.js b/platform/ui/src/components/ohifModal/index.js new file mode 100644 index 000000000..6e9820766 --- /dev/null +++ b/platform/ui/src/components/ohifModal/index.js @@ -0,0 +1,2 @@ +import OHIFModal from './OHIFModal'; +export { OHIFModal }; diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js index 1588da218..abb960d0e 100644 --- a/platform/ui/src/index.js +++ b/platform/ui/src/index.js @@ -25,6 +25,7 @@ import { AboutModal, UserPreferences, UserPreferencesModal, + OHIFModal, } from './components'; import { useDebounce, useMedia } from './hooks'; @@ -52,6 +53,11 @@ import SnackbarProvider, { useSnackbarContext, withSnackbar, } from './utils/SnackbarProvider'; +import ModalProvider, { + useModal, + withModal, + ModalConsumer, +} from './utils/ModalProvider'; export { // Elements @@ -100,6 +106,11 @@ export { SnackbarProvider, useSnackbarContext, withSnackbar, + ModalProvider, + useModal, + ModalConsumer, + withModal, + OHIFModal, // Hooks useDebounce, useMedia, diff --git a/platform/ui/src/utils/ModalProvider.js b/platform/ui/src/utils/ModalProvider.js new file mode 100644 index 000000000..c1734cfb1 --- /dev/null +++ b/platform/ui/src/utils/ModalProvider.js @@ -0,0 +1,83 @@ +import React, { useState, createContext, useContext } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +const ModalContext = createContext(null); +const { Provider, Consumer } = ModalContext; + +export const useModal = () => useContext(ModalContext); + +const ModalProvider = ({ children, modal: Modal }) => { + const DEFAULT_OPTIONS = { + component: null /* The component instance inside the modal. */, + 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. */, + closeButton: true /* Should the modal body render the close button. */, + title: null /* Should the modal render the title independently of the body content. */, + customClassName: null /* The custom class to style the modal. */, + }; + + const [options, setOptions] = useState(DEFAULT_OPTIONS); + + /** + * Show the modal and override its configuration props. + * + * @returns void + */ + const show = (component, props = {}) => + setOptions(Object.assign({}, options, props, { component })); + + /** + * Hide the modal and set its properties to default. + * + * @returns void + */ + const hide = () => setOptions(DEFAULT_OPTIONS); + + return ( + + + {props => { + const { component, footer, header, customClassName } = props; + return component ? ( + + {component} + + ) : null; + }} + + {children} + + ); +}; + +ModalProvider.propTypes = { + children: PropTypes.node, + modal: PropTypes.node, +}; + +/** + * Higher Order Component to use the modal methods through a Class Component. + * + * @returns + */ +export const withModal = Component => { + return function WrappedComponent(props) { + return ; + }; +}; + +export default ModalProvider; + +export const ModalConsumer = ModalContext.Consumer; diff --git a/platform/viewer/src/App.js b/platform/viewer/src/App.js index e42d2bb35..1526009a9 100644 --- a/platform/viewer/src/App.js +++ b/platform/viewer/src/App.js @@ -28,7 +28,7 @@ import { BrowserRouter as Router } from 'react-router-dom'; import { getActiveContexts } from './store/layout/selectors.js'; import i18n from '@ohif/i18n'; import store from './store'; -import { SnackbarProvider } from '@ohif/ui'; +import { SnackbarProvider, ModalProvider, OHIFModal } from '@ohif/ui'; // Contexts import WhiteLabellingContext from './context/WhiteLabellingContext'; @@ -85,6 +85,7 @@ class App extends Component { } render() { + const { whiteLabelling, routerBasename } = this.props; const userManager = this._userManager; const config = { appConfig: this._appConfig, @@ -97,12 +98,12 @@ class App extends Component { - - + + - + + + @@ -118,10 +119,12 @@ class App extends Component { - - + + - + + +
{JSON.stringify(state, null, 2)}