Working cornerstone tools buttons, needs UI updates + onClicks wrapped in toolbarService
This commit is contained in:
commit
a3e1c216c4
@ -1,39 +1,22 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { SidePanel, Toolbar } from '@ohif/ui';
|
||||
import { useToolbarLayout } from '@ohif/core';
|
||||
//
|
||||
import Header from './Header.jsx';
|
||||
import { displaySetManager } from '@ohif/core';
|
||||
|
||||
// function ViewportDataCreator({ setViewportData }) {
|
||||
// const { displaySetInstanceUIDs } = useViewModel();
|
||||
// console.log(displaySetInstanceUIDs);
|
||||
|
||||
// useEffect(() => {
|
||||
// setViewportData([
|
||||
// displaySetManager.getDisplaySetByUID(displaySetInstanceUIDs[0]),
|
||||
// ]);
|
||||
// }, [displaySetInstanceUIDs, setViewportData]);
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
function ViewerLayout({
|
||||
// From Extension Module Params
|
||||
extensionManager,
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
// From Modes
|
||||
leftPanels,
|
||||
rightPanels,
|
||||
viewports,
|
||||
children,
|
||||
ViewportGridComp
|
||||
ViewportGridComp,
|
||||
}) {
|
||||
const [displaySets, setDisplaySets] = useState({});
|
||||
|
||||
//const ViewportGrid = React.Children.only(children);
|
||||
|
||||
const { ToolBarService } = servicesManager.services;
|
||||
/**
|
||||
* Set body classes (tailwindcss) that don't allow vertical
|
||||
* or horizontal overflow (no scrolling). Also guarantee window
|
||||
@ -47,6 +30,7 @@ function ViewerLayout({
|
||||
document.body.classList.remove('overflow-hidden');
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getPanelData = id => {
|
||||
const entry = extensionManager.getModuleEntry(id);
|
||||
// TODO, not sure why sidepanel content has to be JSX, and not a children prop?
|
||||
@ -70,27 +54,84 @@ 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: () => {
|
||||
debugger;
|
||||
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),
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
});
|
||||
|
||||
debugger;
|
||||
|
||||
setToolBarLayout(toolBarLayout);
|
||||
};
|
||||
|
||||
const [toolBarLayout, setToolBarLayout] = useState([
|
||||
{ tools: [], moreTools: [] },
|
||||
{ tools: [] },
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const { unsubscribe } = ToolBarService.subscribe(
|
||||
ToolBarService.EVENTS.TOOL_BAR_MODIFIED,
|
||||
handleToolBarSubscription
|
||||
);
|
||||
|
||||
return unsubscribe;
|
||||
}, []);
|
||||
|
||||
const leftPanelComponents = leftPanels.map(getPanelData);
|
||||
const rightPanelComponents = rightPanels.map(getPanelData);
|
||||
const viewportComponents = viewports.map(getViewportComponentData);
|
||||
|
||||
// let { toolBarLayout } = useToolbarLayout();
|
||||
// if (!toolBarLayout.length) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// TODO -> make toolbar service
|
||||
const toolBarLayout = { tools: [], moreTools: [] };
|
||||
|
||||
//const [primaryToolBarLayout, secondaryToolBarLayout] = toolBarLayout;
|
||||
const primaryToolBarLayout = toolBarLayout;
|
||||
const secondaryToolBarLayout = toolBarLayout;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header
|
||||
tools={primaryToolBarLayout.tools}
|
||||
moreTools={primaryToolBarLayout.moreTools}
|
||||
tools={toolBarLayout[0].tools}
|
||||
moreTools={toolBarLayout[0].moreTools}
|
||||
/>
|
||||
<div
|
||||
className="flex flex-row flex-no-wrap items-stretch overflow-hidden w-full"
|
||||
@ -105,7 +146,7 @@ function ViewerLayout({
|
||||
{/* TOOLBAR + GRID */}
|
||||
<div className="flex flex-col flex-1 h-full">
|
||||
<div className="flex flex-2 w-100 border-b border-transparent h-12">
|
||||
<Toolbar type="secondary" tools={secondaryToolBarLayout.tools} />
|
||||
<Toolbar type="secondary" tools={toolBarLayout[1].tools} />
|
||||
</div>
|
||||
<div className="flex flex-1 h-full overflow-hidden bg-black items-center justify-center pb-2 pt-1">
|
||||
<ViewportGridComp
|
||||
@ -183,6 +224,7 @@ ViewerLayout.propTypes = {
|
||||
extensionManager: PropTypes.shape({
|
||||
getModuleEntry: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
commandsManager: PropTypes.object,
|
||||
// From modes
|
||||
// TODO: Not in love with this shape,
|
||||
toolBarLayout: PropTypes.arrayOf(
|
||||
@ -198,11 +240,4 @@ ViewerLayout.propTypes = {
|
||||
children: PropTypes.oneOfType(PropTypes.node, PropTypes.func).isRequired,
|
||||
};
|
||||
|
||||
ViewerLayout.defaultProps = {
|
||||
toolBarLayout: [
|
||||
{ tools: [], moreTools: [] },
|
||||
{ tools: [], moreTools: [] },
|
||||
],
|
||||
};
|
||||
|
||||
export default ViewerLayout;
|
||||
|
||||
@ -5,9 +5,18 @@ import ViewerLayout from './ViewerLayout';
|
||||
- Init layout based on the displaySets and the objects.
|
||||
*/
|
||||
|
||||
export default function({ servicesManager, extensionManager }) {
|
||||
export default function({
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
commandsManager,
|
||||
}) {
|
||||
function ViewerLayoutWithServices(props) {
|
||||
return ViewerLayout({ servicesManager, extensionManager, ...props });
|
||||
return ViewerLayout({
|
||||
servicesManager,
|
||||
extensionManager,
|
||||
commandsManager,
|
||||
...props,
|
||||
});
|
||||
}
|
||||
|
||||
return [
|
||||
|
||||
@ -12,8 +12,10 @@ export default function mode({ modeConfiguration }) {
|
||||
routes: [
|
||||
{
|
||||
path: 'viewer',
|
||||
init: ({ toolBarManager }) => {
|
||||
toolBarManager.addButtons([
|
||||
init: ({ servicesManager, extensionManager }) => {
|
||||
const { ToolBarService } = servicesManager.services;
|
||||
ToolBarService.init(extensionManager);
|
||||
ToolBarService.addButtons([
|
||||
{
|
||||
id: 'Zoom',
|
||||
namespace: 'org.ohif.cornerstone.toolbarModule.Zoom',
|
||||
@ -53,7 +55,7 @@ export default function mode({ modeConfiguration }) {
|
||||
]);
|
||||
|
||||
// Could import layout selector here from org.ohif.default (when it exists!)
|
||||
toolBarManager.setToolBarLayout([
|
||||
ToolBarService.setToolBarLayout([
|
||||
// Primary
|
||||
{
|
||||
tools: ['Zoom', 'Levels', 'Pan', 'Capture', 'Layout'],
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
export default class toolBarManager {
|
||||
constructor(extensionManager) {
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
setToolBarLayout(layouts) {
|
||||
const toolBarLayout = [];
|
||||
|
||||
layouts.forEach(layout => {
|
||||
const toolBarDefinitions = { tools: [], moreTools: [] };
|
||||
|
||||
const { tools, moreTools } = layout;
|
||||
|
||||
tools &&
|
||||
tools.forEach(element => {
|
||||
const button = this.buttons[element];
|
||||
|
||||
toolBarDefinitions.tools.push(button);
|
||||
});
|
||||
|
||||
moreTools &&
|
||||
moreTools.forEach(element => {
|
||||
const button = this.buttons[element];
|
||||
|
||||
toolBarDefinitions.moreTools.push(button);
|
||||
});
|
||||
|
||||
toolBarLayout.push(toolBarDefinitions);
|
||||
});
|
||||
|
||||
// TODO -> Change this to a service. => emit an event to subscribers to update the toolbar layout.
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
import React, { Component, useContext } from 'react';
|
||||
|
||||
/// TODO MAKE THIS PRETTY DANNY
|
||||
|
||||
const ToolbarLayoutContext = React.createContext({
|
||||
toolBarLayout: [],
|
||||
setToolBarLayout: () => {},
|
||||
});
|
||||
|
||||
ToolbarLayoutContext.displayName = 'ToolbarLayoutContext';
|
||||
|
||||
class ToolbarLayoutProvider extends Component {
|
||||
state = {
|
||||
toolBarLayout: [],
|
||||
};
|
||||
|
||||
render() {
|
||||
const setToolBarLayout = toolBarLayout => {
|
||||
this.setState({ toolBarLayout });
|
||||
};
|
||||
|
||||
return (
|
||||
<ToolbarLayoutContext.Provider
|
||||
value={{
|
||||
toolBarLayout: this.state.toolBarLayout,
|
||||
setToolBarLayout,
|
||||
}}
|
||||
>
|
||||
{this.props.children}
|
||||
</ToolbarLayoutContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const useToolbarLayout = () => useContext(ToolbarLayoutContext);
|
||||
|
||||
export default ToolbarLayoutContext;
|
||||
|
||||
export { ToolbarLayoutProvider, useToolbarLayout };
|
||||
@ -20,12 +20,7 @@ import studies from './studies/';
|
||||
import ui from './ui';
|
||||
import user from './user.js';
|
||||
import dicomMetadataStore from './dicomMetadataStore';
|
||||
import ToolBarManager from './ToolBarManager';
|
||||
import { ViewModelProvider, useViewModel } from './ViewModelContext';
|
||||
import {
|
||||
ToolbarLayoutProvider,
|
||||
useToolbarLayout,
|
||||
} from './ToolbarLayoutContext';
|
||||
import utils, { hotkeys } from './utils/';
|
||||
|
||||
import {
|
||||
@ -35,6 +30,7 @@ import {
|
||||
UINotificationService,
|
||||
UIViewportDialogService,
|
||||
DisplaySetService,
|
||||
ToolBarSerivce,
|
||||
} from './services';
|
||||
|
||||
import IWebApiDataSource from './DataSources/IWebApiDataSource';
|
||||
@ -73,10 +69,10 @@ const OHIF = {
|
||||
UIViewportDialogService,
|
||||
DisplaySetService,
|
||||
MeasurementService,
|
||||
ToolBarSerivce,
|
||||
IWebApiDataSource,
|
||||
dicomMetadataStore,
|
||||
//
|
||||
ToolBarManager,
|
||||
ViewModelProvider,
|
||||
useViewModel,
|
||||
};
|
||||
@ -114,13 +110,11 @@ export {
|
||||
UIViewportDialogService,
|
||||
DisplaySetService,
|
||||
MeasurementService,
|
||||
ToolBarSerivce,
|
||||
IWebApiDataSource,
|
||||
dicomMetadataStore,
|
||||
ToolBarManager,
|
||||
ViewModelProvider,
|
||||
useViewModel,
|
||||
ToolbarLayoutProvider,
|
||||
useToolbarLayout,
|
||||
};
|
||||
|
||||
export { OHIF };
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import pubSubServiceInterface from '../pubSubServiceInterface';
|
||||
|
||||
const EVENTS = {
|
||||
TOOL_BAR_MODIFIED: 'event::toolBarService:toolBarModified',
|
||||
};
|
||||
|
||||
export default class ToolBarService {
|
||||
constructor() {
|
||||
this.displaySets = {};
|
||||
@ -26,6 +30,23 @@ export default class ToolBarService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts displaySetService changes.
|
||||
*
|
||||
* @param {string} eventName The event name
|
||||
* @return void
|
||||
*/
|
||||
_broadcastChange = (eventName, callbackProps) => {
|
||||
const hasListeners = Object.keys(this.listeners).length > 0;
|
||||
const hasCallbacks = Array.isArray(this.listeners[eventName]);
|
||||
|
||||
if (hasListeners && hasCallbacks) {
|
||||
this.listeners[eventName].forEach(listener => {
|
||||
listener.callback(callbackProps);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
setToolBarLayout(layouts) {
|
||||
const toolBarLayout = [];
|
||||
|
||||
@ -51,6 +72,8 @@ export default class ToolBarService {
|
||||
toolBarLayout.push(toolBarDefinitions);
|
||||
});
|
||||
|
||||
// TODO -> Change this to a service. => emit an event to subscribers to update the toolbar layout.
|
||||
this.toolBarLayout = toolBarLayout;
|
||||
|
||||
this._broadcastChange(this.EVENTS.TOOL_BAR_MODIFIED, toolBarLayout);
|
||||
}
|
||||
}
|
||||
|
||||
8
platform/core/src/services/ToolBarService/index.js
Normal file
8
platform/core/src/services/ToolBarService/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
import ToolBarService from './ToolBarService';
|
||||
|
||||
export default {
|
||||
name: 'ToolBarService',
|
||||
create: ({ configuration = {} }) => {
|
||||
return new ToolBarService();
|
||||
},
|
||||
};
|
||||
@ -5,6 +5,7 @@ import UIModalService from './UIModalService';
|
||||
import UINotificationService from './UINotificationService';
|
||||
import UIViewportDialogService from './UIViewportDialogService';
|
||||
import DisplaySetService from './DisplaySetService';
|
||||
import ToolBarSerivce from './ToolBarService';
|
||||
|
||||
export {
|
||||
MeasurementService,
|
||||
@ -14,4 +15,5 @@ export {
|
||||
UINotificationService,
|
||||
UIViewportDialogService,
|
||||
DisplaySetService,
|
||||
ToolBarSerivce,
|
||||
};
|
||||
|
||||
@ -1,19 +1,48 @@
|
||||
window.config = function(props) {
|
||||
var servicesManager = props.servicesManager;
|
||||
|
||||
return {
|
||||
routerBasename: '/',
|
||||
enableGoogleCloudAdapter: true,
|
||||
enableGoogleCloudAdapterUI: false,
|
||||
showStudyList: true,
|
||||
httpErrorHandler: error => {
|
||||
// This is 429 when rejected from the public idc sandbox too often.
|
||||
console.warn(error.status);
|
||||
|
||||
// Could use services manager here to bring up a dialog/modal if needed.
|
||||
console.warn('test, navigate to https://ohif.org/');
|
||||
window.location = 'https://ohif.org/';
|
||||
window.config = {
|
||||
routerBasename: '/',
|
||||
enableGoogleCloudAdapter: true,
|
||||
servers: {
|
||||
// This is an array, but we'll only use the first entry for now
|
||||
dicomWeb: [],
|
||||
},
|
||||
// This is an array, but we'll only use the first entry for now
|
||||
oidc: [
|
||||
{
|
||||
// ~ REQUIRED
|
||||
// Authorization Server URL
|
||||
authority: 'https://accounts.google.com',
|
||||
client_id:
|
||||
'723928408739-k9k9r3i44j32rhu69vlnibipmmk9i57p.apps.googleusercontent.com',
|
||||
redirect_uri: '/callback', // `OHIFStandaloneViewer.js`
|
||||
response_type: 'id_token token',
|
||||
scope:
|
||||
'email profile openid https://www.googleapis.com/auth/cloudplatformprojects.readonly https://www.googleapis.com/auth/cloud-healthcare', // email profile openid
|
||||
// ~ OPTIONAL
|
||||
post_logout_redirect_uri: '/logout-redirect.html',
|
||||
revoke_uri: 'https://accounts.google.com/o/oauth2/revoke?token=',
|
||||
automaticSilentRenew: true,
|
||||
revokeAccessTokenOnSignout: true,
|
||||
},
|
||||
healthcareApiEndpoint: 'https://idc-sandbox-002.appspot.com/v1beta1',
|
||||
};
|
||||
],
|
||||
studyListFunctionsEnabled: true,
|
||||
};
|
||||
|
||||
// window.config = function(props) {
|
||||
// var servicesManager = props.servicesManager;
|
||||
|
||||
// return {
|
||||
// routerBasename: '/',
|
||||
// enableGoogleCloudAdapter: true,
|
||||
// enableGoogleCloudAdapterUI: false,
|
||||
// showStudyList: true,
|
||||
// httpErrorHandler: error => {
|
||||
// // This is 429 when rejected from the public idc sandbox too often.
|
||||
// console.warn(error.status);
|
||||
|
||||
// // Could use services manager here to bring up a dialog/modal if needed.
|
||||
// console.warn('test, navigate to https://ohif.org/');
|
||||
// window.location = 'https://ohif.org/';
|
||||
// },
|
||||
// healthcareApiEndpoint: 'https://idc-sandbox-002.appspot.com/v1beta1',
|
||||
// };
|
||||
// };
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
UIDialogService,
|
||||
MeasurementService,
|
||||
DisplaySetService,
|
||||
ToolBarSerivce,
|
||||
// utils,
|
||||
// redux as reduxOHIF,
|
||||
} from '@ohif/core';
|
||||
@ -45,6 +46,7 @@ function appInit(appConfigOrFunc, defaultExtensions) {
|
||||
UIDialogService,
|
||||
MeasurementService,
|
||||
DisplaySetService,
|
||||
ToolBarSerivce,
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import {
|
||||
displaySetManager,
|
||||
ToolBarManager,
|
||||
useViewModel,
|
||||
useToolbarLayout,
|
||||
} from '@ohif/core';
|
||||
|
||||
export default function DisplaySetCreator({
|
||||
location,
|
||||
mode,
|
||||
dataSourceName,
|
||||
extensionManager,
|
||||
DisplaySetService,
|
||||
}) {
|
||||
console.warn('DisplaySetCreator rerendering');
|
||||
const { routes, sopClassHandlers } = mode;
|
||||
const dataSources = extensionManager.getDataSources(dataSourceName);
|
||||
// TODO: For now assume one unique datasource.
|
||||
|
||||
const dataSource = dataSources[0];
|
||||
const route = routes[0];
|
||||
|
||||
// Add toolbar state to the view model context?
|
||||
const { displaySetInstanceUIDs, setDisplaySetInstanceUIDs } = useViewModel();
|
||||
|
||||
const { toolBarLayout, setToolBarLayout } = useToolbarLayout();
|
||||
|
||||
useEffect(() => {
|
||||
let toolBarManager = new ToolBarManager(extensionManager, setToolBarLayout);
|
||||
route.init({ toolBarManager });
|
||||
}, [mode, dataSourceName, location]);
|
||||
|
||||
const createDisplaySets = useCallback(() => {
|
||||
// Add SOPClassHandlers to a new SOPClassManager.
|
||||
displaySetManager.init(extensionManager, sopClassHandlers, {
|
||||
displaySetInstanceUIDs,
|
||||
setDisplaySetInstanceUIDs,
|
||||
});
|
||||
|
||||
const queryParams = location.search;
|
||||
|
||||
// Call the data source to start building the view model?
|
||||
dataSource.retrieve.series.metadata(
|
||||
queryParams,
|
||||
displaySetManager.makeDisplaySets
|
||||
);
|
||||
}, [displaySetInstanceUIDs, location]);
|
||||
|
||||
useEffect(() => {
|
||||
createDisplaySets();
|
||||
}, [mode, dataSourceName, location]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -2,13 +2,11 @@ import React, { useEffect, useCallback } from 'react';
|
||||
import { useParams } from 'react-router';
|
||||
import PropTypes from 'prop-types';
|
||||
//
|
||||
import { ToolBarManager } from '@ohif/core';
|
||||
import { DragAndDropProvider } from '@ohif/ui';
|
||||
//
|
||||
import { useQuery } from '@hooks';
|
||||
import ViewportGrid from '@components/ViewportGrid';
|
||||
import Compose from './Compose';
|
||||
//import DisplaySetCreator from './DisplaySetCreator';
|
||||
|
||||
export default function ModeRoute({
|
||||
location,
|
||||
@ -69,9 +67,7 @@ export default function ModeRoute({
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// TODO -> Make this into a service
|
||||
let toolBarManager = new ToolBarManager(extensionManager); //, setToolBarLayout);
|
||||
route.init({ toolBarManager });
|
||||
route.init({ servicesManager, extensionManager });
|
||||
}, [mode, dataSourceName, location]);
|
||||
|
||||
// This queries for series, but... What does it do with them?
|
||||
|
||||
Loading…
Reference in New Issue
Block a user