Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a647fd618 | ||
|
|
f8fc31bcac | ||
|
|
b7ab88b0f1 | ||
|
|
57a30d7c34 | ||
|
|
cd90665b0e | ||
|
|
98c657231e | ||
|
|
14da247318 | ||
|
|
6a77d6c778 | ||
|
|
8f1785446b |
No files matched your search
@@ -21,6 +21,19 @@ mv platform/viewer/dist/* .netlify/www/pwa -v
|
||||
# Build && Move script output
|
||||
# yarn run build:package
|
||||
|
||||
# Build && Move Docz Output
|
||||
# Using local yarn install to prevent Gatsby from needing to access
|
||||
# node_modules above the platform/ui folder
|
||||
cd platform/ui
|
||||
yarn install
|
||||
yarn run build
|
||||
cd ../..
|
||||
mkdir -p ./.netlify/www/ui
|
||||
mv platform/ui/.docz/dist/* .netlify/www/ui -v
|
||||
|
||||
# Cache all of the node_module dependencies in
|
||||
# extensions, modules, and platform packages
|
||||
yarn run lerna:cache
|
||||
echo 'Nothing left to see here. Go home, folks.'
|
||||
|
||||
# Build using react-scripts
|
||||
|
||||
@@ -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.8.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.8.4...@ohif/extension-cornerstone@2.8.5) (2020-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.8.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.8.3...@ohif/extension-cornerstone@2.8.4) (2020-07-13)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "2.8.4",
|
||||
"version": "2.8.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": "2.3.9"
|
||||
"react-cornerstone-viewport": "4.0.1"
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
## [0.2.7](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.6...@ohif/extension-dicom-rt@0.2.7) (2020-08-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.5...@ohif/extension-dicom-rt@0.2.6) (2020-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.2.5](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.4...@ohif/extension-dicom-rt@0.2.5) (2020-07-13)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-rt",
|
||||
"version": "0.2.5",
|
||||
"version": "0.2.7",
|
||||
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MODULE_TYPES, utils, DICOMWeb } from '@ohif/core';
|
||||
import loadRTStruct from './loadRTStruct';
|
||||
import getSourceDisplaySet from './getSourceDisplaySet';
|
||||
|
||||
import id from './id';
|
||||
|
||||
@@ -67,6 +68,10 @@ const OHIFDicomRTStructSopClassHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
rtStructDisplaySet.getSourceDisplaySet = function(studies) {
|
||||
return getSourceDisplaySet(studies, rtStructDisplaySet);
|
||||
};
|
||||
|
||||
rtStructDisplaySet.load = function(referencedDisplaySet, studies) {
|
||||
return loadRTStruct(
|
||||
rtStructDisplaySet,
|
||||
|
||||
@@ -17,7 +17,6 @@ const { studyMetadataManager } = utils;
|
||||
|
||||
const refreshViewport = () => {
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
debugger;
|
||||
if (enabledElement.image) {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
}
|
||||
@@ -40,7 +39,6 @@ const RTPanel = ({
|
||||
activeIndex,
|
||||
isOpen,
|
||||
onContourItemClick,
|
||||
noContoursNotification,
|
||||
activeContexts = [],
|
||||
contexts = {},
|
||||
}) => {
|
||||
@@ -126,7 +124,7 @@ const RTPanel = ({
|
||||
}, [isOpen]);
|
||||
|
||||
const toContourItem = (
|
||||
{ ROINumber, ROIName, RTROIObservations, colorArray, visible },
|
||||
{ ROINumber, ROIName, RTROIObservations, colorArray, visible, isSupported },
|
||||
loadedSet
|
||||
) => {
|
||||
let interpretedType = '';
|
||||
@@ -139,6 +137,7 @@ const RTPanel = ({
|
||||
<StructureSetItem
|
||||
key={ROINumber}
|
||||
selected={isSameContour}
|
||||
isDisabled={!isSupported}
|
||||
onClick={() => {
|
||||
setSelectedContour(isSameContour ? null : ROINumber);
|
||||
|
||||
@@ -160,12 +159,6 @@ const RTPanel = ({
|
||||
imageIds
|
||||
);
|
||||
|
||||
if (!imageId) {
|
||||
noContoursNotification();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const frameIndex = imageIds.indexOf(imageId);
|
||||
const SOPInstanceUID = cornerstone.metaData.get(
|
||||
'SOPInstanceUID',
|
||||
@@ -249,7 +242,7 @@ const RTPanel = ({
|
||||
key={SeriesInstanceUID}
|
||||
title={metadata.StructureSetLabel}
|
||||
loading={!isLoaded || !loadedSet}
|
||||
visible={isLoaded && loadedSet.visible}
|
||||
visible={isLoaded && loadedSet && loadedSet.visible}
|
||||
hideVisibleButton={!isLoaded}
|
||||
expanded={
|
||||
isLoaded &&
|
||||
|
||||
@@ -22,11 +22,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dcmrt-structure-set-item.selected .item-actions {
|
||||
height: 35px;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.dcmrt-structure-set-item .item-actions {
|
||||
margin-left: -1px;
|
||||
background-color: var(--ui-gray-darker);
|
||||
@@ -47,7 +42,8 @@
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.dcmrt-structure-set-item .item-actions .btnAction:hover, .dcmrt-structure-set-item .item-actions .btnAction:active {
|
||||
.dcmrt-structure-set-item .item-actions .btnAction:hover,
|
||||
.dcmrt-structure-set-item .item-actions .btnAction:active {
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
|
||||
@@ -86,3 +82,12 @@
|
||||
.dcmrt-structure-set-item .item-label .eye-icon.--visible {
|
||||
color: var(--default-color);
|
||||
}
|
||||
|
||||
.dcmrt-structure-set-item.isDisabled .item-color-section {
|
||||
background-color: #e29e4a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dcmrt-structure-set-item.isDisabled .item-label {
|
||||
color: var(--text-disabled-color);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TableListItem, Icon } from '@ohif/ui';
|
||||
import { TableListItem, Icon, Tooltip, OverlayTrigger } from '@ohif/ui';
|
||||
|
||||
import './StructureSetItem.css';
|
||||
|
||||
@@ -20,6 +20,7 @@ ColoredCircle.propTypes = {
|
||||
const StructureSetItem = ({
|
||||
index,
|
||||
label,
|
||||
isDisabled,
|
||||
onClick,
|
||||
itemClass,
|
||||
color,
|
||||
@@ -31,22 +32,44 @@ const StructureSetItem = ({
|
||||
|
||||
useEffect(() => {
|
||||
setIsVisible(visible);
|
||||
}, [visible])
|
||||
}, [visible]);
|
||||
|
||||
return (
|
||||
<div className={`dcmrt-structure-set-item ${selected && 'selected'}`}>
|
||||
<TableListItem
|
||||
key={index}
|
||||
itemKey={index}
|
||||
itemIndex={index}
|
||||
itemClass={itemClass}
|
||||
itemMeta={<ColoredCircle color={color} />}
|
||||
itemMetaClass="item-color-section"
|
||||
onItemClick={onClick}
|
||||
>
|
||||
<div>
|
||||
<div className="item-label" style={{ marginBottom: 4 }}>
|
||||
<span>{label}</span>
|
||||
let dcmrtClassNames = `dcmrt-structure-set-item`;
|
||||
|
||||
if (selected) {
|
||||
dcmrtClassNames += ' selected';
|
||||
}
|
||||
|
||||
if (isDisabled) {
|
||||
dcmrtClassNames += ' isDisabled';
|
||||
}
|
||||
|
||||
const warningIcon = (
|
||||
<span>
|
||||
<Icon name="exclamation-triangle" />
|
||||
</span>
|
||||
);
|
||||
|
||||
const tableListItem = (
|
||||
<TableListItem
|
||||
key={index}
|
||||
itemKey={index}
|
||||
itemIndex={index}
|
||||
itemClass={itemClass}
|
||||
itemMeta={isDisabled ? warningIcon : <ColoredCircle color={color} />}
|
||||
itemMetaClass="item-color-section"
|
||||
onItemClick={() => {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
onClick();
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div className="item-label" style={{ marginBottom: 4 }}>
|
||||
<span>{label}</span>
|
||||
{!isDisabled && (
|
||||
<Icon
|
||||
className={`eye-icon ${isVisible && '--visible'}`}
|
||||
name={isVisible ? 'eye' : 'eye-closed'}
|
||||
@@ -54,37 +77,72 @@ const StructureSetItem = ({
|
||||
height="20px"
|
||||
onClick={event => {
|
||||
event.stopPropagation();
|
||||
|
||||
if (isDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newVisibility = !isVisible;
|
||||
setIsVisible(newVisibility);
|
||||
onVisibilityChange(newVisibility);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{false && <div className="item-info">{'...'}</div>}
|
||||
{false && (
|
||||
<div className="item-actions">
|
||||
<button
|
||||
className="btnAction"
|
||||
onClick={() => console.log('Relabelling...')}
|
||||
>
|
||||
<span style={{ marginRight: '4px' }}>
|
||||
<Icon name="edit" width="14px" height="14px" />
|
||||
</span>
|
||||
Relabel
|
||||
</button>
|
||||
<button
|
||||
className="btnAction"
|
||||
onClick={() => console.log('Editing description...')}
|
||||
>
|
||||
<span style={{ marginRight: '4px' }}>
|
||||
<Icon name="edit" width="14px" height="14px" />
|
||||
</span>
|
||||
Description
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</TableListItem>
|
||||
|
||||
{false && <div className="item-info">{'...'}</div>}
|
||||
{false && (
|
||||
<div className="item-actions">
|
||||
<button
|
||||
className="btnAction"
|
||||
onClick={() => console.log('Relabelling...')}
|
||||
>
|
||||
<span style={{ marginRight: '4px' }}>
|
||||
<Icon name="edit" width="14px" height="14px" />
|
||||
</span>
|
||||
Relabel
|
||||
</button>
|
||||
<button
|
||||
className="btnAction"
|
||||
onClick={() => console.log('Editing description...')}
|
||||
>
|
||||
<span style={{ marginRight: '4px' }}>
|
||||
<Icon name="edit" width="14px" height="14px" />
|
||||
</span>
|
||||
Description
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</TableListItem>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={dcmrtClassNames}>
|
||||
<React.Fragment>
|
||||
{isDisabled ? (
|
||||
<OverlayTrigger
|
||||
key={index}
|
||||
placement="left"
|
||||
overlay={
|
||||
<Tooltip
|
||||
placement="left"
|
||||
className="in tooltip-warning"
|
||||
id="tooltip-left"
|
||||
>
|
||||
<div className="warningTitle">Unsupported Region</div>
|
||||
<div className="warningContent">
|
||||
Contour type currently unsupported.
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<div>{tableListItem}</div>
|
||||
</OverlayTrigger>
|
||||
) : (
|
||||
<React.Fragment>{tableListItem} </React.Fragment>
|
||||
)}
|
||||
</React.Fragment>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -99,7 +157,7 @@ StructureSetItem.propTypes = {
|
||||
|
||||
StructureSetItem.defaultProps = {
|
||||
itemClass: '',
|
||||
onClick: () => { },
|
||||
onClick: () => {},
|
||||
};
|
||||
|
||||
export default StructureSetItem;
|
||||
@@ -0,0 +1,38 @@
|
||||
export default function getSourceDisplaySet(studies, rtStructDisplaySet) {
|
||||
const referencedDisplaySet = _getReferencedDisplaySet(
|
||||
rtStructDisplaySet,
|
||||
studies
|
||||
);
|
||||
|
||||
rtStructDisplaySet.load(referencedDisplaySet, studies);
|
||||
|
||||
return referencedDisplaySet;
|
||||
}
|
||||
|
||||
const _getReferencedDisplaySet = (rtStructDisplaySet, studies) => {
|
||||
let allDisplaySets = [];
|
||||
|
||||
studies.forEach(study => {
|
||||
allDisplaySets = allDisplaySets.concat(study.displaySets);
|
||||
});
|
||||
|
||||
const otherDisplaySets = allDisplaySets.filter(
|
||||
ds => ds.displaySetInstanceUID !== rtStructDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
|
||||
const ReferencedSeriesSequence = Array.isArray(
|
||||
rtStructDisplaySet.metadata.ReferencedSeriesSequence
|
||||
)
|
||||
? rtStructDisplaySet.metadata.ReferencedSeriesSequence
|
||||
: [rtStructDisplaySet.metadata.ReferencedSeriesSequence];
|
||||
|
||||
const referencedSeriesInstanceUIDs = ReferencedSeriesSequence.map(
|
||||
ReferencedSeries => ReferencedSeries.SeriesInstanceUID
|
||||
);
|
||||
|
||||
const referencedDisplaySet = otherDisplaySets.find(ds =>
|
||||
referencedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID)
|
||||
);
|
||||
|
||||
return referencedDisplaySet;
|
||||
};
|
||||
@@ -21,20 +21,9 @@ export default {
|
||||
init({ servicesManager, configuration });
|
||||
},
|
||||
getPanelModule({ commandsManager, servicesManager, api }) {
|
||||
const { UINotificationService } = servicesManager.services;
|
||||
|
||||
const ExtendedRTPanel = props => {
|
||||
const { activeContexts } = api.hooks.useAppContext();
|
||||
|
||||
const noContoursNotificationHandler = () => {
|
||||
UINotificationService.show({
|
||||
title: 'ROI Contour empty',
|
||||
message: 'The ROI contour has no structure set data.',
|
||||
type: 'error',
|
||||
autoClose: false,
|
||||
});
|
||||
};
|
||||
|
||||
const contourItemClickHandler = contourData => {
|
||||
commandsManager.runCommand('jumpToImage', contourData);
|
||||
};
|
||||
@@ -45,7 +34,6 @@ export default {
|
||||
onContourItemClick={contourItemClickHandler}
|
||||
activeContexts={activeContexts}
|
||||
contexts={api.contexts}
|
||||
noContoursNotification={noContoursNotificationHandler}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -74,12 +74,7 @@ export default async function loadRTStruct(
|
||||
continue;
|
||||
}
|
||||
|
||||
_setROIContourMetadata(
|
||||
structureSet,
|
||||
StructureSetROISequence,
|
||||
RTROIObservationsSequence,
|
||||
ROIContour
|
||||
);
|
||||
const isSupported = false;
|
||||
|
||||
for (let c = 0; c < ContourSequence.length; c++) {
|
||||
const {
|
||||
@@ -91,10 +86,12 @@ export default async function loadRTStruct(
|
||||
|
||||
if (ContourGeometricType !== 'CLOSED_PLANAR') {
|
||||
// TODO: Do we want to visualise types other than closed planar?
|
||||
// We could easily do open planar.
|
||||
// We could easily do open planar and point.
|
||||
continue;
|
||||
}
|
||||
|
||||
isSupported = true;
|
||||
|
||||
const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID;
|
||||
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
||||
const imageIdSpecificToolData = _getOrCreateImageIdSpecificToolData(
|
||||
@@ -126,6 +123,14 @@ export default async function loadRTStruct(
|
||||
|
||||
imageIdSpecificToolData.push(measurementData);
|
||||
}
|
||||
|
||||
_setROIContourMetadata(
|
||||
structureSet,
|
||||
StructureSetROISequence,
|
||||
RTROIObservationsSequence,
|
||||
ROIContour,
|
||||
isSupported
|
||||
);
|
||||
}
|
||||
|
||||
_setToolEnabledIfNotEnabled(rtStructDisplayToolName);
|
||||
@@ -155,7 +160,8 @@ function _setROIContourMetadata(
|
||||
structureSet,
|
||||
StructureSetROISequence,
|
||||
RTROIObservationsSequence,
|
||||
ROIContour
|
||||
ROIContour,
|
||||
isSupported
|
||||
) {
|
||||
const StructureSetROI = StructureSetROISequence.find(
|
||||
structureSetROI =>
|
||||
@@ -167,6 +173,7 @@ function _setROIContourMetadata(
|
||||
ROIName: StructureSetROI.ROIName,
|
||||
ROIGenerationAlgorithm: StructureSetROI.ROIGenerationAlgorithm,
|
||||
ROIDescription: StructureSetROI.ROIDescription,
|
||||
isSupported,
|
||||
visible: true,
|
||||
};
|
||||
|
||||
|
||||
@@ -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.3.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.3...@ohif/extension-dicom-segmentation@0.3.4) (2020-08-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [0.3.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.2...@ohif/extension-dicom-segmentation@0.3.3) (2020-07-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-dicom-segmentation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-dicom-segmentation",
|
||||
"version": "0.3.3",
|
||||
"version": "0.3.4",
|
||||
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
|
||||
+48
-85
@@ -6,6 +6,9 @@ import moment from 'moment';
|
||||
import { utils, log } from '@ohif/core';
|
||||
import { ScrollableArea, TableList, Icon } from '@ohif/ui';
|
||||
|
||||
import setActiveLabelmap from '../../utils/setActiveLabelMap';
|
||||
import refreshViewports from '../../utils/refreshViewports';
|
||||
|
||||
import {
|
||||
BrushColorSelector,
|
||||
BrushRadius,
|
||||
@@ -19,12 +22,6 @@ import SegmentationSettings from '../SegmentationSettings/SegmentationSettings';
|
||||
|
||||
const { studyMetadataManager } = utils;
|
||||
|
||||
const refreshViewport = () => {
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* SegmentationPanel component
|
||||
*
|
||||
@@ -68,8 +65,7 @@ const SegmentationPanel = ({
|
||||
*/
|
||||
const [state, setState] = useState({
|
||||
brushRadius: DEFAULT_BRUSH_RADIUS,
|
||||
brushColor:
|
||||
'rgba(221, 85, 85, 1)',
|
||||
brushColor: 'rgba(221, 85, 85, 1)',
|
||||
selectedSegment: null,
|
||||
selectedSegmentation: null,
|
||||
showSegmentationSettings: false,
|
||||
@@ -78,7 +74,7 @@ const SegmentationPanel = ({
|
||||
segmentList: [],
|
||||
cachedSegmentsProperties: [],
|
||||
isLoading: false,
|
||||
isDisabled: true
|
||||
isDisabled: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -112,7 +108,10 @@ const SegmentationPanel = ({
|
||||
* allows us to easily watch the module or the segmentations loading process in any other component
|
||||
* without subscribing to external events.
|
||||
*/
|
||||
document.addEventListener('extensiondicomsegmentationsegloaded', refreshSegmentations);
|
||||
document.addEventListener(
|
||||
'extensiondicomsegmentationsegloaded',
|
||||
refreshSegmentations
|
||||
);
|
||||
|
||||
/*
|
||||
* These are specific to each element;
|
||||
@@ -127,7 +126,10 @@ const SegmentationPanel = ({
|
||||
);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('extensiondicomsegmentationsegloaded', refreshSegmentations);
|
||||
document.removeEventListener(
|
||||
'extensiondicomsegmentationsegloaded',
|
||||
refreshSegmentations
|
||||
);
|
||||
cornerstoneTools.store.state.enabledElements.forEach(enabledElement =>
|
||||
enabledElement.removeEventListener(
|
||||
'cornerstonetoolslabelmapmodified',
|
||||
@@ -169,26 +171,29 @@ const SegmentationPanel = ({
|
||||
selectedSegmentation: brushStackState.activeLabelmapIndex,
|
||||
labelmapList,
|
||||
segmentList,
|
||||
isDisabled
|
||||
isDisabled,
|
||||
}));
|
||||
} else {
|
||||
setState(state => ({
|
||||
...state,
|
||||
labelmapList: [],
|
||||
segmentList: [],
|
||||
isDisabled
|
||||
isDisabled,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, [
|
||||
viewports,
|
||||
activeIndex,
|
||||
state.isLoading
|
||||
]);
|
||||
}, [viewports, activeIndex, state.isLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
refreshSegmentations();
|
||||
}, [viewports, activeIndex, isOpen, state.selectedSegmentation, activeContexts, state.isLoading]);
|
||||
}, [
|
||||
viewports,
|
||||
activeIndex,
|
||||
isOpen,
|
||||
state.selectedSegmentation,
|
||||
activeContexts,
|
||||
state.isLoading,
|
||||
]);
|
||||
|
||||
/* Handle open/closed panel behaviour */
|
||||
useEffect(() => {
|
||||
@@ -223,12 +228,10 @@ const SegmentationPanel = ({
|
||||
title: displayDescription,
|
||||
description: displayDate,
|
||||
onClick: async () => {
|
||||
const activatedLabelmapIndex = await _setActiveLabelmap(
|
||||
const activatedLabelmapIndex = await setActiveLabelmap(
|
||||
activeViewport,
|
||||
studies,
|
||||
displaySet,
|
||||
firstImageId,
|
||||
brushStackState.activeLabelmapIndex,
|
||||
() => onSelectedSegmentationChange(),
|
||||
onDisplaySetLoadFailure
|
||||
);
|
||||
@@ -376,9 +379,13 @@ const SegmentationPanel = ({
|
||||
return !segmentsHidden[segmentIndex];
|
||||
};
|
||||
|
||||
const cachedSegmentProperties = state.cachedSegmentsProperties[segmentNumber];
|
||||
const cachedSegmentProperties =
|
||||
state.cachedSegmentsProperties[segmentNumber];
|
||||
let visible = isSegmentVisible();
|
||||
if (cachedSegmentProperties && cachedSegmentProperties.visible !== visible) {
|
||||
if (
|
||||
cachedSegmentProperties &&
|
||||
cachedSegmentProperties.visible !== visible
|
||||
) {
|
||||
toggleSegmentVisibility();
|
||||
}
|
||||
|
||||
@@ -406,8 +413,10 @@ const SegmentationPanel = ({
|
||||
onSegmentVisibilityChange(segmentNumber, newVisibility);
|
||||
}
|
||||
|
||||
updateCachedSegmentsProperties(segmentNumber, { visible: newVisibility });
|
||||
refreshViewport();
|
||||
updateCachedSegmentsProperties(segmentNumber, {
|
||||
visible: newVisibility,
|
||||
});
|
||||
refreshViewports();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -429,10 +438,9 @@ const SegmentationPanel = ({
|
||||
const segmentsProperties = state.cachedSegmentsProperties;
|
||||
const segmentProperties = state.cachedSegmentsProperties[segmentNumber];
|
||||
|
||||
segmentsProperties[segmentNumber] =
|
||||
segmentProperties ?
|
||||
{ ...segmentProperties, ...properties } :
|
||||
properties;
|
||||
segmentsProperties[segmentNumber] = segmentProperties
|
||||
? { ...segmentProperties, ...properties }
|
||||
: properties;
|
||||
|
||||
updateState('cachedSegmentsProperties', segmentsProperties);
|
||||
};
|
||||
@@ -499,10 +507,13 @@ const SegmentationPanel = ({
|
||||
configuration.fillAlphaInactive = newConfiguration.fillAlphaInactive;
|
||||
configuration.outlineAlphaInactive = newConfiguration.outlineAlphaInactive;
|
||||
onConfigurationChange(newConfiguration);
|
||||
refreshViewport();
|
||||
refreshViewports();
|
||||
};
|
||||
|
||||
const disabledConfigurationFields = ['outlineAlpha', 'shouldRenderInactiveLabelmaps'];
|
||||
const disabledConfigurationFields = [
|
||||
'outlineAlpha',
|
||||
'shouldRenderInactiveLabelmaps',
|
||||
];
|
||||
if (state.showSegmentationSettings) {
|
||||
return (
|
||||
<SegmentationSettings
|
||||
@@ -514,7 +525,10 @@ const SegmentationPanel = ({
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={`dcmseg-segmentation-panel ${state.isDisabled && 'disabled'}`}>
|
||||
<div
|
||||
className={`dcmseg-segmentation-panel ${state.isDisabled &&
|
||||
'disabled'}`}
|
||||
>
|
||||
<Icon
|
||||
className="cog-icon"
|
||||
name="cog"
|
||||
@@ -613,57 +627,6 @@ const _getReferencedSegDisplaysets = (StudyInstanceUID, SeriesInstanceUID) => {
|
||||
return referencedDisplaysets;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param {*} viewportSpecificData
|
||||
* @param {*} studies
|
||||
* @param {*} displaySet
|
||||
* @param {*} firstImageId
|
||||
* @param {*} activeLabelmapIndex
|
||||
* @returns
|
||||
*/
|
||||
const _setActiveLabelmap = async (
|
||||
viewportSpecificData,
|
||||
studies,
|
||||
displaySet,
|
||||
firstImageId,
|
||||
activeLabelmapIndex,
|
||||
callback = () => { },
|
||||
onDisplaySetLoadFailure
|
||||
) => {
|
||||
if (displaySet.labelmapIndex === activeLabelmapIndex) {
|
||||
log.warn(`${activeLabelmapIndex} is already the active labelmap`);
|
||||
return displaySet.labelmapIndex;
|
||||
}
|
||||
|
||||
if (!displaySet.isLoaded) {
|
||||
// What props does this expect `viewportSpecificData` to have?
|
||||
// TODO: Should this return the `labelmapIndex`?
|
||||
|
||||
const loadPromise = displaySet.load(viewportSpecificData, studies);
|
||||
|
||||
loadPromise.catch(error => {
|
||||
onDisplaySetLoadFailure(error);
|
||||
|
||||
// Return old index.
|
||||
return activeLabelmapIndex;
|
||||
});
|
||||
|
||||
await loadPromise;
|
||||
}
|
||||
|
||||
const { state } = cornerstoneTools.getModule('segmentation');
|
||||
const brushStackState = state.series[firstImageId];
|
||||
brushStackState.activeLabelmapIndex = displaySet.labelmapIndex;
|
||||
|
||||
refreshViewport();
|
||||
|
||||
callback();
|
||||
|
||||
return displaySet.labelmapIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} firstImageId
|
||||
@@ -683,7 +646,7 @@ const _setActiveSegment = (firstImageId, segmentIndex, activeSegmentIndex) => {
|
||||
brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
|
||||
labelmap3D.activeSegmentIndex = segmentIndex;
|
||||
|
||||
refreshViewport();
|
||||
refreshViewports();
|
||||
|
||||
return segmentIndex;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { MODULE_TYPES, utils } from '@ohif/core';
|
||||
import loadSegmentation from './loadSegmentation';
|
||||
import getSourceDisplaySet from './getSourceDisplaySet';
|
||||
|
||||
// TODO: Should probably use dcmjs for this
|
||||
const SOP_CLASS_UIDS = {
|
||||
@@ -54,6 +55,10 @@ export default function getSopClassHandlerModule({ servicesManager }) {
|
||||
SeriesDescription,
|
||||
};
|
||||
|
||||
segDisplaySet.getSourceDisplaySet = function(studies) {
|
||||
return getSourceDisplaySet(studies, segDisplaySet);
|
||||
};
|
||||
|
||||
segDisplaySet.load = function(referencedDisplaySet, studies) {
|
||||
return loadSegmentation(segDisplaySet, referencedDisplaySet, studies);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import setActiveLabelmap from './utils/setActiveLabelMap';
|
||||
|
||||
export default function getSourceDisplaySet(studies, segDisplaySet) {
|
||||
const referencedDisplaySet = _getReferencedDisplaySet(segDisplaySet, studies);
|
||||
|
||||
setActiveLabelmap(referencedDisplaySet, studies, segDisplaySet);
|
||||
|
||||
return referencedDisplaySet;
|
||||
}
|
||||
|
||||
const _getReferencedDisplaySet = (segDisplaySet, studies) => {
|
||||
let allDisplaySets = [];
|
||||
|
||||
studies.forEach(study => {
|
||||
allDisplaySets = allDisplaySets.concat(study.displaySets);
|
||||
});
|
||||
|
||||
const otherDisplaySets = allDisplaySets.filter(
|
||||
ds => ds.displaySetInstanceUID !== segDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
|
||||
const ReferencedSeriesSequence = Array.isArray(
|
||||
segDisplaySet.metadata.ReferencedSeriesSequence
|
||||
)
|
||||
? segDisplaySet.metadata.ReferencedSeriesSequence
|
||||
: [segDisplaySet.metadata.ReferencedSeriesSequence];
|
||||
|
||||
const referencedSeriesInstanceUIDs = ReferencedSeriesSequence.map(
|
||||
ReferencedSeries => ReferencedSeries.SeriesInstanceUID
|
||||
);
|
||||
|
||||
const referencedDisplaySet = otherDisplaySets.find(ds =>
|
||||
referencedSeriesInstanceUIDs.includes(ds.SeriesInstanceUID)
|
||||
);
|
||||
|
||||
return referencedDisplaySet;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export default function refreshViewports() {
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { utils, log } from '@ohif/core';
|
||||
import cornerstoneTools from 'cornerstone-tools';
|
||||
import refreshViewports from './refreshViewports';
|
||||
|
||||
const { studyMetadataManager } = utils;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param {*} viewportSpecificData
|
||||
* @param {*} studies
|
||||
* @param {*} displaySet
|
||||
* @param {*} firstImageId
|
||||
* @param {*} activeLabelmapIndex
|
||||
* @returns
|
||||
*/
|
||||
export default async function setActiveLabelmap(
|
||||
referencedDisplaySet,
|
||||
studies,
|
||||
displaySet,
|
||||
callback = () => {},
|
||||
onDisplaySetLoadFailure = err => {
|
||||
throw new Error(err.message);
|
||||
}
|
||||
) {
|
||||
const studyMetadata = studyMetadataManager.get(
|
||||
referencedDisplaySet.StudyInstanceUID
|
||||
);
|
||||
const firstImageId = studyMetadata.getFirstImageId(
|
||||
referencedDisplaySet.displaySetInstanceUID
|
||||
);
|
||||
|
||||
let { state } = cornerstoneTools.getModule('segmentation');
|
||||
|
||||
let brushStackState = state.series[firstImageId];
|
||||
const activeLabelmapIndex = brushStackState
|
||||
? brushStackState.activeLabelmapIndex
|
||||
: undefined;
|
||||
|
||||
if (displaySet.labelmapIndex === activeLabelmapIndex) {
|
||||
log.warn(`${activeLabelmapIndex} is already the active labelmap`);
|
||||
return displaySet.labelmapIndex;
|
||||
}
|
||||
|
||||
if (!displaySet.isLoaded) {
|
||||
const loadPromise = displaySet.load(referencedDisplaySet, studies);
|
||||
|
||||
loadPromise.catch(error => {
|
||||
onDisplaySetLoadFailure(error);
|
||||
|
||||
// Return old index.
|
||||
return activeLabelmapIndex;
|
||||
});
|
||||
|
||||
await loadPromise;
|
||||
}
|
||||
|
||||
// This might have just been created, so need to use the non-cached value.
|
||||
state = cornerstoneTools.getModule('segmentation').state;
|
||||
brushStackState = state.series[firstImageId];
|
||||
brushStackState.activeLabelmapIndex = displaySet.labelmapIndex;
|
||||
|
||||
refreshViewports();
|
||||
callback();
|
||||
|
||||
return displaySet.labelmapIndex;
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
## [1.6.10](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.9...@ohif/extension-vtk@1.6.10) (2020-08-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.6.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.8...@ohif/extension-vtk@1.6.9) (2020-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.6.8](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.7...@ohif/extension-vtk@1.6.8) (2020-07-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-vtk
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-vtk",
|
||||
"version": "1.6.8",
|
||||
"version": "1.6.10",
|
||||
"description": "OHIF extension for VTK.js",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -53,8 +53,8 @@
|
||||
"react-vtkjs-viewport": "^0.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohif/core": "^2.9.13",
|
||||
"@ohif/ui": "^1.5.2",
|
||||
"@ohif/core": "^2.9.14",
|
||||
"@ohif/ui": "^1.5.3",
|
||||
"cornerstone-tools": "4.15.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.0",
|
||||
"dicom-parser": "^1.8.3",
|
||||
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
NODE_MODULES_CACHE="./node_modules"
|
||||
LERNA_CACHE="$NODE_MODULES_CACHE/lerna-cache"
|
||||
|
||||
echo "Running netlify-lerna-cache.sh"
|
||||
mkdir -p "$NODE_MODULES_CACHE/lerna-cache"
|
||||
|
||||
cache_deps() {
|
||||
PACKAGES=$(ls -1 $1)
|
||||
|
||||
for PKG in $PACKAGES
|
||||
do
|
||||
PKG_NODE_MODULES="$1/$PKG/node_modules"
|
||||
if [ -d $PKG_NODE_MODULES ];
|
||||
then
|
||||
mv $PKG_NODE_MODULES $LERNA_CACHE/$PKG
|
||||
echo "Cached node modules for $PKG"
|
||||
else
|
||||
echo "Unable to cache node modules for $PKG"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
cache_deps platform
|
||||
cache_deps extensions
|
||||
cache_deps modes
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
NODE_MODULES_CACHE="./node_modules"
|
||||
LERNA_CACHE="$NODE_MODULES_CACHE/lerna-cache"
|
||||
|
||||
echo "Running netlify-lerna-restore.sh"
|
||||
mkdir -p "$NODE_MODULES_CACHE/lerna-cache"
|
||||
echo "$NODE_MODULES_CACHE/lerna-cache/*"
|
||||
|
||||
restore_deps() {
|
||||
PACKAGES=$(ls -1 $1)
|
||||
|
||||
for PKG in $PACKAGES
|
||||
do
|
||||
PKG_CACHE="$LERNA_CACHE/$PKG"
|
||||
if [ -d $PKG_CACHE ];
|
||||
then
|
||||
mv $PKG_CACHE $1/$PKG/node_modules
|
||||
echo "Restored node modules for $PKG"
|
||||
else
|
||||
echo "Unable to restore cache for $PKG"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
restore_deps platform
|
||||
restore_deps extensions
|
||||
restore_deps modes
|
||||
+6
-7
@@ -8,6 +8,11 @@
|
||||
# managed by CircleCI and deployed to our Google Hosting
|
||||
#
|
||||
|
||||
[build]
|
||||
base = ""
|
||||
publish = ".netlify/www/"
|
||||
command = "chmod +x .netlify/build-deploy-preview.sh && .netlify/build-deploy-preview.sh"
|
||||
|
||||
# NODE_VERSION in root `.nvmrc` takes priority
|
||||
# YARN_FLAGS: https://www.netlify.com/docs/build-gotchas/#yarn
|
||||
[build.environment]
|
||||
@@ -16,19 +21,13 @@
|
||||
YARN_VERSION = "1.17.3"
|
||||
RUBY_VERSION = "2.6.2"
|
||||
YARN_FLAGS = "--no-ignore-optional --pure-lockfile"
|
||||
NETLIFY_RESTORE = "1"
|
||||
|
||||
# Production context: all deploys from the Production branch set in your site's
|
||||
# deploy contexts will inherit these settings.
|
||||
[context.production]
|
||||
ignore = "exit 0" # Never build production; We'll let our CI do that
|
||||
|
||||
# Deploy Preview context: all deploys generated from a pull/merge request will
|
||||
# inherit these settings.
|
||||
[context.deploy-preview]
|
||||
base = ""
|
||||
publish = ".netlify/www/"
|
||||
command = "chmod +x .netlify/build-deploy-preview.sh && .netlify/build-deploy-preview.sh"
|
||||
|
||||
[[headers]]
|
||||
# Define which paths this specific [[headers]] block will cover.
|
||||
for = "/*"
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
"see-changed": "lerna changed",
|
||||
"docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh",
|
||||
"release": "yarn run lerna:version && yarn run lerna:publish",
|
||||
"lerna:cache": "[ $NETLIFY_RESTORE = 1 ] && ./netlify-lerna-cache.sh || :",
|
||||
"lerna:restore": "[ $NETLIFY_RESTORE = 1 ] && ./netlify-lerna-restore.sh || :",
|
||||
"preinstall": "yarn lerna:restore",
|
||||
"lerna:version": "npx lerna version prerelease --force-publish",
|
||||
"lerna:publish": "lerna publish from-package --canary --dist-tag canary",
|
||||
"link-list": "npm ls --depth=0 --link=true"
|
||||
|
||||
@@ -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.14](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.13...@ohif/core@2.9.14) (2020-08-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.9.13](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.12...@ohif/core@2.9.13) (2020-07-22)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/core",
|
||||
"version": "2.9.13",
|
||||
"version": "2.9.14",
|
||||
"description": "Generic business logic for web-based medical imaging applications",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -139,9 +139,11 @@ export class StudyMetadata extends Metadata {
|
||||
if (displaySet) {
|
||||
displaySet.sopClassModule = true;
|
||||
|
||||
displaySet.isDerived
|
||||
? this._addDerivedDisplaySet(displaySet)
|
||||
: displaySets.push(displaySet);
|
||||
if (displaySet.isDerived) {
|
||||
this._addDerivedDisplaySet(displaySet);
|
||||
}
|
||||
|
||||
displaySets.push(displaySet);
|
||||
|
||||
return displaySets;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
## [1.5.3](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.5.2...@ohif/ui@1.5.3) (2020-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/ui
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.5.2](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.5.1...@ohif/ui@1.5.2) (2020-07-22)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
const path = require('path');
|
||||
// ~~ Plugins
|
||||
const PnpWebpackPlugin = require(`pnp-webpack-plugin`); // Required until Webpack@5
|
||||
|
||||
exports.onCreateWebpackConfig = args => {
|
||||
args.actions.setWebpackConfig({
|
||||
node: { fs: 'empty' },
|
||||
resolve: {
|
||||
plugins: [PnpWebpackPlugin],
|
||||
// Note the '..' in the path because docz gatsby project lives in the '.docz' directory
|
||||
modules: [
|
||||
// platform/ui
|
||||
path.resolve(__dirname, '../node_modules'),
|
||||
// .docz
|
||||
'node_modules',
|
||||
],
|
||||
// resolve: {
|
||||
// symlinks: true,
|
||||
// },
|
||||
},
|
||||
resolveLoader: {
|
||||
plugins: [PnpWebpackPlugin.moduleLoader(module)],
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/ui",
|
||||
"version": "1.5.2",
|
||||
"version": "1.5.3",
|
||||
"description": "A set of React components for Medical Imaging Viewers",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [4.2.16](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.15...@ohif/viewer@4.2.16) (2020-08-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.2.15](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.14...@ohif/viewer@4.2.15) (2020-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.2.14](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.13...@ohif/viewer@4.2.14) (2020-08-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.2.13](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.12...@ohif/viewer@4.2.13) (2020-07-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/viewer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.2.12](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.11...@ohif/viewer@4.2.12) (2020-07-22)
|
||||
|
||||
|
||||
|
||||
@@ -115,13 +115,13 @@ Commands to run the tests:
|
||||
|
||||
```js
|
||||
// Open Cypress Dashboard that provides insight into what happened when your tests ran
|
||||
yarn run cy
|
||||
yarn test:e2e
|
||||
|
||||
// Run all tests using Electron browser headless
|
||||
yarn run cy:run
|
||||
yarn test:e2e:local
|
||||
|
||||
// Run all tests in CI mode
|
||||
yarn run cy:run:ci
|
||||
yarn run test:e2e:ci
|
||||
```
|
||||
|
||||
### Contributing
|
||||
|
||||
@@ -12,6 +12,8 @@ describe('OHIF Microscopy Extension', () => {
|
||||
});
|
||||
|
||||
it('drags and drop a SM thumbnail into viewport', () => {
|
||||
// Waiting for series list to load all displaySets (lots of SRs, before defining which dom element to grab.)
|
||||
cy.wait(3000);
|
||||
cy.get('[data-cy="thumbnail-list"]')
|
||||
.contains('SM')
|
||||
.drag('.viewport-drop-target');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/viewer",
|
||||
"version": "4.2.12",
|
||||
"version": "4.2.16",
|
||||
"description": "OHIF Viewer",
|
||||
"author": "OHIF Contributors",
|
||||
"license": "MIT",
|
||||
@@ -48,18 +48,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@ohif/core": "^2.9.13",
|
||||
"@ohif/extension-cornerstone": "^2.8.4",
|
||||
"@ohif/core": "^2.9.14",
|
||||
"@ohif/extension-cornerstone": "^2.8.5",
|
||||
"@ohif/extension-dicom-html": "^1.2.4",
|
||||
"@ohif/extension-dicom-microscopy": "^0.51.0",
|
||||
"@ohif/extension-dicom-p10-downloader": "^0.1.2",
|
||||
"@ohif/extension-dicom-pdf": "^1.0.3",
|
||||
"@ohif/extension-dicom-rt": "^0.2.5",
|
||||
"@ohif/extension-dicom-segmentation": "^0.3.3",
|
||||
"@ohif/extension-dicom-rt": "^0.2.7",
|
||||
"@ohif/extension-dicom-segmentation": "^0.3.4",
|
||||
"@ohif/extension-lesion-tracker": "^0.2.0",
|
||||
"@ohif/extension-vtk": "^1.6.8",
|
||||
"@ohif/extension-vtk": "^1.6.10",
|
||||
"@ohif/i18n": "^0.52.8",
|
||||
"@ohif/ui": "^1.5.2",
|
||||
"@ohif/ui": "^1.5.3",
|
||||
"@tanem/react-nprogress": "^1.1.25",
|
||||
"classnames": "^2.2.6",
|
||||
"core-js": "^3.2.1",
|
||||
|
||||
@@ -80,6 +80,7 @@ const ViewportGrid = function(props) {
|
||||
// - When updating a panel, ensure that the currently enabled plugin
|
||||
// in the viewport is capable of rendering this display set. If not
|
||||
// then use the most capable available plugin
|
||||
|
||||
const pluginName =
|
||||
!layout.plugin && displaySet && displaySet.plugin
|
||||
? displaySet.plugin
|
||||
|
||||
@@ -4,6 +4,8 @@ import { StudyBrowser } from '@ohif/ui';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
import findDisplaySetByUID from './findDisplaySetByUID';
|
||||
|
||||
const { studyMetadataManager } = OHIF.utils;
|
||||
|
||||
const { setActiveViewportSpecificData } = OHIF.redux.actions;
|
||||
|
||||
// TODO
|
||||
@@ -39,11 +41,27 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||
return {
|
||||
onThumbnailClick: displaySetInstanceUID => {
|
||||
const displaySet = findDisplaySetByUID(
|
||||
let displaySet = findDisplaySetByUID(
|
||||
ownProps.studyMetadata,
|
||||
displaySetInstanceUID
|
||||
);
|
||||
|
||||
if (displaySet.isDerived) {
|
||||
const { Modality } = displaySet;
|
||||
|
||||
displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);
|
||||
|
||||
if (!displaySet) {
|
||||
throw new Error(
|
||||
`Referenced series for ${Modality} dataset not present.`
|
||||
);
|
||||
}
|
||||
|
||||
if (!displaySet) {
|
||||
throw new Error('Source data not present');
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(setActiveViewportSpecificData(displaySet));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -133,12 +133,23 @@ class ViewerMain extends Component {
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID,
|
||||
}) => {
|
||||
const displaySet = this.findDisplaySet(
|
||||
let displaySet = this.findDisplaySet(
|
||||
this.props.studies,
|
||||
StudyInstanceUID,
|
||||
displaySetInstanceUID
|
||||
);
|
||||
|
||||
if (displaySet.isDerived) {
|
||||
const { Modality } = displaySet;
|
||||
displaySet = displaySet.getSourceDisplaySet(this.props.studies);
|
||||
|
||||
if (!displaySet) {
|
||||
throw new Error(
|
||||
`Referenced series for ${Modality} dataset not present.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.props.setViewportSpecificData(viewportIndex, displaySet);
|
||||
};
|
||||
|
||||
|
||||
@@ -1247,34 +1247,13 @@
|
||||
pirates "^4.0.0"
|
||||
source-map-support "^0.5.9"
|
||||
|
||||
"@babel/runtime@7.1.2":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.2.tgz#81c89935f4647706fc54541145e6b4ecfef4b8e3"
|
||||
integrity sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.12.0"
|
||||
|
||||
"@babel/runtime@7.6.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.0.tgz#4fc1d642a9fd0299754e8b5de62c631cf5568205"
|
||||
integrity sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5":
|
||||
"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
|
||||
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6":
|
||||
version "7.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c"
|
||||
integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6"
|
||||
@@ -15617,13 +15596,14 @@ react-codemirror2@^6.0.0:
|
||||
resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-6.0.0.tgz#180065df57a64026026cde569a9708fdf7656525"
|
||||
integrity sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag==
|
||||
|
||||
react-cornerstone-viewport@2.3.9:
|
||||
version "2.3.9"
|
||||
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-2.3.9.tgz#f9761da8e536f0a217137c6ca1a983f5882249f9"
|
||||
integrity sha512-qrhq8CbX/jq6b93cQjV2qC/mhHOvFBpxzxcHlvHzEQZt/rmRMcaYxCqjpNaNbUmmBu61wNkxesUVsggkPTTcqg==
|
||||
react-cornerstone-viewport@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-4.0.1.tgz#6a7ec4c01b0626c4ad11552368f3dfa6cd67bdd5"
|
||||
integrity sha512-47YhFsLS5vCWjiOKS9FwLxtA738HIHuNfdn3EJw6GyWD9jwL5HJQ/Ue1mKATjyHRvb3AyJTJuC/lGl0bsqKbYw==
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
date-fns "^2.2.1"
|
||||
lodash.debounce "^4.0.8"
|
||||
prop-types "^15.7.2"
|
||||
react-resize-detector "^4.2.1"
|
||||
|
||||
@@ -16433,11 +16413,6 @@ regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1:
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
|
||||
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
|
||||
|
||||
regenerator-runtime@^0.12.0:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
|
||||
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
|
||||
|
||||
regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4:
|
||||
version "0.13.5"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
|
||||
|
||||
Reference in new issue
Block a user