[IDC-1129] - DICOM Tag Viewer extension (#2022)
* WIP render top level tags. * Add drop down to select series. * Fix errors with type 2 sequences. * WIP swap instance. * Fix formatting and make fullscreen. * Remove debuggers. * Finish formatting. * Fix error with double SeriesNumber deconstruction. * Address reviewer comments.
This commit is contained in:
parent
a7b5f1847a
commit
0ef88e88eb
@ -22,11 +22,13 @@ const OHIFDicomHtmlSopClassHandler = {
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient, authorizationHeaders) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
const metadata = instance.getData().metadata;
|
||||
const {
|
||||
SeriesDescription,
|
||||
SeriesNumber,
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
} = instance._instance.metadata;
|
||||
} = metadata;
|
||||
|
||||
return {
|
||||
plugin: 'html',
|
||||
@ -37,6 +39,8 @@ const OHIFDicomHtmlSopClassHandler = {
|
||||
SOPInstanceUID: instance.getSOPInstanceUID(),
|
||||
SeriesInstanceUID: series.getSeriesInstanceUID(),
|
||||
StudyInstanceUID: study.getStudyInstanceUID(),
|
||||
SeriesDescription,
|
||||
metadata,
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
|
||||
@ -12,11 +12,13 @@ const DicomMicroscopySopClassHandler = {
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
const metadata = instance.getData().metadata;
|
||||
const {
|
||||
SeriesDescription,
|
||||
SeriesNumber,
|
||||
ContentDate,
|
||||
ContentTime,
|
||||
SeriesNumber,
|
||||
} = instance._instance.metadata;
|
||||
} = metadata;
|
||||
|
||||
// Note: We are passing the dicomweb client into each viewport!
|
||||
|
||||
@ -28,9 +30,11 @@ const DicomMicroscopySopClassHandler = {
|
||||
SOPInstanceUID: instance.getSOPInstanceUID(),
|
||||
SeriesInstanceUID: series.getSeriesInstanceUID(),
|
||||
StudyInstanceUID: study.getStudyInstanceUID(),
|
||||
SeriesDescription,
|
||||
SeriesDate: ContentDate, // Map ContentDate/Time to SeriesTime for series list sorting.
|
||||
SeriesTime: ContentTime,
|
||||
SeriesNumber,
|
||||
metadata,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -12,11 +12,13 @@ const OHIFDicomPDFSopClassHandler = {
|
||||
getDisplaySetFromSeries(series, study, dicomWebClient, authorizationHeaders) {
|
||||
const instance = series.getFirstInstance();
|
||||
|
||||
const metadata = instance.getData().metadata;
|
||||
const {
|
||||
ContentDate,
|
||||
ContentTime,
|
||||
SeriesDescription,
|
||||
SeriesNumber,
|
||||
} = instance._instance.metadata;
|
||||
} = metadata;
|
||||
|
||||
return {
|
||||
plugin: 'pdf',
|
||||
@ -27,9 +29,11 @@ const OHIFDicomPDFSopClassHandler = {
|
||||
SOPInstanceUID: instance.getSOPInstanceUID(),
|
||||
SeriesInstanceUID: series.getSeriesInstanceUID(),
|
||||
StudyInstanceUID: study.getStudyInstanceUID(),
|
||||
SeriesDescription,
|
||||
SeriesDate: ContentDate, // Map ContentDate/Time to SeriesTime for series list sorting.
|
||||
SeriesTime: ContentTime,
|
||||
SeriesNumber,
|
||||
metadata,
|
||||
authorizationHeaders: authorizationHeaders,
|
||||
};
|
||||
},
|
||||
|
||||
@ -56,6 +56,7 @@ const OHIFDicomRTStructSopClassHandler = {
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
SeriesDescription,
|
||||
metadata,
|
||||
};
|
||||
|
||||
if (!metadata.ReferencedSeriesSequence) {
|
||||
|
||||
@ -28,12 +28,12 @@ export default function getSopClassHandlerModule({ servicesManager }) {
|
||||
const {
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
SeriesDescription,
|
||||
FrameOfReferenceUID,
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
StudyInstanceUID,
|
||||
SeriesNumber,
|
||||
} = metadata;
|
||||
|
||||
const segDisplaySet = {
|
||||
@ -55,6 +55,7 @@ export default function getSopClassHandlerModule({ servicesManager }) {
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
SeriesDescription,
|
||||
metadata,
|
||||
};
|
||||
|
||||
segDisplaySet.getSourceDisplaySet = function(studies) {
|
||||
|
||||
8
extensions/dicom-tag-browser/.webpack/webpack.dev.js
Normal file
8
extensions/dicom-tag-browser/.webpack/webpack.dev.js
Normal file
@ -0,0 +1,8 @@
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
return webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
};
|
||||
38
extensions/dicom-tag-browser/.webpack/webpack.prod.js
Normal file
38
extensions/dicom-tag-browser/.webpack/webpack.prod.js
Normal file
@ -0,0 +1,38 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
const SRC_DIR = path.join(__dirname, '../src');
|
||||
const DIST_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });
|
||||
|
||||
return merge(commonConfig, {
|
||||
devtool: 'source-map',
|
||||
stats: {
|
||||
colors: true,
|
||||
hash: true,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
warnings: true,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
sideEffects: true,
|
||||
},
|
||||
output: {
|
||||
path: ROOT_DIR,
|
||||
library: 'OHIFExtDicomP10Downloader',
|
||||
libraryTarget: 'umd',
|
||||
libraryExport: 'default',
|
||||
filename: pkg.main,
|
||||
},
|
||||
});
|
||||
};
|
||||
21
extensions/dicom-tag-browser/LICENSE
Normal file
21
extensions/dicom-tag-browser/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Open Health Imaging Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1
extensions/dicom-tag-browser/README.md
Normal file
1
extensions/dicom-tag-browser/README.md
Normal file
@ -0,0 +1 @@
|
||||
# @ohif/extension-dicom-tag-browser
|
||||
40
extensions/dicom-tag-browser/package.json
Normal file
40
extensions/dicom-tag-browser/package.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-tag-browser",
|
||||
"version": "0.0.1",
|
||||
"description": "OHIF extension for checking DICOM headers.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
"repository": "OHIF/Viewers",
|
||||
"main": "dist/index.umd.js",
|
||||
"module": "src/index.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1.16.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --debug --output-pathinfo",
|
||||
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
|
||||
"build:package": "yarn run build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "^2.6.0",
|
||||
"react": "^16.8.6",
|
||||
"dcmjs": "0.16.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dicomweb-client": "^0.6.0",
|
||||
"react-select": "^3.0.8",
|
||||
"moment": "2.24.0"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
|
||||
const DicomBrowserSelect = ({ value, formatOptionLabel, options }) => (
|
||||
<Select
|
||||
value={value}
|
||||
formatOptionLabel={formatOptionLabel}
|
||||
styles={dicomBrowserSelectStyles}
|
||||
options={options}
|
||||
/>
|
||||
);
|
||||
|
||||
const computedstyle = getComputedStyle(document.body);
|
||||
const uiGrayDarker = computedstyle.getPropertyValue('--ui-gray-darker');
|
||||
const activeColor = computedstyle.getPropertyValue('--active-color');
|
||||
const defaultColor = computedstyle.getPropertyValue('--default-color');
|
||||
const uiGrayDark = computedstyle.getPropertyValue('--ui-gray-dark');
|
||||
|
||||
const dicomBrowserSelectStyles = {
|
||||
singleValue: (base, state) => ({
|
||||
...base,
|
||||
width: '100%',
|
||||
}),
|
||||
control: (base, state) => ({
|
||||
...base,
|
||||
cursor: 'pointer',
|
||||
background: uiGrayDarker,
|
||||
borderRadius: state.isFocused ? '5px 5px 5px 5px' : 5,
|
||||
borderColor: state.isFocused ? activeColor : defaultColor,
|
||||
minHeight: '50px',
|
||||
'&:hover': {
|
||||
borderColor: activeColor,
|
||||
},
|
||||
}),
|
||||
menu: base => ({
|
||||
...base,
|
||||
borderRadius: 5,
|
||||
background: uiGrayDarker,
|
||||
}),
|
||||
option: (base, state) => ({
|
||||
...base,
|
||||
cursor: 'pointer',
|
||||
'&:first-of-type': {
|
||||
borderTopLeftRadius: 5,
|
||||
borderTopRightRadius: 5,
|
||||
},
|
||||
'&:last-of-type': {
|
||||
borderBottomLeftRadius: 5,
|
||||
borderBottomRightRadius: 5,
|
||||
},
|
||||
background: state.isSelected ? uiGrayDark : uiGrayDarker,
|
||||
'&:hover': {
|
||||
background: uiGrayDark,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export default DicomBrowserSelect;
|
||||
@ -0,0 +1,25 @@
|
||||
.dcmseg-segmentation-item {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dcmseg-segmentation-item .segmentation-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dcmseg-segmentation-item .segmentation-meta-title {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
color: white;
|
||||
max-width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
.dcmseg-segmentation-item .segmentation-meta-description {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary-color);
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import './DicomBrowserSelectItem.css';
|
||||
|
||||
const DicomBrowserSelectItem = ({ onClick, title, description }) => {
|
||||
return (
|
||||
<li className="dcmseg-segmentation-item" onClick={onClick}>
|
||||
<div className="segmentation-meta">
|
||||
<div className="segmentation-meta-title">{title}</div>
|
||||
<div className="segmentation-meta-description">{description}</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
DicomBrowserSelectItem.propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
DicomBrowserSelectItem.defaultProps = {
|
||||
description: '',
|
||||
};
|
||||
|
||||
export default DicomBrowserSelectItem;
|
||||
@ -0,0 +1,27 @@
|
||||
.dicom-tag-browser-table {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.dicom-tag-browser-table td {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: var(--table-text-primary-color);
|
||||
border-top: 1px solid #ddd;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dicom-tag-browser-table td.dicom-tag-browser-table-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dicom-tag-browser-table th {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
text-align: center;
|
||||
color: var(--active-color);
|
||||
}
|
||||
|
||||
.dicom-tag-browser-table th.dicom-tag-browser-table-left {
|
||||
text-align: left;
|
||||
}
|
||||
228
extensions/dicom-tag-browser/src/components/DicomTagBrowser.js
Normal file
228
extensions/dicom-tag-browser/src/components/DicomTagBrowser.js
Normal file
@ -0,0 +1,228 @@
|
||||
import React, { useState } from 'react';
|
||||
import { classes } from '@ohif/core';
|
||||
import dcmjs from 'dcmjs';
|
||||
import DicomBrowserSelect from './DicomBrowserSelect';
|
||||
import moment from 'moment';
|
||||
import './DicomTagBrowser.css';
|
||||
import DicomBrowserSelectItem from './DicomBrowserSelectItem';
|
||||
|
||||
const { ImageSet } = classes;
|
||||
const { DicomMetaDictionary } = dcmjs.data;
|
||||
const { nameMap } = DicomMetaDictionary;
|
||||
|
||||
const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
|
||||
const [
|
||||
activeDisplaySetInstanceUID,
|
||||
setActiveDisplaySetInstanceUID,
|
||||
] = useState(displaySetInstanceUID);
|
||||
const [activeInstance, setActiveInstance] = useState(0);
|
||||
|
||||
const activeDisplaySet = displaySets.find(
|
||||
ds => ds.displaySetInstanceUID === activeDisplaySetInstanceUID
|
||||
);
|
||||
|
||||
const displaySetList = displaySets.map(displaySet => {
|
||||
const {
|
||||
displaySetInstanceUID,
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
SeriesDescription,
|
||||
Modality,
|
||||
} = displaySet;
|
||||
|
||||
/* Map to display representation */
|
||||
const dateStr = `${SeriesDate}:${SeriesTime}`.split('.')[0];
|
||||
const date = moment(dateStr, 'YYYYMMDD:HHmmss');
|
||||
const displayDate = date.format('ddd, MMM Do YYYY');
|
||||
|
||||
return {
|
||||
value: displaySetInstanceUID,
|
||||
title: `${SeriesNumber} (${Modality}): ${SeriesDescription}`,
|
||||
description: displayDate,
|
||||
onClick: () => {
|
||||
setActiveDisplaySetInstanceUID(displaySetInstanceUID);
|
||||
setActiveInstance(0);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
let metadata;
|
||||
const isImageStack = activeDisplaySet instanceof ImageSet;
|
||||
|
||||
let selectedInstanceValue;
|
||||
let instanceList;
|
||||
|
||||
if (isImageStack) {
|
||||
const { images } = activeDisplaySet;
|
||||
const image = images[activeInstance];
|
||||
|
||||
instanceList = images.map((image, index) => {
|
||||
const metadata = image.getData().metadata;
|
||||
|
||||
const { InstanceNumber } = metadata;
|
||||
|
||||
return {
|
||||
value: index,
|
||||
title: `Instance Number: ${InstanceNumber}`,
|
||||
description: '',
|
||||
onClick: () => {
|
||||
setActiveInstance(index);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
selectedInstanceValue = instanceList[activeInstance];
|
||||
|
||||
metadata = image.getData().metadata;
|
||||
} else {
|
||||
metadata = activeDisplaySet.metadata;
|
||||
}
|
||||
|
||||
const selectedDisplaySetValue = displaySetList.find(
|
||||
ds => ds.value === activeDisplaySetInstanceUID
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DicomBrowserSelect
|
||||
value={selectedDisplaySetValue}
|
||||
formatOptionLabel={DicomBrowserSelectItem}
|
||||
options={displaySetList}
|
||||
/>
|
||||
{isImageStack ? (
|
||||
<DicomBrowserSelect
|
||||
value={selectedInstanceValue}
|
||||
formatOptionLabel={DicomBrowserSelectItem}
|
||||
options={instanceList}
|
||||
/>
|
||||
) : null}
|
||||
<DicomTagTable instanceMetadata={metadata}></DicomTagTable>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function DicomTagTable({ instanceMetadata }) {
|
||||
const rows = getRows(instanceMetadata);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<table className="dicom-tag-browser-table">
|
||||
<tr>
|
||||
<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">Keyword</th>
|
||||
<th className="dicom-tag-browser-table-left">Value</th>
|
||||
</tr>
|
||||
{rows.map(row => (
|
||||
<tr>
|
||||
<td>{row[0]}</td>
|
||||
<td>{row[1]}</td>
|
||||
<td>{row[2]}</td>
|
||||
<td>{row[3]}</td>
|
||||
</tr>
|
||||
))}
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getRows(metadata, depth = 0) {
|
||||
// Tag, Type, Value, Keyword
|
||||
|
||||
const keywords = Object.keys(metadata);
|
||||
|
||||
let tagIndent = '';
|
||||
|
||||
for (let i = 0; i < depth; i++) {
|
||||
tagIndent += '>';
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
|
||||
for (let i = 0; i < keywords.length; i++) {
|
||||
let keyword = keywords[i];
|
||||
|
||||
if (keyword === '_vrMap') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const tagInfo = nameMap[keyword];
|
||||
|
||||
let value = metadata[keyword];
|
||||
|
||||
if (tagInfo && tagInfo.vr === 'SQ') {
|
||||
const sequenceAsArray = toArray(value);
|
||||
|
||||
// Push line defining the sequence
|
||||
rows.push([`${tagIndent}${tagInfo.tag}`, tagInfo.vr, keyword, '']);
|
||||
|
||||
if (value === null) {
|
||||
// Type 2 Sequence
|
||||
continue;
|
||||
}
|
||||
|
||||
sequenceAsArray.forEach(item => {
|
||||
const sequenceRows = getRows(item, depth + 1);
|
||||
|
||||
sequenceRows.forEach(row => {
|
||||
rows.push(row);
|
||||
});
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
value = value.join('\\');
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
if (value === null) {
|
||||
value = ' ';
|
||||
} else {
|
||||
if (typeof value === 'object') {
|
||||
if (value.InlineBinary) {
|
||||
value = 'Inline Binary';
|
||||
} else if (value.BulkDataURI) {
|
||||
value = `Bulk Data URI`; //: ${value.BulkDataURI}`;
|
||||
} else if (value.Alphabetic) {
|
||||
value = value.Alphabetic;
|
||||
} else {
|
||||
console.error('Unrecognised Value for element:');
|
||||
console.error(value);
|
||||
value = ' ';
|
||||
}
|
||||
} else {
|
||||
console.error('Unrecognised Value for element:');
|
||||
console.error(value);
|
||||
value = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove retired tags
|
||||
keyword = keyword.replace('RETIRED_', '');
|
||||
|
||||
if (tagInfo) {
|
||||
rows.push([`${tagIndent}${tagInfo.tag}`, tagInfo.vr, keyword, value]);
|
||||
} else {
|
||||
// Private tag
|
||||
const tag = `(${keyword.substring(0, 4)},${keyword.substring(4, 8)})`;
|
||||
|
||||
rows.push([`${tagIndent}${tag}`, '', 'Private Tag', value]);
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
function toArray(objectOrArray) {
|
||||
return Array.isArray(objectOrArray) ? objectOrArray : [objectOrArray];
|
||||
}
|
||||
|
||||
export default DicomTagBrowser;
|
||||
52
extensions/dicom-tag-browser/src/getCommandsModule.js
Normal file
52
extensions/dicom-tag-browser/src/getCommandsModule.js
Normal file
@ -0,0 +1,52 @@
|
||||
import { utils } from '@ohif/core';
|
||||
import React from 'react';
|
||||
import DicomTagBrowser from './components/DicomTagBrowser';
|
||||
|
||||
const { studyMetadataManager } = utils;
|
||||
|
||||
export default function getCommandsModule(servicesManager) {
|
||||
const actions = {
|
||||
openDICOMTagViewer({ viewports }) {
|
||||
const { activeViewportIndex, viewportSpecificData } = viewports;
|
||||
const activeViewportSpecificData =
|
||||
viewportSpecificData[activeViewportIndex];
|
||||
|
||||
const {
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
} = activeViewportSpecificData;
|
||||
|
||||
const studyMetadata = studyMetadataManager.get(StudyInstanceUID);
|
||||
const displaySets = studyMetadata.getDisplaySets();
|
||||
|
||||
const { UIModalService } = servicesManager.services;
|
||||
|
||||
const WrappedDicomTagBrowser = function() {
|
||||
return (
|
||||
<DicomTagBrowser
|
||||
displaySets={displaySets}
|
||||
displaySetInstanceUID={displaySetInstanceUID}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
UIModalService.show({
|
||||
content: WrappedDicomTagBrowser,
|
||||
title: `DICOM Tag Browser`,
|
||||
fullscreen: true,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
openDICOMTagViewer: {
|
||||
commandFn: actions.openDICOMTagViewer,
|
||||
storeContexts: ['servers', 'viewports'],
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
actions,
|
||||
definitions,
|
||||
};
|
||||
}
|
||||
26
extensions/dicom-tag-browser/src/index.js
Normal file
26
extensions/dicom-tag-browser/src/index.js
Normal file
@ -0,0 +1,26 @@
|
||||
import getCommandsModule from './getCommandsModule';
|
||||
import toolbarModule from './toolbarModule';
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extension
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id: 'dicom-tag-browser',
|
||||
|
||||
/**
|
||||
* MODULE GETTERS
|
||||
*/
|
||||
getCommandsModule({ servicesManager }) {
|
||||
return getCommandsModule(servicesManager);
|
||||
},
|
||||
getToolbarModule() {
|
||||
return toolbarModule;
|
||||
},
|
||||
};
|
||||
20
extensions/dicom-tag-browser/src/toolbarModule.js
Normal file
20
extensions/dicom-tag-browser/src/toolbarModule.js
Normal file
@ -0,0 +1,20 @@
|
||||
const TOOLBAR_BUTTON_TYPES = {
|
||||
COMMAND: 'command',
|
||||
};
|
||||
|
||||
const definitions = [
|
||||
{
|
||||
id: 'TagBrowser',
|
||||
label: 'Tag Browser',
|
||||
icon: 'list',
|
||||
//
|
||||
type: TOOLBAR_BUTTON_TYPES.COMMAND,
|
||||
commandName: 'openDICOMTagViewer',
|
||||
context: 'VIEWER',
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
definitions,
|
||||
defaultContext: 'VIEWER',
|
||||
};
|
||||
@ -38,6 +38,7 @@ function _show({
|
||||
onClose = null,
|
||||
closeButton = true,
|
||||
title = null,
|
||||
fullscreen = false,
|
||||
customClassName = null,
|
||||
}) {
|
||||
return serviceImplementation._show({
|
||||
@ -48,6 +49,7 @@ function _show({
|
||||
onClose,
|
||||
closeButton,
|
||||
title,
|
||||
fullscreen,
|
||||
customClassName,
|
||||
});
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ const OHIFModal = ({
|
||||
closeButton,
|
||||
shouldCloseOnEsc,
|
||||
isOpen,
|
||||
fullscreen,
|
||||
title,
|
||||
onClose,
|
||||
children,
|
||||
@ -41,9 +42,13 @@ const OHIFModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
const classes = fullscreen
|
||||
? classNames('OHIFModal', className, 'OHIFModal-fullscreen')
|
||||
: classNames('OHIFModal', className);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className={classNames('OHIFModal', className)}
|
||||
className={classes}
|
||||
data-cy="modal"
|
||||
shouldCloseOnEsc={shouldCloseOnEsc}
|
||||
isOpen={isOpen}
|
||||
|
||||
@ -18,9 +18,17 @@
|
||||
@media (min-width: 768px)
|
||||
width: 600px
|
||||
|
||||
&.OHIFModal-fullscreen
|
||||
width: 95%
|
||||
|
||||
@media (min-width: 992px)
|
||||
width: 900px
|
||||
|
||||
&.OHIFModal-fullscreen
|
||||
width: 95%
|
||||
|
||||
|
||||
|
||||
&__content
|
||||
padding: 20px
|
||||
max-height: 90vh;
|
||||
|
||||
@ -36,6 +36,7 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
||||
closeButton: true,
|
||||
title: null,
|
||||
customClassName: '',
|
||||
fullscreen: false,
|
||||
};
|
||||
|
||||
const [options, setOptions] = useState(DEFAULT_OPTIONS);
|
||||
@ -78,6 +79,7 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
||||
title,
|
||||
customClassName,
|
||||
shouldCloseOnEsc,
|
||||
fullscreen,
|
||||
closeButton,
|
||||
} = options;
|
||||
|
||||
@ -89,6 +91,7 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
||||
shouldCloseOnEsc={shouldCloseOnEsc}
|
||||
isOpen={isOpen}
|
||||
title={title}
|
||||
fullscreen={fullscreen}
|
||||
closeButton={closeButton}
|
||||
onClose={() => {
|
||||
if (onClose) {
|
||||
|
||||
@ -29,6 +29,7 @@ import OHIFDicomSegmentationExtension from '@ohif/extension-dicom-segmentation';
|
||||
import OHIFDicomRtExtension from '@ohif/extension-dicom-rt';
|
||||
import OHIFDicomMicroscopyExtension from '@ohif/extension-dicom-microscopy';
|
||||
import OHIFDicomPDFExtension from '@ohif/extension-dicom-pdf';
|
||||
import OHIFDicomTagBrowserExtension from '@ohif/extension-dicom-tag-browser';
|
||||
// Add this for Debugging purposes:
|
||||
//import OHIFDebuggingExtension from '@ohif/extension-debugging';
|
||||
import { version } from '../package.json';
|
||||
@ -53,6 +54,7 @@ const appProps = {
|
||||
OHIFDicomPDFExtension,
|
||||
OHIFDicomSegmentationExtension,
|
||||
OHIFDicomRtExtension,
|
||||
OHIFDicomTagBrowserExtension,
|
||||
//OHIFDebuggingExtension,
|
||||
],
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user