feat: Viewport API + Documentation Page

This commit is contained in:
Rodrigo Antinarelli 2020-04-22 19:00:35 -03:00 committed by James A. Petts
parent 5f9535a74b
commit 12d1ff6bea
6 changed files with 254 additions and 71 deletions

View File

@ -1,38 +1,62 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ViewportActionBar, Notification, Button } from '@ohif/ui';
const Viewport = ({
viewportIndex,
onSeriesChange,
studyData,
isTracked,
studyDate,
modality,
currentSeries,
patientInformation,
activeViewportIndex,
children,
}) => {
const Viewport = ({ viewportIndex, onSeriesChange, studyData, children }) => {
return (
<div className="flex flex-col h-full">
<ViewportActionBar isTracked modality={modality} />
<div className="flex flex-col h-full relative">
<div className="absolute top-0 left-0 w-full">
<ViewportActionBar
onSeriesChange={onSeriesChange}
studyData={studyData}
/>
{/* TODO: NOTIFICATION API DEFINITION - OHIF-112 */}
<Notification
text="Track all measurement for this series?"
type="info"
actionButtons={
<div>
<Button>No</Button>
<Button className="ml-2">No, do not ask again</Button>
<Button className="ml-2" color="primary">
Yes
</Button>
</div>
}
/>
{/* TODO: NOTIFICATION API DEFINITION - OHIF-112 */}
<Notification
text="Track all measurement for this series?"
type="info"
actionButtons={
<div>
<Button>No</Button>
<Button className="ml-2">No, do not ask again</Button>
<Button className="ml-2" color="primary">
Yes
</Button>
</div>
}
/>
</div>
{/* STUDY IMAGE */}
<div className="w-full h-full" id={`viewport-${viewportIndex}`}>
{children}
</div>
</div>
);
};
Viewport.propTypes = {
viewportIndex: PropTypes.number.isRequired,
onSeriesChange: PropTypes.func.isRequired,
studyData: PropTypes.shape({
label: PropTypes.string.isRequired,
isTracked: PropTypes.bool.isRequired,
isLocked: PropTypes.bool.isRequired,
studyDate: PropTypes.string.isRequired,
currentSeries: PropTypes.number.isRequired,
seriesDescription: PropTypes.string.isRequired,
modality: PropTypes.string.isRequired,
patientInformation: PropTypes.shape({
patientName: PropTypes.string.isRequired,
patientSex: PropTypes.string.isRequired,
patientAge: PropTypes.string.isRequired,
MRN: PropTypes.string.isRequired,
thickness: PropTypes.string.isRequired,
spacing: PropTypes.string.isRequired,
scanner: PropTypes.string.isRequired,
}),
}).isRequired,
children: PropTypes.node.isRequired,
};
export default Viewport;

View File

@ -10,7 +10,41 @@ const classes = {
row: 'flex flex-col ml-4',
};
const ViewportActionBar = ({ isTracked, isLocked, modality }) => {
// isTracked: true,
// studyDate: '07-Sep-2010',
// currentSeries: 1,
// modality: 'CT',
// patientInformation: {
// patientName: 'Smith, Jane',
// patientSex: 'F',
// patientAge: '59',
// MRN: '10000001',
// thickness: '5.0mm',
// spacing: '1.25mm',
// scanner: 'Aquilion',
const ViewportActionBar = ({ studyData, onSeriesChange }) => {
const {
label,
isTracked,
isLocked,
modality,
studyDate,
currentSeries,
seriesDescription,
patientInformation,
} = studyData;
const {
patientName,
patientSex,
patientAge,
MRN,
thickness,
spacing,
scanner,
} = patientInformation;
const renderIconStatus = () => {
if (modality === 'SR') {
return (
@ -73,28 +107,36 @@ const ViewportActionBar = ({ isTracked, isLocked, modality }) => {
<div className="flex flex-grow">
<div className="flex items-center">
{renderIconStatus()}
<span className="text-large text-white ml-2">A</span>
<span className="text-large text-white ml-2">{label}</span>
</div>
<div className="flex flex-col justify-start ml-4">
<div className="flex">
<span className="text-base text-white">07-Sep-2010</span>
<span className="text-base text-white">{studyDate}</span>
<span className="border-l border-primary-light ml-2 pl-2 text-base text-primary-light">
S: 1
S: {currentSeries}
</span>
</div>
<div className="flex">
<span className="text-base text-primary-light">
Series description lorem ipsum dolor sit...
</span>
<p className="text-base truncate max-w-sm text-primary-light">
{seriesDescription}
</p>
</div>
</div>
</div>
<div className="ml-2">
<ButtonGroup>
<Button size="initial" className="py-1 px-2">
<Button
size="initial"
className="py-1 px-2"
onClick={() => onSeriesChange('left')}
>
<Icon name="chevron-left" className="text-white w-4" />
</Button>
<Button size="initial" className="py-1 px-2">
<Button
size="initial"
className="py-1 px-2"
onClick={() => onSeriesChange('right')}
>
<Icon name="chevron-right" className="text-white w-4" />
</Button>
</ButtonGroup>
@ -120,22 +162,24 @@ const ViewportActionBar = ({ isTracked, isLocked, modality }) => {
</div>
<div className="flex flex-col ml-2">
<span className="text-base font-bold text-white">
Smith, Jane
{patientName}
</span>
<div className="flex mt-4 pb-4 mb-4 border-b border-secondary-main">
<div className={classnames(classes.firstRow)}>
<span className={classnames(classes.infoHeader)}>Sex</span>
<span className={classnames(classes.infoText)}>F</span>
<span className={classnames(classes.infoText)}>
{patientSex}
</span>
</div>
<div className={classnames(classes.row)}>
<span className={classnames(classes.infoHeader)}>Age</span>
<span className={classnames(classes.infoText)}>59</span>
<span className={classnames(classes.infoText)}>
{patientAge}
</span>
</div>
<div className={classnames(classes.row)}>
<span className={classnames(classes.infoHeader)}>MRN</span>
<span className={classnames(classes.infoText)}>
10000001
</span>
<span className={classnames(classes.infoText)}>{MRN}</span>
</div>
</div>
<div className="flex">
@ -143,14 +187,16 @@ const ViewportActionBar = ({ isTracked, isLocked, modality }) => {
<span className={classnames(classes.infoHeader)}>
Thickness
</span>
<span className={classnames(classes.infoText)}>5.00mm</span>
<span className={classnames(classes.infoText)}>
{thickness}
</span>
</div>
<div className={classnames(classes.row)}>
<span className={classnames(classes.infoHeader)}>
Spacing
</span>
<span className={classnames(classes.infoText)}>
1.25 mm
{spacing}
</span>
</div>
<div className={classnames(classes.row)}>
@ -158,7 +204,7 @@ const ViewportActionBar = ({ isTracked, isLocked, modality }) => {
Scanner
</span>
<span className={classnames(classes.infoText)}>
Aquilion
{scanner}
</span>
</div>
</div>
@ -181,14 +227,26 @@ const ViewportActionBar = ({ isTracked, isLocked, modality }) => {
);
};
ViewportActionBar.defaultProps = {
isLocked: false,
};
ViewportActionBar.propTypes = {
isTracked: PropTypes.bool.isRequired,
isLocked: PropTypes.bool,
modality: PropTypes.string.isRequired,
onSeriesChange: PropTypes.func.isRequired,
studyData: PropTypes.shape({
label: PropTypes.string.isRequired,
isTracked: PropTypes.bool.isRequired,
isLocked: PropTypes.bool.isRequired,
studyDate: PropTypes.string.isRequired,
currentSeries: PropTypes.number.isRequired,
seriesDescription: PropTypes.string.isRequired,
modality: PropTypes.string.isRequired,
patientInformation: PropTypes.shape({
patientName: PropTypes.string.isRequired,
patientSex: PropTypes.string.isRequired,
patientAge: PropTypes.string.isRequired,
MRN: PropTypes.string.isRequired,
thickness: PropTypes.string.isRequired,
spacing: PropTypes.string.isRequired,
scanner: PropTypes.string.isRequired,
}),
}).isRequired,
};
export default ViewportActionBar;

View File

@ -21,25 +21,109 @@ import { ViewportActionBar } from '@ohif/ui';
<Playground>
<div className="p-4 h-64">
<ViewportActionBar isTracked={true} modality="CT" />
<ViewportActionBar
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: true,
isLocked: false,
studyDate: '07-Sep-2010',
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: '2.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
/>
</div>
</Playground>
<Playground>
<div className="p-4 h-64">
<ViewportActionBar isTracked={false} modality="CT" />
<ViewportActionBar
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: true,
studyDate: '07-Sep-2010',
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: '2.0mm',
spacing: '1.25mm',
scanner: 'Aquilion',
},
}}
/>
</div>
</Playground>
<Playground>
<div className="p-4 h-64">
<ViewportActionBar isTracked={false} isLocked={false} modality="SR" />
<ViewportActionBar
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: false,
studyDate: '07-Sep-2010',
currentSeries: 1,
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>
</Playground>
<Playground>
<div className="p-4 h-64">
<ViewportActionBar isTracked={false} isLocked={true} modality="SR" />
<ViewportActionBar
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: true,
studyDate: '07-Sep-2010',
currentSeries: 1,
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>
</Playground>

View File

@ -15,6 +15,9 @@ const ViewportGrid = ({ rows, cols, viewportContents }) => {
'border border-secondary-light': !isActive,
}
)}
onClick={() => {
setActiveViewportIndex(index);
}}
>
{viewportContent}
</div>

View File

@ -80,11 +80,15 @@ import { tabs } from './studyBrowserMockData';
viewportContents={[
<Viewport
viewportIndex={0}
onSeriesChange={() => {}}
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
isTracked: false,
studyDate: '07-Sep-2010',
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',
@ -96,27 +100,38 @@ import { tabs } from './studyBrowserMockData';
scanner: 'Aquilion',
},
}}
isTracked={false}
activeViewportIndex={activeViewportIndex}
/>,
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</Viewport>,
<Viewport
viewportIndex={1}
onSeriesChange={() => {}}
onSeriesChange={(direction) => alert(`Series ${direction}`)}
studyData={{
label: 'A',
isTracked: false,
isLocked: true,
studyDate: '07-Sep-2010',
currentSeries: 1,
modality: 'CT',
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',
},
}}
isTracked={false}
activeViewportIndex={activeViewportIndex}
/>,
>
<div className="flex justify-center items-center h-full">
CONTENT
</div>
</Viewport>,
]}
setActiveViewportIndex={setActiveViewportIndex}
activeViewportIndex={activeViewportIndex}

View File

@ -1,5 +1,4 @@
import React, { useState } from 'react';
import classnames from 'classnames';
import React from 'react';
import { Toolbar } from '@ohif/ui';