Update extension manager to ingest each module type. Add toolbar Manager.
This commit is contained in:
1 parent
a8340b9b69
commit
c42aa37d7f
9 files changed
+186
-85
No files matched your search
@@ -0,0 +1,55 @@
|
||||
export default class toolBarManager {
|
||||
constructor(extensionManager) {
|
||||
this.toolBarLayout = [];
|
||||
this.buttons = {};
|
||||
this.extensionManager = extensionManager;
|
||||
}
|
||||
|
||||
addButtons(buttons) {
|
||||
buttons.forEach(button => {
|
||||
const buttonDefinition = this.extensionManager.getModuleEntry(
|
||||
button.namespace
|
||||
);
|
||||
|
||||
const id = button.id || buttonDefinition.id;
|
||||
|
||||
this.buttons[id] = buttonDefinition;
|
||||
});
|
||||
|
||||
console.log(this.buttons);
|
||||
}
|
||||
|
||||
setToolBarLayout(layouts) {
|
||||
const toolBarLayout = [];
|
||||
|
||||
layouts.forEach(layout => {
|
||||
const toolBarDefinitions = [];
|
||||
|
||||
layout.forEach(element => {
|
||||
if (typeof element === 'object') {
|
||||
// process submenu.
|
||||
|
||||
const subMenuDefinition = { label: element.label, subMenu: [] };
|
||||
|
||||
element.subMenu.forEach(subMenuElement => {
|
||||
const button = this.buttons[subMenuElement];
|
||||
|
||||
subMenuDefinition.subMenu.push(button);
|
||||
});
|
||||
|
||||
toolBarDefinitions.push(subMenuDefinition);
|
||||
} else {
|
||||
const button = this.buttons[element];
|
||||
|
||||
toolBarDefinitions.push(button);
|
||||
}
|
||||
});
|
||||
|
||||
toolBarLayout.push(toolBarDefinitions);
|
||||
});
|
||||
|
||||
this.toolBarLayout = toolBarLayout;
|
||||
|
||||
console.log(this.toolBarLayout);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,9 @@ export default class ExtensionManager {
|
||||
this.modules[moduleType] = [];
|
||||
});
|
||||
this.dataSourceMap = {};
|
||||
|
||||
console.log('modules map');
|
||||
console.log(this.modulesMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,11 +58,9 @@ export default class ExtensionManager {
|
||||
let extensionId = extension.id;
|
||||
|
||||
if (!extensionId) {
|
||||
extensionId = Math.random()
|
||||
.toString(36)
|
||||
.substr(2, 5);
|
||||
|
||||
log.warn(`Extension ID not set. Using random string ID: ${extensionId}`);
|
||||
// Note: Mode framework cannot function without IDs.
|
||||
log.warn(extension);
|
||||
throw new Error(`Extension ID not set`);
|
||||
}
|
||||
|
||||
if (this.registeredExtensionIds.includes(extensionId)) {
|
||||
@@ -89,25 +90,43 @@ export default class ExtensionManager {
|
||||
);
|
||||
|
||||
if (extensionModule) {
|
||||
this._initSpecialModuleTypes(
|
||||
extensionId,
|
||||
moduleType,
|
||||
extensionModule,
|
||||
dataSources
|
||||
);
|
||||
switch (moduleType) {
|
||||
case MODULE_TYPES.COMMANDS:
|
||||
this._initCommandsModule(extensionModule);
|
||||
break;
|
||||
case MODULE_TYPES.DATA_SOURCE:
|
||||
this._initDataSourcesModule(
|
||||
extensionModule,
|
||||
extensionId,
|
||||
dataSources
|
||||
);
|
||||
break;
|
||||
case MODULE_TYPES.TOOLBAR:
|
||||
this._initToolBarModule(extensionModule, extensionId);
|
||||
break;
|
||||
|
||||
case MODULE_TYPES.PANEL:
|
||||
case MODULE_TYPES.SOP_CLASS_HANDLER:
|
||||
case MODULE_TYPES.VIEWPORT:
|
||||
case MODULE_TYPES.CONTEXT:
|
||||
case MODULE_TYPES.LAYOUT_TEMPLATE:
|
||||
// Default for most extension points,
|
||||
// Just adds each entry ready for consumption by mode.
|
||||
if (!extensionModule.forEach) {
|
||||
debugger;
|
||||
}
|
||||
|
||||
extensionModule.forEach(element => {
|
||||
this.modulesMap[
|
||||
`${extensionId}.${moduleType}.${element.name}`
|
||||
] = element;
|
||||
});
|
||||
}
|
||||
|
||||
this.modules[moduleType].push({
|
||||
extensionId,
|
||||
module: extensionModule,
|
||||
});
|
||||
|
||||
// TODO -> deal with command modules.
|
||||
|
||||
extensionModule.forEach(element => {
|
||||
this.modulesMap[
|
||||
`${extensionId}.${moduleType}.${element.name}`
|
||||
] = element;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -124,6 +143,27 @@ export default class ExtensionManager {
|
||||
return this.dataSourceMap[dataSourceName];
|
||||
};
|
||||
|
||||
_initToolBarModule = (extensionModule, extensionId) => {
|
||||
let { definitions, defaultContext } = extensionModule;
|
||||
if (!definitions || Object.keys(definitions).length === 0) {
|
||||
log.warn('Commands Module contains no command definitions');
|
||||
return;
|
||||
}
|
||||
|
||||
defaultContext = defaultContext || 'VIEWER';
|
||||
|
||||
definitions.forEach(definition => {
|
||||
console.log(`${extensionId}.${MODULE_TYPES.TOOLBAR}.${definition.id}`);
|
||||
|
||||
// TODO -> Deep copy instead of mutation? We only do this once, but would be better.
|
||||
definition.context = definition.context || defaultContext;
|
||||
|
||||
this.modulesMap[
|
||||
`${extensionId}.${MODULE_TYPES.TOOLBAR}.${definition.id}`
|
||||
] = definition;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} moduleType
|
||||
@@ -162,64 +202,52 @@ export default class ExtensionManager {
|
||||
}
|
||||
};
|
||||
|
||||
_initSpecialModuleTypes = (
|
||||
extensionId,
|
||||
moduleType,
|
||||
extensionModule,
|
||||
dataSources
|
||||
) => {
|
||||
switch (moduleType) {
|
||||
case 'commandsModule': {
|
||||
const { definitions, defaultContext } = extensionModule;
|
||||
if (!definitions || Object.keys(definitions).length === 0) {
|
||||
log.warn('Commands Module contains no command definitions');
|
||||
return;
|
||||
_initDataSourcesModule(extensionModule, extensionId, dataSources) {
|
||||
extensionModule.forEach(element => {
|
||||
const namespace = `${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`;
|
||||
|
||||
dataSources.forEach(dataSource => {
|
||||
if (dataSource.namespace === namespace) {
|
||||
const dataSourceInstance = element.createDataSource(
|
||||
dataSource.configuration
|
||||
);
|
||||
|
||||
if (this.dataSourceMap[dataSource.sourceName]) {
|
||||
this.dataSourceMap[dataSource.sourceName].push(dataSourceInstance);
|
||||
} else {
|
||||
this.dataSourceMap[dataSource.sourceName] = [dataSourceInstance];
|
||||
}
|
||||
}
|
||||
this._initCommandsModule(definitions, defaultContext);
|
||||
break;
|
||||
}
|
||||
case 'dataSourcesModule': {
|
||||
extensionModule.forEach(element => {
|
||||
const namespace = `${extensionId}.${moduleType}.${element.name}`;
|
||||
});
|
||||
});
|
||||
|
||||
dataSources.forEach(dataSource => {
|
||||
if (dataSource.namespace === namespace) {
|
||||
const dataSourceInstance = element.createDataSource(
|
||||
dataSource.configuration
|
||||
);
|
||||
|
||||
if (this.dataSourceMap[dataSource.sourceName]) {
|
||||
this.dataSourceMap[dataSource.sourceName].push(
|
||||
dataSourceInstance
|
||||
);
|
||||
} else {
|
||||
this.dataSourceMap[dataSource.sourceName] = [
|
||||
dataSourceInstance,
|
||||
];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// code block
|
||||
}
|
||||
};
|
||||
extensionModule.forEach(element => {
|
||||
this.modulesMap[
|
||||
`${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`
|
||||
] = element;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @private
|
||||
* @param {Object[]} commandDefinitions
|
||||
*/
|
||||
_initCommandsModule = (commandDefinitions, defaultContext = 'VIEWER') => {
|
||||
_initCommandsModule = extensionModule => {
|
||||
let { definitions, defaultContext } = extensionModule;
|
||||
if (!definitions || Object.keys(definitions).length === 0) {
|
||||
log.warn('Commands Module contains no command definitions');
|
||||
return;
|
||||
}
|
||||
|
||||
defaultContext = defaultContext || 'VIEWER';
|
||||
|
||||
if (!this._commandsManager.getContext(defaultContext)) {
|
||||
this._commandsManager.createContext(defaultContext);
|
||||
}
|
||||
|
||||
Object.keys(commandDefinitions).forEach(commandName => {
|
||||
const commandDefinition = commandDefinitions[commandName];
|
||||
Object.keys(definitions).forEach(commandName => {
|
||||
const commandDefinition = definitions[commandName];
|
||||
const commandHasContextThatDoesNotExist =
|
||||
commandDefinition.context &&
|
||||
!this._commandsManager.getContext(commandDefinition.context);
|
||||
|
||||
@@ -20,6 +20,7 @@ import ui from './ui';
|
||||
import user from './user.js';
|
||||
import dicomMetadataStore from './dicomMetadataStore';
|
||||
import displaySetManager from './displaySetManager';
|
||||
import ToolBarManager from './ToolBarManager';
|
||||
import utils, { hotkeys } from './utils/';
|
||||
|
||||
import {
|
||||
@@ -68,6 +69,7 @@ const OHIF = {
|
||||
IWebApiDataSource,
|
||||
dicomMetadataStore,
|
||||
displaySetManager,
|
||||
ToolBarManager,
|
||||
};
|
||||
|
||||
export {
|
||||
@@ -105,6 +107,7 @@ export {
|
||||
IWebApiDataSource,
|
||||
dicomMetadataStore,
|
||||
displaySetManager,
|
||||
ToolBarManager,
|
||||
};
|
||||
|
||||
export { OHIF };
|
||||
|
||||
@@ -47,8 +47,6 @@ function appInit(appConfigOrFunc, defaultExtensions) {
|
||||
MeasurementService,
|
||||
]);
|
||||
|
||||
debugger;
|
||||
|
||||
/**
|
||||
* Example: [ext1, ext2, ext3]
|
||||
* Example2: [[ext1, config], ext2, [ext3, config]]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useContext, useEffect, useCallback } from 'react';
|
||||
import { displaySetManager } from '@ohif/core';
|
||||
import { displaySetManager, ToolBarManager } from '@ohif/core';
|
||||
import ViewModelContext from './ViewModelContext';
|
||||
import Compose from './Compose';
|
||||
|
||||
@@ -9,15 +9,21 @@ export default function ModeRoute({
|
||||
dataSourceName,
|
||||
extensionManager,
|
||||
}) {
|
||||
const { routes, sopClassHandlers, extensions } = mode;
|
||||
const { routes, sopClassHandlers, extensions, init } = mode;
|
||||
const dataSources = extensionManager.getDataSources(dataSourceName);
|
||||
|
||||
const toolbarManager = new ToolBarManager(extensionManager);
|
||||
|
||||
// TODO: For now assume one unique datasource.
|
||||
|
||||
const dataSource = dataSources[0];
|
||||
const route = routes[0];
|
||||
|
||||
route.init({ toolbarManager });
|
||||
|
||||
console.log(dataSource);
|
||||
|
||||
// Add toolbar state to the view model context?
|
||||
const { displaySetInstanceUids, setDisplaySetInstanceUids } = useContext(
|
||||
ViewModelContext
|
||||
);
|
||||
@@ -42,11 +48,9 @@ export default function ModeRoute({
|
||||
createDisplaySets();
|
||||
}, [mode, dataSourceName, location]);
|
||||
|
||||
// Deal with toolbar.
|
||||
|
||||
// Only handling one route per mode for now
|
||||
// You can test via http://localhost:3000/example-mode/dicomweb
|
||||
const layoutTemplateData = routes[0].layoutTemplate({ location });
|
||||
const layoutTemplateData = route.layoutTemplate({ location });
|
||||
const layoutTemplateModuleEntry = extensionManager.getModuleEntry(
|
||||
layoutTemplateData.id
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user