Pull in master
This commit is contained in:
commit
e7501933dd
47 files changed
+879
-3000
No files matched your search
@@ -1,112 +1,138 @@
|
||||
import ImageSet from '@ohif/core/src/classes/ImageSet';
|
||||
import { IWebApiDataSource } from '@ohif/core';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id: 'example-extension',
|
||||
id: 'org.ohif.*',
|
||||
|
||||
/**
|
||||
* LIFECYCLE HOOKS
|
||||
*/
|
||||
|
||||
preRegistration({
|
||||
servicesManager = {},
|
||||
commandsManager = {},
|
||||
appConfig = {},
|
||||
configuration = {},
|
||||
}) {},
|
||||
preRegistration() {},
|
||||
beforeExtInit() {},
|
||||
beforeExtDestroy() {},
|
||||
|
||||
/**
|
||||
* MODULE GETTERS
|
||||
* MODULES
|
||||
*/
|
||||
getViewportModule() {
|
||||
return '... react component ...';
|
||||
},
|
||||
getSopClassHandlerModule() {
|
||||
return sopClassHandlerModule;
|
||||
},
|
||||
getPanelModule() {
|
||||
return panelModule;
|
||||
},
|
||||
getToolbarModule() {
|
||||
return panelModule;
|
||||
},
|
||||
getCommandsModule(/* store */) {
|
||||
return commandsModule;
|
||||
},
|
||||
getCommandsModule,
|
||||
getContextModule,
|
||||
getDataSourcesModule,
|
||||
getLayoutTemplateModule,
|
||||
getPanelModule,
|
||||
getSopClassHandlerModule,
|
||||
getToolbarModule() {},
|
||||
getViewportModule,
|
||||
};
|
||||
|
||||
// appConfig,
|
||||
// extensionConfig,
|
||||
// dataSources,
|
||||
// servicesManager,
|
||||
// extensionManager,
|
||||
// commandsManager,
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const commandsModule = {
|
||||
actions: {
|
||||
// Store Contexts + Options
|
||||
exampleAction: ({ viewports, param1 }) => {
|
||||
console.log(`There are ${viewports.length} viewports`);
|
||||
console.log(`param1's value is: ${param1}`);
|
||||
},
|
||||
},
|
||||
const getCommandsModule = () => ({
|
||||
definitions: {
|
||||
exampleActionDef: {
|
||||
commandFn: this.actions.exampleAction,
|
||||
storeContexts: ['viewports'],
|
||||
commandFn: ({ param1 }) => {
|
||||
console.log(`param1's value is: ${param1}`);
|
||||
},
|
||||
// storeContexts: ['viewports'],
|
||||
options: { param1: 'hello world' },
|
||||
context: 'VIEWER', // optional
|
||||
},
|
||||
},
|
||||
};
|
||||
defaultContext: 'ACTIVE_VIEWPORT::DICOMSR',
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const sopClassHandlerModule = {
|
||||
id: 'OHIFDicomHtmlSopClassHandler',
|
||||
sopClassUIDs: Object.values({
|
||||
BASIC_TEXT_SR: '1.2.840.10008.5.1.4.1.1.88.11',
|
||||
ENHANCED_SR: '1.2.840.10008.5.1.4.1.1.88.22',
|
||||
COMPREHENSIVE_SR: '1.2.840.10008.5.1.4.1.1.88.33',
|
||||
PROCEDURE_LOG_STORAGE: '1.2.840.10008.5.1.4.1.1.88.40',
|
||||
MAMMOGRAPHY_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.50',
|
||||
CHEST_CAD_SR: '1.2.840.10008.5.1.4.1.1.88.65',
|
||||
X_RAY_RADIATION_DOSE_SR: '1.2.840.10008.5.1.4.1.1.88.67',
|
||||
}),
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient, authorizationHeaders) {
|
||||
const instance = series.getFirstInstance();
|
||||
const ExampleContext = React.createContext();
|
||||
|
||||
return {
|
||||
plugin: 'html',
|
||||
displaySetInstanceUID: 0, //utils.guid(),
|
||||
wadoRoot: study.getData().wadoRoot,
|
||||
wadoUri: instance.getData().wadouri,
|
||||
SOPInstanceUID: instance.getSOPInstanceUID(),
|
||||
SeriesInstanceUID: series.getSeriesInstanceUID(),
|
||||
StudyInstanceUID: study.getStudyInstanceUID(),
|
||||
authorizationHeaders,
|
||||
};
|
||||
function ExampleContextProvider({ children }) {
|
||||
return (
|
||||
<ExampleContext.Provider value={{ example: 'value' }}>
|
||||
{children}
|
||||
</TrackedMeasurementsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
const getContextModule = () => [
|
||||
{
|
||||
name: 'ExampleContext',
|
||||
context: ExampleContext,
|
||||
provider: ExampleContextProvider,
|
||||
},
|
||||
];
|
||||
|
||||
const getDataSourcesModule = () => [
|
||||
{
|
||||
name: 'exampleDataSource',
|
||||
type: 'webApi', // 'webApi' | 'local' | 'other'
|
||||
createDataSource: dataSourceConfig => {
|
||||
return IWebApiDataSource.create(/* */);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const getLayoutTemplateModule = (/* ... */) => [
|
||||
{
|
||||
id: 'exampleLayout',
|
||||
name: 'exampleLayout',
|
||||
component: ExampleLayoutComponent,
|
||||
},
|
||||
];
|
||||
|
||||
const getPanelModule = () => {
|
||||
return [
|
||||
{
|
||||
name: 'exampleSidePanel',
|
||||
iconName: 'info-circle-o',
|
||||
iconLabel: 'Example',
|
||||
label: 'Hello World',
|
||||
isDisabled: studies => {}, // optional
|
||||
component: ExamplePanelContentComponent,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const panelModule = {
|
||||
menuOptions: [
|
||||
const getSopClassHandlerModule = (/* ... */) => {
|
||||
const BASIC_TEXT_SR = '1.2.840.10008.5.1.4.1.1.88.11';
|
||||
|
||||
return [
|
||||
{
|
||||
icon: 'th-list',
|
||||
label: 'Segments',
|
||||
target: 'segment-panel',
|
||||
isDisabled: studies => {
|
||||
return false;
|
||||
name: 'ExampleSopClassHandle',
|
||||
sopClassUids: [BASIC_TEXT_SR],
|
||||
getDisplaySetsFromSeries: instances => {
|
||||
const imageSet = new ImageSet(instances);
|
||||
|
||||
imageSet.setAttributes(/** */);
|
||||
imageSet.sortBy((a, b) => 0);
|
||||
|
||||
return imageSet;
|
||||
},
|
||||
},
|
||||
],
|
||||
components: [
|
||||
{
|
||||
id: 'segment-panel',
|
||||
component: '... react component ...',
|
||||
},
|
||||
],
|
||||
defaultContext: ['VIEWER'],
|
||||
];
|
||||
};
|
||||
|
||||
const getToolbarModule = () => {};
|
||||
|
||||
// displaySet, viewportIndex, dataSource
|
||||
const getViewportModule = () => {
|
||||
const wrappedViewport = props => {
|
||||
return (
|
||||
<ExampleViewport
|
||||
{...props}
|
||||
onEvent={data => {
|
||||
commandsManager.runCommand('commandName', data);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return [{ name: 'example', component: wrappedViewport }];
|
||||
};
|
||||
@@ -145,4 +145,8 @@ CornerstoneViewportDownloadForm.propTypes = {
|
||||
activeViewportIndex: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default CornerstoneViewportDownloadForm;
|
||||
// export default CornerstoneViewportDownloadForm;
|
||||
|
||||
export default function HelloWorld() {
|
||||
return <div>Hello World</div>;
|
||||
}
|
||||
@@ -148,13 +148,13 @@ const commandsModule = ({ servicesManager }) => {
|
||||
const enabledElement = getEnabledElement(viewports.activeViewportIndex);
|
||||
return enabledElement;
|
||||
},
|
||||
showDownloadViewportModal: ({ title, viewports }) => {
|
||||
const activeViewportIndex = viewports.activeViewportIndex;
|
||||
showDownloadViewportModal: () => {
|
||||
const activeViewportIndex = 1; // viewports.activeViewportIndex;
|
||||
const { UIModalService } = servicesManager.services;
|
||||
if (UIModalService) {
|
||||
UIModalService.show({
|
||||
content: CornerstoneViewportDownloadForm,
|
||||
title,
|
||||
title: 'Download High Quality Image',
|
||||
contentProps: {
|
||||
activeViewportIndex,
|
||||
onClose: UIModalService.hide,
|
||||
@@ -318,7 +318,7 @@ const commandsModule = ({ servicesManager }) => {
|
||||
},
|
||||
showDownloadViewportModal: {
|
||||
commandFn: actions.showDownloadViewportModal,
|
||||
storeContexts: ['viewports'],
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
getActiveViewportEnabledElement: {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import init from './init.js';
|
||||
import commandsModule from './commandsModule.js';
|
||||
import toolbarModule from './toolbarModule.js';
|
||||
import CornerstoneViewportDownloadForm from './CornerstoneViewportDownloadForm';
|
||||
|
||||
const Component = React.lazy(() => {
|
||||
@@ -48,9 +47,6 @@ export default {
|
||||
{ name: 'cornerstone', component: ExtendedOHIFCornerstoneViewport },
|
||||
];
|
||||
},
|
||||
getToolbarModule() {
|
||||
return toolbarModule;
|
||||
},
|
||||
getCommandsModule({ servicesManager }) {
|
||||
return commandsModule({ servicesManager });
|
||||
},
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
// TODO: A way to add Icons that don't already exist?
|
||||
// - Register them and add
|
||||
// - Include SVG Source/Inline?
|
||||
// - By URL, or own component?
|
||||
|
||||
// What KINDS of toolbar buttons do we have...
|
||||
// - One's that dispatch commands
|
||||
// - One's that set tool's active
|
||||
// - More custom, like CINE
|
||||
// - Built in for one's like this, or custom components?
|
||||
|
||||
// Visible?
|
||||
// Disabled?
|
||||
// Based on contexts or misc. criteria?
|
||||
@@ -17,241 +6,118 @@
|
||||
// setToolActive commands should receive the button event that triggered
|
||||
// so we can do the "bind to this button" magic
|
||||
|
||||
const TOOLBAR_BUTTON_TYPES = {
|
||||
COMMAND: 'command',
|
||||
SET_TOOL_ACTIVE: 'setToolActive',
|
||||
BUILT_IN: 'builtIn',
|
||||
};
|
||||
// const definitions = [
|
||||
// // OLD
|
||||
// {
|
||||
// id: 'StackScroll',
|
||||
// label: 'Stack Scroll',
|
||||
// icon: 'bars',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
// commandName: 'setToolActive',
|
||||
// commandOptions: { toolName: 'StackScroll' },
|
||||
// },
|
||||
// {
|
||||
// id: 'Reset',
|
||||
// label: 'Reset',
|
||||
// icon: 'reset',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'resetViewport',
|
||||
// },
|
||||
// {
|
||||
// id: 'Cine',
|
||||
// label: 'CINE',
|
||||
// icon: 'youtube',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.BUILT_IN,
|
||||
// options: {
|
||||
// behavior: TOOLBAR_BUTTON_BEHAVIORS.CINE,
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 'More',
|
||||
// label: 'More',
|
||||
// icon: 'ellipse-circle',
|
||||
// buttons: [
|
||||
// {
|
||||
// id: 'Magnify',
|
||||
// label: 'Magnify',
|
||||
// icon: 'circle',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
// commandName: 'setToolActive',
|
||||
// commandOptions: { toolName: 'Magnify' },
|
||||
// },
|
||||
// {
|
||||
// id: 'WwwcRegion',
|
||||
// label: 'ROI Window',
|
||||
// icon: 'stop',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
// commandName: 'setToolActive',
|
||||
// commandOptions: { toolName: 'WwwcRegion' },
|
||||
// },
|
||||
// {
|
||||
// id: 'Invert',
|
||||
// label: 'Invert',
|
||||
// icon: 'adjust',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'invertViewport',
|
||||
// },
|
||||
// {
|
||||
// id: 'RotateRight',
|
||||
// label: 'Rotate Right',
|
||||
// icon: 'rotate-right',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'rotateViewportCW',
|
||||
// },
|
||||
// {
|
||||
// id: 'FlipH',
|
||||
// label: 'Flip H',
|
||||
// icon: 'ellipse-h',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'flipViewportHorizontal',
|
||||
// },
|
||||
// {
|
||||
// id: 'FlipV',
|
||||
// label: 'Flip V',
|
||||
// icon: 'ellipse-v',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'flipViewportVertical',
|
||||
// },
|
||||
// {
|
||||
// id: 'Clear',
|
||||
// label: 'Clear',
|
||||
// icon: 'trash',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'clearAnnotations',
|
||||
// },
|
||||
// {
|
||||
// id: 'Eraser',
|
||||
// label: 'Eraser',
|
||||
// icon: 'eraser',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
// commandName: 'setToolActive',
|
||||
// commandOptions: { toolName: 'Eraser' },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 'Exit2DMPR',
|
||||
// label: 'Exit 2D MPR',
|
||||
// icon: 'times',
|
||||
// //
|
||||
// type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
// commandName: 'setCornerstoneLayout',
|
||||
// context: 'ACTIVE_VIEWPORT::VTK',
|
||||
// },
|
||||
// ];
|
||||
|
||||
const TOOLBAR_BUTTON_BEHAVIORS = {
|
||||
CINE: 'CINE',
|
||||
DOWNLOAD_SCREEN_SHOT: 'DOWNLOAD_SCREEN_SHOT',
|
||||
};
|
||||
|
||||
/* TODO: Export enums through a extension manager. */
|
||||
const enums = {
|
||||
TOOLBAR_BUTTON_TYPES,
|
||||
TOOLBAR_BUTTON_BEHAVIORS,
|
||||
};
|
||||
|
||||
const definitions = [
|
||||
// UPDATED
|
||||
{
|
||||
id: 'Zoom',
|
||||
label: 'Zoom',
|
||||
icon: 'tool-zoom',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Zoom' },
|
||||
},
|
||||
{
|
||||
id: 'Wwwc',
|
||||
label: 'Levels',
|
||||
icon: 'tool-window-level',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Wwwc' },
|
||||
},
|
||||
{
|
||||
id: 'Pan',
|
||||
label: 'Pan',
|
||||
icon: 'tool-move',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Pan' },
|
||||
},
|
||||
{
|
||||
id: 'Capture',
|
||||
label: 'Capture',
|
||||
icon: 'tool-capture',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.BUILT_IN,
|
||||
options: {
|
||||
behavior: TOOLBAR_BUTTON_BEHAVIORS.DOWNLOAD_SCREEN_SHOT,
|
||||
togglable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'Annotate',
|
||||
label: 'Annotate',
|
||||
icon: 'tool-annotate',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'ArrowAnnotate' },
|
||||
},
|
||||
{
|
||||
id: 'Bidirectional',
|
||||
label: 'Bidirectional',
|
||||
icon: 'tool-bidirectional',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Bidirectional' },
|
||||
},
|
||||
{
|
||||
id: 'Ellipse',
|
||||
label: 'Ellipse',
|
||||
icon: 'tool-elipse',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'EllipticalRoi' },
|
||||
},
|
||||
{
|
||||
id: 'Length',
|
||||
label: 'Length',
|
||||
icon: 'tool-length',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Length' },
|
||||
},
|
||||
// OLD
|
||||
{
|
||||
id: 'StackScroll',
|
||||
label: 'Stack Scroll',
|
||||
icon: 'bars',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'StackScroll' },
|
||||
},
|
||||
|
||||
{
|
||||
id: 'Angle',
|
||||
label: 'Angle',
|
||||
icon: 'angle-left',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Angle' },
|
||||
},
|
||||
{
|
||||
id: 'Reset',
|
||||
label: 'Reset',
|
||||
icon: 'reset',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'resetViewport',
|
||||
},
|
||||
{
|
||||
id: 'Cine',
|
||||
label: 'CINE',
|
||||
icon: 'youtube',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.BUILT_IN,
|
||||
options: {
|
||||
behavior: TOOLBAR_BUTTON_BEHAVIORS.CINE,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'More',
|
||||
label: 'More',
|
||||
icon: 'ellipse-circle',
|
||||
buttons: [
|
||||
{
|
||||
id: 'Magnify',
|
||||
label: 'Magnify',
|
||||
icon: 'circle',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Magnify' },
|
||||
},
|
||||
{
|
||||
id: 'WwwcRegion',
|
||||
label: 'ROI Window',
|
||||
icon: 'stop',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'WwwcRegion' },
|
||||
},
|
||||
{
|
||||
id: 'DragProbe',
|
||||
label: 'Probe',
|
||||
icon: 'dot-circle',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'DragProbe' },
|
||||
},
|
||||
{
|
||||
id: 'RectangleRoi',
|
||||
label: 'Rectangle',
|
||||
icon: 'square-o',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'RectangleRoi' },
|
||||
},
|
||||
{
|
||||
id: 'Invert',
|
||||
label: 'Invert',
|
||||
icon: 'adjust',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'invertViewport',
|
||||
},
|
||||
{
|
||||
id: 'RotateRight',
|
||||
label: 'Rotate Right',
|
||||
icon: 'rotate-right',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'rotateViewportCW',
|
||||
},
|
||||
{
|
||||
id: 'FlipH',
|
||||
label: 'Flip H',
|
||||
icon: 'ellipse-h',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'flipViewportHorizontal',
|
||||
},
|
||||
{
|
||||
id: 'FlipV',
|
||||
label: 'Flip V',
|
||||
icon: 'ellipse-v',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'flipViewportVertical',
|
||||
},
|
||||
{
|
||||
id: 'Clear',
|
||||
label: 'Clear',
|
||||
icon: 'trash',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'clearAnnotations',
|
||||
},
|
||||
{
|
||||
id: 'Eraser',
|
||||
label: 'Eraser',
|
||||
icon: 'eraser',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Eraser' },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'Exit2DMPR',
|
||||
label: 'Exit 2D MPR',
|
||||
icon: 'times',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'setCornerstoneLayout',
|
||||
context: 'ACTIVE_VIEWPORT::VTK',
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
definitions,
|
||||
defaultContext: 'ACTIVE_VIEWPORT::CORNERSTONE',
|
||||
};
|
||||
export default [];
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function ToolbarDivider() {
|
||||
return (
|
||||
<span className="self-center w-1 h-8 mx-2 border-l border-common-dark" />
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui';
|
||||
|
||||
function LayoutSelector() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
function LayoutSelector() {
|
||||
if (isOpen) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}
|
||||
window.addEventListener('click', LayoutSelector);
|
||||
return () => {
|
||||
window.removeEventListener('click', LayoutSelector);
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
const dropdownContent = isOpen ? OHIFLayoutSelector : undefined;
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
id="Layout"
|
||||
label="Grid Layout"
|
||||
icon="tool-layout"
|
||||
onClick={() => {
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
dropdownContent={dropdownContent}
|
||||
isActive={isOpen}
|
||||
type="primary"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
LayoutSelector.propTypes = {
|
||||
children: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
export default LayoutSelector;
|
||||
@@ -1,10 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
//
|
||||
import { NavBar, Svg, Icon, IconButton, Toolbar } from '@ohif/ui';
|
||||
import { NavBar, Svg, Icon, IconButton } from '@ohif/ui';
|
||||
|
||||
function Header({ tools, moreTools }) {
|
||||
const [activeTool, setActiveTool] = useState('Zoom');
|
||||
function Header({ children }) {
|
||||
// const dropdownContent = [
|
||||
// {
|
||||
// name: 'Soft tissue',
|
||||
@@ -14,80 +13,16 @@ function Header({ tools, moreTools }) {
|
||||
// { name: 'Liver', value: '150 / 90' },
|
||||
// { name: 'Bone', value: '2500 / 480' },
|
||||
// { name: 'Brain', value: '80 / 40' },
|
||||
// ];
|
||||
// ]
|
||||
|
||||
// TODO -> In ToolBarManager => Consume commandName and commandOptions and create onClick?
|
||||
|
||||
/*
|
||||
const tools = [
|
||||
{
|
||||
id: 'Zoom',
|
||||
label: 'Zoom',
|
||||
icon: 'tool-zoom',
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Zoom' },
|
||||
onClick: () => setActiveTool('Zoom'),
|
||||
},
|
||||
{
|
||||
id: 'Wwwc',
|
||||
label: 'Levels',
|
||||
icon: 'tool-window-level',
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Wwwc' },
|
||||
onClick: () => setActiveTool('Wwwc'),
|
||||
dropdownContent: (
|
||||
<div>
|
||||
{dropdownContent.map((row, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex justify-between py-2 px-3 hover:bg-secondary-dark cursor-pointer"
|
||||
>
|
||||
<div>
|
||||
<span className="text-base text-white">{row.name}</span>
|
||||
<span className="text-base text-primary-light ml-3">
|
||||
{row.value}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-base text-primary-active ml-4">{i}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'Pan',
|
||||
label: 'Pan',
|
||||
icon: 'tool-move',
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Pan' },
|
||||
onClick: () => setActiveTool('Pan'),
|
||||
},
|
||||
{
|
||||
id: 'Capture',
|
||||
label: 'Capture',
|
||||
icon: 'tool-capture',
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Capture' },
|
||||
onClick: () => setActiveTool('Capture'),
|
||||
},
|
||||
{
|
||||
id: 'Layout',
|
||||
label: 'Layout',
|
||||
icon: 'tool-layout',
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Layout' },
|
||||
onClick: () => setActiveTool('Layout'),
|
||||
},
|
||||
];
|
||||
*/
|
||||
return (
|
||||
<NavBar className="justify-between border-b-4 border-black">
|
||||
<div className="flex flex-1 justify-between">
|
||||
<div className="flex justify-between flex-1">
|
||||
<div className="flex items-center">
|
||||
<div className="mr-3 inline-flex items-center">
|
||||
<div className="inline-flex items-center mr-3">
|
||||
<Icon
|
||||
name="chevron-left"
|
||||
className="text-primary-active w-8 cursor-pointer"
|
||||
className="w-8 cursor-pointer text-primary-active"
|
||||
onClick={() => alert('Navigate to previous page')}
|
||||
/>
|
||||
<a href="#" className="ml-4">
|
||||
@@ -95,15 +30,9 @@ function Header({ tools, moreTools }) {
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">{children}</div>
|
||||
<div className="flex items-center">
|
||||
<Toolbar
|
||||
tools={tools}
|
||||
activeTool={activeTool}
|
||||
moreTools={moreTools}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<span className="mr-3 text-common-light text-lg">
|
||||
<span className="mr-3 text-lg text-common-light">
|
||||
FOR INVESTIGATIONAL USE ONLY
|
||||
</span>
|
||||
<IconButton
|
||||
@@ -123,8 +52,7 @@ function Header({ tools, moreTools }) {
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
tools: PropTypes.array.isRequired,
|
||||
moreTools: PropTypes.array.isRequired,
|
||||
children: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -0,0 +1,41 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ToolbarButton } from '@ohif/ui';
|
||||
|
||||
function NestedMenu({ children }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
function closeNestedMenu() {
|
||||
if (isOpen) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}
|
||||
window.addEventListener('click', closeNestedMenu);
|
||||
return () => {
|
||||
window.removeEventListener('click', closeNestedMenu);
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
const dropdownContent = isOpen ? children : undefined;
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
id="More"
|
||||
label="More"
|
||||
icon="tool-more-menu"
|
||||
onClick={() => {
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
dropdownContent={dropdownContent}
|
||||
isActive={isOpen}
|
||||
type="primary"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
NestedMenu.propTypes = {
|
||||
children: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
export default NestedMenu;
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { SidePanel, Toolbar } from '@ohif/ui';
|
||||
//
|
||||
import { SidePanel } from '@ohif/ui';
|
||||
import Header from './Header.jsx';
|
||||
import NestedMenu from './ToolbarButtonNestedMenu.jsx';
|
||||
|
||||
function ViewerLayout({
|
||||
// From Extension Module Params
|
||||
@@ -54,71 +55,23 @@ function ViewerLayout({
|
||||
};
|
||||
};
|
||||
|
||||
const handleToolBarSubscription = newToolBarLayout => {
|
||||
// Get buttons to pass to toolbars.
|
||||
console.log(commandsManager);
|
||||
|
||||
const firstTool = newToolBarLayout[0].tools[0];
|
||||
|
||||
const toolBarLayout = [];
|
||||
|
||||
newToolBarLayout.forEach(newToolBar => {
|
||||
const toolBar = { tools: [], moreTools: [] };
|
||||
|
||||
Object.keys(newToolBar).forEach(key => {
|
||||
if (newToolBar[key].length) {
|
||||
newToolBar[key].forEach(tool => {
|
||||
const commandOptions = tool.commandOptions || {};
|
||||
|
||||
toolBar[key].push({
|
||||
context: tool.context,
|
||||
icon: tool.icon,
|
||||
id: tool.id,
|
||||
label: tool.label,
|
||||
type: 'setToolActive',
|
||||
onClick: () => {
|
||||
commandsManager.runCommand(tool.commandName, commandOptions);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
toolBarLayout.push(toolBar);
|
||||
|
||||
// if (newToolBar.moreTools && newToolBar.moreTools.length) {
|
||||
// newToolBar.moreTools.forEach(tool => {
|
||||
// const commandOptions = tool.commandOptions || {};
|
||||
|
||||
// toolBar.push({
|
||||
// context: tool.context,
|
||||
// icon: tool.icon,
|
||||
// id: tool.id,
|
||||
// label: tool.label,
|
||||
// type: 'setToolActive',
|
||||
// command: () =>
|
||||
// commandsManager.runCommand(tool.commandName, commandOptions),
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
});
|
||||
|
||||
setToolBarLayout(toolBarLayout);
|
||||
};
|
||||
|
||||
const [toolBarLayout, setToolBarLayout] = useState([
|
||||
{ tools: [], moreTools: [] },
|
||||
{ tools: [] },
|
||||
]);
|
||||
const [toolbars, setToolbars] = useState({ primary: [], secondary: [] });
|
||||
|
||||
useEffect(() => {
|
||||
const { unsubscribe } = ToolBarService.subscribe(
|
||||
ToolBarService.EVENTS.TOOL_BAR_MODIFIED,
|
||||
handleToolBarSubscription
|
||||
() => {
|
||||
console.warn('~~~ TOOL BAR MODIFIED EVENT CAUGHT');
|
||||
const updatedToolbars = {
|
||||
primary: ToolBarService.getButtonSection('primary'),
|
||||
secondary: ToolBarService.getButtonSection('secondary'),
|
||||
};
|
||||
setToolbars(updatedToolbars);
|
||||
}
|
||||
);
|
||||
|
||||
return unsubscribe;
|
||||
}, []);
|
||||
}, [ToolBarService]);
|
||||
|
||||
const leftPanelComponents = leftPanels.map(getPanelData);
|
||||
const rightPanelComponents = rightPanels.map(getPanelData);
|
||||
@@ -126,10 +79,30 @@ function ViewerLayout({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header
|
||||
tools={toolBarLayout[0].tools}
|
||||
moreTools={toolBarLayout[0].moreTools}
|
||||
/>
|
||||
<Header>
|
||||
<div className="relative flex justify-center">
|
||||
{toolbars.primary.map(toolDef => {
|
||||
const isNested = Array.isArray(toolDef);
|
||||
|
||||
if (!isNested) {
|
||||
const { id, Component, componentProps } = toolDef;
|
||||
|
||||
return <Component key={id} id={id} {...componentProps} />;
|
||||
} else {
|
||||
return (
|
||||
<NestedMenu>
|
||||
<div className="flex">
|
||||
{toolDef.map(x => {
|
||||
const { id, Component, componentProps } = x;
|
||||
return <Component key={id} id={id} {...componentProps} />;
|
||||
})}
|
||||
</div>
|
||||
</NestedMenu>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</Header>
|
||||
<div
|
||||
className="flex flex-row flex-no-wrap items-stretch w-full overflow-hidden"
|
||||
style={{ height: 'calc(100vh - 57px' }}
|
||||
@@ -145,67 +118,17 @@ function ViewerLayout({
|
||||
{/* TOOLBAR + GRID */}
|
||||
<div className="flex flex-col flex-1 h-full">
|
||||
<div className="flex h-12 border-b border-transparent flex-2 w-100">
|
||||
<Toolbar type="secondary" tools={toolBarLayout[1].tools} />
|
||||
{toolbars.secondary.map(toolDef => {
|
||||
const { id, Component, componentProps } = toolDef;
|
||||
|
||||
return <Component key={id} id={id} {...componentProps} />;
|
||||
})}
|
||||
</div>
|
||||
<div className="flex items-center justify-center flex-1 h-full pt-1 pb-2 overflow-hidden bg-black">
|
||||
<ViewportGridComp
|
||||
servicesManager={servicesManager}
|
||||
viewportComponents={viewportComponents}
|
||||
/>
|
||||
{/*
|
||||
viewportContents={[
|
||||
<Viewport
|
||||
viewportIndex={0}
|
||||
onSeriesChange={direction => alert(`Series ${direction}`)}
|
||||
studyData={{
|
||||
label: 'A',
|
||||
isTracked: true,
|
||||
isLocked: false,
|
||||
studyDate: '07-Sep-2011',
|
||||
currentSeries: 1,
|
||||
seriesDescription:
|
||||
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
|
||||
modality: 'CT',
|
||||
patientInformation: {
|
||||
patientName: 'Smith, Jane',
|
||||
patientSex: 'F',
|
||||
patientAge: '59',
|
||||
MRN: '10000001',
|
||||
thickness: '5.0mm',
|
||||
spacing: '1.25mm',
|
||||
scanner: 'Aquilion',
|
||||
},
|
||||
}}
|
||||
>
|
||||
</Viewport>,
|
||||
<Viewport
|
||||
viewportIndex={1}
|
||||
onSeriesChange={direction => alert(`Series ${direction}`)}
|
||||
studyData={{
|
||||
label: 'A',
|
||||
isTracked: false,
|
||||
isLocked: true,
|
||||
studyDate: '07-Sep-2010',
|
||||
currentSeries: 2,
|
||||
seriesDescription:
|
||||
'Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit Series description lorem ipsum dolor sit ',
|
||||
modality: 'SR',
|
||||
patientInformation: {
|
||||
patientName: 'Smith, Jane',
|
||||
patientSex: 'F',
|
||||
patientAge: '59',
|
||||
MRN: '10000001',
|
||||
thickness: '2.0mm',
|
||||
spacing: '1.25mm',
|
||||
scanner: 'Aquilion',
|
||||
},
|
||||
}}
|
||||
>
|
||||
</Viewport>,
|
||||
]}
|
||||
setActiveViewportIndex={setActiveViewportIndex}
|
||||
activeViewportIndex={activeViewportIndex}
|
||||
/>*/}
|
||||
</div>
|
||||
</div>
|
||||
{rightPanelComponents.length && (
|
||||
@@ -227,14 +150,6 @@ ViewerLayout.propTypes = {
|
||||
}).isRequired,
|
||||
commandsManager: PropTypes.object,
|
||||
// From modes
|
||||
// TODO: Not in love with this shape,
|
||||
toolBarLayout: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
tools: PropTypes.array,
|
||||
moreTools: PropTypes.array,
|
||||
})
|
||||
).isRequired,
|
||||
//displaySetInstanceUids: PropTypes.any.isRequired,
|
||||
leftPanels: PropTypes.array,
|
||||
rightPanels: PropTypes.array,
|
||||
/** Responsible for rendering our grid of viewports; provided by consuming application */
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// SEE:
|
||||
// https://github.com/OHIF/Viewers/blob/b58aa4575ab72fe3f493cc5a4261b4f8256516ab/platform/viewer/src/appExtensions/MeasurementsPanel/index.js#L18-L49
|
||||
import React from 'react';
|
||||
import { useViewportGrid } from '@ohif/ui';
|
||||
|
||||
function getCommandsModule({ servicesManager }) {
|
||||
const { UIDialogService } = servicesManager.services;
|
||||
|
||||
const definitions = {
|
||||
toggleLayoutSelectionDialog: {
|
||||
commandFn: () => {
|
||||
if (!UIDialogService) {
|
||||
window.alert(
|
||||
'Unable to show dialog; no UI Dialog Service available.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use SimpleDialog component
|
||||
// TODO: update position on window resize
|
||||
// TODO: Expand service API to check if dialog w/ ID is already open
|
||||
// TODO: Import and call `useViewportGrid`
|
||||
UIDialogService.dismiss({ id: 'layoutSelection' });
|
||||
UIDialogService.create({
|
||||
id: 'layoutSelection',
|
||||
centralize: true,
|
||||
isDraggable: false,
|
||||
showOverlay: true,
|
||||
content: Test,
|
||||
});
|
||||
},
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
context: 'VIEWER',
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
definitions,
|
||||
defaultContext: 'VIEWER',
|
||||
};
|
||||
}
|
||||
|
||||
function Test() {
|
||||
const [
|
||||
{ numCols, numRows, activeViewportIndex, viewports },
|
||||
dispatch,
|
||||
] = useViewportGrid();
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
dispatch({
|
||||
type: 'SET_LAYOUT',
|
||||
payload: {
|
||||
numCols: 2,
|
||||
numRows: 2,
|
||||
},
|
||||
});
|
||||
}}
|
||||
style={{ color: 'white' }}
|
||||
>
|
||||
Hello World!
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default getCommandsModule;
|
||||
@@ -1,19 +1,98 @@
|
||||
const TOOLBAR_BUTTON_TYPES = {
|
||||
COMMAND: 'command',
|
||||
SET_TOOL_ACTIVE: 'setToolActive',
|
||||
BUILT_IN: 'builtIn',
|
||||
};
|
||||
import { ToolbarButton } from '@ohif/ui';
|
||||
import ToolbarDivider from './Toolbar/ToolbarDivider.jsx';
|
||||
import ToolbarLayoutSelector from './Toolbar/ToolbarLayoutSelector.jsx';
|
||||
|
||||
const definitions = [
|
||||
{
|
||||
id: 'Layout',
|
||||
label: 'Layout',
|
||||
icon: 'tool-layout',
|
||||
commandName: 'toggleLayoutSelectionDialog',
|
||||
commandOptions: { },
|
||||
},
|
||||
];
|
||||
export default function getToolbarModule({ commandsManager, servicesManager }) {
|
||||
const toolbarService = servicesManager.services.ToolBarService;
|
||||
|
||||
export default function getToolbarModule() {
|
||||
return { definitions, defaultContext: 'ACTIVE_VIEWPORT::CORNERSTONE' };
|
||||
return [
|
||||
{
|
||||
name: 'ohif.divider',
|
||||
defaultComponent: ToolbarDivider,
|
||||
clickHandler: () => {},
|
||||
},
|
||||
{
|
||||
name: 'ohif.action',
|
||||
defaultComponent: ToolbarButton,
|
||||
requiredConfig: [],
|
||||
optionalConfig: [],
|
||||
requiredProps: [],
|
||||
optionalProps: [],
|
||||
clickHandler: (evt, btn, btnSectionName) => {
|
||||
const { props } = btn;
|
||||
commandsManager.runCommand(props.commandName, props.commandOptions);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ohif.radioGroup',
|
||||
defaultComponent: ToolbarButton,
|
||||
requiredConfig: ['groupName'],
|
||||
optionalConfig: [],
|
||||
requiredProps: [],
|
||||
optionalProps: [],
|
||||
clickHandler: (evt, clickedBtn, btnSectionName) => {
|
||||
const { props } = clickedBtn;
|
||||
const allButtons = toolbarService.getButtons();
|
||||
|
||||
// Set all buttons in same group to inactive
|
||||
Object.keys(allButtons).forEach(btnName => {
|
||||
const btn = allButtons[btnName];
|
||||
const isRadioGroupBtn =
|
||||
btn.config &&
|
||||
btn.config.groupName &&
|
||||
btn.type === 'ohif.radioGroup';
|
||||
|
||||
if (
|
||||
isRadioGroupBtn &&
|
||||
clickedBtn.config.groupName === btn.config.groupName
|
||||
) {
|
||||
btn.props.isActive = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Set our clicked button to active
|
||||
allButtons[clickedBtn.id].props.isActive = true;
|
||||
|
||||
// Run button logic/command
|
||||
commandsManager.runCommand(props.commandName, props.commandOptions);
|
||||
|
||||
// Set buttons & trigger notification
|
||||
toolbarService.setButtons(allButtons);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ohif.layoutSelector',
|
||||
defaultComponent: ToolbarLayoutSelector,
|
||||
requiredConfig: [],
|
||||
optionalConfig: [],
|
||||
requiredProps: [],
|
||||
optionalProps: [],
|
||||
clickHandler: (evt, clickedBtn, btnSectionName) => {},
|
||||
},
|
||||
{
|
||||
name: 'ohif.toggle',
|
||||
defaultComponent: ToolbarButton,
|
||||
requiredConfig: [],
|
||||
optionalConfig: [],
|
||||
requiredProps: [],
|
||||
optionalProps: [],
|
||||
clickHandler: (evt, clickedBtn, btnSectionName) => {
|
||||
const { props } = clickedBtn;
|
||||
const allButtons = toolbarService.getButtons();
|
||||
const thisButton = allButtons[clickedBtn.id];
|
||||
|
||||
// Set our clicked button to active
|
||||
thisButton.props.isActive = !thisButton.props.isActive;
|
||||
|
||||
// Run button logic/command
|
||||
// MAKE SURE THIS SUPPORTS TOGGLE!
|
||||
// commandsManager.runCommand(props.commandName, props.commandOptions);
|
||||
// What if just toggled "content"?
|
||||
// commandName OR content?
|
||||
|
||||
// Set buttons & trigger notification
|
||||
toolbarService.setButtons(allButtons);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import getCommandsModule from './getCommandsModule.js';
|
||||
import getContextModule from './getContextModule.js';
|
||||
import getDataSourcesModule from './getDataSourcesModule.js';
|
||||
import getLayoutTemplateModule from './getLayoutTemplateModule.js';
|
||||
@@ -12,7 +11,6 @@ export default {
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id,
|
||||
getCommandsModule,
|
||||
getContextModule,
|
||||
getDataSourcesModule,
|
||||
getLayoutTemplateModule,
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// SEE:
|
||||
// https://github.com/OHIF/Viewers/blob/b58aa4575ab72fe3f493cc5a4261b4f8256516ab/platform/viewer/src/appExtensions/MeasurementsPanel/index.js#L18-L49
|
||||
import React from 'react';
|
||||
import { useViewportGrid } from '@ohif/ui';
|
||||
|
||||
function getCommandsModule({ servicesManager }) {
|
||||
const { UIDialogService } = servicesManager.services;
|
||||
|
||||
const definitions = {
|
||||
toggleLayoutSelectionDialog: {
|
||||
commandFn: () => {
|
||||
if (!UIDialogService) {
|
||||
window.alert(
|
||||
'Unable to show dialog; no UI Dialog Service available.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use SimpleDialog component
|
||||
// TODO: update position on window resize
|
||||
// TODO: Expand service API to check if dialog w/ ID is already open
|
||||
// TODO: Import and call `useViewportGrid`
|
||||
UIDialogService.dismiss({ id: 'layoutSelection' });
|
||||
UIDialogService.create({
|
||||
id: 'layoutSelection',
|
||||
centralize: true,
|
||||
isDraggable: false,
|
||||
showOverlay: true,
|
||||
content: Test,
|
||||
});
|
||||
},
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
context: 'VIEWER',
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
definitions,
|
||||
defaultContext: 'VIEWER',
|
||||
};
|
||||
}
|
||||
|
||||
function Test() {
|
||||
const [
|
||||
{ numCols, numRows, activeViewportIndex, viewports },
|
||||
dispatch,
|
||||
] = useViewportGrid();
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
dispatch({
|
||||
type: 'SET_LAYOUT',
|
||||
payload: {
|
||||
numCols: 2,
|
||||
numRows: 2,
|
||||
},
|
||||
});
|
||||
}}
|
||||
style={{ color: 'white' }}
|
||||
>
|
||||
Hello World!
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default getCommandsModule;
|
||||
@@ -1,4 +1,3 @@
|
||||
import getCommandsModule from './getCommandsModule.js';
|
||||
import getContextModule from './getContextModule.js';
|
||||
import getPanelModule from './getPanelModule.js';
|
||||
import getViewportModule from './getViewportModule.js';
|
||||
@@ -8,7 +7,6 @@ export default {
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id: 'org.ohif.measurement-tracking',
|
||||
getCommandsModule,
|
||||
getContextModule,
|
||||
getPanelModule,
|
||||
getViewportModule,
|
||||
|
||||
@@ -128,7 +128,9 @@ const definitions = [
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
definitions,
|
||||
defaultContext: 'ACTIVE_VIEWPORT::VTK',
|
||||
};
|
||||
export default [];
|
||||
|
||||
// export default {
|
||||
// definitions,
|
||||
// defaultContext: 'ACTIVE_VIEWPORT::VTK',
|
||||
// };
|
||||
Reference in new issue
Block a user