Compare commits

...

14 Commits

Author SHA1 Message Date
ohif-bot
fa4b03d62d chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.8.2
 - @ohif/extension-dicom-html@1.2.3
 - @ohif/extension-dicom-rt@0.2.1
 - @ohif/extension-dicom-segmentation@0.3.1
 - @ohif/extension-vtk@1.6.3
 - @ohif/core@2.9.8
 - @ohif/viewer@4.2.5
2020-06-15 15:44:36 +00:00
Igor Octaviano
698e900b85
fix: 🐛 Disable seg panel when data for seg unavailable (#1732)
* Add disable state for invalid data

* fix: 🐛 Disable seg panel when data for seg unavailable

We need to gracefully handle errors if data for segmentation is
unavailable and disable the segmentation panel

 Closes: #1728

* Bump dcmjs version

dcmjs
  * @ohif/core: ^0.12.2 → ^0.13.0
  * @ohif/extension-cornerstone: ^0.12.3 → ^0.13.0
  * @ohif/extension-dicom-html: ^0.12.3 → ^0.13.0
  * @ohif/extension-dicom-rt: ^0.12.3 → ^0.13.0
  * @ohif/extension-dicom-segmentation: ^0.12.2 → ^0.13.0
  * @ohif/extension-vtk: ^0.12.2 → ^0.13.0
  * @ohif/viewer: ^0.12.2 → ^0.13.0

* Remove error barrier

* Fix e2e

Co-authored-by: James Petts <jamesapetts@gmail.com>
2020-06-15 16:41:36 +01:00
ohif-bot
b7d47383c5 chore(release): publish [skip ci]
- @ohif/viewer@4.2.4
2020-06-15 12:47:19 +00:00
Rodrigo Antinarelli
6123741765
fix: OIDC Redirect erases query parameters (#1773)
* fix: OIDC Redirect erases query parameters

* prevent issues

Co-authored-by: James Petts <jamesapetts@gmail.com>
2020-06-15 13:43:10 +01:00
ohif-bot
ab25be3520 chore(release): publish [skip ci]
- @ohif/extension-vtk@1.6.2
 - @ohif/ui@1.5.1
 - @ohif/viewer@4.2.3
2020-06-05 16:03:56 +00:00
Rodrigo Antinarelli
950a54c704
Feat/1767 error boundary stack trace (#1772)
* feat: ErrorBoundary collapsed stack trace

* button styles

* Change "Toggle stack trace" to "Stack Trace"

Co-authored-by: James Petts <jamesapetts@gmail.com>
2020-06-05 17:00:36 +01:00
ohif-bot
4293c073f0 chore(release): publish [skip ci]
- @ohif/extension-dicom-p10-downloader@0.1.1
 - @ohif/extension-vtk@1.6.1
 - @ohif/core@2.9.7
 - @ohif/viewer@4.2.2
2020-06-04 11:02:53 +00:00
Emanuel Fiuza de Oliveira
62a2cd5ff3
Fix: #1130 Fixing support for download of an entire study (#1753)
Co-authored-by: James Petts <jamesapetts@gmail.com>
2020-06-04 12:01:05 +01:00
ohif-bot
2d827c2a49 chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.8.1
 - @ohif/viewer@4.2.1
2020-06-04 10:27:47 +00:00
Igor Octaviano
a8305772d0
fix: 🐛 Infinite frame index change when quickly jumping between (#1734)
* Remove debounce and use react-cornerstone-viewport native debounce time

* fix: 🐛 Infinite frame index change when quickly jumping between

This change removes the debounced callback function from the app and
instead uses the native debounce time from react-cornerstone-viewport.
This change allows the application to set its state in a more controled
way.

 Closes: #1733

* Bump rcv version

Co-authored-by: James Petts <jamesapetts@gmail.com>
2020-06-04 11:25:19 +01:00
ohif-bot
eab115e70c chore(release): publish [skip ci]
- @ohif/extension-cornerstone@2.8.0
 - @ohif/extension-dicom-microscopy@0.51.0
 - @ohif/extension-dicom-rt@0.2.0
 - @ohif/extension-dicom-segmentation@0.3.0
 - @ohif/extension-vtk@1.6.0
 - @ohif/ui@1.5.0
 - @ohif/viewer@4.2.0
2020-06-04 09:54:24 +00:00
Rodrigo Antinarelli
c02b232b0c
feat: 🎸 1729 - error boundary wrapper (#1764)
* Add error boundaries

* Fix PWA e2e.

* feat: ErrorBoundaryDialog

* replace component to use ErrorBoundaryDialog

* add proptypes

* fix context

* remove ErrorBoundary from extensions

Co-authored-by: igoroctaviano <igoroctaviano@gmail.com>
Co-authored-by: James A. Petts <jamesapetts@gmail.com>
2020-06-04 10:52:30 +01:00
ohif-bot
f01640d009 chore(release): publish [skip ci]
- @ohif/viewer@4.1.0
2020-05-15 18:59:23 +00:00
Steve Pieper
63fd65690c
feat: expose some app internals as window.app (#1735)
* feat: expose some app internals as window.app

This can help developers explore and access some
internal functionaltiy for debugging in the console.

For example, this command can download the currently
viewed study:

ohif.app.commandsManager.runCommand("downloadAndZip", {listOfUIDs: [window.location.href.split("/").pop()]})

TODO: collect this example and other handy functions on a wiki page

Co-authored-by: dannyrb <danny.ri.brown@gmail.com>

* fix: typo in window.ohif.app assignment

Co-authored-by: dannyrb <danny.ri.brown@gmail.com>
2020-05-15 14:55:54 -04:00
53 changed files with 764 additions and 234 deletions

View File

@ -3,6 +3,39 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.8.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.8.1...@ohif/extension-cornerstone@2.8.2) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
## [2.8.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.8.0...@ohif/extension-cornerstone@2.8.1) (2020-06-04)
### Bug Fixes
* 🐛 Infinite frame index change when quickly jumping between ([#1734](https://github.com/OHIF/Viewers/issues/1734)) ([a830577](https://github.com/OHIF/Viewers/commit/a8305772d0fbec506549ad7ea08504a8bc3a4f39)), closes [#1733](https://github.com/OHIF/Viewers/issues/1733)
# [2.8.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.7.3...@ohif/extension-cornerstone@2.8.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
## [2.7.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-cornerstone@2.7.2...@ohif/extension-cornerstone@2.7.3) (2020-05-12)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-cornerstone",
"version": "2.7.3",
"version": "2.8.2",
"description": "OHIF extension for Cornerstone",
"author": "OHIF",
"license": "MIT",
@ -36,7 +36,7 @@
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "4.15.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.12.3",
"dcmjs": "0.13.0",
"dicom-parser": "^1.8.3",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
@ -51,6 +51,6 @@
"classnames": "^2.2.6",
"lodash.merge": "^4.6.2",
"lodash.throttle": "^4.1.1",
"react-cornerstone-viewport": "2.3.8"
"react-cornerstone-viewport": "2.3.9"
}
}

View File

@ -4,7 +4,6 @@ import ConnectedCornerstoneViewport from './ConnectedCornerstoneViewport';
import OHIF from '@ohif/core';
import PropTypes from 'prop-types';
import cornerstone from 'cornerstone-core';
import debounce from 'lodash.debounce';
const { StackManager } = OHIF.utils;
@ -216,9 +215,10 @@ class OHIFCornerstoneViewport extends Component {
});
}
const debouncedNewImageHandler = debounce(({ currentImageIdIndex, sopInstanceUid }) => {
const newImageHandler = ({ currentImageIdIndex, sopInstanceUid }) => {
const { displaySet } = this.props.viewportData;
const { StudyInstanceUID } = displaySet;
if (currentImageIdIndex > 0) {
this.props.onNewImage({
StudyInstanceUID,
@ -227,7 +227,7 @@ class OHIFCornerstoneViewport extends Component {
activeViewportIndex: viewportIndex,
});
}
}, 700);
};
return (
<>
@ -235,7 +235,8 @@ class OHIFCornerstoneViewport extends Component {
viewportIndex={viewportIndex}
imageIds={imageIds}
imageIdIndex={currentImageIdIndex}
onNewImage={debouncedNewImageHandler}
onNewImage={newImageHandler}
onNewImageDebounceTime={700}
// ~~ Connected (From REDUX)
// frameRate={frameRate}
// isPlaying={false}

View File

@ -39,7 +39,9 @@ export default {
const onNewImageHandler = jumpData => {
commandsManager.runCommand('jumpToImage', jumpData);
};
return <OHIFCornerstoneViewport {...props} onNewImage={onNewImageHandler} />;
return (
<OHIFCornerstoneViewport {...props} onNewImage={onNewImageHandler} />
);
};
return ExtendedOHIFCornerstoneViewport;

View File

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.2.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.2.2...@ohif/extension-dicom-html@1.2.3) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
## [1.2.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-html@1.2.1...@ohif/extension-dicom-html@1.2.2) (2020-05-04)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-html",
"version": "1.2.2",
"version": "1.2.3",
"description": "OHIF extension for rendering structured reports to HTML",
"author": "OHIF",
"license": "MIT",
@ -29,7 +29,7 @@
},
"peerDependencies": {
"@ohif/core": "^0.50.0",
"dcmjs": "^0.12.3",
"dcmjs": "0.13.0",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"

View File

@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.51.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.9...@ohif/extension-dicom-microscopy@0.51.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
## [0.50.9](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-microscopy@0.50.8...@ohif/extension-dicom-microscopy@0.50.9) (2020-04-02)
**Note:** Version bump only for package @ohif/extension-dicom-microscopy

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-microscopy",
"version": "0.50.9",
"version": "0.51.0",
"description": "OHIF extension for Dicom Microscopy",
"author": "OHIF",
"license": "MIT",

View File

@ -92,8 +92,8 @@ class DicomMicroscopyViewport extends Component {
{this.state.error ? (
<h2>{JSON.stringify(this.state.error)}</h2>
) : (
<div style={style} ref={this.container} />
)}
<div style={style} ref={this.container} />
)}
</div>
);
}

View File

@ -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.1.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-p10-downloader@0.1.0...@ohif/extension-dicom-p10-downloader@0.1.1) (2020-06-04)
**Note:** Version bump only for package @ohif/extension-dicom-p10-downloader
# [0.1.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-p10-downloader@0.0.2...@ohif/extension-dicom-p10-downloader@0.1.0) (2020-04-23)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-p10-downloader",
"version": "0.1.0",
"version": "0.1.1",
"description": "OHIF extension for downloading DICOM P10 files",
"author": "OHIF",
"license": "MIT",

View File

@ -2,6 +2,7 @@ import OHIF from '@ohif/core';
import {
save,
getDicomWebClientFromContext,
getStudyInstanceUIDFromStudies,
getSOPInstanceReferenceFromActiveViewport,
getSOPInstanceReferencesFromViewports,
} from './utils';
@ -41,6 +42,14 @@ export function getCommands(context) {
listOfUIDs
);
},
downloadAndZipStudy({ servers, studies, progress }) {
const dicomWebClient = getDicomWebClientFromContext(context, servers);
const listOfUIDs = getStudyInstanceUIDFromStudies(studies);
return save(
_downloadAndZip(dicomWebClient, listOfUIDs, { progress }),
listOfUIDs
);
},
downloadAndZipSeriesOnViewports({ servers, viewports, progress }) {
const dicomWebClient = getDicomWebClientFromContext(context, servers);
const listOfUIDs = getSOPInstanceReferencesFromViewports(viewports);
@ -64,6 +73,11 @@ export function getCommands(context) {
commandFn: queue.bindSafe(actions.downloadAndZip, error),
storeContexts: ['servers'],
},
downloadAndZipStudy: {
commandFn: queue.bindSafe(actions.downloadAndZipStudy, error),
storeContexts: ['servers', 'studies'],
options: { progress },
},
downloadAndZipSeriesOnViewports: {
commandFn: queue.bindSafe(actions.downloadAndZipSeriesOnViewports, error),
storeContexts: ['servers', 'viewports'],

View File

@ -100,11 +100,16 @@ function save(promise, listOfUIDs) {
});
}
function getStudyInstanceUIDFromStudies(studies) {
return Object.keys(Object(Object(studies).studyData)).slice(0, 1);
}
export {
save,
validDicomUid,
getDicomWebClientFromConfig,
getDicomWebClientFromContext,
getStudyInstanceUIDFromStudies,
getSOPInstanceReferenceFromActiveViewport,
getSOPInstanceReferencesFromViewports,
};

