feat: v2 Table Component
This commit is contained in:
parent
01c5456ccf
commit
34961e5624
@ -1,23 +1,7 @@
|
|||||||
import * as utils from './src/utils/';
|
import * as utils from './src/utils/';
|
||||||
import {
|
export * from './src/components';
|
||||||
ModalProvider,
|
|
||||||
ModalConsumer,
|
export { utils };
|
||||||
useModal,
|
|
||||||
withModal,
|
|
||||||
} from './src/contextProviders';
|
|
||||||
|
|
||||||
export {
|
|
||||||
Button,
|
|
||||||
ButtonGroup,
|
|
||||||
DateRange,
|
|
||||||
Icon,
|
|
||||||
IconButton,
|
|
||||||
Input,
|
|
||||||
NavBar,
|
|
||||||
Select,
|
|
||||||
Svg,
|
|
||||||
ThemeWrapper,
|
|
||||||
Typography,
|
|
||||||
} from './src/components';
|
|
||||||
export { StudyList } from './src/views';
|
export { StudyList } from './src/views';
|
||||||
export { ModalProvider, ModalConsumer, useModal, withModal, utils };
|
export { ModalProvider, ModalConsumer, useModal, withModal, utils };
|
||||||
|
|||||||
35
platform/ui/src/components/Table/Table.jsx
Normal file
35
platform/ui/src/components/Table/Table.jsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
const Table = ({ children, className, fullWidth, style }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
'text-lg text-white',
|
||||||
|
{
|
||||||
|
'w-full': fullWidth,
|
||||||
|
},
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={style}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Table.defaultProps = {
|
||||||
|
className: '',
|
||||||
|
fullWidth: true,
|
||||||
|
style: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
Table.propTypes = {
|
||||||
|
fullWidth: PropTypes.bool,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
style: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Table;
|
||||||
63
platform/ui/src/components/Table/Table.mdx
Normal file
63
platform/ui/src/components/Table/Table.mdx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
name: Table
|
||||||
|
menu: Components
|
||||||
|
route: components/table
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Playground, Props, Link } from 'docz';
|
||||||
|
import { Table, TableHead, TableBody, TableRow, TableCell } from '@ohif/ui';
|
||||||
|
|
||||||
|
# Table
|
||||||
|
|
||||||
|
Tables display sets of data.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { Table } from '@ohfi/ui';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic usage
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<div className="p-4">
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Item 01</TableCell>
|
||||||
|
<TableCell>Item 02</TableCell>
|
||||||
|
<TableCell>Item 03</TableCell>
|
||||||
|
<TableCell>Item 04</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Content 01</TableCell>
|
||||||
|
<TableCell>Content 02</TableCell>
|
||||||
|
<TableCell>Content 03</TableCell>
|
||||||
|
<TableCell>Content 04</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</Playground>
|
||||||
|
|
||||||
|
## Table width
|
||||||
|
|
||||||
|
Table has full width by default. If you want to change its width, you will have
|
||||||
|
to set the `fullWidth` prop to `false` and then define your own table width by
|
||||||
|
passing a `className` or by `style`.
|
||||||
|
|
||||||
|
## Table components
|
||||||
|
|
||||||
|
<Link to="components/table-head">TableHead</Link>
|
||||||
|
<br />
|
||||||
|
<Link to="components/table-body">TableBody</Link>
|
||||||
|
<br />
|
||||||
|
<Link to="components/table-row">TableRow</Link>
|
||||||
|
<br />
|
||||||
|
<Link to="components/table-cell">TableCell</Link>
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<Props of={Table} />
|
||||||
2
platform/ui/src/components/Table/index.js
Normal file
2
platform/ui/src/components/Table/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import Table from './Table';
|
||||||
|
export default Table;
|
||||||
32
platform/ui/src/components/TableBody/TableBody.jsx
Normal file
32
platform/ui/src/components/TableBody/TableBody.jsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
const TableBody = ({ children, className, style }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
'mt-2 max-h-48 overflow-y-scroll ohif-scrollbar',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={style}
|
||||||
|
>
|
||||||
|
{React.Children.map(children, child =>
|
||||||
|
React.cloneElement(child, { isTableHead: false })
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TableBody.defaultProps = {
|
||||||
|
className: '',
|
||||||
|
style: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
TableBody.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
style: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableBody;
|
||||||
2
platform/ui/src/components/TableBody/index.js
Normal file
2
platform/ui/src/components/TableBody/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import TableBody from './TableBody';
|
||||||
|
export default TableBody;
|
||||||
43
platform/ui/src/components/TableCell/TableCell.jsx
Normal file
43
platform/ui/src/components/TableCell/TableCell.jsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
const TableCell = ({ children, className, isTableHead, size, style }) => {
|
||||||
|
const sizeClasses = {
|
||||||
|
small: 'flex-0.3',
|
||||||
|
normal: 'flex-1',
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
'px-2 last:border-r-0 break-all',
|
||||||
|
sizeClasses[size],
|
||||||
|
{
|
||||||
|
'border-r border-custom-violetPale': !isTableHead,
|
||||||
|
},
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={style}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TableCell.defaultProps = {
|
||||||
|
className: '',
|
||||||
|
isTableHead: false,
|
||||||
|
size: 'normal',
|
||||||
|
style: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
TableCell.propTypes = {
|
||||||
|
isTableHead: PropTypes.bool,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
size: PropTypes.oneOf(['small', 'normal']),
|
||||||
|
style: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableCell;
|
||||||
2
platform/ui/src/components/TableCell/index.js
Normal file
2
platform/ui/src/components/TableCell/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import TableCell from './TableCell';
|
||||||
|
export default TableCell;
|
||||||
32
platform/ui/src/components/TableHead/TableHead.jsx
Normal file
32
platform/ui/src/components/TableHead/TableHead.jsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
const TableHead = ({ children, className, style }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
'bg-custom-navy border-b border-custom-violetPale flex font-bold',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={style}
|
||||||
|
>
|
||||||
|
{React.cloneElement(children, {
|
||||||
|
isTableHead: true,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TableHead.defaultProps = {
|
||||||
|
className: '',
|
||||||
|
style: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
TableHead.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
style: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableHead;
|
||||||
2
platform/ui/src/components/TableHead/index.js
Normal file
2
platform/ui/src/components/TableHead/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import TableHead from './TableHead';
|
||||||
|
export default TableHead;
|
||||||
28
platform/ui/src/components/TableRow/TableRow.jsx
Normal file
28
platform/ui/src/components/TableRow/TableRow.jsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
const TableRow = ({ children, className, isTableHead, style }) => {
|
||||||
|
return (
|
||||||
|
<div className={classnames('w-full flex', className)} style={style}>
|
||||||
|
{React.Children.map(children, child =>
|
||||||
|
React.cloneElement(child, { isTableHead })
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TableRow.defaultProps = {
|
||||||
|
isTableHead: false,
|
||||||
|
className: '',
|
||||||
|
style: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
TableRow.propTypes = {
|
||||||
|
isTableHead: PropTypes.bool,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
style: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableRow;
|
||||||
2
platform/ui/src/components/TableRow/index.js
Normal file
2
platform/ui/src/components/TableRow/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import TableRow from './TableRow';
|
||||||
|
export default TableRow;
|
||||||
@ -7,6 +7,11 @@ import Input from './Input';
|
|||||||
import NavBar from './NavBar';
|
import NavBar from './NavBar';
|
||||||
import Select from './Select';
|
import Select from './Select';
|
||||||
import Svg from './Svg';
|
import Svg from './Svg';
|
||||||
|
import Table from './Table';
|
||||||
|
import TableBody from './TableBody';
|
||||||
|
import TableCell from './TableCell';
|
||||||
|
import TableHead from './TableHead';
|
||||||
|
import TableRow from './TableRow';
|
||||||
import ThemeWrapper from './ThemeWrapper/';
|
import ThemeWrapper from './ThemeWrapper/';
|
||||||
import Typography from './Typography';
|
import Typography from './Typography';
|
||||||
|
|
||||||
@ -20,6 +25,11 @@ export {
|
|||||||
NavBar,
|
NavBar,
|
||||||
Select,
|
Select,
|
||||||
Svg,
|
Svg,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
ThemeWrapper,
|
ThemeWrapper,
|
||||||
Typography,
|
Typography,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -36,6 +36,7 @@ export const Layout = ({ children }) => {
|
|||||||
onClick={() => setSidebarOpen(false)}
|
onClick={() => setSidebarOpen(false)}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
id="main-container"
|
||||||
className={classnames('py-10 w-full', {
|
className={classnames('py-10 w-full', {
|
||||||
'px-4 lg:px-20': sidebarOpen,
|
'px-4 lg:px-20': sidebarOpen,
|
||||||
'px-4 lg:px-8': !sidebarOpen,
|
'px-4 lg:px-8': !sidebarOpen,
|
||||||
|
|||||||
@ -31,19 +31,19 @@ export const Sidebar = React.forwardRef((props, ref) => {
|
|||||||
<div className="block lg:hidden">
|
<div className="block lg:hidden">
|
||||||
<div
|
<div
|
||||||
onClick={() => props.onClick()}
|
onClick={() => props.onClick()}
|
||||||
className="fixed z-10 left-0 w-full h-full bg-black opacity-80"
|
className="fixed left-0 w-full h-full bg-black opacity-80"
|
||||||
style={{ top: '81px' }}
|
style={{ top: 81, zIndex: 99999 }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
data-testid="sidebar"
|
data-testid="sidebar"
|
||||||
className={classnames(
|
className={classnames(
|
||||||
'p-8 flex-col bg-white top-0 overflow-auto z-10 border-r border-gray-400 hidden fixed left-0 bottom-0 lg:block lg:sticky lg:h-screen lg:top-0'
|
'p-8 flex-col bg-white top-0 overflow-auto border-r border-gray-400 hidden fixed left-0 bottom-0 lg:block lg:sticky lg:h-screen lg:top-0'
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
display: props.sidebarOpen ? 'block' : 'none',
|
display: props.sidebarOpen ? 'block' : 'none',
|
||||||
top: '81px',
|
zIndex: 99999,
|
||||||
minWidth: 250,
|
minWidth: 250,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -6,7 +6,11 @@
|
|||||||
background: #000;
|
background: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-testid='main-container'] > h2 {
|
#main-container > h2 {
|
||||||
margin: 20px 0;
|
@apply font-bold my-8 text-2xl;
|
||||||
font-weight: bold;
|
}
|
||||||
|
|
||||||
|
#main-container > ul li a,
|
||||||
|
#main-container > a {
|
||||||
|
@apply underline text-blue-500;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,14 +3,23 @@ import PropTypes from 'prop-types';
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { Button, Icon, Typography } from '@ohif/ui';
|
import {
|
||||||
|
Button,
|
||||||
|
Icon,
|
||||||
|
Typography,
|
||||||
|
Table,
|
||||||
|
TableHead,
|
||||||
|
TableBody,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
} from '@ohif/ui';
|
||||||
|
|
||||||
const getGridColClass = (filtersMeta, name) => {
|
const getGridColClass = (filtersMeta, name) => {
|
||||||
const filter = filtersMeta.find(filter => filter.name === name);
|
const filter = filtersMeta.find(filter => filter.name === name);
|
||||||
return (filter && filter.gridCol && `w-${filter.gridCol}/24`) || '';
|
return (filter && filter.gridCol && `w-${filter.gridCol}/24`) || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const TableRow = props => {
|
const StudyTableRow = props => {
|
||||||
const {
|
const {
|
||||||
AccessionNumber,
|
AccessionNumber,
|
||||||
Modalities,
|
Modalities,
|
||||||
@ -30,11 +39,6 @@ const TableRow = props => {
|
|||||||
'px-4 py-2 text-base',
|
'px-4 py-2 text-base',
|
||||||
{ 'border-b border-custom-violetPale': !isOpened },
|
{ 'border-b border-custom-violetPale': !isOpened },
|
||||||
];
|
];
|
||||||
const seriesWidthClasses = {
|
|
||||||
normal: 'px-2 flex-1',
|
|
||||||
small: 'px-2 flex-0.3',
|
|
||||||
};
|
|
||||||
const seriesBodyClasses = 'border-r border-custom-violetPale';
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<tr>
|
<tr>
|
||||||
@ -176,75 +180,35 @@ const TableRow = props => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<div className="w-full text-lg">
|
<Table>
|
||||||
<div className="bg-custom-navy border-b border-custom-violetPale flex">
|
<TableHead>
|
||||||
<div
|
<TableRow>
|
||||||
className={classnames(
|
<TableCell size="normal">Description</TableCell>
|
||||||
seriesWidthClasses.normal,
|
<TableCell size="small">Series</TableCell>
|
||||||
'font-bold'
|
<TableCell size="small">Modality</TableCell>
|
||||||
)}
|
<TableCell size="normal">Instances</TableCell>
|
||||||
>
|
</TableRow>
|
||||||
Description
|
</TableHead>
|
||||||
</div>
|
|
||||||
<div
|
<TableBody>
|
||||||
className={classnames(
|
|
||||||
seriesWidthClasses.small,
|
|
||||||
'font-bold'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Series
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={classnames(
|
|
||||||
seriesWidthClasses.small,
|
|
||||||
'font-bold'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Modality
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={classnames(
|
|
||||||
seriesWidthClasses.normal,
|
|
||||||
'font-bold'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Instances
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-2 max-h-48 overflow-y-scroll ohif-scrollbar">
|
|
||||||
{series.map((seriesItem, i) => (
|
{series.map((seriesItem, i) => (
|
||||||
<div className="w-full flex" key={i}>
|
<TableRow key={i}>
|
||||||
<div
|
<TableCell size="normal">
|
||||||
className={classnames(
|
|
||||||
seriesWidthClasses.normal,
|
|
||||||
seriesBodyClasses
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Patient Protocol
|
Patient Protocol
|
||||||
</div>
|
</TableCell>
|
||||||
<div
|
<TableCell size="small">
|
||||||
className={classnames(
|
|
||||||
seriesWidthClasses.small,
|
|
||||||
seriesBodyClasses
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{seriesItem.SeriesNumber}
|
{seriesItem.SeriesNumber}
|
||||||
</div>
|
</TableCell>
|
||||||
<div
|
<TableCell size="small">
|
||||||
className={classnames(
|
|
||||||
seriesWidthClasses.small,
|
|
||||||
seriesBodyClasses
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{seriesItem.Modality}
|
{seriesItem.Modality}
|
||||||
</div>
|
</TableCell>
|
||||||
<div className={classnames('pl-3 flex-1')}>
|
<TableCell size="normal">
|
||||||
{seriesItem.instances.length}
|
{seriesItem.instances.length}
|
||||||
</div>
|
</TableCell>
|
||||||
</div>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</div>
|
</TableBody>
|
||||||
</div>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -258,7 +222,7 @@ const TableRow = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
TableRow.propTypes = {
|
StudyTableRow.propTypes = {
|
||||||
AccessionNumber: PropTypes.string.isRequired,
|
AccessionNumber: PropTypes.string.isRequired,
|
||||||
Modalities: PropTypes.string.isRequired,
|
Modalities: PropTypes.string.isRequired,
|
||||||
Instances: PropTypes.number.isRequired,
|
Instances: PropTypes.number.isRequired,
|
||||||
@ -275,7 +239,7 @@ const StudyListTable = ({ studies, numOfStudies, filtersMeta }) => {
|
|||||||
<table className="w-full text-white">
|
<table className="w-full text-white">
|
||||||
<tbody>
|
<tbody>
|
||||||
{studies.map((study, i) => (
|
{studies.map((study, i) => (
|
||||||
<TableRow
|
<StudyTableRow
|
||||||
key={i}
|
key={i}
|
||||||
AccessionNumber={study.AccessionNumber || ''}
|
AccessionNumber={study.AccessionNumber || ''}
|
||||||
Modalities={study.Modalities || ''}
|
Modalities={study.Modalities || ''}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user