OHIF with Cornerstone3D 2.0 (#4347)
This commit is contained in:
1 parent
8981a61b8c
commit
7ce7127d7c
803 files changed
+32760
-15893
No files matched your search
@@ -12,15 +12,23 @@ import {
|
||||
utilities as cstUtils,
|
||||
ReferenceLinesTool,
|
||||
} from '@cornerstonejs/tools';
|
||||
|
||||
import { Types as OhifTypes } from '@ohif/core';
|
||||
import {
|
||||
callLabelAutocompleteDialog,
|
||||
showLabelAnnotationPopup,
|
||||
createReportAsync,
|
||||
callInputDialog,
|
||||
colorPickerDialog,
|
||||
} from '@ohif/extension-default';
|
||||
import { vec3, mat4 } from 'gl-matrix';
|
||||
|
||||
import CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';
|
||||
import { callLabelAutocompleteDialog, showLabelAnnotationPopup } from './utils/callInputDialog';
|
||||
import toggleImageSliceSync from './utils/imageSliceSync/toggleImageSliceSync';
|
||||
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
|
||||
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
|
||||
import toggleVOISliceSync from './utils/toggleVOISliceSync';
|
||||
import { usePositionPresentationStore, useSegmentationPresentationStore } from './stores';
|
||||
|
||||
const toggleSyncFunctions = {
|
||||
imageSlice: toggleImageSliceSync,
|
||||
@@ -29,6 +37,7 @@ const toggleSyncFunctions = {
|
||||
|
||||
function commandsModule({
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
commandsManager,
|
||||
}: OhifTypes.Extensions.ExtensionParams): OhifTypes.Extensions.CommandsModule {
|
||||
const {
|
||||
@@ -101,7 +110,49 @@ function commandsModule({
|
||||
|
||||
commandsManager.run(options, optionsToUse);
|
||||
},
|
||||
updateStoredSegmentationPresentation: ({ displaySet, type }) => {
|
||||
const { setSegmentationPresentation } = useSegmentationPresentationStore.getState();
|
||||
|
||||
const referencedDisplaySetInstanceUID = displaySet.referencedDisplaySetInstanceUID;
|
||||
setSegmentationPresentation(referencedDisplaySetInstanceUID, [
|
||||
{
|
||||
segmentationId: displaySet.displaySetInstanceUID,
|
||||
hydrated: true,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
},
|
||||
updateStoredPositionPresentation: ({ viewportId, displaySetInstanceUID }) => {
|
||||
const presentations = cornerstoneViewportService.getPresentations(viewportId);
|
||||
const { positionPresentationStore, setPositionPresentation, getPositionPresentationId } =
|
||||
usePositionPresentationStore.getState();
|
||||
|
||||
// Look inside positionPresentationStore and find the key that includes the displaySetInstanceUID
|
||||
// and the value has viewportId as activeViewportId.
|
||||
const previousReferencedDisplaySetStoreKey = Object.entries(positionPresentationStore).find(
|
||||
([key, value]) => key.includes(displaySetInstanceUID) && value.viewportId === viewportId
|
||||
)?.[0];
|
||||
|
||||
if (previousReferencedDisplaySetStoreKey) {
|
||||
setPositionPresentation(
|
||||
previousReferencedDisplaySetStoreKey,
|
||||
presentations.positionPresentation
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if not found means we have not visited that referencedDisplaySetInstanceUID before
|
||||
// so we need to grab the positionPresentationId directly from the store,
|
||||
// Todo: this is really hacky, we should have a better way for this
|
||||
|
||||
const positionPresentationId = getPositionPresentationId({
|
||||
displaySetInstanceUIDs: [displaySetInstanceUID],
|
||||
viewportId,
|
||||
});
|
||||
|
||||
setPositionPresentation(positionPresentationId, presentations.positionPresentation);
|
||||
},
|
||||
getNearbyToolData({ nearbyToolData, element, canvasCoordinates }) {
|
||||
return nearbyToolData ?? cstUtils.getAnnotationNearPoint(element, canvasCoordinates);
|
||||
},
|
||||
@@ -435,9 +486,10 @@ function commandsModule({
|
||||
viewport.setCamera({ viewUp: rotatedViewUp as CoreTypes.Point3 });
|
||||
viewport.render();
|
||||
} else if (viewport.getRotation !== undefined) {
|
||||
const currentRotation = viewport.getRotation();
|
||||
const presentation = viewport.getViewPresentation();
|
||||
const { rotation: currentRotation } = presentation;
|
||||
const newRotation = (currentRotation + rotation) % 360;
|
||||
viewport.setProperties({ rotation: newRotation });
|
||||
viewport.setViewPresentation({ rotation: newRotation });
|
||||
viewport.render();
|
||||
}
|
||||
},
|
||||
@@ -554,7 +606,7 @@ function commandsModule({
|
||||
|
||||
// Set slice to last slice
|
||||
const options = { imageIndex: jumpIndex };
|
||||
cstUtils.jumpToSlice(viewport.element, options);
|
||||
csUtils.jumpToSlice(viewport.element, options);
|
||||
},
|
||||
scroll: ({ direction }) => {
|
||||
const enabledElement = _getActiveViewportEnabledElement();
|
||||
@@ -566,7 +618,7 @@ function commandsModule({
|
||||
const { viewport } = enabledElement;
|
||||
const options = { delta: direction };
|
||||
|
||||
cstUtils.scroll(viewport, options);
|
||||
csUtils.scroll(viewport, options);
|
||||
},
|
||||
setViewportColormap: ({
|
||||
viewportId,
|
||||
@@ -577,7 +629,6 @@ function commandsModule({
|
||||
}) => {
|
||||
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
||||
|
||||
const actorEntries = viewport.getActors();
|
||||
let hpOpacity;
|
||||
// Retrieve active protocol's viewport match details
|
||||
const { viewportMatchDetails } = hangingProtocolService.getActiveProtocol();
|
||||
@@ -596,14 +647,8 @@ function commandsModule({
|
||||
// HP takes priority over the default opacity
|
||||
colormap = { ...colormap, opacity: hpOpacity || opacity };
|
||||
|
||||
const setViewportProperties = (viewport, uid) => {
|
||||
const actorEntry = actorEntries.find(entry => entry.uid.includes(uid));
|
||||
const { actor: volumeActor, uid: volumeId } = actorEntry;
|
||||
viewport.setProperties({ colormap, volumeActor }, volumeId);
|
||||
};
|
||||
|
||||
if (viewport instanceof StackViewport) {
|
||||
setViewportProperties(viewport, viewportId);
|
||||
viewport.setProperties({ colormap });
|
||||
}
|
||||
|
||||
if (viewport instanceof VolumeViewport) {
|
||||
@@ -611,7 +656,9 @@ function commandsModule({
|
||||
const { viewports } = viewportGridService.getState();
|
||||
displaySetInstanceUID = viewports.get(viewportId)?.displaySetInstanceUIDs[0];
|
||||
}
|
||||
setViewportProperties(viewport, displaySetInstanceUID);
|
||||
|
||||
const volumeId = viewport.getVolumeId();
|
||||
viewport.setProperties({ colormap }, volumeId);
|
||||
}
|
||||
|
||||
if (immediate) {
|
||||
@@ -827,6 +874,339 @@ function commandsModule({
|
||||
ins?.resetCrosshairs();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Creates a labelmap for the active viewport
|
||||
*/
|
||||
createLabelmapForViewport: async ({ viewportId, options = {} }) => {
|
||||
const { viewportGridService, displaySetService, segmentationService } =
|
||||
servicesManager.services;
|
||||
const { viewports } = viewportGridService.getState();
|
||||
const targetViewportId = viewportId;
|
||||
|
||||
const viewport = viewports.get(targetViewportId);
|
||||
|
||||
// Todo: add support for multiple display sets
|
||||
const displaySetInstanceUID =
|
||||
options.displaySetInstanceUID || viewport.displaySetInstanceUIDs[0];
|
||||
|
||||
const segs = segmentationService.getSegmentations();
|
||||
|
||||
const label = options.label || `Segmentation ${segs.length + 1}`;
|
||||
const segmentationId = options.segmentationId || `${csUtils.uuidv4()}`;
|
||||
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
|
||||
const generatedSegmentationId = await segmentationService.createLabelmapForDisplaySet(
|
||||
displaySet,
|
||||
{
|
||||
label,
|
||||
segmentationId,
|
||||
segments: options.createInitialSegment
|
||||
? {
|
||||
1: {
|
||||
label: 'Segment 1',
|
||||
active: true,
|
||||
},
|
||||
}
|
||||
: {},
|
||||
}
|
||||
);
|
||||
|
||||
await segmentationService.addSegmentationRepresentation(viewportId, {
|
||||
segmentationId,
|
||||
type: Enums.SegmentationRepresentations.Labelmap,
|
||||
});
|
||||
|
||||
return generatedSegmentationId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the active segmentation for a viewport
|
||||
* @param props.segmentationId - The ID of the segmentation to set as active
|
||||
*/
|
||||
setActiveSegmentation: ({ segmentationId }) => {
|
||||
const { viewportGridService, segmentationService } = servicesManager.services;
|
||||
segmentationService.setActiveSegmentation(
|
||||
viewportGridService.getActiveViewportId(),
|
||||
segmentationId
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new segment to a segmentation
|
||||
* @param props.segmentationId - The ID of the segmentation to add the segment to
|
||||
*/
|
||||
addSegmentCommand: ({ segmentationId }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.addSegment(segmentationId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the active segment and jumps to its center
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
* @param props.segmentIndex - The index of the segment to activate
|
||||
*/
|
||||
setActiveSegmentAndCenterCommand: ({ segmentationId, segmentIndex }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setActiveSegment(segmentationId, segmentIndex);
|
||||
segmentationService.jumpToSegmentCenter(segmentationId, segmentIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the visibility of a segment
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
* @param props.segmentIndex - The index of the segment
|
||||
* @param props.type - The type of visibility to toggle
|
||||
*/
|
||||
toggleSegmentVisibilityCommand: ({ segmentationId, segmentIndex, type }) => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
segmentationService.toggleSegmentVisibility(
|
||||
viewportGridService.getActiveViewportId(),
|
||||
segmentationId,
|
||||
segmentIndex,
|
||||
type
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the lock state of a segment
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
* @param props.segmentIndex - The index of the segment
|
||||
*/
|
||||
toggleSegmentLockCommand: ({ segmentationId, segmentIndex }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.toggleSegmentLocked(segmentationId, segmentIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the visibility of a segmentation representation
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
* @param props.type - The type of representation
|
||||
*/
|
||||
toggleSegmentationVisibilityCommand: ({ segmentationId, type }) => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
segmentationService.toggleSegmentationRepresentationVisibility(
|
||||
viewportGridService.getActiveViewportId(),
|
||||
{ segmentationId, type }
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Downloads a segmentation
|
||||
* @param props.segmentationId - The ID of the segmentation to download
|
||||
*/
|
||||
downloadSegmentationCommand: ({ segmentationId }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.downloadSegmentation(segmentationId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stores a segmentation and shows it in the viewport
|
||||
* @param props.segmentationId - The ID of the segmentation to store
|
||||
*/
|
||||
storeSegmentationCommand: async ({ segmentationId }) => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
const datasources = extensionManager.getActiveDataSource();
|
||||
|
||||
const displaySetInstanceUIDs = await createReportAsync({
|
||||
servicesManager,
|
||||
getReport: () =>
|
||||
commandsManager.runCommand('storeSegmentation', {
|
||||
segmentationId,
|
||||
dataSource: datasources[0],
|
||||
}),
|
||||
reportType: 'Segmentation',
|
||||
});
|
||||
|
||||
if (displaySetInstanceUIDs) {
|
||||
segmentationService.remove(segmentationId);
|
||||
viewportGridService.setDisplaySetsForViewport({
|
||||
viewportId: viewportGridService.getActiveViewportId(),
|
||||
displaySetInstanceUIDs,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Downloads a segmentation as RTSS
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
*/
|
||||
downloadRTSSCommand: ({ segmentationId }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.downloadRTSS(segmentationId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the style for a segmentation
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
* @param props.type - The type of style
|
||||
* @param props.key - The style key to set
|
||||
* @param props.value - The style value
|
||||
*/
|
||||
setSegmentationStyleCommand: ({ segmentationId, type, key, value }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setStyle({ type }, { [key]: value });
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a segment from a segmentation
|
||||
* @param props.segmentationId - The ID of the segmentation
|
||||
* @param props.segmentIndex - The index of the segment to delete
|
||||
*/
|
||||
deleteSegmentCommand: ({ segmentationId, segmentIndex }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.removeSegment(segmentationId, segmentIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes an entire segmentation
|
||||
* @param props.segmentationId - The ID of the segmentation to delete
|
||||
*/
|
||||
deleteSegmentationCommand: ({ segmentationId }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.remove(segmentationId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a segmentation from the viewport
|
||||
* @param props.segmentationId - The ID of the segmentation to remove
|
||||
*/
|
||||
removeSegmentationFromViewportCommand: ({ segmentationId }) => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
segmentationService.removeSegmentationRepresentations(
|
||||
viewportGridService.getActiveViewportId(),
|
||||
{ segmentationId }
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles rendering of inactive segmentations
|
||||
*/
|
||||
toggleRenderInactiveSegmentationsCommand: () => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
const viewportId = viewportGridService.getActiveViewportId();
|
||||
const renderInactive = segmentationService.getRenderInactiveSegmentations(viewportId);
|
||||
segmentationService.setRenderInactiveSegmentations(viewportId, !renderInactive);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the fill alpha value for a segmentation type
|
||||
* @param props.type - The type of segmentation
|
||||
* @param props.value - The alpha value to set
|
||||
*/
|
||||
setFillAlphaCommand: ({ type, value }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setStyle({ type }, { fillAlpha: value });
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the outline width for a segmentation type
|
||||
* @param props.type - The type of segmentation
|
||||
* @param props.value - The width value to set
|
||||
*/
|
||||
setOutlineWidthCommand: ({ type, value }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setStyle({ type }, { outlineWidth: value });
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets whether to render fill for a segmentation type
|
||||
* @param props.type - The type of segmentation
|
||||
* @param props.value - Whether to render fill
|
||||
*/
|
||||
setRenderFillCommand: ({ type, value }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setStyle({ type }, { renderFill: value });
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets whether to render outline for a segmentation type
|
||||
* @param props.type - The type of segmentation
|
||||
* @param props.value - Whether to render outline
|
||||
*/
|
||||
setRenderOutlineCommand: ({ type, value }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setStyle({ type }, { renderOutline: value });
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the fill alpha for inactive segmentations
|
||||
* @param props.type - The type of segmentation
|
||||
* @param props.value - The alpha value to set
|
||||
*/
|
||||
setFillAlphaInactiveCommand: ({ type, value }) => {
|
||||
const { segmentationService } = servicesManager.services;
|
||||
segmentationService.setStyle({ type }, { fillAlphaInactive: value });
|
||||
},
|
||||
|
||||
editSegmentLabel: ({ segmentationId, segmentIndex }) => {
|
||||
const { segmentationService, uiDialogService } = servicesManager.services;
|
||||
const segmentation = segmentationService.getSegmentation(segmentationId);
|
||||
|
||||
if (!segmentation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const segment = segmentation.segments[segmentIndex];
|
||||
const { label } = segment;
|
||||
|
||||
callInputDialog(uiDialogService, label, (label, actionId) => {
|
||||
if (label === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
segmentationService.setSegmentLabel(segmentationId, segmentIndex, label);
|
||||
});
|
||||
},
|
||||
|
||||
editSegmentationLabel: ({ segmentationId }) => {
|
||||
const { segmentationService, uiDialogService } = servicesManager.services;
|
||||
const segmentation = segmentationService.getSegmentation(segmentationId);
|
||||
|
||||
if (!segmentation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { label } = segmentation;
|
||||
|
||||
callInputDialog(uiDialogService, label, (label, actionId) => {
|
||||
if (label === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
segmentationService.addOrUpdateSegmentation({ segmentationId, label });
|
||||
});
|
||||
},
|
||||
|
||||
editSegmentColor: ({ segmentationId, segmentIndex }) => {
|
||||
const { segmentationService, uiDialogService, viewportGridService } =
|
||||
servicesManager.services;
|
||||
const viewportId = viewportGridService.getActiveViewportId();
|
||||
const color = segmentationService.getSegmentColor(viewportId, segmentationId, segmentIndex);
|
||||
|
||||
const rgbaColor = {
|
||||
r: color[0],
|
||||
g: color[1],
|
||||
b: color[2],
|
||||
a: color[3] / 255.0,
|
||||
};
|
||||
|
||||
colorPickerDialog(uiDialogService, rgbaColor, (newRgbaColor, actionId) => {
|
||||
if (actionId === 'cancel') {
|
||||
return;
|
||||
}
|
||||
|
||||
const color = [newRgbaColor.r, newRgbaColor.g, newRgbaColor.b, newRgbaColor.a * 255.0];
|
||||
segmentationService.setSegmentColor(viewportId, segmentationId, segmentIndex, color);
|
||||
});
|
||||
},
|
||||
|
||||
getRenderInactiveSegmentations: () => {
|
||||
const { segmentationService, viewportGridService } = servicesManager.services;
|
||||
return segmentationService.getRenderInactiveSegmentations(
|
||||
viewportGridService.getActiveViewportId()
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
@@ -988,6 +1368,84 @@ function commandsModule({
|
||||
toggleActiveDisabledToolbar: {
|
||||
commandFn: actions.toggleActiveDisabledToolbar,
|
||||
},
|
||||
updateStoredPositionPresentation: {
|
||||
commandFn: actions.updateStoredPositionPresentation,
|
||||
},
|
||||
updateStoredSegmentationPresentation: {
|
||||
commandFn: actions.updateStoredSegmentationPresentation,
|
||||
},
|
||||
createLabelmapForViewport: {
|
||||
commandFn: actions.createLabelmapForViewport,
|
||||
},
|
||||
setActiveSegmentation: {
|
||||
commandFn: actions.setActiveSegmentation,
|
||||
},
|
||||
addSegment: {
|
||||
commandFn: actions.addSegmentCommand,
|
||||
},
|
||||
setActiveSegmentAndCenter: {
|
||||
commandFn: actions.setActiveSegmentAndCenterCommand,
|
||||
},
|
||||
toggleSegmentVisibility: {
|
||||
commandFn: actions.toggleSegmentVisibilityCommand,
|
||||
},
|
||||
toggleSegmentLock: {
|
||||
commandFn: actions.toggleSegmentLockCommand,
|
||||
},
|
||||
toggleSegmentationVisibility: {
|
||||
commandFn: actions.toggleSegmentationVisibilityCommand,
|
||||
},
|
||||
downloadSegmentation: {
|
||||
commandFn: actions.downloadSegmentationCommand,
|
||||
},
|
||||
storeSegmentation: {
|
||||
commandFn: actions.storeSegmentationCommand,
|
||||
},
|
||||
downloadRTSS: {
|
||||
commandFn: actions.downloadRTSSCommand,
|
||||
},
|
||||
setSegmentationStyle: {
|
||||
commandFn: actions.setSegmentationStyleCommand,
|
||||
},
|
||||
deleteSegment: {
|
||||
commandFn: actions.deleteSegmentCommand,
|
||||
},
|
||||
deleteSegmentation: {
|
||||
commandFn: actions.deleteSegmentationCommand,
|
||||
},
|
||||
removeSegmentationFromViewport: {
|
||||
commandFn: actions.removeSegmentationFromViewportCommand,
|
||||
},
|
||||
toggleRenderInactiveSegmentations: {
|
||||
commandFn: actions.toggleRenderInactiveSegmentationsCommand,
|
||||
},
|
||||
setFillAlpha: {
|
||||
commandFn: actions.setFillAlphaCommand,
|
||||
},
|
||||
setOutlineWidth: {
|
||||
commandFn: actions.setOutlineWidthCommand,
|
||||
},
|
||||
setRenderFill: {
|
||||
commandFn: actions.setRenderFillCommand,
|
||||
},
|
||||
setRenderOutline: {
|
||||
commandFn: actions.setRenderOutlineCommand,
|
||||
},
|
||||
setFillAlphaInactive: {
|
||||
commandFn: actions.setFillAlphaInactiveCommand,
|
||||
},
|
||||
editSegmentLabel: {
|
||||
commandFn: actions.editSegmentLabel,
|
||||
},
|
||||
editSegmentationLabel: {
|
||||
commandFn: actions.editSegmentationLabel,
|
||||
},
|
||||
editSegmentColor: {
|
||||
commandFn: actions.editSegmentColor,
|
||||
},
|
||||
getRenderInactiveSegmentations: {
|
||||
commandFn: actions.getRenderInactiveSegmentations,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
Reference in new issue
Block a user