View File

@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.2.0...@ohif/extension-dicom-rt@0.2.1) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
# [0.2.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.1.4...@ohif/extension-dicom-rt@0.2.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
## [0.1.4](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-rt@0.1.3...@ohif/extension-dicom-rt@0.1.4) (2020-05-14)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-rt",
"version": "0.1.4",
"version": "0.2.1",
"description": "OHIF extension for rendering DICOM RTSTRUCTs on top of cornerstone images.",
"author": "OHIF",
"license": "MIT",
@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "4.15.1",
"dcmjs": "^0.12.3",
"dcmjs": "0.13.0",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"

View File

@ -31,7 +31,18 @@ const refreshViewport = () => {
* @param {number} props.isOpen - isOpen
* @returns component
*/
const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }) => {
const RTPanel = ({
studies,
viewports,
activeIndex,
isOpen,
onContourItemClick,
activeContexts = [],
contexts = {}
}) => {
const isVTK = () => activeContexts.includes(contexts.VTK);
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
const [selectedContour, setSelectedContour] = useState();
const DEFAULT_SET_INDEX = 0;
const DEFAULT_STATE = {
@ -119,33 +130,35 @@ const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }
onClick={() => {
setSelectedContour(isSameContour ? null : ROINumber);
const enabledElements = cornerstone.getEnabledElements();
const element = enabledElements[activeIndex].element;
const toolState = cornerstoneTools.getToolState(element, 'stack');
if (isCornerstone()) {
const enabledElements = cornerstone.getEnabledElements();
const element = enabledElements[activeIndex].element;
const toolState = cornerstoneTools.getToolState(element, 'stack');
if (!toolState) {
return;
if (!toolState) {
return;
}
const imageIds = toolState.data[0].imageIds;
const module = cornerstoneTools.getModule('rtstruct');
const imageId = module.getters.imageIdOfCenterFrameOfROIContour(
state.selectedSet.SeriesInstanceUID,
ROINumber,
imageIds
);
const frameIndex = imageIds.indexOf(imageId);
const SOPInstanceUID = cornerstone.metaData.get('SOPInstanceUID', imageId);
const StudyInstanceUID = cornerstone.metaData.get('StudyInstanceUID', imageId);
onContourItemClick({
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
activeViewportIndex: activeIndex
});
}
const imageIds = toolState.data[0].imageIds;
const module = cornerstoneTools.getModule('rtstruct');
const imageId = module.getters.imageIdOfCenterFrameOfROIContour(
state.selectedSet.SeriesInstanceUID,
ROINumber,
imageIds
);
const frameIndex = imageIds.indexOf(imageId);
const SOPInstanceUID = cornerstone.metaData.get('SOPInstanceUID', imageId);
const StudyInstanceUID = cornerstone.metaData.get('StudyInstanceUID', imageId);
onContourItemClick({
StudyInstanceUID,
SOPInstanceUID,
frameIndex,
activeViewportIndex: activeIndex
});
}}
label={`${ROIName} ${interpretedType}`}
index={ROINumber}

View File

@ -20,14 +20,21 @@ export default {
preRegistration({ servicesManager, configuration = {} }) {
init({ servicesManager, configuration });
},
getPanelModule({ commandsManager }) {
getPanelModule({ commandsManager, api }) {
const ExtendedRTPanel = props => {
const { activeContexts } = api.hooks.useAppContext();
const contourItemClickHandler = contourData => {
commandsManager.runCommand('jumpToImage', contourData);
};
return (
<RTPanel {...props} onContourItemClick={contourItemClickHandler} />
<RTPanel
{...props}
onContourItemClick={contourItemClickHandler}
activeContexts={activeContexts}
contexts={api.contexts}
/>
);
};

View File

@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.3.0...@ohif/extension-dicom-segmentation@0.3.1) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
# [0.3.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.2.6...@ohif/extension-dicom-segmentation@0.3.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
## [0.2.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-dicom-segmentation@0.2.5...@ohif/extension-dicom-segmentation@0.2.6) (2020-05-12)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-dicom-segmentation",
"version": "0.2.6",
"version": "0.3.1",
"description": "OHIF extension for viewing segmentations in the 2D MPR view",
"author": "OHIF",
"license": "MIT",
@ -31,7 +31,7 @@
"@ohif/core": "^0.50.0",
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "4.15.1",
"dcmjs": "^0.12.2",
"dcmjs": "0.13.0",
"prop-types": "^15.6.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"

View File

@ -8,6 +8,11 @@
flex-direction: column;
}
.dcmseg-segmentation-panel.disabled {
opacity: 0.6;
pointer-events: none;
}
.dcmseg-segmentation-panel h3 {
padding-left: 20px;
margin-top: 0;

View File

@ -49,8 +49,8 @@ const SegmentationPanel = ({
onConfigurationChange,
onDisplaySetLoadFailure,
onSelectedSegmentationChange,
activeContexts,
contexts,
activeContexts = [],
contexts = {},
}) => {
const isVTK = () => activeContexts.includes(contexts.VTK);
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
@ -77,7 +77,8 @@ const SegmentationPanel = ({
labelmapList: [],
segmentList: [],
cachedSegmentsProperties: [],
isLoading: false
isLoading: false,
isDisabled: true
});
useEffect(() => {
@ -139,39 +140,45 @@ const SegmentationPanel = ({
const refreshSegmentations = useCallback(() => {
const module = cornerstoneTools.getModule('segmentation');
const activeViewport = viewports[activeIndex];
const studyMetadata = studyMetadataManager.get(
activeViewport.StudyInstanceUID
);
const firstImageId = studyMetadata.getFirstImageId(
activeViewport.displaySetInstanceUID
);
const brushStackState = module.state.series[firstImageId];
if (brushStackState) {
const labelmap3D =
brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
const labelmapList = getLabelmapList(
brushStackState,
firstImageId,
activeViewport
const isDisabled = !activeViewport || !activeViewport.StudyInstanceUID;
if (!isDisabled) {
const studyMetadata = studyMetadataManager.get(
activeViewport.StudyInstanceUID
);
const segmentList = getSegmentList(
labelmap3D,
firstImageId,
brushStackState
const firstImageId = studyMetadata.getFirstImageId(
activeViewport.displaySetInstanceUID
);
setState(state => ({
...state,
brushStackState,
selectedSegmentation: brushStackState.activeLabelmapIndex,
labelmapList,
segmentList,
}));
} else {
setState(state => ({
...state,
labelmapList: [],
segmentList: [],
}));
const brushStackState = module.state.series[firstImageId];
if (brushStackState) {
const labelmap3D =
brushStackState.labelmaps3D[brushStackState.activeLabelmapIndex];
const labelmapList = getLabelmapList(
brushStackState,
firstImageId,
activeViewport
);
const segmentList = getSegmentList(
labelmap3D,
firstImageId,
brushStackState
);
setState(state => ({
...state,
brushStackState,
selectedSegmentation: brushStackState.activeLabelmapIndex,
labelmapList,
segmentList,
isDisabled
}));
} else {
setState(state => ({
...state,
labelmapList: [],
segmentList: [],
isDisabled
}));
}
}
}, [
viewports,
@ -181,7 +188,7 @@ const SegmentationPanel = ({
useEffect(() => {
refreshSegmentations();
}, [viewports, activeIndex, state.selectedSegmentation, activeContexts, state.isLoading]);
}, [viewports, activeIndex, isOpen, state.selectedSegmentation, activeContexts, state.isLoading]);
/* Handle open/closed panel behaviour */
useEffect(() => {
@ -507,7 +514,7 @@ const SegmentationPanel = ({
);
} else {
return (
<div className="dcmseg-segmentation-panel">
<div className={`dcmseg-segmentation-panel ${state.isDisabled && 'disabled'}`}>
<Icon
className="cog-icon"
name="cog"

View File

@ -24,7 +24,7 @@ export default {
return toolbarModule;
},
getPanelModule({ commandsManager, api, servicesManager }) {
const { UINotificationService } = servicesManager;
const { UINotificationService } = servicesManager.services;
const ExtendedSegmentationPanel = props => {
const { activeContexts } = api.hooks.useAppContext();
@ -46,7 +46,7 @@ export default {
const onSegmentVisibilityChangeHandler = (segmentNumber, visible) => {
commandsManager.runCommand('setSegmentConfiguration', {
segmentNumber,
visible
visible,
});
};
@ -55,7 +55,7 @@ export default {
globalOpacity: configuration.fillAlpha,
outlineThickness: configuration.outlineWidth,
renderOutline: configuration.renderOutline,
visible: configuration.renderFill
visible: configuration.renderFill,
});
};

View File

@ -3,6 +3,44 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.3](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.2...@ohif/extension-vtk@1.6.3) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
## [1.6.2](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.1...@ohif/extension-vtk@1.6.2) (2020-06-05)
**Note:** Version bump only for package @ohif/extension-vtk
## [1.6.1](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.6.0...@ohif/extension-vtk@1.6.1) (2020-06-04)
**Note:** Version bump only for package @ohif/extension-vtk
# [1.6.0](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.5.6...@ohif/extension-vtk@1.6.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
## [1.5.6](https://github.com/OHIF/Viewers/compare/@ohif/extension-vtk@1.5.5...@ohif/extension-vtk@1.5.6) (2020-05-14)
**Note:** Version bump only for package @ohif/extension-vtk

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/extension-vtk",
"version": "1.5.6",
"version": "1.6.3",
"description": "OHIF extension for VTK.js",
"author": "OHIF",
"license": "MIT",
@ -35,7 +35,7 @@
"cornerstone-core": "^2.2.8",
"cornerstone-tools": "4.15.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.12.2",
"dcmjs": "0.13.0",
"dicom-parser": "^1.8.3",
"i18next": "^17.0.3",
"i18next-browser-languagedetector": "^3.0.1",
@ -53,8 +53,8 @@
"react-vtkjs-viewport": "^0.9.0"
},
"devDependencies": {
"@ohif/core": "^2.9.6",
"@ohif/ui": "^1.4.4",
"@ohif/core": "^2.9.8",
"@ohif/ui": "^1.5.1",
"cornerstone-tools": "4.15.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dicom-parser": "^1.8.3",

View File

@ -1,3 +1,4 @@
import React from 'react';
import asyncComponent from './asyncComponent.js';
import commandsModule from './commandsModule.js';
import toolbarModule from './toolbarModule.js';
@ -16,7 +17,8 @@ const vtkExtension = {
id: 'vtk',
getViewportModule({ commandsManager }) {
return withCommandsManager(OHIFVTKViewport, commandsManager);
const ExtendedVTKViewport = props => <OHIFVTKViewport {...props} />;
return withCommandsManager(ExtendedVTKViewport, commandsManager);
},
getToolbarModule() {
return toolbarModule;

View File

@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.9.8](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.7...@ohif/core@2.9.8) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
## [2.9.7](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.6...@ohif/core@2.9.7) (2020-06-04)
**Note:** Version bump only for package @ohif/core
## [2.9.6](https://github.com/OHIF/Viewers/compare/@ohif/core@2.9.5...@ohif/core@2.9.6) (2020-05-14)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/core",
"version": "2.9.6",
"version": "2.9.8",
"description": "Generic business logic for web-based medical imaging applications",
"author": "OHIF Core Team",
"license": "MIT",
@ -39,7 +39,7 @@
"dependencies": {
"@babel/runtime": "^7.5.5",
"ajv": "^6.10.0",
"dcmjs": "^0.12.2",
"dcmjs": "0.13.0",
"dicomweb-client": "^0.6.0",
"immer": "6.0.2",
"isomorphic-base64": "^1.0.2",

View File

@ -13,7 +13,7 @@ const findMostRecentStructuredReport = studies => {
// Skip series that may not have instances yet
// This can happen if we have retrieved just the initial
// details about the series via QIDO-RS, but not the full metadata
if (!series.instances.length) {
if (!series.instances || !series.instances.length) {
return;
}

View File

@ -6,11 +6,12 @@ const defaultState = {
const servers = (state = defaultState, action) => {
switch (action.type) {
case 'SET_STUDY_DATA':
const updatedStudyData = cloneDeep(state).studyData;
updatedStudyData[action.StudyInstanceUID] = action.data;
case 'SET_STUDY_DATA': {
const updatedStudyData = cloneDeep(state.studyData);
updatedStudyData[action.StudyInstanceUID] = cloneDeep(action.data);
return Object.assign({}, state, { studyData: updatedStudyData });
}
default:
return state;
}

View File

@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.5.1](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.5.0...@ohif/ui@1.5.1) (2020-06-05)
**Note:** Version bump only for package @ohif/ui
# [1.5.0](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.4.4...@ohif/ui@1.5.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
## [1.4.4](https://github.com/OHIF/Viewers/compare/@ohif/ui@1.4.3...@ohif/ui@1.4.4) (2020-05-04)

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/ui",
"version": "1.4.4",
"version": "1.5.1",
"description": "A set of React components for Medical Imaging Viewers",
"author": "OHIF Contributors",
"license": "MIT",
@ -53,6 +53,7 @@
"react-dnd-html5-backend": "^9.4.0",
"react-dnd-touch-backend": "^9.4.0",
"react-draggable": "^4.1.0",
"react-error-boundary": "^2.2.1",
"react-i18next": "^10.11.0",
"react-modal": "^3.11.1",
"react-with-direction": "1.3.0"

View File

@ -0,0 +1,51 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ErrorBoundary } from 'react-error-boundary';
import './ErrorFallback.css';
const ErrorFallback = ({ error, componentStack, resetErrorBoundary }) => {
return (
<div className="ErrorFallback" role="alert">
<p>Something went wrong.</p>
<pre>{error.message}</pre>
<pre>{componentStack}</pre>
</div>
);
};
const OHIFErrorBoundary = ({
context = 'OHIF',
onReset = () => {},
onError = () => {},
fallbackComponent,
children,
}) => {
const onErrorHandler = (error, componentStack) => {
console.error(`${context} Error Boundary`, error, componentStack);
onError(error, componentStack);
};
const onResetHandler = () => {
onReset();
};
return (
<ErrorBoundary
FallbackComponent={fallbackComponent || ErrorFallback}
onReset={onResetHandler}
onError={onErrorHandler}
>
{children}
</ErrorBoundary>
);
};
OHIFErrorBoundary.propTypes = {
context: PropTypes.string,
onReset: PropTypes.func,
onError: PropTypes.func,
children: PropTypes.node.isRequired,
fallbackComponent: PropTypes.element,
};
export default OHIFErrorBoundary;

View File

@ -0,0 +1,4 @@
.ErrorFallback {
padding: 10px;
color: var(--active-color);
}

View File

@ -0,0 +1 @@
export { default as ErrorBoundary } from './ErrorBoundary';

View File

@ -7,7 +7,6 @@ import { AboutContent } from './content/aboutContent/AboutContent';
import { TabComponents, TabFooter } from './tabComponents';
import { HotkeyField } from './customForm';
import { LanguageSwitcher } from './languageSwitcher';
import { Checkbox } from './checkbox';
import { CineDialog } from './cineDialog';
import { ViewportDownloadForm } from './content/viewportDownloadForm';
@ -25,8 +24,10 @@ import {
} from './studyList';
import { ToolbarSection } from './toolbarSection';
import { Tooltip } from './tooltip';
import { ErrorBoundary } from './errorBoundary';
export {
ErrorBoundary,
ContextMenu,
Checkbox,
CineDialog,

View File

@ -51,3 +51,9 @@ button.close
position: relative;
display: inline-block;
vertical-align: middle;
.btn-sm
padding: .25rem .5rem;
font-size: .875rem;
line-height: 1.5;
border-radius: .2rem;

View File

@ -29,6 +29,7 @@ import {
Tooltip,
AboutContent,
OHIFModal,
ErrorBoundary
} from './components';
import { useDebounce, useMedia } from './hooks';
@ -123,6 +124,7 @@ export {
DialogProvider,
withDialog,
useDialog,
ErrorBoundary,
// Hooks
useDebounce,
useMedia,

View File

@ -3,6 +3,74 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.2.5](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.4...@ohif/viewer@4.2.5) (2020-06-15)
### Bug Fixes
* 🐛 Disable seg panel when data for seg unavailable ([#1732](https://github.com/OHIF/Viewers/issues/1732)) ([698e900](https://github.com/OHIF/Viewers/commit/698e900b85121d3c2a46747c443ef69fb7a8c95b)), closes [#1728](https://github.com/OHIF/Viewers/issues/1728)
## [4.2.4](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.3...@ohif/viewer@4.2.4) (2020-06-15)
### Bug Fixes
* OIDC Redirect erases query parameters ([#1773](https://github.com/OHIF/Viewers/issues/1773)) ([6123741](https://github.com/OHIF/Viewers/commit/6123741765e81d0bea8fbd5dbb0f310aaca0fb33))
## [4.2.3](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.2...@ohif/viewer@4.2.3) (2020-06-05)
**Note:** Version bump only for package @ohif/viewer
## [4.2.2](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.1...@ohif/viewer@4.2.2) (2020-06-04)
**Note:** Version bump only for package @ohif/viewer
## [4.2.1](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.2.0...@ohif/viewer@4.2.1) (2020-06-04)
**Note:** Version bump only for package @ohif/viewer
# [4.2.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.1.0...@ohif/viewer@4.2.0) (2020-06-04)
### Features
* 🎸 1729 - error boundary wrapper ([#1764](https://github.com/OHIF/Viewers/issues/1764)) ([c02b232](https://github.com/OHIF/Viewers/commit/c02b232b0cc24f38af5d5e3831d987d048e60ada))
# [4.1.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@4.0.0...@ohif/viewer@4.1.0) (2020-05-15)
### Features
* expose some app internals as window.app ([#1735](https://github.com/OHIF/Viewers/issues/1735)) ([63fd656](https://github.com/OHIF/Viewers/commit/63fd65690cba450721870a6222e0fb3ad71bb291))
# [4.0.0](https://github.com/OHIF/Viewers/compare/@ohif/viewer@3.11.11...@ohif/viewer@4.0.0) (2020-05-14)

View File

@ -52,7 +52,7 @@ describe('OHIF Study List', function() {
//Wait result list to be displayed
cy.waitStudyList();
cy.get('@searchResult').should($list => {
expect($list.length).to.be.eq(15); // TODO: Where are you hiding MISTER^MR?
expect($list.length).to.be.eq(16); // TODO: Where are you hiding MISTER^MR?
expect($list).to.contain('MR');
});
});
@ -147,7 +147,7 @@ describe('OHIF Study List', function() {
//Wait result list to be displayed
cy.waitStudyList();
cy.get('@searchResult').should($list => {
expect($list.length).to.be.eq(15); // TODO: Where are you hiding MISTER^MR?
expect($list.length).to.be.eq(16); // TODO: Where are you hiding MISTER^MR?
expect($list).to.contain('MR');
});
});

View File

@ -1,7 +1,7 @@
describe('OHIF Microscopy Extension', () => {
before(() => {
cy.openStudyModality('SM');
cy.expectMinimumThumbnails(6);
cy.expectMinimumThumbnails(2);
});
it('checks if series thumbnails are being displayed', () => {

View File

@ -1,6 +1,6 @@
{
"name": "@ohif/viewer",
"version": "4.0.0",
"version": "4.2.5",
"description": "OHIF Viewer",
"author": "OHIF Contributors",
"license": "MIT",
@ -48,18 +48,18 @@
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"@ohif/core": "^2.9.6",
"@ohif/extension-cornerstone": "^2.7.3",
"@ohif/extension-dicom-html": "^1.2.2",
"@ohif/extension-dicom-microscopy": "^0.50.9",
"@ohif/extension-dicom-p10-downloader": "^0.1.0",
"@ohif/core": "^2.9.8",
"@ohif/extension-cornerstone": "^2.8.2",
"@ohif/extension-dicom-html": "^1.2.3",
"@ohif/extension-dicom-microscopy": "^0.51.0",
"@ohif/extension-dicom-p10-downloader": "^0.1.1",
"@ohif/extension-dicom-pdf": "^1.0.3",
"@ohif/extension-dicom-rt": "^0.1.4",
"@ohif/extension-dicom-segmentation": "^0.2.6",
"@ohif/extension-dicom-rt": "^0.2.1",
"@ohif/extension-dicom-segmentation": "^0.3.1",
"@ohif/extension-lesion-tracker": "^0.2.0",
"@ohif/extension-vtk": "^1.5.6",
"@ohif/extension-vtk": "^1.6.3",
"@ohif/i18n": "^0.52.8",
"@ohif/ui": "^1.4.4",
"@ohif/ui": "^1.5.1",
"@tanem/react-nprogress": "^1.1.25",
"classnames": "^2.2.6",
"core-js": "^3.2.1",
@ -67,7 +67,7 @@
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "4.15.1",
"cornerstone-wado-image-loader": "^3.1.0",
"dcmjs": "^0.12.2",
"dcmjs": "0.13.0",
"dicom-parser": "^1.8.3",
"dicomweb-client": "^0.4.4",
"hammerjs": "^2.0.8",

View File

@ -13,6 +13,7 @@ import {
ModalProvider,
DialogProvider,
OHIFModal,
ErrorBoundary
} from '@ohif/ui';
import {
@ -71,6 +72,14 @@ let extensionManager;
// TODO[react] Use a provider when the whole tree is React
window.store = store;
window.ohif = window.ohif || {};
window.ohif.app = {
commandsManager,
hotkeysManager,
servicesManager,
extensionManager,
};
class App extends Component {
static propTypes = {
config: PropTypes.oneOfType([
@ -159,53 +168,57 @@ class App extends Component {
if (this._userManager) {
return (
<Provider store={store}>
<AppProvider config={this._appConfig}>
<I18nextProvider i18n={i18n}>
<OidcProvider store={store} userManager={this._userManager}>
<UserManagerContext.Provider value={this._userManager}>
<Router basename={routerBasename}>
<WhiteLabelingContext.Provider value={whiteLabeling}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider
modal={OHIFModal}
service={UIModalService}
>
<OHIFStandaloneViewer
userManager={this._userManager}
/>
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</WhiteLabelingContext.Provider>
</Router>
</UserManagerContext.Provider>
</OidcProvider>
</I18nextProvider>
</AppProvider>
</Provider>
<ErrorBoundary context='App'>
<Provider store={store}>
<AppProvider config={this._appConfig}>
<I18nextProvider i18n={i18n}>
<OidcProvider store={store} userManager={this._userManager}>
<UserManagerContext.Provider value={this._userManager}>
<Router basename={routerBasename}>
<WhiteLabelingContext.Provider value={whiteLabeling}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider
modal={OHIFModal}
service={UIModalService}
>
<OHIFStandaloneViewer
userManager={this._userManager}
/>
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</WhiteLabelingContext.Provider>
</Router>
</UserManagerContext.Provider>
</OidcProvider>
</I18nextProvider>
</AppProvider>
</Provider>
</ErrorBoundary>
);
}
return (
<Provider store={store}>
<AppProvider config={this._appConfig}>
<I18nextProvider i18n={i18n}>
<Router basename={routerBasename}>
<WhiteLabelingContext.Provider value={whiteLabeling}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider modal={OHIFModal} service={UIModalService}>
<OHIFStandaloneViewer />
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</WhiteLabelingContext.Provider>
</Router>
</I18nextProvider>
</AppProvider>
</Provider>
<ErrorBoundary context='App'>
<Provider store={store}>
<AppProvider config={this._appConfig}>
<I18nextProvider i18n={i18n}>
<Router basename={routerBasename}>
<WhiteLabelingContext.Provider value={whiteLabeling}>
<SnackbarProvider service={UINotificationService}>
<DialogProvider service={UIDialogService}>
<ModalProvider modal={OHIFModal} service={UIModalService}>
<OHIFStandaloneViewer />
</ModalProvider>
</DialogProvider>
</SnackbarProvider>
</WhiteLabelingContext.Provider>
</Router>
</I18nextProvider>
</AppProvider>
</Provider>
</ErrorBoundary>
);
}

View File

@ -5,7 +5,7 @@ import { Route, Switch } from 'react-router-dom';
import { NProgress } from '@tanem/react-nprogress';
import { CSSTransition } from 'react-transition-group';
import { connect } from 'react-redux';
import { ViewerbaseDragDropContext } from '@ohif/ui';
import { ViewerbaseDragDropContext, ErrorBoundary } from '@ohif/ui';
import { SignoutCallbackComponent } from 'redux-oidc';
import asyncComponent from './components/AsyncComponent.js';
import * as RoutesUtil from './routes/routesUtil';
@ -52,10 +52,13 @@ class OHIFStandaloneViewer extends Component {
const { appConfig = {} } = this.context;
const userNotLoggedIn = userManager && (!user || user.expired);
if (userNotLoggedIn) {
const pathname = this.props.location.pathname;
const { pathname, search } = this.props.location;
if (pathname !== '/callback') {
sessionStorage.setItem('ohif-redirect-to', pathname);
sessionStorage.setItem(
'ohif-redirect-to',
JSON.stringify({ pathname, search })
);
}
return (
@ -103,12 +106,21 @@ class OHIFStandaloneViewer extends Component {
userManager.removeUser().then(() => {
if (targetLinkUri !== null) {
const ohifRedirectTo = {
pathname: new URL(targetLinkUri).pathname,
};
sessionStorage.setItem(
'ohif-redirect-to',
new URL(targetLinkUri).pathname
JSON.stringify(ohifRedirectTo)
);
} else {
sessionStorage.setItem('ohif-redirect-to', '/');
const ohifRedirectTo = {
pathname: '/',
};
sessionStorage.setItem(
'ohif-redirect-to',
JSON.stringify(ohifRedirectTo)
);
}
if (loginHint !== null) {
@ -191,8 +203,10 @@ class OHIFStandaloneViewer extends Component {
{match === null ? (
<></>
) : (
<ErrorBoundary context={match.url}>
<Component match={match} location={this.props.location} />
)}
</ErrorBoundary>
)}
</CSSTransition>
)}
</Route>

View File

@ -0,0 +1,18 @@
.ErrorBoundaryDialogTitle {
margin-top: 0;
}
.ErrorBoundaryDialogButton {
outline: none;
}
.ErrorBoundaryDialogIcon {
margin-right: 5px;
width: 10px;
transform: rotate(-90deg);
vertical-align: middle;
}
.ErrorBoundaryDialogIcon.opened {
transform: rotate(0deg);
}

View File

@ -0,0 +1,72 @@
import React, { useState } from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { ErrorBoundary, Icon } from '@ohif/ui';
import { servicesManager } from './../../App';
import './ErrorBoundaryDialog.css';
const { UIModalService } = servicesManager.services;
const ErrorBoundaryDialog = ({ context, children }) => {
const handleOnError = (error, componentStack) => {
const ErrorDialog = () => {
const [open, setOpen] = useState(false);
return (
<div className="ErrorFallback" role="alert">
<div className="ErrorBoundaryDialog">
<h3 className="ErrorBoundaryDialogTitle">
{context}: <span>{error.message}</span>
</h3>
</div>
<button
className="btn btn-primary btn-sm ErrorBoundaryDialogButton"
onClick={() => setOpen(s => !s)}
>
<Icon
name="chevron-down"
className={classnames('ErrorBoundaryDialogIcon', {
opened: open,
})}
/>
Stack Trace
</button>
{open && <pre>{componentStack}</pre>}
</div>
);
};
UIModalService.show({
content: ErrorDialog,
title: `Something went wrong in ${context}`,
});
};
const fallbackComponent = () => (
<div className="ErrorFallback" role="alert">
<p>
Error rendering {context}. <br /> Check the browser console for more
details.
</p>
</div>
);
return (
<ErrorBoundary
fallbackComponent={fallbackComponent}
context={context}
onError={handleOnError}
>
{children}
</ErrorBoundary>
);
};
ErrorBoundaryDialog.propTypes = {
context: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
};
export default ErrorBoundaryDialog;

View File

@ -0,0 +1,3 @@
import ErrorBoundaryDialog from './ErrorBoundaryDialog';
export default ErrorBoundaryDialog;

View File

@ -12,7 +12,7 @@ import EmptyViewport from './EmptyViewport.js';
const { loadAndCacheDerivedDisplaySets } = utils;
const ViewportGrid = function (props) {
const ViewportGrid = function(props) {
const {
activeViewportIndex,
availablePlugins,
@ -24,7 +24,7 @@ const ViewportGrid = function (props) {
studies,
viewportData,
children,
isStudyLoaded
isStudyLoaded,
} = props;
const rowSize = 100 / numRows;
@ -54,7 +54,7 @@ const ViewportGrid = function (props) {
});
});
}
}, [studies, viewportData, isStudyLoaded]);
}, [studies, viewportData, isStudyLoaded, snackbar]);
const getViewportPanes = () =>
layout.viewports.map((layout, viewportIndex) => {

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import './ViewportPane.css';
const ViewportPane = function(props) {
const ViewportPane = function (props) {
const { children, onDrop, viewportIndex, className: propClassName } = props;
const [{ hovered, highlighted }, drop] = useDrop({
accept: 'thumbnail',

View File

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import ViewerRetrieveStudyData from './ViewerRetrieveStudyData.js';
import OHIF from '@ohif/core';
const { clearViewportSpecificData } = OHIF.redux.actions;
const { clearViewportSpecificData, setStudyData } = OHIF.redux.actions;
const isActive = a => a.active === true;
const mapStateToProps = (state, ownProps) => {
@ -14,6 +14,9 @@ const mapStateToProps = (state, ownProps) => {
};
const mapDispatchToProps = dispatch => {
return {
setStudyData: (StudyInstanceUID, data) => {
dispatch(setStudyData(StudyInstanceUID, data));
},
clearViewportSpecificData: () => {
dispatch(clearViewportSpecificData());
},

View File

@ -2,8 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { MODULE_TYPES } from '@ohif/core';
import OHIF, { DICOMSR } from '@ohif/core';
import OHIF, { MODULE_TYPES, DICOMSR } from '@ohif/core';
import { withDialog } from '@ohif/ui';
import moment from 'moment';
import ConnectedHeader from './ConnectedHeader.js';
@ -11,6 +10,7 @@ import ToolbarRow from './ToolbarRow.js';
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
import ConnectedViewerMain from './ConnectedViewerMain.js';
import SidePanel from './../components/SidePanel.js';
import ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';
import { extensionManager } from './../App.js';
// Contexts
@ -26,6 +26,7 @@ class Viewer extends Component {
PropTypes.shape({
StudyInstanceUID: PropTypes.string.isRequired,
StudyDate: PropTypes.string,
PatientID: PropTypes.string,
displaySets: PropTypes.arrayOf(
PropTypes.shape({
displaySetInstanceUID: PropTypes.string.isRequired,
@ -256,42 +257,44 @@ class Viewer extends Component {
</WhiteLabelingContext.Consumer>
{/* TOOLBAR */}
<ToolbarRow
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
selectedLeftSidePanel={
this.state.isLeftSidePanelOpen
? this.state.selectedLeftSidePanel
: ''
}
selectedRightSidePanel={
this.state.isRightSidePanelOpen
? this.state.selectedRightSidePanel
: ''
}
handleSidePanelChange={(side, selectedPanel) => {
const sideClicked = side && side[0].toUpperCase() + side.slice(1);
const openKey = `is${sideClicked}SidePanelOpen`;
const selectedKey = `selected${sideClicked}SidePanel`;
const updatedState = Object.assign({}, this.state);
const isOpen = updatedState[openKey];
const prevSelectedPanel = updatedState[selectedKey];
// RoundedButtonGroup returns `null` if selected button is clicked
const isSameSelectedPanel =
prevSelectedPanel === selectedPanel || selectedPanel === null;
updatedState[selectedKey] = selectedPanel || prevSelectedPanel;
const isClosedOrShouldClose = !isOpen || isSameSelectedPanel;
if (isClosedOrShouldClose) {
updatedState[openKey] = !updatedState[openKey];
<ErrorBoundaryDialog context="ToolbarRow">
<ToolbarRow
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
selectedLeftSidePanel={
this.state.isLeftSidePanelOpen
? this.state.selectedLeftSidePanel
: ''
}
selectedRightSidePanel={
this.state.isRightSidePanelOpen
? this.state.selectedRightSidePanel
: ''
}
handleSidePanelChange={(side, selectedPanel) => {
const sideClicked = side && side[0].toUpperCase() + side.slice(1);
const openKey = `is${sideClicked}SidePanelOpen`;
const selectedKey = `selected${sideClicked}SidePanel`;
const updatedState = Object.assign({}, this.state);
this.setState(updatedState);
}}
studies={this.props.studies}
/>
const isOpen = updatedState[openKey];
const prevSelectedPanel = updatedState[selectedKey];
// RoundedButtonGroup returns `null` if selected button is clicked
const isSameSelectedPanel =
prevSelectedPanel === selectedPanel || selectedPanel === null;
updatedState[selectedKey] = selectedPanel || prevSelectedPanel;
const isClosedOrShouldClose = !isOpen || isSameSelectedPanel;
if (isClosedOrShouldClose) {
updatedState[openKey] = !updatedState[openKey];
}
this.setState(updatedState);
}}
studies={this.props.studies}
/>
</ErrorBoundaryDialog>
{/*<ConnectedStudyLoadingMonitor studies={this.props.studies} />*/}
{/*<StudyPrefetcher studies={this.props.studies} />*/}
@ -299,37 +302,46 @@ class Viewer extends Component {
{/* VIEWPORTS + SIDEPANELS */}
<div className="FlexboxLayout">
{/* LEFT */}
<SidePanel from="left" isOpen={this.state.isLeftSidePanelOpen}>
{VisiblePanelLeft ? (
<VisiblePanelLeft
viewports={this.props.viewports}
studies={this.props.studies}
activeIndex={this.props.activeViewportIndex}
/>
) : (
<ErrorBoundaryDialog context="LeftSidePanel">
<SidePanel from="left" isOpen={this.state.isLeftSidePanelOpen}>
{VisiblePanelLeft ? (
<VisiblePanelLeft
viewports={this.props.viewports}
studies={this.props.studies}
activeIndex={this.props.activeViewportIndex}
/>
) : (
<ConnectedStudyBrowser
studies={this.state.thumbnails}
studyMetadata={this.props.studies}
/>
)}
</SidePanel>
</SidePanel>
</ErrorBoundaryDialog>
{/* MAIN */}
<div className={classNames('main-content')}>
<ConnectedViewerMain studies={this.props.studies} isStudyLoaded={this.props.isStudyLoaded} />
<ErrorBoundaryDialog context="ViewerMain">
<ConnectedViewerMain
studies={this.props.studies}
isStudyLoaded={this.props.isStudyLoaded}
/>
</ErrorBoundaryDialog>
</div>
{/* RIGHT */}
<SidePanel from="right" isOpen={this.state.isRightSidePanelOpen}>
{VisiblePanelRight && (
<VisiblePanelRight
isOpen={this.state.isRightSidePanelOpen}
viewports={this.props.viewports}
studies={this.props.studies}
activeIndex={this.props.activeViewportIndex}
/>
)}
</SidePanel>
<ErrorBoundaryDialog context="RightSidePanel">
<SidePanel from="right" isOpen={this.state.isRightSidePanelOpen}>
{VisiblePanelRight && (
<VisiblePanelRight
isOpen={this.state.isRightSidePanelOpen}
viewports={this.props.viewports}
studies={this.props.studies}
activeIndex={this.props.activeViewportIndex}
/>
)}
</SidePanel>
</ErrorBoundaryDialog>
</div>
</>
);
@ -349,7 +361,7 @@ export default withDialog(Viewer);
* @param {Study[]} studies
* @param {DisplaySet[]} studies[].displaySets
*/
const _mapStudiesToThumbnails = function (studies) {
const _mapStudiesToThumbnails = function(studies) {
return studies.map(study => {
const { StudyInstanceUID } = study;

View File

@ -154,11 +154,21 @@ const _sortStudyDisplaySet = (study, studyMetadata) => {
studyMetadata.sortDisplaySets(study.displaySets);
};
const _thinStudyData = study => {
return {
StudyInstanceUID: study.StudyInstanceUID,
series: study.series.map(item => ({
SeriesInstanceUID: item.SeriesInstanceUID
})),
}
};
function ViewerRetrieveStudyData({
server,
studyInstanceUIDs,
seriesInstanceUIDs,
clearViewportSpecificData,
setStudyData,
}) {
// hooks
const [error, setError] = useState(false);
@ -220,6 +230,7 @@ function ViewerRetrieveStudyData({
if (Array.isArray(studiesData) && studiesData.length > 0) {
// Map studies to new format, update metadata manager?
const studies = studiesData.map(study => {
setStudyData(study.StudyInstanceUID, _thinStudyData(study));
const studyMetadata = new OHIFStudyMetadata(
study,
study.StudyInstanceUID
@ -369,6 +380,7 @@ ViewerRetrieveStudyData.propTypes = {
seriesInstanceUIDs: PropTypes.array,
server: PropTypes.object,
clearViewportSpecificData: PropTypes.func.isRequired,
setStudyData: PropTypes.func.isRequired,
};
export default ViewerRetrieveStudyData;

View File

@ -14,9 +14,11 @@ class CallbackPage extends Component {
<CallbackComponent
userManager={this.props.userManager}
successCallback={() => {
const pathname = sessionStorage.getItem('ohif-redirect-to');
const { pathname, search = '' } = JSON.parse(
sessionStorage.getItem('ohif-redirect-to')
);
this.props.history.push(pathname);
this.props.history.push({ pathname, search });
}}
errorCallback={error => {
//this.props.history.push("/");

View File

@ -1247,7 +1247,7 @@
pirates "^4.0.0"
source-map-support "^0.5.9"
"@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.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==
@ -6534,10 +6534,10 @@ dateformat@^3.0.0:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
dcmjs@^0.12.2:
version "0.12.2"
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.12.2.tgz#1c16e19c27ff43202abc7cd25c5ecd6d8bf7672e"
integrity sha512-B7cEVCfDi3mOLKoBYUMYy+6COjLZhtKaesNpq5XNA4IbEH4EJYVweJfiI9gsR5hypv9LAPg72xG/xrbqjy8TgQ==
dcmjs@0.13.0:
version "0.13.0"
resolved "https://registry.yarnpkg.com/dcmjs/-/dcmjs-0.13.0.tgz#16310a137a0fe800ccb2d4751a28cf023765f347"
integrity sha512-U+qGwlnkG8vwDKB4R7ryqQUtWQM1JHMKMBw5+Oy8wcPxS+vDmaRTqIcAItMh1DcZ0ia8RN0VI5TBVCOJl7GVhA==
dependencies:
"@babel/polyfill" "^7.8.3"
"@babel/runtime" "^7.8.4"
@ -15603,10 +15603,10 @@ 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.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/react-cornerstone-viewport/-/react-cornerstone-viewport-2.3.8.tgz#7af8360f29bca986ae4e36b4e503269b88ddc52f"
integrity sha512-aiG2uVNrDY6SQx4t/HBxIA3zsMsCwT+6TpcXK9qSSoXhs+X6OTmYEKncWUqL0jtxU1yfh6JTUz8ARTg03gtF+A==
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==
dependencies:
classnames "^2.2.6"
date-fns "^2.2.1"
@ -15796,6 +15796,13 @@ react-dropzone@^10.1.7:
file-selector "^0.1.11"
prop-types "^15.7.2"
react-error-boundary@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-2.2.1.tgz#32ed74386a90482060cc2fea948bb7135465c4cb"
integrity sha512-8SZMkJRFUb0JuluHKwuUtkh5vvVWBg3O/bJIWgNMhMJv529aG//TmcphR3cSMhCWjz1vFZDb4taJd6pmwP5mEQ==
dependencies:
"@babel/runtime" "^7.9.6"
react-error-overlay@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.1.tgz#417addb0814a90f3a7082eacba7cee588d00da89"