Split ViewportLayout into parts and clean-up

This commit is contained in:
dannyrb 2020-05-14 15:57:45 -04:00 committed by James A. Petts
parent 0c74a9bbcd
commit ba152f082b
4 changed files with 346 additions and 306 deletions

View File

@ -0,0 +1,130 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
//
import { NavBar, Svg, Icon, IconButton, Toolbar } from '@ohif/ui';
function Header({ tools, moreTools }) {
const [activeTool, setActiveTool] = useState('Zoom');
// const dropdownContent = [
// {
// name: 'Soft tissue',
// value: '400/40',
// },
// { name: 'Lung', value: '1500 / -600' },
// { 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 items-center">
<div className="mr-3 inline-flex items-center">
<Icon
name="chevron-left"
className="text-primary-active w-8 cursor-pointer"
onClick={() => alert('Navigate to previous page')}
/>
<a href="#" className="ml-4">
<Svg name="logo-ohif" />
</a>
</div>
</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">
FOR INVESTIGATIONAL USE ONLY
</span>
<IconButton
variant="text"
color="inherit"
className="text-primary-active"
onClick={() => {}}
>
<React.Fragment>
<Icon name="settings" /> <Icon name="chevron-down" />
</React.Fragment>
</IconButton>
</div>
</div>
</NavBar>
);
}
Header.propTypes = {
tools: PropTypes.array.isRequired,
moreTools: PropTypes.array.isRequired,
};
export default Header;

View File

@ -0,0 +1,52 @@
import React from 'react';
import PropTypes from 'prop-types';
//
import { Toolbar } from '@ohif/ui';
function SecondaryToolbar({ tools }) {
// const tools = [
// {
// id: 'Annotate',
// label: 'Annotate',
// icon: 'tool-annotate',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Annotate' },
// onClick: () => console.log('Activate Annotate'),
// },
// {
// id: 'Bidirectional',
// label: 'Bidirectional',
// icon: 'tool-bidirectional',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Bidirectional' },
// onClick: () => console.log('Activate Bidirectional'),
// },
// {
// id: 'Elipse',
// label: 'Elipse',
// icon: 'tool-elipse',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Elipse' },
// onClick: () => console.log('Activate Elipse'),
// },
// {
// id: 'Length',
// label: 'Length',
// icon: 'tool-length',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Length' },
// onClick: () => console.log('Activate Length'),
// },
// ];
return <Toolbar type="secondary" tools={tools} />;
}
SecondaryToolbar.propTypes = {
tools: PropTypes.array.isRequired,
};
export default SecondaryToolbar;

View File

@ -0,0 +1,162 @@
import React from 'react';
import PropTypes from 'prop-types';
import { SidePanel } from '@ohif/ui';
//
import Header from './Header.jsx';
import SecondaryToolbar from './SecondaryToolbar.jsx';
function ViewerLayout({
// From Extension Module Params
extensionManager,
// From Modes
leftPanels,
rightPanels,
toolBarLayout,
displaySetInstanceUids,
ViewportGrid,
}) {
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,
};
};
const leftPanelComponents = leftPanels.map(getPanelData);
const rightPanelComponents = rightPanels.map(getPanelData);
console.warn(displaySetInstanceUids);
console.warn(toolBarLayout);
const [primaryToolBarLayout, secondaryToolBarLayout] = toolBarLayout;
return (
<div>
<Header
tools={primaryToolBarLayout.tools}
moreTools={primaryToolBarLayout.moreTools}
/>
<div
className="flex flex-row flex-no-wrap flex-1 items-stretch overflow-hidden w-full"
style={{ height: 'calc(100vh - 57px' }}
>
<SidePanel
side="left"
defaultComponentOpen={leftPanelComponents[0].name}
childComponents={leftPanelComponents}
/>
<div className="flex flex-col flex-1 h-full pb-2">
<div className="flex flex-2 w-100 border-b border-transparent h-12">
<SecondaryToolbar tools={secondaryToolBarLayout.tools} />
</div>
<div className="flex flex-1 h-full overflow-hidden bg-black items-center justify-center">
<ViewportGrid />
{/*<ViewportGrid
rows={1}
cols={2}
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',
},
}}
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</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',
},
}}
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</Viewport>,
]}
setActiveViewportIndex={setActiveViewportIndex}
activeViewportIndex={activeViewportIndex}
/>*/}
</div>
</div>
<SidePanel
side="right"
defaultComponentOpen={rightPanelComponents[0].name}
childComponents={rightPanelComponents}
/>
</div>
</div>
);
}
ViewerLayout.propTypes = {
// From extension module params
extensionManager: PropTypes.shape({
getModuleEntry: PropTypes.func.isRequired,
}).isRequired,
// 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 */
ViewportGrid: PropTypes.oneOfType(PropTypes.node, PropTypes.func).isRequired,
};
ViewerLayout.defaultProps = {
toolBarLayout: [
{ tools: [], moreTools: [] },
{ tools: [], moreTools: [] },
],
};
export default ViewerLayout;

