feat!: Ability to configure cornerstone tools via extension configuration (#1229)

* Fix ExtensionManager bug and add test to bandaid

* Add tools configuration to extension manager preinit

* Fix reducing of configs

* Merge internal with external configs

* Merge internal with external configs

* Remove dialog from init in measurementstable

* Testing injected configuration

* New way to set config

* Add new prop to dialog provider to allow disabling last position

* Remove code from preinit in cornerstone

* Add new prop to dialog provider to allow disabling last position

* Add centralize to dialogs

* Reorder dialogs when adding them

* Fix draggable styles (cursor)

* Remove repositioning methods from labelling flow and remove overlay from labelling manager

* Fix empty array being set in bringToFront

* Add new command to update table and pass commands manager to modules/preinit hook

* Ad UIContextMenu service / factory

* Use new contextmenu service in measurementspanel extension

* Use dialogs for arrow annotate in default

* Remove positioning funcionality from tool context menu

* Add context menu service

* Pass commandsModule to extension

* Update edit description dialog and simple dialog to position relative

* Remove style code from labelling flow and manager

* Remove eventdata from labelling

* Remove labelling code from measurement init

* Add commandsmanager to provider

* Update contextmenu provider and service

* Add touchstart and mouseclick to hide contextmenu

* Hide labelling if click/touch

* Remove labelling and context menu dead code

* Fix undefined bug if ViewerMain grid has no children

* Fix broken prop on context menu

* Update commandsmodule based on master

* Fix broken configuration

* Update script tag config

* Remove cornerstone from toolcontextmenu

* Remove cornerstone from toolcontextmenu

* Split labelling and context menu providers

* Split labelling and context menu providers

* Update test

* Destructure extensions into new array

* CR Update: Move default arrow config to cornerstone instead of default

* CR Update: Fix app configuration props structure

* CR Update: Fix app configuration prop in script tag and extract commands manager from providers

* CR Update: Create custom providers to use commandsManager

* CR Update: Use services directly in measurementspanel

* CR Update: Pass components to providers

* CR Update: Remove position from dialog

* CR Update: fix dialog prop check

* CR Update: Fix comments

* CR Update: Update documentation

* CR Update: Add test default configuration

* CR Update: Add default empy array to extensions

* CR Update: Update i18n configuration all ot match current function configuration

* CR Update: Add defaults to injected dependencies in configuration and extension configuration

* CR Update: Add defaults to configuration with no args

* Update documentation

* CR Update: Add default for tools

* CR Update: Update config object to i18n

* CR Update: spread defaults

* CR Update: Add tool configuration example to cornerstone extension

* CR Update: Add tool configuration to netlify (testing)

* CR Update: Remove netlify config for tools

* CR Update: Rollback changes to i18n to be fixed later

* CR Update: Update documentation and pass whole cornerstone config object instead of tools key

SEE: https://www.conventionalcommits.org/en/v1.0.0/#commit-message-with-both-and-breaking-change-footer

BREAKING CHANGE: modifies the exposed react <App /> components props. The contract for providing configuration for the app has changed. Please reference updated documentation for guidance.
This commit is contained in:
Igor Octaviano authored and Danny Brown committed 2019-12-09 12:47:23 -05:00
1 parent fd7620ced9
commit 55a580659e
66 files changed
+1464 -1223

No files matched your search

+1 -1
View File
@@ -59,7 +59,7 @@ export class CommandsManager {
*
* @method
* @param {string} contextName - Namespace for commands
* @returs {Object} - the matched context
* @returns {Object} - the matched context
*/
getContext(contextName) {
const context = this.contexts[contextName];
@@ -26,7 +26,7 @@ export default class ExtensionManager {
const hasConfiguration = Array.isArray(extension);
if (hasConfiguration) {
const [ohifExtension, configuration] = extensions;
const [ohifExtension, configuration] = extension;
this.registerExtension(ohifExtension, configuration);
} else {
this.registerExtension(extension);
@@ -37,6 +37,24 @@ describe('ExtensionManager.js', () => {
// Assert
expect(extensionManager.registerExtension.mock.calls.length).toBe(3);
});
it('calls registerExtension() for each extension passing its configuration if tuple', () => {
const fakeConfiguration = { testing: true };
extensionManager.registerExtension = jest.fn();
// SUT
const fakeExtensions = [
{ one: '1' },
[{ two: '2' }, fakeConfiguration],
{ three: '3 ' },
];
extensionManager.registerExtensions(fakeExtensions);
// Assert
expect(extensionManager.registerExtension.mock.calls[1]).toContain(
fakeConfiguration
);
});
});
describe('registerExtension()', () => {
+6
View File
@@ -23,6 +23,8 @@ import {
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
} from './services';
const OHIF = {
@@ -53,6 +55,8 @@ const OHIF = {
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
};
export {
@@ -82,6 +86,8 @@ export {
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
};
export { OHIF };
+2
View File
@@ -13,6 +13,8 @@ describe('Top level exports', () => {
'createUINotificationService',
'createUIModalService',
'createUIDialogService',
'createUIContextMenuService',
'createUILabellingFlowService',
//
'utils',
'studies',
@@ -0,0 +1,63 @@
/**
* UI Context Menu
*
* @typedef {Object} ContextMenuProps
* @property {Event} event The event with tool information.
*/
const uiContextMenuServicePublicAPI = {
name: 'UIContextMenuService',
hide,
show,
setServiceImplementation,
};
const uiContextMenuServiceImplementation = {
_show: () => console.warn('show() NOT IMPLEMENTED'),
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
};
function createUIContextMenuService() {
return uiContextMenuServicePublicAPI;
}
/**
* Show a new UI ContextMenu dialog;
*
* @param {ContextMenuProps} props { event }
*/
function show({ event }) {
return uiContextMenuServiceImplementation._show({
event,
});
}
/**
* Hide a UI ContextMenu dialog;
*
*/
function hide() {
return uiContextMenuServiceImplementation._hide();
}
/**
*
*
* @param {*} {
* show: showImplementation,
* hide: hideImplementation,
* }
*/
function setServiceImplementation({
show: showImplementation,
hide: hideImplementation,
}) {
if (showImplementation) {
uiContextMenuServiceImplementation._show = showImplementation;
}
if (hideImplementation) {
uiContextMenuServiceImplementation._hide = hideImplementation;
}
}
export default createUIContextMenuService;
@@ -17,8 +17,9 @@
* @property {Object} contentProps The dialog content props.
* @property {boolean} [isDraggable=true] Controls if dialog content is draggable or not.
* @property {boolean} [showOverlay=false] Controls dialog overlay.
* @property {boolean} [centralize=false] Center the dialog on the screen.
* @property {boolean} [preservePosition=true] Use last position instead of default.
* @property {ElementPosition} defaultPosition Specifies the `x` and `y` that the dragged item should start at.
* @property {ElementPosition} position If this property is present, the item becomes 'controlled' and is not responsive to user input.
* @property {Function} onStart Called when dragging starts. If `false` is returned any handler, the action will cancel.
* @property {Function} onStop Called when dragging stops.
* @property {Function} onDrag Called while dragging.
@@ -45,7 +46,7 @@ function createUIDialogService() {
/**
* Show a new UI dialog;
*
* @param {DialogProps} props { id, content, contentProps, onStart, onDrag, onStop, isDraggable, showOverlay, defaultPosition, position }
* @param {DialogProps} props { id, content, contentProps, onStart, onDrag, onStop, centralize, isDraggable, showOverlay, preservePosition, defaultPosition }
*/
function create({
id,
@@ -54,10 +55,11 @@ function create({
onStart,
onDrag,
onStop,
centralize = false,
preservePosition = true,
isDraggable = true,
showOverlay = false,
defaultPosition,
position,
}) {
return uiDialogServiceImplementation._create({
id,
@@ -66,10 +68,11 @@ function create({
onStart,
onDrag,
onStop,
centralize,
preservePosition,
isDraggable,
showOverlay,
defaultPosition,
position,
});
}
@@ -0,0 +1,68 @@
/**
* 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 uiLabellingFlowServicePublicAPI = {
name: 'UILabellingFlowService',
show,
hide,
setServiceImplementation,
};
const uiLabellingFlowServiceImplementation = {
_show: () => console.warn('show() NOT IMPLEMENTED'),
_hide: () => console.warn('hide() NOT IMPLEMENTED'),
};
function createUILabellingFlowService() {
return uiLabellingFlowServicePublicAPI;
}
/**
* Hide a UI LabellingFlow dialog;
*
*/
function hide() {
return uiLabellingFlowServiceImplementation._hide();
}
/**
* Show a new UI LabellingFlow dialog;
*
* @param {LabellingFlowProps} props { defaultPosition, centralize, props }
*/
function show({ defaultPosition, centralize, props }) {
return uiLabellingFlowServiceImplementation._show({
defaultPosition,
centralize,
props,
});
}
/**
*
*
* @param {*} {
* show: showImplementation,
* hide: hideImplementation,
* }
*/
function setServiceImplementation({
show: showImplementation,
hide: hideImplementation,
}) {
if (showImplementation) {
uiLabellingFlowServiceImplementation._show = showImplementation;
}
if (hideImplementation) {
uiLabellingFlowServiceImplementation._hide = hideImplementation;
}
}
export default createUILabellingFlowService;
+4
View File
@@ -2,10 +2,14 @@ import ServicesManager from './ServicesManager.js';
import createUINotificationService from './UINotificationService';
import createUIModalService from './UIModalService';
import createUIDialogService from './UIDialogService';
import createUIContextMenuService from './UIContextMenuService';
import createUILabellingFlowService from './UILabellingFlowService';
export {
createUINotificationService,
createUIModalService,
createUIDialogService,
createUIContextMenuService,
createUILabellingFlowService,
ServicesManager,
};