From 3cf2eb5ed80e966f0e8a3f9c6b6a67f98b32b8bb Mon Sep 17 00:00:00 2001 From: Erik Ziegler Date: Sat, 9 May 2020 20:23:43 +0200 Subject: [PATCH] Wire up contextModule, panelModule, layoutTemplateModule. Viewer sort of displays --- extensions/default/src/getContextModule.js | 32 +++++++++++- ...esModule.js => getLayoutTemplateModule.js} | 22 ++++----- extensions/default/src/getPanelModule.js | 41 ++++++++++++++++ extensions/default/src/getSidePanelModule.js | 26 ---------- extensions/default/src/index.js | 8 +-- modes/example/src/index.js | 10 ++-- .../core/src/extensions/ExtensionManager.js | 32 ++++++------ .../src/extensions/ExtensionManager.test.js | 2 +- platform/core/src/extensions/MODULE_TYPES.js | 2 + platform/viewer/src/routes/ModeRoute.js | 49 +++++++++++-------- .../viewer/src/routes/ViewModelContext.js | 2 + 11 files changed, 141 insertions(+), 85 deletions(-) rename extensions/default/src/{getLayoutTemplatesModule.js => getLayoutTemplateModule.js} (96%) create mode 100644 extensions/default/src/getPanelModule.js delete mode 100644 extensions/default/src/getSidePanelModule.js diff --git a/extensions/default/src/getContextModule.js b/extensions/default/src/getContextModule.js index 304edf563..c4aff41f0 100644 --- a/extensions/default/src/getContextModule.js +++ b/extensions/default/src/getContextModule.js @@ -1,10 +1,38 @@ +import React, { useState } from 'react'; +import ViewModelContext from '@ohif/viewer/src/routes/ViewModelContext'; + +const HelloWorldContext = React.createContext({ + message: 'HelloWorldContextTesting', + setMessage: () => {}, +}); + +HelloWorldContext.displayName = 'HelloWorldContext'; + +function HelloWorldContextProvider({ children }) { + const [message, setMessage] = useState('HelloWorldContextTesting'); + + return ( + + {children} + + ); +} + function getContextModule() { return [ { - name: 'myContext', - context: '', // TODO => //ContextComponent, + name: 'HelloWorldContext', + context: HelloWorldContext, + provider: HelloWorldContextProvider, }, ]; } +export { HelloWorldContext }; + export default getContextModule; diff --git a/extensions/default/src/getLayoutTemplatesModule.js b/extensions/default/src/getLayoutTemplateModule.js similarity index 96% rename from extensions/default/src/getLayoutTemplatesModule.js rename to extensions/default/src/getLayoutTemplateModule.js index f85eba2b0..0fdee6694 100644 --- a/extensions/default/src/getLayoutTemplatesModule.js +++ b/extensions/default/src/getLayoutTemplateModule.js @@ -1,26 +1,23 @@ import React, { useState } from 'react'; import { SidePanel, NavBar, Svg, Icon, IconButton, Toolbar } from '@ohif/ui'; +import { + HelloWorldContext, + AnotherHelloWorldContext, +} from './getContextModule'; export default function() { return [ // Layout Template Definition + // TODO: this is weird naming { - id: 'org.ohif.defaults.viewerLayout', + name: 'viewerLayout', + id: 'viewerLayout', component: viewerLayout, }, ]; } -/* { - id: 'org.ohif.defaults.viewerLayout', - props: { - leftPanelIds: ['org.ohif.defaults.seriesList'], - rightPanelIds: ['org.ohif.defaults.measure'], - }, - }, - */ - const Header = () => { const [activeTool, setActiveTool] = useState('Zoom'); const dropdownContent = [ @@ -176,12 +173,15 @@ const ViewportToolbar = () => { function viewerLayout({ leftPanels, rightPanels, extensionManager }) { const getPanelData = id => { const entry = extensionManager.getModuleEntry(id); + // TODO, not sure why sidepanel content has to be JSX, and not a children prop? + const content = entry.component({}); + return { iconName: entry.iconName, iconLabel: entry.iconLabel, label: entry.label, name: entry.name, - content: entry.component, + content, }; }; diff --git a/extensions/default/src/getPanelModule.js b/extensions/default/src/getPanelModule.js new file mode 100644 index 000000000..e90e37a1f --- /dev/null +++ b/extensions/default/src/getPanelModule.js @@ -0,0 +1,41 @@ +import React from 'react'; +import { + HelloWorldContext, + AnotherHelloWorldContext, +} from './getContextModule'; + +function helloWorldComponent({}) { + return ( + + {value => ( +
+

+ {'Hello world. Context value:'} + {JSON.stringify(value)} +

+
+ )} +
+ ); +} + +function getPanelModule() { + return [ + { + name: 'seriesList', + iconName: 'group-layers', + iconLabel: 'Studies', + label: 'Studies', + component: helloWorldComponent, + }, + { + name: 'measure', + iconName: 'list-bullets', + iconLabel: 'Measure', + label: 'Measurements', + component: helloWorldComponent, + }, + ]; +} + +export default getPanelModule; diff --git a/extensions/default/src/getSidePanelModule.js b/extensions/default/src/getSidePanelModule.js deleted file mode 100644 index 0ab68ed47..000000000 --- a/extensions/default/src/getSidePanelModule.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; - -function helloWorldComponent() { - return
{'Hello world'}
; -} - -function getSidePanelModule() { - return [ - { - name: 'org.ohif.defaults.seriesList', - iconName: 'group-layers', - iconLabel: 'Studies', - label: 'Studies', - component: helloWorldComponent, - }, - { - name: 'org.ohif.defaults.measure', - iconName: 'list-bullets', - iconLabel: 'Measure', - label: 'Measurements', - component: helloWorldComponent, - }, - ]; -} - -export default getSidePanelModule; diff --git a/extensions/default/src/index.js b/extensions/default/src/index.js index 4543d51f2..572c826f1 100644 --- a/extensions/default/src/index.js +++ b/extensions/default/src/index.js @@ -1,7 +1,7 @@ import getContextModule from './getContextModule.js'; import getDataSourcesModule from './getDataSourcesModule.js'; -import getLayoutTemplatesModule from './getLayoutTemplatesModule.js'; -import getSidePanelModule from './getSidePanelModule.js'; +import getLayoutTemplateModule from './getLayoutTemplateModule.js'; +import getPanelModule from './getPanelModule.js'; export default { /** @@ -10,6 +10,6 @@ export default { id: 'org.ohif.default', getContextModule, getDataSourcesModule, - getLayoutTemplatesModule, - getSidePanelModule, + getLayoutTemplateModule, + getPanelModule, }; diff --git a/modes/example/src/index.js b/modes/example/src/index.js index bd54fbf00..ef99e7cdd 100644 --- a/modes/example/src/index.js +++ b/modes/example/src/index.js @@ -21,18 +21,18 @@ export default function mode({ modeConfiguration }) { }, layoutTemplate: ({ routeProps }) => { return { - id: 'org.ohif.defaults.viewerLayout', + id: 'org.ohif.default.layoutTemplateModule.viewerLayout', props: { // named slots - leftPanels: ['org.ohif.defaults.seriesList'], - rightPanels: ['org.ohif.defaults.measure'], + leftPanels: ['org.ohif.default.panelModule.seriesList'], + rightPanels: ['org.ohif.default.panelModule.measure'], }, }; }, }, ], - extensions: ['org.ohif.defaults', 'org.ohif.cornerstone'], - sopClassHandlers: ['org.ohif.defaults.stack'], + extensions: ['org.ohif.default', 'org.ohif.cornerstone'], + sopClassHandlers: ['org.ohif.default.sopClassHandlerModule.stack'], }; } diff --git a/platform/core/src/extensions/ExtensionManager.js b/platform/core/src/extensions/ExtensionManager.js index c05548c13..66eb4e07e 100644 --- a/platform/core/src/extensions/ExtensionManager.js +++ b/platform/core/src/extensions/ExtensionManager.js @@ -25,7 +25,7 @@ export default class ExtensionManager { * * @param {Object[]} extensions - Array of extensions */ - registerExtensions(extensions) { + registerExtensions = extensions => { extensions.forEach(extension => { const hasConfiguration = Array.isArray(extension); @@ -36,7 +36,7 @@ export default class ExtensionManager { this.registerExtension(extension); } }); - } + }; /** * @@ -44,7 +44,7 @@ export default class ExtensionManager { * @param {Object} extension * @param {Object} configuration */ - registerExtension(extension, configuration = {}) { + registerExtension = (extension, configuration = {}) => { if (!extension) { log.warn( 'Attempting to register a null/undefined extension. Exiting early.' @@ -97,23 +97,25 @@ export default class ExtensionManager { }); extensionModule.forEach(element => { - this.modulesMap[`${extensionId}.${moduleType}.${element.name}`]; + this.modulesMap[ + `${extensionId}.${moduleType}.${element.name}` + ] = element; }); } }); // Track extension registration this.registeredExtensionIds.push(extensionId); - } + }; - getModuleEntry(stringEntry) { + getModuleEntry = stringEntry => { return this.modulesMap[stringEntry]; - } + }; - getDataSource(dataSourceId) { + getDataSource = dataSourceId => { // Note: this currently uses the data source name, which feels weird... return this.dataSourceMap[dataSourceId]; - } + }; /** * @private @@ -121,7 +123,7 @@ export default class ExtensionManager { * @param {Object} extension * @param {string} extensionId - Used for logging warnings */ - _getExtensionModule(moduleType, extension, extensionId, configuration) { + _getExtensionModule = (moduleType, extension, extensionId, configuration) => { const getModuleFnName = 'get' + _capitalizeFirstCharacter(moduleType); const getModuleFn = extension[getModuleFnName]; @@ -150,9 +152,9 @@ export default class ExtensionManager { `Exception thrown while trying to call ${getModuleFnName} for the ${extensionId} extension` ); } - } + }; - _initSpecialModuleTypes(moduleType, extensionModule) { + _initSpecialModuleTypes = (moduleType, extensionModule) => { switch (moduleType) { case 'commandsModule': { const { definitions, defaultContext } = extensionModule; @@ -173,14 +175,14 @@ export default class ExtensionManager { default: // code block } - } + }; /** * * @private * @param {Object[]} commandDefinitions */ - _initCommandsModule(commandDefinitions, defaultContext = 'VIEWER') { + _initCommandsModule = (commandDefinitions, defaultContext = 'VIEWER') => { if (!this._commandsManager.getContext(defaultContext)) { this._commandsManager.createContext(defaultContext); } @@ -201,7 +203,7 @@ export default class ExtensionManager { commandDefinition ); }); - } + }; } /** diff --git a/platform/core/src/extensions/ExtensionManager.test.js b/platform/core/src/extensions/ExtensionManager.test.js index 42965c4a1..5ed3fad8d 100644 --- a/platform/core/src/extensions/ExtensionManager.test.js +++ b/platform/core/src/extensions/ExtensionManager.test.js @@ -226,7 +226,7 @@ describe('ExtensionManager.js', () => { return { definitions: { exampleDefinition: { - commandFn: () => { }, + commandFn: () => {}, storeContexts: [], options: {}, }, diff --git a/platform/core/src/extensions/MODULE_TYPES.js b/platform/core/src/extensions/MODULE_TYPES.js index f0ce4f0cf..887347aba 100644 --- a/platform/core/src/extensions/MODULE_TYPES.js +++ b/platform/core/src/extensions/MODULE_TYPES.js @@ -5,4 +5,6 @@ export default { SOP_CLASS_HANDLER: 'sopClassHandlerModule', TOOLBAR: 'toolbarModule', VIEWPORT: 'viewportModule', + CONTEXT: 'contextModule', + LAYOUT_TEMPLATE: 'layoutTemplateModule', }; diff --git a/platform/viewer/src/routes/ModeRoute.js b/platform/viewer/src/routes/ModeRoute.js index 8014db6f9..afb4d4b26 100644 --- a/platform/viewer/src/routes/ModeRoute.js +++ b/platform/viewer/src/routes/ModeRoute.js @@ -18,18 +18,16 @@ export default function ModeRoute({ // Deal with toolbar. // Only handling one route per mode for now - const layoutTemplateData = routes[0].layoutTemplate({ location }); - /*const LayoutComponent = extensionManager.getModuleEntry( - layoutTemplateData.id - );*/ - // You can test via http://localhost:3000/example-mode/dicomweb - const LayoutComponent = () => ( -
- {`Reached the route for Mode: ${mode.id} and Data Source: ${dataSourceId}`} -
+ const layoutTemplateData = routes[0].layoutTemplate({ location }); + + const layoutTemplateModuleEntry = extensionManager.getModuleEntry( + layoutTemplateData.id ); + const LayoutComponent = layoutTemplateModuleEntry.component; + //const LayoutComponent = props =>
{'Testing'}
; + // Add SOPClassHandlers to a new SOPClassManager. /*const manager = new SOPClassHandlerManager( extensionManager, @@ -49,24 +47,33 @@ export default function ModeRoute({ //manager.createDisplaySets.then(setDisplaySetInstanceUids); }; - // TODO: For each extension, look up their context modules - //const contextModules = extensions.getContextModules(); - //const contextModuleProviders = contextModules.map(a => a.context.Provider); - //const CombinedContextProvider = Compose(contextModuleProviders); + // For each extension, look up their context modules + let contextModules = []; + extensions.forEach(extensionId => { + const allRegisteredModuleIds = Object.keys(extensionManager.modulesMap); + const moduleIds = allRegisteredModuleIds.filter(id => + id.includes(`${extensionId}.contextModule.`) + ); + + if (!moduleIds || !moduleIds.length) { + return; + } + + const modules = moduleIds.map(extensionManager.getModuleEntry); + contextModules = contextModules.concat(modules); + }); + + const contextModuleProviders = contextModules.map(a => a.provider); + const CombinedContextProvider = ({ children }) => + Compose({ components: contextModuleProviders, children }); return ( - - ); - - /*return ( - );*/ + ); } diff --git a/platform/viewer/src/routes/ViewModelContext.js b/platform/viewer/src/routes/ViewModelContext.js index bc6390e50..4ecf723b7 100644 --- a/platform/viewer/src/routes/ViewModelContext.js +++ b/platform/viewer/src/routes/ViewModelContext.js @@ -5,6 +5,8 @@ const ViewModelContext = React.createContext({ setDisplaySetInstanceUids: () => {}, }); +ViewModelContext.displayName = 'ViewModelContext'; + class ViewModelProvider extends Component { state = { displaySetInstanceUids: [],