refactor: Remove LabelingFlow/ContextMenu services and reimplement on top of the Dialog service #1264 (#1292)
* Remove ContextMenu and Labelling services and provider to use DialogService directly * Refactor init to display labelling * Cleanup labelling flow in measurements init * Cleanup viewer imports * Add classname to toolcontextmenu * Add error message
This commit is contained in:
parent
f78abe2afa
commit
b58aa4575a
@ -23,8 +23,6 @@ import {
|
|||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
} from './services';
|
} from './services';
|
||||||
|
|
||||||
const OHIF = {
|
const OHIF = {
|
||||||
@ -55,8 +53,6 @@ const OHIF = {
|
|||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -86,8 +82,6 @@ export {
|
|||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { OHIF };
|
export { OHIF };
|
||||||
|
|||||||
@ -13,8 +13,6 @@ describe('Top level exports', () => {
|
|||||||
'UINotificationService',
|
'UINotificationService',
|
||||||
'UIModalService',
|
'UIModalService',
|
||||||
'UIDialogService',
|
'UIDialogService',
|
||||||
'UIContextMenuService',
|
|
||||||
'UILabellingFlowService',
|
|
||||||
//
|
//
|
||||||
'utils',
|
'utils',
|
||||||
'studies',
|
'studies',
|
||||||
|
|||||||
@ -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;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -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;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -2,14 +2,10 @@ import ServicesManager from './ServicesManager.js';
|
|||||||
import UINotificationService from './UINotificationService';
|
import UINotificationService from './UINotificationService';
|
||||||
import UIModalService from './UIModalService';
|
import UIModalService from './UIModalService';
|
||||||
import UIDialogService from './UIDialogService';
|
import UIDialogService from './UIDialogService';
|
||||||
import UIContextMenuService from './UIContextMenuService';
|
|
||||||
import UILabellingFlowService from './UILabellingFlowService';
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
ServicesManager,
|
ServicesManager,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,20 +1,19 @@
|
|||||||
.ToolContextMenu {
|
.ContextMenu {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 1px solid white;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
display: block;
|
display: block;
|
||||||
width: 170px;
|
width: 170px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ToolContextMenu > ul {
|
.ContextMenu>ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ToolContextMenu > ul > li > button {
|
.ContextMenu>ul>li>button {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border: none;
|
border: none;
|
||||||
@ -25,10 +24,10 @@
|
|||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ToolContextMenu > ul > li > button:hover {
|
.ContextMenu>ul>li>button:hover {
|
||||||
color: #16202b;
|
color: #16202b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ToolContextMenu > ul > li > button:active {
|
.ContextMenu>ul>li>button:active {
|
||||||
color: #79f9fe;
|
color: #79f9fe;
|
||||||
}
|
}
|
||||||
27
platform/ui/src/components/contextMenu/ContextMenu.js
Normal file
27
platform/ui/src/components/contextMenu/ContextMenu.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import './ContextMenu.css';
|
||||||
|
|
||||||
|
const ContextMenu = ({ items, onClick }) => {
|
||||||
|
return (
|
||||||
|
<div className="ContextMenu">
|
||||||
|
<ul>
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<li key={index}>
|
||||||
|
<button className="form-action" onClick={() => onClick(item)}>
|
||||||
|
<span key={index}>{item.label}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ContextMenu.propTypes = {
|
||||||
|
items: PropTypes.array.isRequired,
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ContextMenu;
|
||||||
1
platform/ui/src/components/contextMenu/index.js
Normal file
1
platform/ui/src/components/contextMenu/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as ContextMenu } from './ContextMenu.js';
|
||||||
@ -17,6 +17,7 @@ import { RoundedButtonGroup } from './roundedButtonGroup';
|
|||||||
import { SelectTree } from './selectTree';
|
import { SelectTree } from './selectTree';
|
||||||
import { SimpleDialog } from './simpleDialog';
|
import { SimpleDialog } from './simpleDialog';
|
||||||
import { OHIFModal } from './ohifModal';
|
import { OHIFModal } from './ohifModal';
|
||||||
|
import { ContextMenu } from './contextMenu';
|
||||||
import {
|
import {
|
||||||
PageToolbar,
|
PageToolbar,
|
||||||
StudyList,
|
StudyList,
|
||||||
@ -27,6 +28,7 @@ import { ToolbarSection } from './toolbarSection';
|
|||||||
import { Tooltip } from './tooltip';
|
import { Tooltip } from './tooltip';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
ContextMenu,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
ViewportDownloadForm,
|
ViewportDownloadForm,
|
||||||
|
|||||||
@ -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 (
|
|
||||||
<Provider
|
|
||||||
value={{
|
|
||||||
show,
|
|
||||||
hide,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 (
|
|
||||||
<Component
|
|
||||||
{...props}
|
|
||||||
modal={{
|
|
||||||
show,
|
|
||||||
hide,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
@ -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 (
|
|
||||||
<Provider
|
|
||||||
value={{
|
|
||||||
show,
|
|
||||||
hide,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 (
|
|
||||||
<Component
|
|
||||||
{...props}
|
|
||||||
modal={{
|
|
||||||
show,
|
|
||||||
hide,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
@ -18,15 +18,3 @@ export {
|
|||||||
withDialog,
|
withDialog,
|
||||||
useDialog,
|
useDialog,
|
||||||
} from './DialogProvider.js';
|
} from './DialogProvider.js';
|
||||||
export {
|
|
||||||
default as ContextMenuProvider,
|
|
||||||
withContextMenu,
|
|
||||||
useContextMenu,
|
|
||||||
ContextMenuConsumer,
|
|
||||||
} from './ContextMenuProvider.js';
|
|
||||||
export {
|
|
||||||
default as LabellingFlowProvider,
|
|
||||||
withLabellingFlow,
|
|
||||||
useLabellingFlow,
|
|
||||||
LabellingFlowConsumer,
|
|
||||||
} from './LabellingFlowProvider.js';
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
ContextMenu,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
ViewportDownloadForm,
|
ViewportDownloadForm,
|
||||||
@ -60,14 +61,6 @@ import {
|
|||||||
ModalConsumer,
|
ModalConsumer,
|
||||||
useModal,
|
useModal,
|
||||||
withModal,
|
withModal,
|
||||||
ContextMenuProvider,
|
|
||||||
ContextMenuConsumer,
|
|
||||||
useContextMenu,
|
|
||||||
withContextMenu,
|
|
||||||
LabellingFlowProvider,
|
|
||||||
LabellingFlowConsumer,
|
|
||||||
useLabellingFlow,
|
|
||||||
withLabellingFlow,
|
|
||||||
} from './contextProviders';
|
} from './contextProviders';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -80,6 +73,7 @@ export {
|
|||||||
TextArea,
|
TextArea,
|
||||||
TextInput,
|
TextInput,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
|
ContextMenu,
|
||||||
ViewportDownloadForm,
|
ViewportDownloadForm,
|
||||||
ExpandableToolMenu,
|
ExpandableToolMenu,
|
||||||
Icon,
|
Icon,
|
||||||
@ -125,14 +119,6 @@ export {
|
|||||||
DialogProvider,
|
DialogProvider,
|
||||||
withDialog,
|
withDialog,
|
||||||
useDialog,
|
useDialog,
|
||||||
ContextMenuProvider,
|
|
||||||
ContextMenuConsumer,
|
|
||||||
useContextMenu,
|
|
||||||
withContextMenu,
|
|
||||||
LabellingFlowProvider,
|
|
||||||
LabellingFlowConsumer,
|
|
||||||
useLabellingFlow,
|
|
||||||
withLabellingFlow,
|
|
||||||
// Hooks
|
// Hooks
|
||||||
useDebounce,
|
useDebounce,
|
||||||
useMedia,
|
useMedia,
|
||||||
|
|||||||
@ -8,9 +8,6 @@ import { hot } from 'react-hot-loader/root';
|
|||||||
|
|
||||||
import OHIFCornerstoneExtension from '@ohif/extension-cornerstone';
|
import OHIFCornerstoneExtension from '@ohif/extension-cornerstone';
|
||||||
|
|
||||||
import ToolContextMenu from './connectedComponents/ToolContextMenu';
|
|
||||||
import LabellingFlow from './components/Labelling/LabellingFlow';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SnackbarProvider,
|
SnackbarProvider,
|
||||||
ModalProvider,
|
ModalProvider,
|
||||||
@ -18,11 +15,6 @@ import {
|
|||||||
OHIFModal,
|
OHIFModal,
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
|
||||||
import {
|
|
||||||
LabellingFlowProvider,
|
|
||||||
ContextMenuProvider,
|
|
||||||
} from './appCustomProviders';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CommandsManager,
|
CommandsManager,
|
||||||
ExtensionManager,
|
ExtensionManager,
|
||||||
@ -31,8 +23,6 @@ import {
|
|||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
utils,
|
utils,
|
||||||
redux as reduxOHIF,
|
redux as reduxOHIF,
|
||||||
} from '@ohif/core';
|
} from '@ohif/core';
|
||||||
@ -135,13 +125,7 @@ class App extends Component {
|
|||||||
} = this._appConfig;
|
} = this._appConfig;
|
||||||
|
|
||||||
this.initUserManager(oidc);
|
this.initUserManager(oidc);
|
||||||
_initServices([
|
_initServices([UINotificationService, UIModalService, UIDialogService]);
|
||||||
UINotificationService,
|
|
||||||
UIModalService,
|
|
||||||
UIDialogService,
|
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
]);
|
|
||||||
_initExtensions(
|
_initExtensions(
|
||||||
[...defaultExtensions, ...extensions],
|
[...defaultExtensions, ...extensions],
|
||||||
cornerstoneExtensionConfig
|
cornerstoneExtensionConfig
|
||||||
@ -161,9 +145,7 @@ class App extends Component {
|
|||||||
const {
|
const {
|
||||||
UINotificationService,
|
UINotificationService,
|
||||||
UIDialogService,
|
UIDialogService,
|
||||||
UILabellingFlowService,
|
|
||||||
UIModalService,
|
UIModalService,
|
||||||
UIContextMenuService,
|
|
||||||
} = servicesManager.services;
|
} = servicesManager.services;
|
||||||
|
|
||||||
if (this._userManager) {
|
if (this._userManager) {
|
||||||
@ -181,21 +163,9 @@ class App extends Component {
|
|||||||
modal={OHIFModal}
|
modal={OHIFModal}
|
||||||
service={UIModalService}
|
service={UIModalService}
|
||||||
>
|
>
|
||||||
<LabellingFlowProvider
|
<OHIFStandaloneViewer
|
||||||
service={UILabellingFlowService}
|
userManager={this._userManager}
|
||||||
labellingComponent={LabellingFlow}
|
/>
|
||||||
commandsManager={commandsManager}
|
|
||||||
>
|
|
||||||
<ContextMenuProvider
|
|
||||||
service={UIContextMenuService}
|
|
||||||
contextMenuComponent={ToolContextMenu}
|
|
||||||
commandsManager={commandsManager}
|
|
||||||
>
|
|
||||||
<OHIFStandaloneViewer
|
|
||||||
userManager={this._userManager}
|
|
||||||
/>
|
|
||||||
</ContextMenuProvider>
|
|
||||||
</LabellingFlowProvider>
|
|
||||||
</ModalProvider>
|
</ModalProvider>
|
||||||
</DialogProvider>
|
</DialogProvider>
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
@ -218,19 +188,7 @@ class App extends Component {
|
|||||||
<SnackbarProvider service={UINotificationService}>
|
<SnackbarProvider service={UINotificationService}>
|
||||||
<DialogProvider service={UIDialogService}>
|
<DialogProvider service={UIDialogService}>
|
||||||
<ModalProvider modal={OHIFModal} service={UIModalService}>
|
<ModalProvider modal={OHIFModal} service={UIModalService}>
|
||||||
<LabellingFlowProvider
|
<OHIFStandaloneViewer />
|
||||||
service={UILabellingFlowService}
|
|
||||||
labellingComponent={LabellingFlow}
|
|
||||||
commandsManager={commandsManager}
|
|
||||||
>
|
|
||||||
<ContextMenuProvider
|
|
||||||
service={UIContextMenuService}
|
|
||||||
contextMenuComponent={ToolContextMenu}
|
|
||||||
commandsManager={commandsManager}
|
|
||||||
>
|
|
||||||
<OHIFStandaloneViewer />
|
|
||||||
</ContextMenuProvider>
|
|
||||||
</LabellingFlowProvider>
|
|
||||||
</ModalProvider>
|
</ModalProvider>
|
||||||
</DialogProvider>
|
</DialogProvider>
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
|
|||||||
@ -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 (
|
|
||||||
<ContextMenuProvider
|
|
||||||
service={service}
|
|
||||||
contextMenuComponent={contextMenuComponent}
|
|
||||||
onDelete={onDeleteHandler}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</ContextMenuProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
@ -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 (
|
|
||||||
<LabellingFlowProvider
|
|
||||||
service={service}
|
|
||||||
labellingComponent={labellingComponent}
|
|
||||||
onUpdateLabelling={onUpdateLabellingHandler}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</LabellingFlowProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
export {
|
|
||||||
default as LabellingFlowProvider,
|
|
||||||
} from './LabellingFlowProvider/LabellingFlowProvider.js';
|
|
||||||
export {
|
|
||||||
default as ContextMenuProvider,
|
|
||||||
} from './ContextMenuProvider/ContextMenuProvider.js';
|
|
||||||
@ -2,6 +2,8 @@ import React from 'react';
|
|||||||
import ConnectedMeasurementTable from './ConnectedMeasurementTable.js';
|
import ConnectedMeasurementTable from './ConnectedMeasurementTable.js';
|
||||||
import init from './init.js';
|
import init from './init.js';
|
||||||
|
|
||||||
|
import LabellingFlow from '../../components/Labelling/LabellingFlow';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Only required property. Should be a unique value across all extensions.
|
* Only required property. Should be a unique value across all extensions.
|
||||||
@ -13,32 +15,51 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getPanelModule({ servicesManager, commandsManager }) {
|
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 = () => (
|
const ExtendedConnectedMeasurementTable = () => (
|
||||||
<ConnectedMeasurementTable
|
<ConnectedMeasurementTable
|
||||||
onRelabel={tool => {
|
onRelabel={tool =>
|
||||||
if (UILabellingFlowService) {
|
showLabellingDialog(
|
||||||
UILabellingFlowService.show({
|
{ editLocation: true, skipAddLabelButton: true },
|
||||||
centralize: true,
|
tool
|
||||||
props: {
|
)
|
||||||
skipAddLabelButton: true,
|
}
|
||||||
editLocation: true,
|
onEditDescription={tool =>
|
||||||
measurementData: tool,
|
showLabellingDialog({ editDescriptionOnDialog: true }, tool)
|
||||||
},
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onEditDescription={tool => {
|
|
||||||
if (UILabellingFlowService) {
|
|
||||||
UILabellingFlowService.show({
|
|
||||||
centralize: true,
|
|
||||||
props: {
|
|
||||||
editDescriptionOnDialog: true,
|
|
||||||
measurementData: tool,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onSaveComplete={message => {
|
onSaveComplete={message => {
|
||||||
if (UINotificationService) {
|
if (UINotificationService) {
|
||||||
UINotificationService.show(message);
|
UINotificationService.show(message);
|
||||||
|
|||||||
@ -3,6 +3,9 @@ import cornerstone from 'cornerstone-core';
|
|||||||
import csTools from 'cornerstone-tools';
|
import csTools from 'cornerstone-tools';
|
||||||
import throttle from 'lodash.throttle';
|
import throttle from 'lodash.throttle';
|
||||||
|
|
||||||
|
import LabellingFlow from '../../components/Labelling/LabellingFlow';
|
||||||
|
import ToolContextMenu from '../../connectedComponents/ToolContextMenu';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
onAdded,
|
onAdded,
|
||||||
onRemoved,
|
onRemoved,
|
||||||
@ -29,10 +32,7 @@ export default function init({
|
|||||||
commandsManager,
|
commandsManager,
|
||||||
configuration,
|
configuration,
|
||||||
}) {
|
}) {
|
||||||
const {
|
const { UIDialogService } = servicesManager.services;
|
||||||
UIContextMenuService,
|
|
||||||
UILabellingFlowService,
|
|
||||||
} = servicesManager.services;
|
|
||||||
|
|
||||||
// TODO: MEASUREMENT_COMPLETED (not present in initial implementation)
|
// TODO: MEASUREMENT_COMPLETED (not present in initial implementation)
|
||||||
const onMeasurementsChanged = (action, event) => {
|
const onMeasurementsChanged = (action, event) => {
|
||||||
@ -46,21 +46,108 @@ export default function init({
|
|||||||
'labelmapModified'
|
'labelmapModified'
|
||||||
);
|
);
|
||||||
|
|
||||||
const onRightClick = event => {
|
const _getDefaultPosition = event => ({
|
||||||
if (UIContextMenuService) {
|
x: (event && event.currentPoints.client.x) || 0,
|
||||||
UIContextMenuService.show({ event: event.detail });
|
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 => {
|
const onTouchPress = event => {
|
||||||
if (UIContextMenuService) {
|
if (!UIDialogService) {
|
||||||
UIContextMenuService.show({
|
console.warn('Unable to show dialog; no UI Dialog Service available.');
|
||||||
event: event.detail,
|
return;
|
||||||
props: {
|
|
||||||
isTouchEvent: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UIDialogService.create({
|
||||||
|
eventData: event.detail,
|
||||||
|
content: ToolContextMenu,
|
||||||
|
contentProps: {
|
||||||
|
isTouchEvent: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onTouchStart = () => resetLabelligAndContextMenu();
|
const onTouchStart = () => resetLabelligAndContextMenu();
|
||||||
@ -68,10 +155,13 @@ export default function init({
|
|||||||
const onMouseClick = () => resetLabelligAndContextMenu();
|
const onMouseClick = () => resetLabelligAndContextMenu();
|
||||||
|
|
||||||
const resetLabelligAndContextMenu = () => {
|
const resetLabelligAndContextMenu = () => {
|
||||||
if (UILabellingFlowService && UIContextMenuService) {
|
if (!UIDialogService) {
|
||||||
UILabellingFlowService.hide();
|
console.warn('Unable to show dialog; no UI Dialog Service available.');
|
||||||
UIContextMenuService.hide();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UIDialogService.dismiss({ id: 'context-menu' });
|
||||||
|
UIDialogService.dismiss({ id: 'labelling' });
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: This makes scrolling painfully slow
|
// TODO: This makes scrolling painfully slow
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { commandsManager } from './../App.js';
|
import { commandsManager } from './../App.js';
|
||||||
|
|
||||||
import './ToolContextMenu.css';
|
import { ContextMenu } from '@ohif/ui';
|
||||||
|
|
||||||
const toolTypes = [
|
const toolTypes = [
|
||||||
'Angle',
|
'Angle',
|
||||||
@ -24,11 +24,13 @@ const ToolContextMenu = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const defaultDropdownItems = [
|
const defaultDropdownItems = [
|
||||||
{
|
{
|
||||||
|
label: 'Delete measurement',
|
||||||
actionType: 'Delete',
|
actionType: 'Delete',
|
||||||
action: ({ nearbyToolData, eventData }) =>
|
action: ({ nearbyToolData, eventData }) =>
|
||||||
onDelete(nearbyToolData, eventData),
|
onDelete(nearbyToolData, eventData),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
label: 'Relabel',
|
||||||
actionType: 'setLabel',
|
actionType: 'setLabel',
|
||||||
action: ({ nearbyToolData, eventData }) => {
|
action: ({ nearbyToolData, eventData }) => {
|
||||||
const { tool: measurementData } = nearbyToolData;
|
const { tool: measurementData } = nearbyToolData;
|
||||||
@ -51,7 +53,10 @@ const ToolContextMenu = ({
|
|||||||
availableToolTypes: toolTypes,
|
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 (
|
if (
|
||||||
isTouchEvent &&
|
isTouchEvent &&
|
||||||
nearbyToolData &&
|
nearbyToolData &&
|
||||||
@ -63,21 +68,10 @@ const ToolContextMenu = ({
|
|||||||
let dropdownItems = [];
|
let dropdownItems = [];
|
||||||
if (nearbyToolData) {
|
if (nearbyToolData) {
|
||||||
defaultDropdownItems.forEach(item => {
|
defaultDropdownItems.forEach(item => {
|
||||||
item.params = {
|
item.params = { eventData, nearbyToolData };
|
||||||
eventData,
|
|
||||||
nearbyToolData,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (item.actionType === 'Delete') {
|
|
||||||
item.text = 'Delete measurement';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.actionType === 'setLabel') {
|
|
||||||
item.text = 'Relabel';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.actionType === 'setDescription') {
|
if (item.actionType === 'setDescription') {
|
||||||
item.text = `${
|
item.label = `${
|
||||||
nearbyToolData.tool.description ? 'Edit' : 'Add'
|
nearbyToolData.tool.description ? 'Edit' : 'Add'
|
||||||
} Description`;
|
} Description`;
|
||||||
}
|
}
|
||||||
@ -89,7 +83,7 @@ const ToolContextMenu = ({
|
|||||||
return dropdownItems;
|
return dropdownItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
const itemOnClickHandler = (action, params, onClose) => {
|
const onClickHandler = ({ action, params }) => {
|
||||||
action(params);
|
action(params);
|
||||||
if (onClose) {
|
if (onClose) {
|
||||||
onClose();
|
onClose();
|
||||||
@ -99,23 +93,9 @@ const ToolContextMenu = ({
|
|||||||
const dropdownItems = getDropdownItems(eventData, isTouchEvent);
|
const dropdownItems = getDropdownItems(eventData, isTouchEvent);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
dropdownItems.length &&
|
<div className="ToolContextMenu">
|
||||||
eventData && (
|
<ContextMenu items={dropdownItems} onClick={onClickHandler} />;
|
||||||
<div className="ToolContextMenu">
|
</div>
|
||||||
<ul className="bounded">
|
|
||||||
{dropdownItems.map(({ params, action, text, actionType }) => (
|
|
||||||
<li key={actionType}>
|
|
||||||
<button
|
|
||||||
className="form-action"
|
|
||||||
onClick={() => itemOnClickHandler(action, params, onClose)}
|
|
||||||
>
|
|
||||||
<span key={actionType}>{text}</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -123,6 +103,9 @@ ToolContextMenu.propTypes = {
|
|||||||
isTouchEvent: PropTypes.bool.isRequired,
|
isTouchEvent: PropTypes.bool.isRequired,
|
||||||
eventData: PropTypes.object,
|
eventData: PropTypes.object,
|
||||||
onClose: PropTypes.func,
|
onClose: PropTypes.func,
|
||||||
|
onSetDescription: PropTypes.func,
|
||||||
|
onSetLabel: PropTypes.func,
|
||||||
|
onDelete: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
ToolContextMenu.defaultProps = {
|
ToolContextMenu.defaultProps = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user