diff --git a/platform/core/src/index.js b/platform/core/src/index.js
index 6c1d70d71..1a2106f7d 100644
--- a/platform/core/src/index.js
+++ b/platform/core/src/index.js
@@ -23,8 +23,6 @@ import {
UINotificationService,
UIModalService,
UIDialogService,
- UIContextMenuService,
- UILabellingFlowService,
} from './services';
const OHIF = {
@@ -55,8 +53,6 @@ const OHIF = {
UINotificationService,
UIModalService,
UIDialogService,
- UIContextMenuService,
- UILabellingFlowService,
};
export {
@@ -86,8 +82,6 @@ export {
UINotificationService,
UIModalService,
UIDialogService,
- UIContextMenuService,
- UILabellingFlowService,
};
export { OHIF };
diff --git a/platform/core/src/index.test.js b/platform/core/src/index.test.js
index d823c3d3e..3026ffd50 100644
--- a/platform/core/src/index.test.js
+++ b/platform/core/src/index.test.js
@@ -13,8 +13,6 @@ describe('Top level exports', () => {
'UINotificationService',
'UIModalService',
'UIDialogService',
- 'UIContextMenuService',
- 'UILabellingFlowService',
//
'utils',
'studies',
diff --git a/platform/core/src/services/UIContextMenuService/index.js b/platform/core/src/services/UIContextMenuService/index.js
deleted file mode 100644
index dc27b774c..000000000
--- a/platform/core/src/services/UIContextMenuService/index.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * UI Context Menu
- *
- * @typedef {Object} ContextMenuProps
- * @property {Event} event The event with tool information.
- */
-
-const name = 'UIContextMenuService';
-
-const publicAPI = {
- name,
- hide: _hide,
- show: _show,
- setServiceImplementation,
-};
-
-const serviceImplementation = {
- _show: () => console.warn('show() NOT IMPLEMENTED'),
- _hide: () => console.warn('hide() NOT IMPLEMENTED'),
-};
-
-/**
- * Show a new UI ContextMenu dialog;
- *
- * @param {ContextMenuProps} props { event }
- */
-function _show({ event }) {
- return serviceImplementation._show({
- event,
- });
-}
-
-/**
- * Hide a UI ContextMenu dialog;
- *
- */
-function _hide() {
- return serviceImplementation._hide();
-}
-
-/**
- *
- *
- * @param {*} {
- * show: showImplementation,
- * hide: hideImplementation,
- * }
- */
-function setServiceImplementation({
- show: showImplementation,
- hide: hideImplementation,
-}) {
- if (showImplementation) {
- serviceImplementation._show = showImplementation;
- }
- if (hideImplementation) {
- serviceImplementation._hide = hideImplementation;
- }
-}
-
-export default {
- name,
- create: ({ configuration = {} }) => {
- return publicAPI;
- },
-};
diff --git a/platform/core/src/services/UILabellingFlowService/index.js b/platform/core/src/services/UILabellingFlowService/index.js
deleted file mode 100644
index 7f374b1e7..000000000
--- a/platform/core/src/services/UILabellingFlowService/index.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * UI Labelling Flow
- *
- * @typedef {Object} LabellingFlowProps
- * @property {Object} defaultPosition The position of the labelling dialog.
- * @property {boolean} centralize conditional to center the labelling dialog.
- * @property {Object} props The labelling props.
- *
- */
-
-const name = 'UILabellingFlowService';
-
-const publicAPI = {
- name,
- show: _show,
- hide: _hide,
- setServiceImplementation,
-};
-
-const serviceImplementation = {
- _show: () => console.warn('show() NOT IMPLEMENTED'),
- _hide: () => console.warn('hide() NOT IMPLEMENTED'),
-};
-
-/**
- * Hide a UI LabellingFlow dialog;
- *
- */
-function _hide() {
- return serviceImplementation._hide();
-}
-
-/**
- * Show a new UI LabellingFlow dialog;
- *
- * @param {LabellingFlowProps} props { defaultPosition, centralize, props }
- */
-function _show({ defaultPosition, centralize, props }) {
- return serviceImplementation._show({
- defaultPosition,
- centralize,
- props,
- });
-}
-
-/**
- *
- *
- * @param {*} {
- * show: showImplementation,
- * hide: hideImplementation,
- * }
- */
-function setServiceImplementation({
- show: showImplementation,
- hide: hideImplementation,
-}) {
- if (showImplementation) {
- serviceImplementation._show = showImplementation;
- }
- if (hideImplementation) {
- serviceImplementation._hide = hideImplementation;
- }
-}
-
-export default {
- name,
- create: ({ configuration = {} }) => {
- return publicAPI;
- },
-};
diff --git a/platform/core/src/services/index.js b/platform/core/src/services/index.js
index f2e8ff864..9ac507c50 100644
--- a/platform/core/src/services/index.js
+++ b/platform/core/src/services/index.js
@@ -2,14 +2,10 @@ import ServicesManager from './ServicesManager.js';
import UINotificationService from './UINotificationService';
import UIModalService from './UIModalService';
import UIDialogService from './UIDialogService';
-import UIContextMenuService from './UIContextMenuService';
-import UILabellingFlowService from './UILabellingFlowService';
export {
UINotificationService,
UIModalService,
UIDialogService,
- UIContextMenuService,
- UILabellingFlowService,
ServicesManager,
};
diff --git a/platform/viewer/src/connectedComponents/ToolContextMenu.css b/platform/ui/src/components/contextMenu/ContextMenu.css
similarity index 65%
rename from platform/viewer/src/connectedComponents/ToolContextMenu.css
rename to platform/ui/src/components/contextMenu/ContextMenu.css
index 66fa17495..4facf3c41 100644
--- a/platform/viewer/src/connectedComponents/ToolContextMenu.css
+++ b/platform/ui/src/components/contextMenu/ContextMenu.css
@@ -1,20 +1,19 @@
-.ToolContextMenu {
+.ContextMenu {
position: relative;
background-color: white;
- border: 1px solid white;
border-radius: 5px;
z-index: 1000;
display: block;
width: 170px;
}
-.ToolContextMenu > ul {
+.ContextMenu>ul {
list-style-type: none;
padding-left: 0;
margin: 0;
}
-.ToolContextMenu > ul > li > button {
+.ContextMenu>ul>li>button {
padding: 10px;
font-size: 14px;
border: none;
@@ -25,10 +24,10 @@
background: none;
}
-.ToolContextMenu > ul > li > button:hover {
+.ContextMenu>ul>li>button:hover {
color: #16202b;
}
-.ToolContextMenu > ul > li > button:active {
+.ContextMenu>ul>li>button:active {
color: #79f9fe;
}
diff --git a/platform/ui/src/components/contextMenu/ContextMenu.js b/platform/ui/src/components/contextMenu/ContextMenu.js
new file mode 100644
index 000000000..9dc5a174f
--- /dev/null
+++ b/platform/ui/src/components/contextMenu/ContextMenu.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import './ContextMenu.css';
+
+const ContextMenu = ({ items, onClick }) => {
+ return (
+
+
+ {items.map((item, index) => (
+ -
+
+
+ ))}
+
+
+ );
+};
+
+ContextMenu.propTypes = {
+ items: PropTypes.array.isRequired,
+ onClick: PropTypes.func.isRequired,
+};
+
+export default ContextMenu;
diff --git a/platform/ui/src/components/contextMenu/index.js b/platform/ui/src/components/contextMenu/index.js
new file mode 100644
index 000000000..5cb9a3ad5
--- /dev/null
+++ b/platform/ui/src/components/contextMenu/index.js
@@ -0,0 +1 @@
+export { default as ContextMenu } from './ContextMenu.js';
diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js
index 81ae9dfe4..5daca57b1 100644
--- a/platform/ui/src/components/index.js
+++ b/platform/ui/src/components/index.js
@@ -17,6 +17,7 @@ import { RoundedButtonGroup } from './roundedButtonGroup';
import { SelectTree } from './selectTree';
import { SimpleDialog } from './simpleDialog';
import { OHIFModal } from './ohifModal';
+import { ContextMenu } from './contextMenu';
import {
PageToolbar,
StudyList,
@@ -27,6 +28,7 @@ import { ToolbarSection } from './toolbarSection';
import { Tooltip } from './tooltip';
export {
+ ContextMenu,
Checkbox,
CineDialog,
ViewportDownloadForm,
diff --git a/platform/ui/src/contextProviders/ContextMenuProvider.js b/platform/ui/src/contextProviders/ContextMenuProvider.js
deleted file mode 100644
index 1d1ee22c3..000000000
--- a/platform/ui/src/contextProviders/ContextMenuProvider.js
+++ /dev/null
@@ -1,147 +0,0 @@
-import React, {
- createContext,
- useContext,
- useEffect,
- useCallback,
-} from 'react';
-import PropTypes from 'prop-types';
-
-import { useDialog } from '@ohif/ui';
-import { useLabellingFlow } from '@ohif/ui';
-
-const ContextMenuContext = createContext(null);
-const { Provider } = ContextMenuContext;
-
-export const useContextMenu = () => useContext(ContextMenuContext);
-
-const ContextMenuProvider = ({
- children,
- service,
- contextMenuComponent: ContextMenuComponent,
- onDelete,
-}) => {
- const { create, dismiss } = useDialog();
- const { show: showLabellingFlow } = useLabellingFlow();
-
- /**
- * Sets the implementation of a context menu service that can be used by extensions.
- *
- * @returns void
- */
- useEffect(() => {
- if (service) {
- service.setServiceImplementation({
- show,
- hide,
- });
- }
- }, [hide, service, show]);
-
- const hide = useCallback(() => dismiss({ id: 'context-menu' }), [dismiss]);
-
- /**
- * Show the context menu and override its configuration props.
- *
- * @param {ContextMenuProps} props { eventData, isTouchEvent, onClose, visible }
- * @returns void
- */
- const show = useCallback(
- ({ event }) => {
- hide();
- create({
- id: 'context-menu',
- isDraggable: false,
- preservePosition: false,
- content: ContextMenuComponent,
- contentProps: {
- eventData: event,
- onDelete: (nearbyToolData, eventData) =>
- onDelete(nearbyToolData, eventData),
- onClose: () => dismiss({ id: 'context-menu' }),
- onSetLabel: (eventData, measurementData) =>
- showLabellingFlow({
- event: eventData,
- centralize: true,
- props: {
- measurementData,
- skipAddLabelButton: true,
- editLocation: true,
- },
- }),
- onSetDescription: (eventData, measurementData) =>
- showLabellingFlow({
- event: eventData,
- centralize: false,
- defaultPosition: _getDefaultPosition(eventData),
- props: {
- measurementData,
- editDescriptionOnDialog: true,
- },
- }),
- },
- defaultPosition: _getDefaultPosition(event),
- });
- },
- [ContextMenuComponent, create, dismiss, hide, onDelete, showLabellingFlow]
- );
-
- const _getDefaultPosition = event => ({
- x: (event && event.currentPoints.client.x) || 0,
- y: (event && event.currentPoints.client.y) || 0,
- });
-
- return (
-
- {children}
-
- );
-};
-
-/**
- * Higher Order Component to use the context menu methods through a Class Component.
- *
- * @returns
- */
-export const withContextMenu = Component => {
- return function WrappedComponent(props) {
- const { show, hide } = useContextMenu();
- return (
-
- );
- };
-};
-
-ContextMenuProvider.defaultProps = {
- service: null,
-};
-
-ContextMenuProvider.propTypes = {
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]).isRequired,
- service: PropTypes.shape({
- setServiceImplementation: PropTypes.func,
- }),
- contextMenuComponent: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- PropTypes.func,
- ]).isRequired,
- onDelete: PropTypes.func.isRequired,
-};
-
-export default ContextMenuProvider;
-
-export const ContextMenuConsumer = ContextMenuContext.Consumer;
diff --git a/platform/ui/src/contextProviders/LabellingFlowProvider.js b/platform/ui/src/contextProviders/LabellingFlowProvider.js
deleted file mode 100644
index a5c266d8f..000000000
--- a/platform/ui/src/contextProviders/LabellingFlowProvider.js
+++ /dev/null
@@ -1,136 +0,0 @@
-import React, {
- createContext,
- useContext,
- useEffect,
- useCallback,
-} from 'react';
-import PropTypes from 'prop-types';
-
-import { useDialog } from './DialogProvider';
-
-const LabellingFlowContext = createContext(null);
-const { Provider } = LabellingFlowContext;
-
-export const useLabellingFlow = () => useContext(LabellingFlowContext);
-
-const LabellingFlowProvider = ({
- children,
- service,
- labellingComponent: LabellingComponent,
- onUpdateLabelling,
-}) => {
- const { create, dismiss } = useDialog();
-
- /**
- * Sets the implementation of a labelling flow service that can be used by extensions.
- *
- * @returns void
- */
- useEffect(() => {
- if (service) {
- service.setServiceImplementation({
- show,
- hide,
- });
- }
- }, [hide, service, show]);
-
- const hide = useCallback(() => dismiss({ id: 'labelling' }), [dismiss]);
-
- const show = useCallback(
- ({ centralize, defaultPosition, props }) => {
- hide();
- create({
- id: 'labelling',
- centralize,
- isDraggable: false,
- showOverlay: true,
- content: LabellingComponent,
- defaultPosition,
- contentProps: {
- visible: true,
- measurementData: props.measurementData,
- labellingDoneCallback: () => dismiss({ id: 'labelling' }),
- updateLabelling: labellingData =>
- _updateLabellingHandler(labellingData, props.measurementData),
- ...props,
- },
- });
- },
- [LabellingComponent, _updateLabellingHandler, create, dismiss, hide]
- );
-
- const _updateLabellingHandler = useCallback(
- (labellingData, measurementData) => {
- const { location, description, response } = labellingData;
-
- if (location) {
- measurementData.location = location;
- }
-
- measurementData.description = description || '';
-
- if (response) {
- measurementData.response = response;
- }
-
- onUpdateLabelling(labellingData, measurementData);
- },
- [onUpdateLabelling]
- );
-
- return (
-
- {children}
-
- );
-};
-
-/**
- * Higher Order Component to use the labelling flow methods through a Class Component.
- *
- * @returns
- */
-export const withLabellingFlow = Component => {
- return function WrappedComponent(props) {
- const { show, hide } = useLabellingFlow();
- return (
-
- );
- };
-};
-
-LabellingFlowProvider.defaultProps = {
- service: null,
-};
-
-LabellingFlowProvider.propTypes = {
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]).isRequired,
- service: PropTypes.shape({
- setServiceImplementation: PropTypes.func,
- }),
- labellingComponent: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- PropTypes.func,
- ]).isRequired,
- onUpdateLabelling: PropTypes.func.isRequired,
-};
-
-export default LabellingFlowProvider;
-
-export const LabellingFlowConsumer = LabellingFlowContext.Consumer;
diff --git a/platform/ui/src/contextProviders/index.js b/platform/ui/src/contextProviders/index.js
index 821b6ce9e..e4ca06143 100644
--- a/platform/ui/src/contextProviders/index.js
+++ b/platform/ui/src/contextProviders/index.js
@@ -18,15 +18,3 @@ export {
withDialog,
useDialog,
} from './DialogProvider.js';
-export {
- default as ContextMenuProvider,
- withContextMenu,
- useContextMenu,
- ContextMenuConsumer,
-} from './ContextMenuProvider.js';
-export {
- default as LabellingFlowProvider,
- withLabellingFlow,
- useLabellingFlow,
- LabellingFlowConsumer,
-} from './LabellingFlowProvider.js';
diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js
index 1672d4b13..88e3aee77 100644
--- a/platform/ui/src/index.js
+++ b/platform/ui/src/index.js
@@ -1,4 +1,5 @@
import {
+ ContextMenu,
Checkbox,
CineDialog,
ViewportDownloadForm,
@@ -60,14 +61,6 @@ import {
ModalConsumer,
useModal,
withModal,
- ContextMenuProvider,
- ContextMenuConsumer,
- useContextMenu,
- withContextMenu,
- LabellingFlowProvider,
- LabellingFlowConsumer,
- useLabellingFlow,
- withLabellingFlow,
} from './contextProviders';
export {
@@ -80,6 +73,7 @@ export {
TextArea,
TextInput,
CineDialog,
+ ContextMenu,
ViewportDownloadForm,
ExpandableToolMenu,
Icon,
@@ -125,14 +119,6 @@ export {
DialogProvider,
withDialog,
useDialog,
- ContextMenuProvider,
- ContextMenuConsumer,
- useContextMenu,
- withContextMenu,
- LabellingFlowProvider,
- LabellingFlowConsumer,
- useLabellingFlow,
- withLabellingFlow,
// Hooks
useDebounce,
useMedia,
diff --git a/platform/viewer/src/App.js b/platform/viewer/src/App.js
index 9f01c3e29..801e6df21 100644
--- a/platform/viewer/src/App.js
+++ b/platform/viewer/src/App.js
@@ -8,9 +8,6 @@ import { hot } from 'react-hot-loader/root';
import OHIFCornerstoneExtension from '@ohif/extension-cornerstone';
-import ToolContextMenu from './connectedComponents/ToolContextMenu';
-import LabellingFlow from './components/Labelling/LabellingFlow';
-
import {
SnackbarProvider,
ModalProvider,
@@ -18,11 +15,6 @@ import {
OHIFModal,
} from '@ohif/ui';
-import {
- LabellingFlowProvider,
- ContextMenuProvider,
-} from './appCustomProviders';
-
import {
CommandsManager,
ExtensionManager,
@@ -31,8 +23,6 @@ import {
UINotificationService,
UIModalService,
UIDialogService,
- UIContextMenuService,
- UILabellingFlowService,
utils,
redux as reduxOHIF,
} from '@ohif/core';
@@ -135,13 +125,7 @@ class App extends Component {
} = this._appConfig;
this.initUserManager(oidc);
- _initServices([
- UINotificationService,
- UIModalService,
- UIDialogService,
- UIContextMenuService,
- UILabellingFlowService,
- ]);
+ _initServices([UINotificationService, UIModalService, UIDialogService]);
_initExtensions(
[...defaultExtensions, ...extensions],
cornerstoneExtensionConfig
@@ -161,9 +145,7 @@ class App extends Component {
const {
UINotificationService,
UIDialogService,
- UILabellingFlowService,
UIModalService,
- UIContextMenuService,
} = servicesManager.services;
if (this._userManager) {
@@ -181,21 +163,9 @@ class App extends Component {
modal={OHIFModal}
service={UIModalService}
>
-
-
-
-
-
+
@@ -218,19 +188,7 @@ class App extends Component {
-
-
-
-
-
+
diff --git a/platform/viewer/src/appCustomProviders/ContextMenuProvider/ContextMenuProvider.js b/platform/viewer/src/appCustomProviders/ContextMenuProvider/ContextMenuProvider.js
deleted file mode 100644
index 4cd75d9f8..000000000
--- a/platform/viewer/src/appCustomProviders/ContextMenuProvider/ContextMenuProvider.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { ContextMenuProvider } from '@ohif/ui';
-
-const CustomContextMenuProvider = ({
- children,
- service,
- contextMenuComponent,
- commandsManager,
-}) => {
- const onDeleteHandler = (nearbyToolData, eventData) => {
- const element = eventData.element;
- commandsManager.runCommand('removeToolState', {
- element,
- toolType: nearbyToolData.toolType,
- tool: nearbyToolData.tool,
- });
- };
-
- return (
-
- {children}
-
- );
-};
-
-CustomContextMenuProvider.defaultProps = {
- service: null,
-};
-
-CustomContextMenuProvider.propTypes = {
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]).isRequired,
- service: PropTypes.shape({
- setServiceImplementation: PropTypes.func,
- }),
- contextMenuComponent: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- PropTypes.func,
- ]).isRequired,
- commandsManager: PropTypes.object.isRequired,
-};
-
-export default CustomContextMenuProvider;
diff --git a/platform/viewer/src/appCustomProviders/LabellingFlowProvider/LabellingFlowProvider.js b/platform/viewer/src/appCustomProviders/LabellingFlowProvider/LabellingFlowProvider.js
deleted file mode 100644
index 097a0350f..000000000
--- a/platform/viewer/src/appCustomProviders/LabellingFlowProvider/LabellingFlowProvider.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { LabellingFlowProvider } from '@ohif/ui';
-
-const CustomLabellingFlowProvider = ({
- children,
- service,
- labellingComponent,
- commandsManager,
-}) => {
- const onUpdateLabellingHandler = (labellingData, measurementData) => {
- commandsManager.runCommand(
- 'updateTableWithNewMeasurementData',
- measurementData
- );
- };
-
- return (
-
- {children}
-
- );
-};
-
-CustomLabellingFlowProvider.defaultProps = {
- service: null,
-};
-
-CustomLabellingFlowProvider.propTypes = {
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]).isRequired,
- service: PropTypes.shape({
- setServiceImplementation: PropTypes.func,
- }),
- labellingComponent: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- PropTypes.func,
- ]).isRequired,
- commandsManager: PropTypes.object.isRequired,
-};
-
-export default CustomLabellingFlowProvider;
diff --git a/platform/viewer/src/appCustomProviders/index.js b/platform/viewer/src/appCustomProviders/index.js
deleted file mode 100644
index f66c8e462..000000000
--- a/platform/viewer/src/appCustomProviders/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export {
- default as LabellingFlowProvider,
-} from './LabellingFlowProvider/LabellingFlowProvider.js';
-export {
- default as ContextMenuProvider,
-} from './ContextMenuProvider/ContextMenuProvider.js';
diff --git a/platform/viewer/src/appExtensions/MeasurementsPanel/index.js b/platform/viewer/src/appExtensions/MeasurementsPanel/index.js
index cfa471964..41d1f2f99 100644
--- a/platform/viewer/src/appExtensions/MeasurementsPanel/index.js
+++ b/platform/viewer/src/appExtensions/MeasurementsPanel/index.js
@@ -2,6 +2,8 @@ import React from 'react';
import ConnectedMeasurementTable from './ConnectedMeasurementTable.js';
import init from './init.js';
+import LabellingFlow from '../../components/Labelling/LabellingFlow';
+
export default {
/**
* Only required property. Should be a unique value across all extensions.
@@ -13,32 +15,51 @@ export default {
},
getPanelModule({ servicesManager, commandsManager }) {
- const { UILabellingFlowService, UINotificationService } = servicesManager.services;
+ const { UINotificationService, UIDialogService } = servicesManager.services;
+
+ const showLabellingDialog = (props, measurementData) => {
+ if (!UIDialogService) {
+ console.warn('Unable to show dialog; no UI Dialog Service available.');
+ return;
+ }
+
+ UIDialogService.dismiss({ id: 'labelling' });
+ UIDialogService.create({
+ id: 'labelling',
+ centralize: true,
+ isDraggable: false,
+ showOverlay: true,
+ content: LabellingFlow,
+ contentProps: {
+ measurementData,
+ labellingDoneCallback: () =>
+ UIDialogService.dismiss({ id: 'labelling' }),
+ updateLabelling: ({ location, description, response }) => {
+ measurementData.location = location || measurementData.location;
+ measurementData.description = description || '';
+ measurementData.response = response || measurementData.response;
+
+ commandsManager.runCommand(
+ 'updateTableWithNewMeasurementData',
+ measurementData
+ );
+ },
+ ...props,
+ },
+ });
+ };
+
const ExtendedConnectedMeasurementTable = () => (
{
- if (UILabellingFlowService) {
- UILabellingFlowService.show({
- centralize: true,
- props: {
- skipAddLabelButton: true,
- editLocation: true,
- measurementData: tool,
- },
- });
- }
- }}
- onEditDescription={tool => {
- if (UILabellingFlowService) {
- UILabellingFlowService.show({
- centralize: true,
- props: {
- editDescriptionOnDialog: true,
- measurementData: tool,
- },
- });
- }
- }}
+ onRelabel={tool =>
+ showLabellingDialog(
+ { editLocation: true, skipAddLabelButton: true },
+ tool
+ )
+ }
+ onEditDescription={tool =>
+ showLabellingDialog({ editDescriptionOnDialog: true }, tool)
+ }
onSaveComplete={message => {
if (UINotificationService) {
UINotificationService.show(message);
diff --git a/platform/viewer/src/appExtensions/MeasurementsPanel/init.js b/platform/viewer/src/appExtensions/MeasurementsPanel/init.js
index 0c299b81a..924081e9e 100644
--- a/platform/viewer/src/appExtensions/MeasurementsPanel/init.js
+++ b/platform/viewer/src/appExtensions/MeasurementsPanel/init.js
@@ -3,6 +3,9 @@ import cornerstone from 'cornerstone-core';
import csTools from 'cornerstone-tools';
import throttle from 'lodash.throttle';
+import LabellingFlow from '../../components/Labelling/LabellingFlow';
+import ToolContextMenu from '../../connectedComponents/ToolContextMenu';
+
const {
onAdded,
onRemoved,
@@ -29,10 +32,7 @@ export default function init({
commandsManager,
configuration,
}) {
- const {
- UIContextMenuService,
- UILabellingFlowService,
- } = servicesManager.services;
+ const { UIDialogService } = servicesManager.services;
// TODO: MEASUREMENT_COMPLETED (not present in initial implementation)
const onMeasurementsChanged = (action, event) => {
@@ -46,21 +46,108 @@ export default function init({
'labelmapModified'
);
- const onRightClick = event => {
- if (UIContextMenuService) {
- UIContextMenuService.show({ event: event.detail });
+ const _getDefaultPosition = event => ({
+ x: (event && event.currentPoints.client.x) || 0,
+ y: (event && event.currentPoints.client.y) || 0,
+ });
+
+ const _updateLabellingHandler = (labellingData, measurementData) => {
+ const { location, description, response } = labellingData;
+
+ if (location) {
+ measurementData.location = location;
}
+
+ measurementData.description = description || '';
+
+ if (response) {
+ measurementData.response = response;
+ }
+
+ commandsManager.runCommand(
+ 'updateTableWithNewMeasurementData',
+ measurementData
+ );
+ };
+
+ const showLabellingDialog = (props, contentProps, measurementData) => {
+ if (!UIDialogService) {
+ console.warn('Unable to show dialog; no UI Dialog Service available.');
+ return;
+ }
+
+ UIDialogService.create({
+ id: 'labelling',
+ isDraggable: false,
+ showOverlay: true,
+ content: LabellingFlow,
+ contentProps: {
+ measurementData,
+ labellingDoneCallback: () =>
+ UIDialogService.dismiss({ id: 'labelling' }),
+ updateLabelling: labellingData =>
+ _updateLabellingHandler(labellingData, measurementData),
+ ...contentProps,
+ },
+ ...props,
+ });
+ };
+
+ const onRightClick = event => {
+ if (!UIDialogService) {
+ console.warn('Unable to show dialog; no UI Dialog Service available.');
+ return;
+ }
+
+ UIDialogService.dismiss({ id: 'context-menu' });
+ UIDialogService.create({
+ id: 'context-menu',
+ isDraggable: false,
+ preservePosition: false,
+ defaultPosition: _getDefaultPosition(event.detail),
+ content: ToolContextMenu,
+ contentProps: {
+ eventData: event.detail,
+ onDelete: (nearbyToolData, eventData) => {
+ const element = eventData.element;
+ commandsManager.runCommand('removeToolState', {
+ element,
+ toolType: nearbyToolData.toolType,
+ tool: nearbyToolData.tool,
+ });
+ },
+ onClose: () => UIDialogService.dismiss({ id: 'context-menu' }),
+ onSetLabel: (eventData, measurementData) => {
+ showLabellingDialog(
+ { centralize: true, isDraggable: false },
+ { skipAddLabelButton: true, editLocation: true },
+ measurementData
+ );
+ },
+ onSetDescription: (eventData, measurementData) => {
+ showLabellingDialog(
+ { defaultPosition: _getDefaultPosition(eventData) },
+ { editDescriptionOnDialog: true },
+ measurementData
+ );
+ },
+ },
+ });
};
const onTouchPress = event => {
- if (UIContextMenuService) {
- UIContextMenuService.show({
- event: event.detail,
- props: {
- isTouchEvent: true,
- },
- });
+ if (!UIDialogService) {
+ console.warn('Unable to show dialog; no UI Dialog Service available.');
+ return;
}
+
+ UIDialogService.create({
+ eventData: event.detail,
+ content: ToolContextMenu,
+ contentProps: {
+ isTouchEvent: true,
+ },
+ });
};
const onTouchStart = () => resetLabelligAndContextMenu();
@@ -68,10 +155,13 @@ export default function init({
const onMouseClick = () => resetLabelligAndContextMenu();
const resetLabelligAndContextMenu = () => {
- if (UILabellingFlowService && UIContextMenuService) {
- UILabellingFlowService.hide();
- UIContextMenuService.hide();
+ if (!UIDialogService) {
+ console.warn('Unable to show dialog; no UI Dialog Service available.');
+ return;
}
+
+ UIDialogService.dismiss({ id: 'context-menu' });
+ UIDialogService.dismiss({ id: 'labelling' });
};
// TODO: This makes scrolling painfully slow
diff --git a/platform/viewer/src/connectedComponents/ToolContextMenu.js b/platform/viewer/src/connectedComponents/ToolContextMenu.js
index 18bb57684..3974ad396 100644
--- a/platform/viewer/src/connectedComponents/ToolContextMenu.js
+++ b/platform/viewer/src/connectedComponents/ToolContextMenu.js
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { commandsManager } from './../App.js';
-import './ToolContextMenu.css';
+import { ContextMenu } from '@ohif/ui';
const toolTypes = [
'Angle',
@@ -24,11 +24,13 @@ const ToolContextMenu = ({
}) => {
const defaultDropdownItems = [
{
+ label: 'Delete measurement',
actionType: 'Delete',
action: ({ nearbyToolData, eventData }) =>
onDelete(nearbyToolData, eventData),
},
{
+ label: 'Relabel',
actionType: 'setLabel',
action: ({ nearbyToolData, eventData }) => {
const { tool: measurementData } = nearbyToolData;
@@ -51,7 +53,10 @@ const ToolContextMenu = ({
availableToolTypes: toolTypes,
});
- // Annotate tools for touch events already have a press handle to edit it, has a better UX for deleting it
+ /*
+ * Annotate tools for touch events already have a press handle to edit it,
+ * has a better UX for deleting it.
+ */
if (
isTouchEvent &&
nearbyToolData &&
@@ -63,21 +68,10 @@ const ToolContextMenu = ({
let dropdownItems = [];
if (nearbyToolData) {
defaultDropdownItems.forEach(item => {
- item.params = {
- eventData,
- nearbyToolData,
- };
-
- if (item.actionType === 'Delete') {
- item.text = 'Delete measurement';
- }
-
- if (item.actionType === 'setLabel') {
- item.text = 'Relabel';
- }
+ item.params = { eventData, nearbyToolData };
if (item.actionType === 'setDescription') {
- item.text = `${
+ item.label = `${
nearbyToolData.tool.description ? 'Edit' : 'Add'
} Description`;
}
@@ -89,7 +83,7 @@ const ToolContextMenu = ({
return dropdownItems;
};
- const itemOnClickHandler = (action, params, onClose) => {
+ const onClickHandler = ({ action, params }) => {
action(params);
if (onClose) {
onClose();
@@ -99,23 +93,9 @@ const ToolContextMenu = ({
const dropdownItems = getDropdownItems(eventData, isTouchEvent);
return (
- dropdownItems.length &&
- eventData && (
-
-
- {dropdownItems.map(({ params, action, text, actionType }) => (
- -
-
-
- ))}
-
-
- )
+
+ ;
+
);
};
@@ -123,6 +103,9 @@ ToolContextMenu.propTypes = {
isTouchEvent: PropTypes.bool.isRequired,
eventData: PropTypes.object,
onClose: PropTypes.func,
+ onSetDescription: PropTypes.func,
+ onSetLabel: PropTypes.func,
+ onDelete: PropTypes.func,
};
ToolContextMenu.defaultProps = {