Update sidePanel to support multiple components

This commit is contained in:
Gustavo Lelis 2020-04-22 23:13:08 -03:00 committed by James A. Petts
parent 802a8d5f1b
commit 08ebfd5865
3 changed files with 181 additions and 105 deletions

View File

@ -1,4 +1,4 @@
import React, { useState, useCallback } from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
@ -53,30 +53,78 @@ const position = {
},
};
const getChildComponent = (childComponents, componentOpen) => {
if (Array.isArray(childComponents)) {
return childComponents.find(
(_childComponent) => _childComponent.name === componentOpen
);
} else {
return childComponents;
}
};
const SidePanel = ({
side,
className,
children,
defaultIsOpen,
componentLabel,
iconLabel,
iconName,
defaultComponentOpen,
childComponents,
}) => {
const [isOpen, setIsOpen] = useState(defaultIsOpen);
const openStatus = isOpen ? 'open' : 'closed';
const [componentOpen, setComponentOpen] = useState(defaultComponentOpen);
const openStatus = componentOpen ? 'open' : 'closed';
const style = Object.assign({}, styleMap[openStatus][side], baseStyle);
const getSidePanelHeader = useCallback(() => {
return (
<React.Fragment>
{isOpen ? (
const childComponent = getChildComponent(childComponents, componentOpen);
const getPanelButtons = () => {
const _childComponents = Array.isArray(childComponents)
? childComponents
: [childComponents];
return _childComponents.map((childComponent) => {
return (
<Button
key={childComponent.name}
variant="text"
color="inherit"
onClick={() => {
setComponentOpen(childComponent.name);
}}
style={{
minWidth: `${collapsedWidth}px`,
width: `${collapsedWidth}px`,
}}
className="flex flex-col text-xs px-1 py-1 text-white border-transparent border-b"
>
<Icon
name={childComponent.iconName}
className="text-primary-active"
/>
<span className="mt-2 text-white text-xs">
{childComponent.iconLabel}
</span>
</Button>
);
});
};
return (
<div
className={classnames(
className,
baseClasses,
classesMap[openStatus][side]
)}
style={style}
>
{componentOpen ? (
<React.Fragment>
<div className="px-3 border-b border-secondary-light">
<Button
variant="text"
color="inherit"
rounded="none"
onClick={() => {
setIsOpen(false);
setComponentOpen(null);
}}
className="flex flex-row items-center px-3 h-12 relative w-full"
>
@ -89,58 +137,45 @@ const SidePanel = ({
style={{ ...position[side] }}
/>
<span className="flex-1 text-primary-active">
{componentLabel}
{childComponent.label}
</span>
</Button>
</div>
) : (
<Button
variant="text"
color="inherit"
onClick={() => {
setIsOpen(true);
}}
style={{
minWidth: `${collapsedWidth}px`,
width: `${collapsedWidth}px`,
}}
className="flex flex-col text-xs px-1 py-1 text-white border-transparent border-b"
>
<Icon name={iconName} className="text-primary-active" />
<span className="mt-2 text-white text-xs">{iconLabel}</span>
</Button>
)}
</React.Fragment>
);
}, [componentLabel, iconLabel, iconName, isOpen, side]);
return (
<div
className={classnames(
className,
baseClasses,
classesMap[openStatus][side]
{childComponent.content}
</React.Fragment>
) : (
<React.Fragment>{getPanelButtons()}</React.Fragment>
)}
style={style}
>
{getSidePanelHeader()}
{isOpen && children}
</div>
);
};
SidePanel.defaultProps = {
defaultIsOpen: false,
defaultComponentOpen: null,
};
SidePanel.propTypes = {
side: PropTypes.oneOf(['left', 'right']).isRequired,
iconLabel: PropTypes.string.isRequired,
componentLabel: PropTypes.string.isRequired,
iconName: PropTypes.string.isRequired,
defaultIsOpen: PropTypes.bool,
className: PropTypes.string,
children: PropTypes.node,
defaultComponentOpen: PropTypes.string,
childComponents: PropTypes.oneOfType([
PropTypes.shape({
iconName: PropTypes.string.isRequired,
iconLabel: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
content: PropTypes.node,
}),
PropTypes.arrayOf(
PropTypes.shape({
iconName: PropTypes.string.isRequired,
iconLabel: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
content: PropTypes.node,
})
),
]),
};
export default SidePanel;

View File

@ -24,19 +24,52 @@ import { SidePanel } from '@ohif/ui';
>
<SidePanel
side="left"
iconName="group-layers"
iconLabel="Studies"
componentLabel="Studies"
defaultIsOpen={false}
>
<div className="flex justify-center text-white p-2">panel content</div>
</SidePanel>
childComponents={{
iconName: "group-layers",
iconLabel: "Studies",
name: "studies",
label: "Studies",
content: <div className="flex justify-center text-white p-2">panel content</div>,
}}
/>
<div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white">
CONTENT
</div>
</div>
</Playground>
## Multiple panels
<Playground>
<div
className="flex flex-row flex-no-wrap flex-1 items-stretch overflow-hidden w-full"
style={{ height: '500px' }}
>
<SidePanel
side="left"
childComponents={[{
iconName: "group-layers",
iconLabel: "Studies",
name: "studies",
label: "Studies",
content: <div className="flex justify-center text-white p-2">studies panel content</div>,
},
{
iconName: "list-bullets",
iconLabel: "Measure",
name: "measurements",
label: "Measurements",
content: <div className="flex justify-center text-white p-2">measure panel content</div>,
}]}
/>
<div className="flex flex-1 h-100 overflow-hidden bg-primary-main items-center justify-center text-white">
CONTENT
</div>
</div>
</Playground>
## Properties
<Props of={SidePanel} />

View File

@ -57,14 +57,18 @@ import { tabs } from './studyBrowserMockData';
>
<SidePanel
side="left"
iconName="group-layers"
iconLabel="Studies"
componentLabel="Studies"
defaultIsOpen={true}
>
<StudyBrowser tabs={tabs} />
</SidePanel>
<div className="flex flex-col flex-1 h-100">
defaultComponentOpen='studies'
childComponents={{
iconName: 'group-layers',
iconLabel: 'Studies',
label: 'Studies',
name: 'studies',
content: (
<StudyBrowser tabs={tabs} />
)
}}
/>
<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 />
</div>
@ -100,45 +104,49 @@ import { tabs } from './studyBrowserMockData';
</div>
<SidePanel
side="right"
iconName="list-bullets"
iconLabel="Measure"
componentLabel="Measurements"
defaultIsOpen={true}
>
<MeasurementsPanel
descriptionData={descriptionData}
measurementTableData={measurementTableData}
actionButtons={
<>
<ButtonGroup onClick={() => alert('Export')}>
<Button
className="text-white border-primary-main bg-black text-base py-2 px-2"
size="initial"
color="inherit"
>
Export
</Button>
<IconButton
className="bg-black border-primary-main px-2 text-white px-2"
color="inherit"
size="initial"
>
<Icon name="arrow-down" />
</IconButton>
</ButtonGroup>
<Button
className="text-white border border-primary-main bg-black text-base py-2 px-2 ml-2"
variant="outlined"
size="initial"
color="inherit"
onClick={() => alert('Create Report')}
>
Create Report
</Button>
</>
}
/>
</SidePanel>
defaultComponentOpen="measurements"
childComponents={{
iconName: 'list-bullets',
iconLabel: 'Measure',
label: 'Measurements',
name: 'measurements',
content: (
<MeasurementsPanel
descriptionData={descriptionData}
measurementTableData={measurementTableData}
actionButtons={
<React.Fragment>
<ButtonGroup onClick={() => alert('Export')}>
<Button
className="text-white border-primary-main bg-black text-base py-2 px-2"
size="initial"
color="inherit"
>
Export
</Button>
<IconButton
className="bg-black border-primary-main px-2 text-white px-2"
color="inherit"
size="initial"
>
<Icon name="arrow-down" />
</IconButton>
</ButtonGroup>
<Button
className="text-white border border-primary-main bg-black text-base py-2 px-2 ml-2"
variant="outlined"
size="initial"
color="inherit"
onClick={() => alert('Create Report')}
>
Create Report
</Button>
</React.Fragment>
}
/>
)
}}
/>
</div>
</div>
);