View File

@ -1,22 +1,9 @@
import React, { useState } from 'react';
import { SidePanel, NavBar, Svg, Icon, IconButton, Toolbar } from '@ohif/ui';
import {
HelloWorldContext,
AnotherHelloWorldContext,
} from './getContextModule';
// import {LayoutManager} from '@ohif/core';
import ViewerLayout from './ViewerLayout';
/*
- Define layout for the viewer in mode configuration.
- Pass in the viewport types that can populate the viewer.
- Init layout based on the displaySets and the objects.
-
*/
export default function() {
@ -26,298 +13,7 @@ export default function() {
{
name: 'viewerLayout',
id: 'viewerLayout',
component: viewerLayout,
component: ViewerLayout,
},
];
}
const Header = ({ tools, moreTools }) => {
const [activeTool, setActiveTool] = useState('Zoom');
const dropdownContent = [
{
name: 'Soft tissue',
value: '400/40',
},
{ name: 'Lung', value: '1500 / -600' },
{ 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 items-center">
<div className="mr-3 inline-flex items-center">
<Icon
name="chevron-left"
className="text-primary-active w-8 cursor-pointer"
onClick={() => alert('Navigate to previous page')}
/>
<a href="#" className="ml-4">
<Svg name="logo-ohif" />
</a>
</div>
</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">
FOR INVESTIGATIONAL USE ONLY
</span>
<IconButton
variant="text"
color="inherit"
className="text-primary-active"
onClick={() => {}}
>
<React.Fragment>
<Icon name="settings" /> <Icon name="chevron-down" />
</React.Fragment>
</IconButton>
</div>
</div>
</NavBar>
);
};
const ViewportToolbar = ({ tools }) => {
// const tools = [
// {
// id: 'Annotate',
// label: 'Annotate',
// icon: 'tool-annotate',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Annotate' },
// onClick: () => console.log('Activate Annotate'),
// },
// {
// id: 'Bidirectional',
// label: 'Bidirectional',
// icon: 'tool-bidirectional',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Bidirectional' },
// onClick: () => console.log('Activate Bidirectional'),
// },
// {
// id: 'Elipse',
// label: 'Elipse',
// icon: 'tool-elipse',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Elipse' },
// onClick: () => console.log('Activate Elipse'),
// },
// {
// id: 'Length',
// label: 'Length',
// icon: 'tool-length',
// type: null,
// commandName: 'setToolActive',
// commandOptions: { toolName: 'Length' },
// onClick: () => console.log('Activate Length'),
// },
// ];
return <Toolbar type="secondary" tools={tools} />;
};
function viewerLayout({
leftPanels,
rightPanels,
extensionManager,
toolBarLayout,
displaySetInstanceUids,
}) {
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,
};
};
const leftPanelComponents = leftPanels.map(getPanelData);
const rightPanelComponents = rightPanels.map(getPanelData);
console.warn(displaySetInstanceUids);
console.warn(toolBarLayout);
const [primaryToolBarLayout, secondaryToolBarLayout] = toolBarLayout;
return (
<div>
<Header
tools={primaryToolBarLayout.tools}
moreTools={primaryToolBarLayout.moreTools}
/>
<div
className="flex flex-row flex-no-wrap flex-1 items-stretch overflow-hidden w-full"
style={{ height: 'calc(100vh - 57px' }}
>
<SidePanel
side="left"
defaultComponentOpen={leftPanelComponents[0].name}
childComponents={leftPanelComponents}
/>
<div className="flex flex-col flex-1 h-full pb-2">
<div className="flex flex-2 w-100 border-b border-transparent h-12">
<ViewportToolbar tools={secondaryToolBarLayout.tools} />
</div>
<div className="flex flex-1 h-full overflow-hidden bg-black items-center justify-center">
{/*<ViewportGrid
rows={1}
cols={2}
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',
},
}}
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</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',
},
}}
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</Viewport>,
]}
setActiveViewportIndex={setActiveViewportIndex}
activeViewportIndex={activeViewportIndex}
/>*/}
</div>
</div>
<SidePanel
side="right"
defaultComponentOpen={rightPanelComponents[0].name}
childComponents={rightPanelComponents}
/>
</div>
</div>
);
}
viewerLayout.defaultProps = {
toolBarLayout: [
{ tools: [], moreTools: [] },
{ tools: [], moreTools: [] },
],
};