Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cffc44f0f4 | ||
|
|
ea0fc07e30 | ||
|
|
b8d241fa33 | ||
|
|
ccdfcd4a85 |
No files matched your search
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.9.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.9.4...@ohif/extension-cornerstone@2.9.5) (2020-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.9.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.9.3...@ohif/extension-cornerstone@2.9.4) (2020-09-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "2.9.4",
|
||||
"version": "2.9.5",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -51,6 +51,6 @@
|
||||
"classnames": "^2.2.6",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"react-cornerstone-viewport": "4.0.2"
|
||||
"react-cornerstone-viewport": "4.0.4"
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-tag-browser@0.0.2...@ohif/extension-dicom-tag-browser@0.0.3) (2020-09-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 0.0.2 (2020-09-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-tag-browser
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-tag-browser",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"description": "OHIF extension for checking DICOM headers.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -39,6 +39,7 @@ const dicomBrowserSelectStyles = {
|
||||
}),
|
||||
option: (base, state) => ({
|
||||
...base,
|
||||
width: '100%',
|
||||
cursor: 'pointer',
|
||||
'&:first-of-type': {
|
||||
borderTopLeftRadius: 5,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dcmseg-segmentation-item .segmentation-meta {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.dicom-tag-browser-table td {
|
||||
.dicom-tag-browser-table tr {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: var(--table-text-primary-color);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { classes } from '@ohif/core';
|
||||
import dcmjs from 'dcmjs';
|
||||
import DicomBrowserSelect from './DicomBrowserSelect';
|
||||
@@ -16,73 +16,96 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
|
||||
setActiveDisplaySetInstanceUID,
|
||||
] = useState(displaySetInstanceUID);
|
||||
const [activeInstance, setActiveInstance] = useState(0);
|
||||
const [tags, setTags] = useState([]);
|
||||
const [instanceList, setInstanceList] = useState([]);
|
||||
const [displaySetList, setDisplaySetList] = useState([]);
|
||||
const [isImageStack, setIsImageStack] = useState(false);
|
||||
|
||||
const activeDisplaySet = displaySets.find(
|
||||
ds => ds.displaySetInstanceUID === activeDisplaySetInstanceUID
|
||||
);
|
||||
useEffect(() => {
|
||||
const activeDisplaySet = displaySets.find(
|
||||
ds => ds.displaySetInstanceUID === activeDisplaySetInstanceUID
|
||||
);
|
||||
|
||||
const displaySetList = displaySets.map(displaySet => {
|
||||
const {
|
||||
displaySetInstanceUID,
|
||||
SeriesDate,
|
||||
SeriesTime,
|
||||
SeriesNumber,
|
||||
SeriesDescription,
|
||||
Modality,
|
||||
} = displaySet;
|
||||
const newDisplaySetList = 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;
|
||||
/* 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: index,
|
||||
title: `Instance Number: ${InstanceNumber}`,
|
||||
description: '',
|
||||
value: displaySetInstanceUID,
|
||||
title: `${SeriesNumber} (${Modality}): ${SeriesDescription}`,
|
||||
description: displayDate,
|
||||
onClick: () => {
|
||||
setActiveInstance(index);
|
||||
setActiveDisplaySetInstanceUID(displaySetInstanceUID);
|
||||
setActiveInstance(0);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
selectedInstanceValue = instanceList[activeInstance];
|
||||
let metadata;
|
||||
const isImageStack = activeDisplaySet instanceof ImageSet;
|
||||
|
||||
metadata = image.getData().metadata;
|
||||
} else {
|
||||
metadata = activeDisplaySet.metadata;
|
||||
}
|
||||
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);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
metadata = image.getData().metadata;
|
||||
} else {
|
||||
metadata = activeDisplaySet.metadata;
|
||||
}
|
||||
|
||||
setTags(getSortedTags(metadata));
|
||||
setInstanceList(instanceList);
|
||||
setDisplaySetList(newDisplaySetList);
|
||||
setIsImageStack(isImageStack);
|
||||
}, [activeDisplaySetInstanceUID, activeInstance]);
|
||||
|
||||
const selectedDisplaySetValue = displaySetList.find(
|
||||
ds => ds.value === activeDisplaySetInstanceUID
|
||||
);
|
||||
|
||||
let instanceSelectList = null;
|
||||
|
||||
if (isImageStack) {
|
||||
const selectedInstanceValue = instanceList[activeInstance];
|
||||
|
||||
instanceSelectList = (
|
||||
<DicomBrowserSelect
|
||||
value={selectedInstanceValue}
|
||||
formatOptionLabel={DicomBrowserSelectItem}
|
||||
options={instanceList}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DicomBrowserSelect
|
||||
@@ -90,20 +113,14 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
|
||||
formatOptionLabel={DicomBrowserSelectItem}
|
||||
options={displaySetList}
|
||||
/>
|
||||
{isImageStack ? (
|
||||
<DicomBrowserSelect
|
||||
value={selectedInstanceValue}
|
||||
formatOptionLabel={DicomBrowserSelectItem}
|
||||
options={instanceList}
|
||||
/>
|
||||
) : null}
|
||||
<DicomTagTable instanceMetadata={metadata}></DicomTagTable>
|
||||
{instanceSelectList}
|
||||
<DicomTagTable tags={tags}></DicomTagTable>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function DicomTagTable({ instanceMetadata }) {
|
||||
const rows = getRows(instanceMetadata);
|
||||
function DicomTagTable({ tags }) {
|
||||
const rows = getFormattedRowsFromTags(tags);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -114,19 +131,71 @@ function DicomTagTable({ instanceMetadata }) {
|
||||
<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>
|
||||
))}
|
||||
{rows.map(row => {
|
||||
const className = row.className ? row.className : null;
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td>{row[0]}</td>
|
||||
<td className="dicom-tag-browser-table-center">{row[1]}</td>
|
||||
<td>{row[2]}</td>
|
||||
<td>{row[3]}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getFormattedRowsFromTags(tags) {
|
||||
const rows = [];
|
||||
|
||||
tags.forEach(tagInfo => {
|
||||
if (tagInfo.vr === 'SQ') {
|
||||
rows.push([
|
||||
`${tagInfo.tagIndent}${tagInfo.tag}`,
|
||||
tagInfo.vr,
|
||||
tagInfo.keyword,
|
||||
'',
|
||||
]);
|
||||
|
||||
const { values } = tagInfo;
|
||||
|
||||
values.forEach((item, index) => {
|
||||
const formatedRowsFromTags = getFormattedRowsFromTags(item);
|
||||
|
||||
rows.push([
|
||||
`${item[0].tagIndent}(FFFE,E000)`,
|
||||
'',
|
||||
`Item #${index}`,
|
||||
'',
|
||||
]);
|
||||
|
||||
rows.push(...formatedRowsFromTags);
|
||||
});
|
||||
} else {
|
||||
rows.push([
|
||||
`${tagInfo.tagIndent}${tagInfo.tag}`,
|
||||
tagInfo.vr,
|
||||
tagInfo.keyword,
|
||||
tagInfo.value,
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
function getSortedTags(metadata) {
|
||||
const tagList = getRows(metadata);
|
||||
|
||||
// Sort top level tags, sequence groups are sorted when created.
|
||||
_sortTagList(tagList);
|
||||
|
||||
return tagList;
|
||||
}
|
||||
|
||||
function getRows(metadata, depth = 0) {
|
||||
// Tag, Type, Value, Keyword
|
||||
|
||||
@@ -138,6 +207,10 @@ function getRows(metadata, depth = 0) {
|
||||
tagIndent += '>';
|
||||
}
|
||||
|
||||
if (depth > 0) {
|
||||
tagIndent += ' '; // If indented, add a space after the indents.
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
|
||||
for (let i = 0; i < keywords.length; i++) {
|
||||
@@ -155,7 +228,16 @@ function getRows(metadata, depth = 0) {
|
||||
const sequenceAsArray = toArray(value);
|
||||
|
||||
// Push line defining the sequence
|
||||
rows.push([`${tagIndent}${tagInfo.tag}`, tagInfo.vr, keyword, '']);
|
||||
|
||||
const sequence = {
|
||||
tag: tagInfo.tag,
|
||||
tagIndent,
|
||||
vr: tagInfo.vr,
|
||||
keyword,
|
||||
values: [],
|
||||
};
|
||||
|
||||
rows.push(sequence);
|
||||
|
||||
if (value === null) {
|
||||
// Type 2 Sequence
|
||||
@@ -165,9 +247,10 @@ function getRows(metadata, depth = 0) {
|
||||
sequenceAsArray.forEach(item => {
|
||||
const sequenceRows = getRows(item, depth + 1);
|
||||
|
||||
sequenceRows.forEach(row => {
|
||||
rows.push(row);
|
||||
});
|
||||
// Sort the sequence group.
|
||||
_sortTagList(sequenceRows);
|
||||
|
||||
sequence.values.push(sequenceRows);
|
||||
});
|
||||
|
||||
continue;
|
||||
@@ -205,16 +288,30 @@ function getRows(metadata, depth = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
// tag / vr/ keyword/ value
|
||||
|
||||
// Remove retired tags
|
||||
keyword = keyword.replace('RETIRED_', '');
|
||||
|
||||
if (tagInfo) {
|
||||
rows.push([`${tagIndent}${tagInfo.tag}`, tagInfo.vr, keyword, value]);
|
||||
rows.push({
|
||||
tag: tagInfo.tag,
|
||||
tagIndent,
|
||||
vr: tagInfo.vr,
|
||||
keyword,
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
// Private tag
|
||||
const tag = `(${keyword.substring(0, 4)},${keyword.substring(4, 8)})`;
|
||||
|
||||
rows.push([`${tagIndent}${tag}`, '', 'Private Tag', value]);
|
||||
rows.push({
|
||||
tag,
|
||||
tagIndent,
|
||||
vr: '',
|
||||
keyword: 'Private Tag',
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,4 +322,14 @@ function toArray(objectOrArray) {
|
||||
return Array.isArray(objectOrArray) ? objectOrArray : [objectOrArray];
|
||||
}
|
||||
|
||||
function _sortTagList(tagList) {
|
||||
tagList.sort((a, b) => {
|
||||
if (a.tag < b.tag) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
export default DicomTagBrowser;
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [4.5.13](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.12...@ohif/viewer@4.5.13) (2020-09-29)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.5.12](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.11...@ohif/viewer@4.5.12) (2020-09-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.5.11](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.5.10...@ohif/viewer@4.5.11) (2020-09-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
@@ -6,6 +6,9 @@ describe('OHIF HTML Extension', () => {
|
||||
cy.expectMinimumThumbnails(5);
|
||||
});
|
||||
|
||||
// TODO -> Commented these out until we get a seperate temporary PACS running on the CI.
|
||||
// As pointing these tests at a public PACS with public STOW functionality means this always breaks.
|
||||
|
||||
it('checks if series thumbnails are being displayed', () => {
|
||||
cy.get('[data-cy="thumbnail-list"]')
|
||||
.contains('SR')
|
||||
@@ -13,66 +16,66 @@ describe('OHIF HTML Extension', () => {
|
||||
.should('to.be.at.least', 1);
|
||||
});
|
||||
|
||||
it('drags and drop a SR thumbnail into viewport', () => {
|
||||
cy.get('[data-cy="thumbnail-list"]')
|
||||
.contains('SR')
|
||||
.first()
|
||||
.drag('.viewport-drop-target');
|
||||
// it('drags and drop a SR thumbnail into viewport', () => {
|
||||
// cy.get('[data-cy="thumbnail-list"]')
|
||||
// .contains('SR')
|
||||
// .first()
|
||||
// .drag('.viewport-drop-target');
|
||||
|
||||
cy.get(':nth-child(2) > h1').should(
|
||||
'contain.text',
|
||||
'Imaging Measurement Report'
|
||||
);
|
||||
});
|
||||
// cy.get(':nth-child(2) > h1').should(
|
||||
// 'contain.text',
|
||||
// 'Imaging Measurement Report'
|
||||
// );
|
||||
// });
|
||||
|
||||
it('checks if the HTML viewport has been set to active by interaction', () => {
|
||||
cy.setLayout('3', '3');
|
||||
// it('checks if the HTML viewport has been set to active by interaction', () => {
|
||||
// cy.setLayout('3', '3');
|
||||
|
||||
// check if viewport has been set as active by CLICKING
|
||||
cy.get('[data-cy=viewprt-grid] > :nth-child(4)')
|
||||
.click()
|
||||
.then($viewport => {
|
||||
cy.wrap($viewport).should('have.class', 'active');
|
||||
});
|
||||
// // check if viewport has been set as active by CLICKING
|
||||
// cy.get('[data-cy=viewprt-grid] > :nth-child(4)')
|
||||
// .click()
|
||||
// .then($viewport => {
|
||||
// cy.wrap($viewport).should('have.class', 'active');
|
||||
// });
|
||||
|
||||
// check if viewport has been set as active by SCROLLING
|
||||
cy.get('[data-cy=viewprt-grid] > :nth-child(7)').then($viewport => {
|
||||
cy.wrap($viewport)
|
||||
.find('[data-cy=dicom-html-viewport]')
|
||||
.scrollTo('bottom');
|
||||
cy.wrap($viewport).should('have.class', 'active');
|
||||
});
|
||||
// // check if viewport has been set as active by SCROLLING
|
||||
// cy.get('[data-cy=viewprt-grid] > :nth-child(7)').then($viewport => {
|
||||
// cy.wrap($viewport)
|
||||
// .find('[data-cy=dicom-html-viewport]')
|
||||
// .scrollTo('bottom');
|
||||
// cy.wrap($viewport).should('have.class', 'active');
|
||||
// });
|
||||
|
||||
cy.setLayout('1', '1');
|
||||
});
|
||||
// cy.setLayout('1', '1');
|
||||
// });
|
||||
});
|
||||
|
||||
describe('OHIF PDF Extension', () => {
|
||||
before(() => {
|
||||
cy.checkStudyRouteInViewer(
|
||||
'1.2.826.0.13854362241694438965858641723883466450351448'
|
||||
);
|
||||
cy.expectMinimumThumbnails(5);
|
||||
});
|
||||
// describe('OHIF PDF Extension', () => {
|
||||
// before(() => {
|
||||
// cy.checkStudyRouteInViewer(
|
||||
// '1.2.826.0.13854362241694438965858641723883466450351448'
|
||||
// );
|
||||
// cy.expectMinimumThumbnails(5);
|
||||
// });
|
||||
|
||||
it('checks if series thumbnails are being displayed', () => {
|
||||
cy.get('[data-cy="thumbnail-list"]')
|
||||
.contains('DOC')
|
||||
.its('length')
|
||||
.should('to.be.at.least', 1);
|
||||
});
|
||||
// it('checks if series thumbnails are being displayed', () => {
|
||||
// cy.get('[data-cy="thumbnail-list"]')
|
||||
// .contains('DOC')
|
||||
// .its('length')
|
||||
// .should('to.be.at.least', 1);
|
||||
// });
|
||||
|
||||
it('drags and drop a PDF thumbnail into viewport', () => {
|
||||
cy.get('[data-cy="thumbnail-list"]')
|
||||
.contains('DOC')
|
||||
.scrollIntoView()
|
||||
.drag('.viewport-drop-target');
|
||||
// it('drags and drop a PDF thumbnail into viewport', () => {
|
||||
// cy.get('[data-cy="thumbnail-list"]')
|
||||
// .contains('DOC')
|
||||
// .scrollIntoView()
|
||||
// .drag('.viewport-drop-target');
|
||||
|
||||
cy.get('.DicomPDFViewport')
|
||||
.its('length')
|
||||
.should('be.eq', 1);
|
||||
// cy.get('.DicomPDFViewport')
|
||||
// .its('length')
|
||||
// .should('to.be.at.least', 1);
|
||||
|
||||
//Take Screenshot
|
||||
cy.screenshot('PDF Extension - Should load PDF file');
|
||||
});
|
||||
});
|
||||
// //Take Screenshot
|
||||
// cy.screenshot('PDF Extension - Should load PDF file');
|
||||
// });
|
||||
// });
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/viewer",
|
||||
"version": "4.5.11",
|
||||
"version": "4.5.13",
|
||||
"description": "OHIF Viewer",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
@@ -49,7 +49,7 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@ohif/core": "^2.10.5",
|
||||
"@ohif/extension-cornerstone": "^2.9.4",
|
||||
"@ohif/extension-cornerstone": "^2.9.5",
|
||||
"@ohif/extension-debugging": "^0.1.5",
|
||||
"@ohif/extension-dicom-html": "^1.2.8",
|
||||
"@ohif/extension-dicom-microscopy": "^0.51.3",
|
||||
|
||||
@@ -55,7 +55,7 @@ const appProps = {
|
||||
OHIFDicomSegmentationExtension,
|
||||
OHIFDicomRtExtension,
|
||||
//[OHIFDebuggingExtension, { mailTo: 'support@canceridc.dev' }],
|
||||
//OHIFDicomTagBrowserExtension,
|
||||
OHIFDicomTagBrowserExtension,
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user