get ViewportDialog to display as a part of machine transition

This commit is contained in:
dannyrb committed 2020-06-05 15:19:09 -04:00
1 parent a4fc5e21b2
commit 00f8d56a4e
14 files changed
+318 -212

No files matched your search

@@ -17,7 +17,8 @@ const publicAPI = {
};
const serviceImplementation = {
_viewports: [],
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
_show: () => console.warn('show() NOT IMPLEMENTED'),
};
/**
@@ -25,39 +26,21 @@ const serviceImplementation = {
*
* @param {ViewportDialogProps} props { content, contentProps, viewportIndex }
*/
function _show({ content = null, contentProps = null, viewportIndex }) {
const viewportIndexImplementation =
(viewportIndex !== undefined &&
serviceImplementation._viewports[viewportIndex]) ||
{};
if (!viewportIndexImplementation._show) {
console.warn('show() NOT IMPLEMENTED');
return;
}
return viewportIndexImplementation._show({
content,
contentProps,
function _show({ viewportIndex, type, message, actions, onSubmit }) {
return serviceImplementation._show({
viewportIndex,
type,
message,
actions,
onSubmit,
});
}
/**
* Hides/dismisses the viewport dialog, if currently shown
*
* @param {*} { viewportIndex }
*/
function _hide({ viewportIndex }) {
const viewportIndexImplementation =
(viewportIndex && serviceImplementation._viewports[viewportIndex]) || {};
if (!viewportIndexImplementation._hide) {
console.warn('hide() NOT IMPLEMENTED');
return;
}
return viewportIndexImplementation._hide();
function _hide() {
return serviceImplementation._hide();
}
/**
@@ -72,22 +55,12 @@ function _hide({ viewportIndex }) {
function setServiceImplementation({
hide: hideImplementation,
show: showImplementation,
viewportIndex,
}) {
if (viewportIndex !== undefined) {
const newImplementations = {};
if (hideImplementation) {
newImplementations._hide = hideImplementation;
}
if (showImplementation) {
newImplementations._show = showImplementation;
}
serviceImplementation._viewports[viewportIndex] = Object.assign(
{},
serviceImplementation._viewports[viewportIndex],
newImplementations
);
if (hideImplementation) {
serviceImplementation._hide = hideImplementation;
}
if (showImplementation) {
serviceImplementation._show = showImplementation;
}
}
@@ -1,9 +1,9 @@
import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { Icon } from '@ohif/ui';
import { Button, Icon } from '@ohif/ui';
const Notification = ({ type, text, actionButtons }) => {
const Notification = ({ type, message, actions, onSubmit }) => {
const iconsByType = {
error: {
icon: 'info',
@@ -35,12 +35,30 @@ const Notification = ({ type, text, actionButtons }) => {
const { icon, color } = getIconData();
return (
<div className="mx-2 mt-2 p-2 flex flex-col bg-common-bright rounded">
<div className="flex flex-col p-2 mx-2 mt-2 rounded bg-common-bright">
<div className="flex flex-grow">
<Icon name={icon} className={classnames('w-5', color)} />
<span className="text-base text-black ml-2">{text}</span>
<span className="ml-2 text-base text-black">{message}</span>
</div>
<div className="flex justify-end mt-2">
{actions.map((action, index) => {
const isFirst = index === 0;
const isPrimary = action.type === 'primary';
return (
<Button
key={index}
className={classnames({ 'ml-2': !isFirst })}
color={isPrimary ? 'primary' : undefined}
onClick={() => {
onSubmit(action.value);
}}
>
{action.text}
</Button>
);
})}
</div>
<div className="flex justify-end mt-2">{actionButtons}</div>
</div>
);
};
@@ -51,8 +69,15 @@ Notification.defaultProps = {
Notification.propTypes = {
type: PropTypes.string,
text: PropTypes.string.isRequired,
actionButtons: PropTypes.node.isRequired,
message: PropTypes.string.isRequired,
actions: PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.string.isRequired,
value: PropTypes.any.isRequired,
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired,
})
).isRequired,
onSubmit: PropTypes.func.isRequired,
};
export default Notification;
@@ -5,7 +5,7 @@ route: components/notification
---
import { Playground, Props } from 'docz';
import { Notification, Button } from '@ohif/ui';
import { Notification } from '@ohif/ui';
# Notification
@@ -22,23 +22,31 @@ import { Notification } from '@ohif/ui';
<Playground>
{() => {
const actionButtons = () => {
return (
<div>
<Button>No</Button>
<Button className="ml-2">No, do not ask again</Button>
<Button className="ml-2" color="primary">
Yes
</Button>
</div>
);
};
return (
<div className="p-4 w-full lg:w-2/3">
<Notification
text="Track all measurement for this series?"
message="Track all measurement for this series?"
type="info"
actionButtons={actionButtons()}
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
window.alert(value);
}}
/>
</div>
);
@@ -4,7 +4,7 @@ import { ViewportActionBar, Notification, Button } from '@ohif/ui';
const Viewport = ({ viewportIndex, onSeriesChange, studyData, children }) => {
return (
<div className="flex flex-col h-full relative">
<div className="relative flex flex-col h-full">
<div className="absolute top-0 left-0 w-full">
<ViewportActionBar
onSeriesChange={onSeriesChange}
@@ -13,17 +13,28 @@ const Viewport = ({ viewportIndex, onSeriesChange, studyData, children }) => {
{/* TODO: NOTIFICATION API DEFINITION - OHIF-112 */}
<Notification
text="Track all measurement for this series?"
message="Track all measurement for this series?"
type="info"
actionButtons={
<div>
<Button>No</Button>
<Button className="ml-2">No, do not ask again</Button>
<Button className="ml-2" color="primary">
Yes
</Button>
</div>
}
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => {
window.alert(value);
}}
/>
</div>
@@ -7,10 +7,20 @@ import React, {
} from 'react';
import PropTypes from 'prop-types';
const DEFAULT_OPTIONS = {
content: null,
contentProps: null,
customClassName: null,
const DEFAULT_STATE = {
viewportIndex: null,
message: undefined,
type: 'info', // "error" | "warning" | "info" | "success"
actions: undefined, // array of { type, text, value }
// dismissable?
// blockInteraction (single viewport? allViewports? everything?)
// TODO: Buttons --> type/color? text? value?
onSubmit: () => {
console.log('btn value?');
},
onDismiss: () => {
console.log('dismiss? -1');
},
};
const ViewportDialogContext = createContext(null);
@@ -18,42 +28,26 @@ const { Provider } = ViewportDialogContext;
export const useViewportDialog = () => useContext(ViewportDialogContext);
const ViewportDialogProvider = ({
children,
dialog: Dialog,
service,
viewportIndex,
}) => {
const [options, setOptions] = useState(DEFAULT_OPTIONS);
const show = useCallback((props) => setOptions({ ...options, ...props }), [
options,
]);
const hide = useCallback(() => setOptions(DEFAULT_OPTIONS), []);
const ViewportDialogProvider = ({ children, service }) => {
const [viewportDialogState, setViewportDialogState] = useState(DEFAULT_STATE);
const show = useCallback(
params => setViewportDialogState({ ...viewportDialogState, ...params }),
[viewportDialogState]
);
const hide = useCallback(() => setViewportDialogState(DEFAULT_STATE), []);
useEffect(() => {
if (service) {
service.setServiceImplementation({ hide, show, viewportIndex });
service.setServiceImplementation({
hide,
show,
});
}
}, [hide, service, show, viewportIndex]);
const {
content: ViewportDialogContent,
contentProps,
customClassName,
} = options;
}, [hide, service, show]);
return (
<Provider value={{ show, hide }}>
<div className="relative w-full h-full">
{ViewportDialogContent && (
<Dialog className={customClassName}>
<ViewportDialogContent {...contentProps} show={show} hide={hide} />
</Dialog>
)}
{children}
</div>
<Provider value={[viewportDialogState, { show, hide }]}>
{children}
</Provider>
);
};
@@ -64,16 +58,9 @@ ViewportDialogProvider.propTypes = {
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]).isRequired,
/** dialog component */
dialog: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
PropTypes.func,
]).isRequired,
service: PropTypes.shape({
setServiceImplementation: PropTypes.func,
}),
viewportIndex: PropTypes.number,
};
export default ViewportDialogProvider;
@@ -28,19 +28,26 @@ component across all application.
const ViewportNotification = ({ hide }) => {
return (
<Notification
text="Track all measurement for this series?"
message="Track all measurement for this series?"
type="info"
actionButtons={
<div>
<Button onClick={hide}>No</Button>
<Button onClick={hide} className="ml-2">
No, do not ask again
</Button>
<Button onClick={hide} className="ml-2" color="primary">
Yes
</Button>
</div>
}
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => { window.alert(value); }}
/>
);
};
@@ -88,17 +95,26 @@ component across all application.
const ViewportNotification = ({ hide }) => {
return (
<Notification
text="Track all measurement for this series?"
message="Track all measurement for this series?"
type="info"
actionButtons={
<div>
<Button onClick={hide}>No</Button>
<Button className="ml-2">No, do not ask again</Button>
<Button className="ml-2" color="primary">
Yes
</Button>
</div>
}
actions={[
{
type: 'cancel',
text: 'No',
value: 0,
},
{
type: 'secondary',
text: 'No, do not ask again',
value: -1,
},
{
type: 'primary',
text: 'Yes',
value: 1,
},
]}
onSubmit={value => { window.alert(value); }}
/>
);
};
+17 -8
View File
@@ -6,8 +6,10 @@ import {
DialogProvider,
Modal,
ModalProvider,
Notification,
SnackbarProvider,
ThemeWrapper,
ViewportDialogProvider,
ViewportGridProvider,
} from '@ohif/ui';
// Viewer Project
@@ -48,7 +50,12 @@ function App({ config, defaultExtensions }) {
extensionManager,
servicesManager
);
const { UIDialogService, UIModalService, UINotificationService } = servicesManager.services;
const {
UIDialogService,
UIModalService,
UINotificationService,
UIViewportDialogService,
} = servicesManager.services;
// A UI Service may need to use the ViewportGrid context
const viewportGridReducer = (state, action) => {
@@ -82,13 +89,15 @@ function App({ config, defaultExtensions }) {
}}
reducer={viewportGridReducer}
>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider modal={Modal} service={UIModalService}>
{appRoutes}
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
<ViewportDialogProvider service={UIViewportDialogService}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider modal={Modal} service={UIModalService}>
{appRoutes}
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</ViewportDialogProvider>
</ViewportGridProvider>
</ThemeWrapper>
</Router>
+2
View File
@@ -6,6 +6,7 @@ import {
UINotificationService,
UIModalService,
UIDialogService,
UIViewportDialogService,
MeasurementService,
DisplaySetService,
ToolBarSerivce,
@@ -44,6 +45,7 @@ function appInit(appConfigOrFunc, defaultExtensions) {
UINotificationService,
UIModalService,
UIDialogService,
UIViewportDialogService,
MeasurementService,
DisplaySetService,
ToolBarSerivce,