Replace instance dropdown to slider for dicom tag browser
This commit is contained in:
parent
d956963ef0
commit
ef341d1518
@ -3,6 +3,11 @@
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dicom-tag-browser-table-wrapper {
|
||||||
|
height: 500px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
.dicom-tag-browser-table tr {
|
.dicom-tag-browser-table tr {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
@ -11,6 +16,20 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dicom-tag-browser-content {
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dicom-tag-browser-instance-range .range {
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dicom-tag-browser-instance-range {
|
||||||
|
padding: 20px 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.dicom-tag-browser-table td.dicom-tag-browser-table-center {
|
.dicom-tag-browser-table td.dicom-tag-browser-table-center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { classes, cornerstone as OHIFCornerstone } from '@ohif/core';
|
import { classes, cornerstone as OHIFCornerstone } from '@ohif/core';
|
||||||
|
import { Range } from '@ohif/ui';
|
||||||
import dcmjs from 'dcmjs';
|
import dcmjs from 'dcmjs';
|
||||||
import DicomBrowserSelect from './DicomBrowserSelect';
|
import DicomBrowserSelect from './DicomBrowserSelect';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
@ -99,26 +100,35 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
|
|||||||
let instanceSelectList = null;
|
let instanceSelectList = null;
|
||||||
|
|
||||||
if (isImageStack) {
|
if (isImageStack) {
|
||||||
const selectedInstanceValue = instanceList[activeInstance];
|
|
||||||
|
|
||||||
instanceSelectList = (
|
instanceSelectList = (
|
||||||
<DicomBrowserSelect
|
<div className="dicom-tag-browser-instance-range">
|
||||||
value={selectedInstanceValue}
|
<Range
|
||||||
formatOptionLabel={DicomBrowserSelectItem}
|
showValue
|
||||||
options={instanceList}
|
step={1}
|
||||||
/>
|
min={1}
|
||||||
|
max={instanceList.length - 1}
|
||||||
|
value={activeInstance}
|
||||||
|
valueRenderer={value => <p>Instance Number: {value}</p>}
|
||||||
|
onChange={({ target }) => {
|
||||||
|
const instanceIndex = parseInt(target.value);
|
||||||
|
setActiveInstance(instanceIndex);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="dicom-tag-browser-content">
|
||||||
<DicomBrowserSelect
|
<DicomBrowserSelect
|
||||||
value={selectedDisplaySetValue}
|
value={selectedDisplaySetValue}
|
||||||
formatOptionLabel={DicomBrowserSelectItem}
|
formatOptionLabel={DicomBrowserSelectItem}
|
||||||
options={displaySetList}
|
options={displaySetList}
|
||||||
/>
|
/>
|
||||||
{instanceSelectList}
|
{instanceSelectList}
|
||||||
<DicomTagTable tags={tags} meta={meta}></DicomTagTable>
|
<div className="dicom-tag-browser-table-wrapper">
|
||||||
|
<DicomTagTable tags={tags} meta={meta}></DicomTagTable>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -127,30 +137,28 @@ function DicomTagTable({ tags, meta }) {
|
|||||||
const rows = getFormattedRowsFromTags(tags, meta);
|
const rows = getFormattedRowsFromTags(tags, meta);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<table className="dicom-tag-browser-table">
|
||||||
<table className="dicom-tag-browser-table">
|
<tbody>
|
||||||
<tbody>
|
<tr>
|
||||||
<tr>
|
<th className="dicom-tag-browser-table-left">Tag</th>
|
||||||
<th className="dicom-tag-browser-table-left">Tag</th>
|
<th className="dicom-tag-browser-table-left">Value Representation</th>
|
||||||
<th className="dicom-tag-browser-table-left">Value Representation</th>
|
<th className="dicom-tag-browser-table-left">Keyword</th>
|
||||||
<th className="dicom-tag-browser-table-left">Keyword</th>
|
<th className="dicom-tag-browser-table-left">Value</th>
|
||||||
<th className="dicom-tag-browser-table-left">Value</th>
|
</tr>
|
||||||
</tr>
|
{rows.map((row, index) => {
|
||||||
{rows.map((row, index) => {
|
const className = row.className ? row.className : null;
|
||||||
const className = row.className ? row.className : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className={className} key={`DICOMTagRow-${index}`}>
|
<tr className={className} key={`DICOMTagRow-${index}`}>
|
||||||
<td>{row[0]}</td>
|
<td>{row[0]}</td>
|
||||||
<td className="dicom-tag-browser-table-center">{row[1]}</td>
|
<td className="dicom-tag-browser-table-center">{row[1]}</td>
|
||||||
<td>{row[2]}</td>
|
<td>{row[2]}</td>
|
||||||
<td>{row[3]}</td>
|
<td>{row[3]}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,12 +191,16 @@ function getFormattedRowsFromTags(tags, meta) {
|
|||||||
} else {
|
} else {
|
||||||
if (tagInfo.vr === 'xs') {
|
if (tagInfo.vr === 'xs') {
|
||||||
try {
|
try {
|
||||||
const dataset = metadataProvider.getStudyDataset(meta.StudyInstanceUID);
|
const dataset = metadataProvider.getStudyDataset(
|
||||||
|
meta.StudyInstanceUID
|
||||||
|
);
|
||||||
const tag = dcmjs.data.Tag.fromPString(tagInfo.tag).toCleanString();
|
const tag = dcmjs.data.Tag.fromPString(tagInfo.tag).toCleanString();
|
||||||
const originalTagInfo = dataset[tag];
|
const originalTagInfo = dataset[tag];
|
||||||
tagInfo.vr = originalTagInfo.vr;
|
tagInfo.vr = originalTagInfo.vr;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to parse value representation for tag '${tagInfo.keyword}'`);
|
console.error(
|
||||||
|
`Failed to parse value representation for tag '${tagInfo.keyword}'`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export default function getCommandsModule(servicesManager) {
|
|||||||
|
|
||||||
const { UIModalService } = servicesManager.services;
|
const { UIModalService } = servicesManager.services;
|
||||||
|
|
||||||
const WrappedDicomTagBrowser = function () {
|
const WrappedDicomTagBrowser = function() {
|
||||||
return (
|
return (
|
||||||
<DicomTagBrowser
|
<DicomTagBrowser
|
||||||
displaySets={displaySets}
|
displaySets={displaySets}
|
||||||
@ -34,7 +34,7 @@ export default function getCommandsModule(servicesManager) {
|
|||||||
content: WrappedDicomTagBrowser,
|
content: WrappedDicomTagBrowser,
|
||||||
title: `DICOM Tag Browser`,
|
title: `DICOM Tag Browser`,
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
showScrollbar: true
|
noScroll: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
* @property {boolean} [closeButton=true] Should the modal body render the close button.
|
* @property {boolean} [closeButton=true] Should the modal body render the close button.
|
||||||
* @property {string} [title=null] Should the modal render the title independently of the body content.
|
* @property {string} [title=null] Should the modal render the title independently of the body content.
|
||||||
* @property {string} [customClassName=null] The custom class to style the modal.
|
* @property {string} [customClassName=null] The custom class to style the modal.
|
||||||
* @property {boolean} [showScrollbar=null] Show or hide scrollbar.
|
* @property {boolean} [showScrollbar=false] Show or hide scrollbar.
|
||||||
|
* @property {boolean} [noScroll=false] Disable or not the scrollbar.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const name = 'UIModalService';
|
const name = 'UIModalService';
|
||||||
@ -29,7 +30,7 @@ const serviceImplementation = {
|
|||||||
/**
|
/**
|
||||||
* Show a new UI modal;
|
* Show a new UI modal;
|
||||||
*
|
*
|
||||||
* @param {ModalProps} props { content, contentProps, shouldCloseOnEsc, isOpen, onClose, closeButton, title, customClassName, showScrollbar }
|
* @param {ModalProps} props { content, contentProps, shouldCloseOnEsc, isOpen, onClose, closeButton, title, customClassName, showScrollbar, noScroll }
|
||||||
*/
|
*/
|
||||||
function _show({
|
function _show({
|
||||||
content = null,
|
content = null,
|
||||||
@ -41,7 +42,8 @@ function _show({
|
|||||||
title = null,
|
title = null,
|
||||||
fullscreen = false,
|
fullscreen = false,
|
||||||
customClassName = null,
|
customClassName = null,
|
||||||
showScrollbar = false
|
showScrollbar = false,
|
||||||
|
noScroll = false,
|
||||||
}) {
|
}) {
|
||||||
return serviceImplementation._show({
|
return serviceImplementation._show({
|
||||||
content,
|
content,
|
||||||
@ -53,7 +55,8 @@ function _show({
|
|||||||
title,
|
title,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
customClassName,
|
customClassName,
|
||||||
showScrollbar
|
showScrollbar,
|
||||||
|
noScroll,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,10 @@
|
|||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&.noScroll &__content {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.visibleScrollbar) &__content
|
&:not(.visibleScrollbar) &__content
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
|||||||
@ -82,14 +82,20 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
|||||||
shouldCloseOnEsc,
|
shouldCloseOnEsc,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
closeButton,
|
closeButton,
|
||||||
showScrollbar
|
showScrollbar,
|
||||||
|
noScroll,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Provider value={{ show, hide }}>
|
<Provider value={{ show, hide }}>
|
||||||
{ModalContent && (
|
{ModalContent && (
|
||||||
<Modal
|
<Modal
|
||||||
className={classNames(customClassName, ModalContent.className, { 'visibleScrollbar': showScrollbar })}
|
className={classNames(
|
||||||
|
customClassName,
|
||||||
|
ModalContent.className,
|
||||||
|
{ visibleScrollbar: showScrollbar },
|
||||||
|
{ noScroll }
|
||||||
|
)}
|
||||||
shouldCloseOnEsc={shouldCloseOnEsc}
|
shouldCloseOnEsc={shouldCloseOnEsc}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title={title}
|
title={title}
|
||||||
|
|||||||
@ -28,7 +28,13 @@ class Range extends Component {
|
|||||||
className="range"
|
className="range"
|
||||||
/>
|
/>
|
||||||
{this.props.showPercentage && <span>{`${this.state.value}%`}</span>}
|
{this.props.showPercentage && <span>{`${this.state.value}%`}</span>}
|
||||||
{this.props.showValue && <span>{this.state.value}</span>}
|
{this.props.showValue && (
|
||||||
|
<span>
|
||||||
|
{this.props.valueRenderer
|
||||||
|
? this.props.valueRenderer(this.state.value)
|
||||||
|
: this.state.value}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -40,6 +46,7 @@ Range.propTypes = {
|
|||||||
max: PropTypes.number.isRequired,
|
max: PropTypes.number.isRequired,
|
||||||
step: PropTypes.number,
|
step: PropTypes.number,
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
|
valueRenderer: PropTypes.func,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
showPercentage: PropTypes.bool,
|
showPercentage: PropTypes.bool,
|
||||||
showValue: PropTypes.bool,
|
showValue: PropTypes.bool,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user