get ViewportDialog to display as a part of machine transition
This commit is contained in:
parent
a4fc5e21b2
commit
00f8d56a4e
@ -0,0 +1,81 @@
|
||||
import React, { useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Machine } from 'xstate';
|
||||
import { useMachine } from '@xstate/react';
|
||||
import {
|
||||
machineConfiguration,
|
||||
defaultOptions,
|
||||
} from './measurementTrackingMachine';
|
||||
|
||||
const TrackedMeasurementsContext = React.createContext();
|
||||
TrackedMeasurementsContext.displayName = 'TrackedMeasurementsContext';
|
||||
const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} param0
|
||||
*/
|
||||
function TrackedMeasurementsContextProvider(
|
||||
UIViewportDialogService,
|
||||
{ children }
|
||||
) {
|
||||
function promptUser() {
|
||||
// TODO: ... ActiveViewport? Or Study + Series --> Viewport?
|
||||
// Let's just use zero for meow?
|
||||
return new Promise(function(resolve, reject) {
|
||||
const handleSubmit = result => {
|
||||
UIViewportDialogService.hide();
|
||||
resolve(result);
|
||||
};
|
||||
|
||||
UIViewportDialogService.show({
|
||||
viewportIndex: 0,
|
||||
type: 'info',
|
||||
message: 'Would you like to track?',
|
||||
actions: [
|
||||
{ type: 'cancel', text: 'No', value: 0 },
|
||||
{ type: 'secondary', text: 'No, do not ask again', value: -1 },
|
||||
{ type: 'primary', text: 'Yes', value: 1 },
|
||||
],
|
||||
onSubmit: handleSubmit,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const machOptions = Object.assign({}, defaultOptions);
|
||||
// Merge services
|
||||
machOptions.services = Object.assign({}, machOptions.services, {
|
||||
shouldTrackPrompt: promptUser,
|
||||
});
|
||||
|
||||
console.log(
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
machOptions
|
||||
);
|
||||
|
||||
const measurementTrackingMachine = Machine(machineConfiguration, machOptions);
|
||||
|
||||
const [
|
||||
trackedMeasurements,
|
||||
sendTrackedMeasurementsEvent,
|
||||
trackedMeasurementsService,
|
||||
] = useMachine(measurementTrackingMachine);
|
||||
|
||||
return (
|
||||
<TrackedMeasurementsContext.Provider
|
||||
value={[trackedMeasurements, sendTrackedMeasurementsEvent]}
|
||||
>
|
||||
{children}
|
||||
</TrackedMeasurementsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
TrackedMeasurementsContextProvider.propTypes = {
|
||||
children: PropTypes.oneOf([PropTypes.func, PropTypes.node]),
|
||||
};
|
||||
|
||||
export {
|
||||
TrackedMeasurementsContext,
|
||||
TrackedMeasurementsContextProvider,
|
||||
useTrackedMeasurements,
|
||||
};
|
||||
@ -1,45 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useMachine } from '@xstate/react';
|
||||
import {
|
||||
measurementTrackingMachine,
|
||||
defaultOptions,
|
||||
} from './measurementTrackingMachine';
|
||||
|
||||
const TrackedMeasurementsContext = React.createContext();
|
||||
|
||||
TrackedMeasurementsContext.displayName = 'TrackedMeasurementsContext';
|
||||
|
||||
const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} param0
|
||||
*/
|
||||
function TrackedMeasurementsContextProvider({ children }) {
|
||||
// TODO: Configure `UIViewportNotificationService` for appropriate actions
|
||||
const measurementTrackingMachineOptions = Object.assign({}, defaultOptions);
|
||||
const [
|
||||
trackedMeasurements,
|
||||
sendTrackedMeasurementsEvent,
|
||||
trackedMeasurementsService,
|
||||
] = useMachine(measurementTrackingMachine, measurementTrackingMachineOptions);
|
||||
|
||||
return (
|
||||
<TrackedMeasurementsContext.Provider
|
||||
value={[trackedMeasurements, sendTrackedMeasurementsEvent]}
|
||||
>
|
||||
{children}
|
||||
</TrackedMeasurementsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
TrackedMeasurementsContextProvider.propTypes = {
|
||||
children: PropTypes.oneOf([PropTypes.func, PropTypes.node]),
|
||||
};
|
||||
|
||||
export {
|
||||
TrackedMeasurementsContext,
|
||||
TrackedMeasurementsContextProvider,
|
||||
useTrackedMeasurements,
|
||||
};
|
||||
} from './TrackedMeasurementsContext.jsx';
|
||||
|
||||
@ -27,7 +27,7 @@ const machineConfiguration = {
|
||||
prompt: {
|
||||
invoke: {
|
||||
id: 'shouldTrackPrompt',
|
||||
src: () => confirmDialog('Should we start tracking?'),
|
||||
src: 'shouldTrackPrompt',
|
||||
onDone: {
|
||||
target: 'validateResponse',
|
||||
actions: assign({ promptResponse: (ctx, evt) => evt.data }),
|
||||
@ -135,6 +135,11 @@ function confirmDialog(msg) {
|
||||
}
|
||||
|
||||
const defaultOptions = {
|
||||
services: {
|
||||
shouldTrackPrompt: () => {
|
||||
return confirmDialog('Should we start tracking?');
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
clearContext: assign({
|
||||
prevTrackedStudy: '',
|
||||
@ -186,11 +191,13 @@ const defaultOptions = {
|
||||
},
|
||||
};
|
||||
|
||||
const measurementTrackingMachine = Machine(machineConfiguration, defaultOptions);
|
||||
// const measurementTrackingMachine = Machine(
|
||||
// machineConfiguration,
|
||||
// defaultOptions
|
||||
// );
|
||||
// .transition(state, eventArgument).value
|
||||
// const service = interpret(measurementTrackingMachine).start();
|
||||
// .send(event): nextState
|
||||
// .state (getter)
|
||||
// .onTransition(state => { state.vale })
|
||||
export { defaultOptions, machineConfiguration, measurementTrackingMachine };
|
||||
export default measurementTrackingMachine;
|
||||
export { defaultOptions, machineConfiguration };
|
||||
|
||||
@ -4,12 +4,18 @@ import {
|
||||
useTrackedMeasurements,
|
||||
} from './contexts';
|
||||
|
||||
function getContextModule() {
|
||||
function getContextModule({ servicesManager }) {
|
||||
const { UIViewportDialogService } = servicesManager.services;
|
||||
const BoundTrackedMeasurementsContextProvider = TrackedMeasurementsContextProvider.bind(
|
||||
null,
|
||||
UIViewportDialogService
|
||||
);
|
||||
|
||||
return [
|
||||
{
|
||||
name: 'TrackedMeasurementsContext',
|
||||
context: TrackedMeasurementsContext,
|
||||
provider: TrackedMeasurementsContextProvider,
|
||||
provider: BoundTrackedMeasurementsContextProvider,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
const Component = React.lazy(() => {
|
||||
return import('./viewports/OHIFCornerstoneViewport');
|
||||
return import('./viewports/TrackedCornerstoneViewport');
|
||||
});
|
||||
|
||||
const OHIFCornerstoneViewport = props => {
|
||||
|
||||
@ -3,12 +3,16 @@ import PropTypes from 'prop-types';
|
||||
import cornerstone from 'cornerstone-core';
|
||||
import CornerstoneViewport from 'react-cornerstone-viewport';
|
||||
import OHIF, { DicomMetadataStore } from '@ohif/core';
|
||||
import { ViewportActionBar, useViewportGrid } from '@ohif/ui';
|
||||
import {
|
||||
Notification,
|
||||
ViewportActionBar,
|
||||
useViewportGrid,
|
||||
useViewportDialog,
|
||||
} from '@ohif/ui';
|
||||
import debounce from 'lodash.debounce';
|
||||
import throttle from 'lodash.throttle';
|
||||
import { useTrackedMeasurements } from './../getContextModule';
|
||||
|
||||
|
||||
// const cine = viewportSpecificData.cine;
|
||||
|
||||
// isPlaying = cine.isPlaying === true;
|
||||
@ -16,7 +20,7 @@ import { useTrackedMeasurements } from './../getContextModule';
|
||||
|
||||
const { StackManager } = OHIF.utils;
|
||||
|
||||
function OHIFCornerstoneViewport({
|
||||
function TrackedCornerstoneViewport({
|
||||
children,
|
||||
dataSource,
|
||||
displaySet,
|
||||
@ -24,6 +28,10 @@ function OHIFCornerstoneViewport({
|
||||
}) {
|
||||
const [trackedMeasurements] = useTrackedMeasurements();
|
||||
const [{ viewports }, dispatchViewportGrid] = useViewportGrid();
|
||||
// viewportIndex, onSubmit
|
||||
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
|
||||
console.warn('VIEWPORT DIALOG', viewportDialogState, viewportDialogApi);
|
||||
|
||||
const [viewportData, setViewportData] = useState(null);
|
||||
// TODO: Still needed? Better way than import `OHIF` and destructure?
|
||||
// Why is this managed by `core`?
|
||||
@ -98,7 +106,7 @@ function OHIFCornerstoneViewport({
|
||||
// );
|
||||
// TODO: This display contains the meta for all instances.
|
||||
// That can't be right...
|
||||
console.log('DISPLAYSET', displaySet)
|
||||
console.log('DISPLAYSET', displaySet);
|
||||
// const seriesMeta = DicomMetadataStore.getSeries(this.props.displaySet.StudyInstanceUID, '');
|
||||
// console.log(seriesMeta);
|
||||
|
||||
@ -145,22 +153,35 @@ function OHIFCornerstoneViewport({
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<CornerstoneViewport
|
||||
viewportIndex={viewportIndex}
|
||||
imageIds={imageIds}
|
||||
imageIdIndex={currentImageIdIndex}
|
||||
// TODO: ViewportGrid Context?
|
||||
isActive={true} // todo
|
||||
isStackPrefetchEnabled={true} // todo
|
||||
isPlaying={false}
|
||||
frameRate={24}
|
||||
/>
|
||||
{childrenWithProps}
|
||||
{/* TODO: Viewport interface to accept stack or layers of content like this? */}
|
||||
<div className="relative flex flex-row w-full h-full">
|
||||
<CornerstoneViewport
|
||||
viewportIndex={viewportIndex}
|
||||
imageIds={imageIds}
|
||||
imageIdIndex={currentImageIdIndex}
|
||||
// TODO: ViewportGrid Context?
|
||||
isActive={true} // todo
|
||||
isStackPrefetchEnabled={true} // todo
|
||||
isPlaying={false}
|
||||
frameRate={24}
|
||||
/>
|
||||
<div style={{ position: 'absolute' }}>
|
||||
{viewportDialogState.viewportIndex === viewportIndex && (
|
||||
<Notification
|
||||
message={viewportDialogState.message}
|
||||
type={viewportDialogState.type}
|
||||
actions={viewportDialogState.actions}
|
||||
onSubmit={viewportDialogState.onSubmit}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{childrenWithProps}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
OHIFCornerstoneViewport.propTypes = {
|
||||
TrackedCornerstoneViewport.propTypes = {
|
||||
displaySet: PropTypes.object.isRequired,
|
||||
viewportIndex: PropTypes.number.isRequired,
|
||||
dataSource: PropTypes.object,
|
||||
@ -168,7 +189,7 @@ OHIFCornerstoneViewport.propTypes = {
|
||||
customProps: PropTypes.object,
|
||||
};
|
||||
|
||||
OHIFCornerstoneViewport.defaultProps = {
|
||||
TrackedCornerstoneViewport.defaultProps = {
|
||||
customProps: {},
|
||||
};
|
||||
|
||||
@ -207,6 +228,6 @@ async function _getViewportData(dataSource, displaySet) {
|
||||
};
|
||||
|
||||
return viewportData;
|
||||
};
|
||||
}
|
||||
|
||||
export default OHIFCornerstoneViewport;
|
||||
export default TrackedCornerstoneViewport;
|
||||
@ -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); }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user