feat: Allow configurable context menus (#2894)

* feat: Context menu

feat: Custom context menu

Adding documentation

PR updates

* fix: Capture tool exception

* PR updates

* Add fully worked out examples in the basic test mode/extension

* Fix the menu display

* fix: Make the commands on clicks much more configurable

* Wait for load before double clicking

* docs

* PR changes - nothing functional, just moving things endlessly

* PR comments

* PR changes - rename the default context menu

* Renamed the cornerstoneContextMenu to measurementsContextMenu

* Add chevron right to the sub-menus
This commit is contained in:
Bill Wallace authored and GitHub committed 2023-03-22 17:45:28 -04:00
1 parent 4e94b588a7
commit bc642fd2b6
40 files changed
+1472 -280

No files matched your search

@@ -0,0 +1,80 @@
/**
* Coding values is a map of simple string coding values to a set of
* attributes associated with the coding value.
*
* The simple string is in the format `<codingSchemeDesignator>:<codingValue>`
* That allows extracting the DICOM attributes from the designator/value, and
* allows for passing around the simple string.
* The additional attributes contained in the object include:
* * text - this is the coding scheme text display value, and may be language specific
* * type - this defines a named type, typically 'site'. Different names can be used
* to allow setting different findingSites values in order to define a hierarchy.
* * color - used to apply annotation color
* It is also possible to define additional attributes here, used by custom
* extensions.
*
* See https://dicom.nema.org/medical/dicom/current/output/html/part16.html
* for definitions of SCT and other code values.
*/
const codingValues = {
id: 'codingValues',
// Sites
'SCT:69536005': {
text: 'Head',
type: 'site',
},
'SCT:45048000': {
text: 'Neck',
type: 'site',
},
'SCT:818981001': {
text: 'Abdomen',
type: 'site',
},
'SCT:816092008': {
text: 'Pelvis',
type: 'site',
},
// Findings
'SCT:371861004': {
text: 'Mild intimal coronary irregularities',
color: 'green',
},
'SCT:194983005': {
text: 'Aortic insufficiency',
color: 'darkred',
},
'SCT:399232001': {
text: '2-chamber',
},
'SCT:103340004': {
text: 'SAX',
},
'SCT:91134007': {
text: 'MV',
},
'SCT:122972007': {
text: 'PV',
},
// Orientations
'SCT:24422004': {
text: 'Axial',
color: '#000000',
type: 'orientation',
},
'SCT:81654009': {
text: 'Coronal',
color: '#000000',
type: 'orientation',
},
'SCT:30730003': {
text: 'Sagittal',
color: '#000000',
type: 'orientation',
},
};
export default codingValues;
@@ -0,0 +1,27 @@
import codingValues from './codingValues';
const codeMenuItem = {
id: '@ohif/contextMenuAnnotationCode',
codingValues,
/** Applies the code value setup for this item */
transform: function (customizationService) {
const { code: codeRef } = this;
if (!codeRef) throw new Error(`item ${this} has no code ref`);
const codingValues = customizationService.get('codingValues');
const code = codingValues[codeRef];
return {
...this,
codeRef,
code: { ref: codeRef, ...code },
label: code.text,
commands: [
{
commandName: 'updateMeasurement',
},
],
};
},
};
export default codeMenuItem;
@@ -0,0 +1,100 @@
const findingsContextMenu = {
id: 'measurementsContextMenu',
customizationType: 'ohif.contextMenu',
menus: [
{
id: 'forExistingMeasurement',
// selector restricts context menu to when there is nearbyToolData
selector: ({ nearbyToolData }) => !!nearbyToolData,
items: [
{
customizationType: 'ohif.contextSubMenu',
label: 'Site',
actionType: 'ShowSubMenu',
subMenu: 'siteSelectionSubMenu',
},
{
customizationType: 'ohif.contextSubMenu',
label: 'Finding',
actionType: 'ShowSubMenu',
subMenu: 'findingSelectionSubMenu',
},
{
// customizationType is implicit here in the configuration setup
label: 'Delete Measurement',
commands: [
{
commandName: 'deleteMeasurement',
},
],
},
{
label: 'Add Label',
commands: [
{
commandName: 'setMeasurementLabel',
},
],
},
// The example below shows how to include a delegating sub-menu,
// Only available on the @ohif/hp-extension.mn hanging protocol
// To demonstrate, select the 3x1 layout from the protocol menu
// and right click on a measurement.
{
label: 'IncludeSubMenu',
selector: ({ protocol }) => protocol?.id === '@ohif/hp-extension.mn',
delegating: true,
subMenu: 'orientationSelectionSubMenu',
},
],
},
{
id: 'orientationSelectionSubMenu',
selector: ({ nearbyToolData }) => !!nearbyToolData,
items: [
{
customizationType: '@ohif/contextMenuAnnotationCode',
code: 'SCT:24422004',
},
{
customizationType: '@ohif/contextMenuAnnotationCode',
code: 'SCT:81654009',
},
],
},
{
id: 'findingSelectionSubMenu',
selector: ({ nearbyToolData }) => !!nearbyToolData,
items: [
{
customizationType: '@ohif/contextMenuAnnotationCode',
code: 'SCT:371861004',
},
{
customizationType: '@ohif/contextMenuAnnotationCode',
code: 'SCT:194983005',
},
],
},
{
id: 'siteSelectionSubMenu',
selector: ({ nearbyToolData }) => !!nearbyToolData,
items: [
{
customizationType: '@ohif/contextMenuAnnotationCode',
code: 'SCT:69536005',
},
{
customizationType: '@ohif/contextMenuAnnotationCode',
code: 'SCT:45048000',
},
],
},
],
};
export default findingsContextMenu;
@@ -0,0 +1,5 @@
import codingValues from './codingValues';
import contextMenuCodeItem from './contextMenuCodeItem';
import findingsContextMenu from './findingsContextMenu';
export { codingValues, contextMenuCodeItem, findingsContextMenu };
@@ -0,0 +1,14 @@
import {
codingValues,
contextMenuCodeItem,
findingsContextMenu,
} from './custom-context-menu';
export default function getCustomizationModule() {
return [
{
name: 'custom-context-menu',
value: [codingValues, contextMenuCodeItem, findingsContextMenu],
},
];
}
+4
View File
@@ -3,6 +3,7 @@ import { Types } from '@ohif/core';
import { id } from './id';
import getHangingProtocolModule from './hp';
import getCustomizationModule from './getCustomizationModule';
// import {setViewportZoomPan, storeViewportZoomPan } from './custom-viewport/setViewportZoomPan';
import sameAs from './custom-attribute/sameAs';
import numberOfDisplaySets from './custom-attribute/numberOfDisplaySets';
@@ -59,6 +60,9 @@ const testExtension: Types.Extensions.Extension = {
/** Registers some additional hanging protocols. See hp/index.tsx for more details */
getHangingProtocolModule,
/** Registers some customizations */
getCustomizationModule,
};
export default testExtension;