fix(viewportDialog): viewportDialoge not appearing in non-tracked viewports (#3071)
* fix: viewportdialoge not appearing in non-tracked viewports * feat(viewports): Introduce useViewportDialog and remove deprecated API This commit introduces the `useViewportDialog` hook and replaces the deprecated `viewportDialogApi` with the new `viewportDialogState`. Additionally, the notifications in `OHIFCornerstoneRTViewport` and `OHIFCornerstoneViewport` have been removed. Finally, the `CinePlayer` component now accepts optional parameters. * fix tests
This commit is contained in:
parent
c9d3c08cb6
commit
f377153b60
@ -2,10 +2,8 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import OHIF, { utils } from '@ohif/core';
|
import OHIF, { utils } from '@ohif/core';
|
||||||
import {
|
import {
|
||||||
Notification,
|
|
||||||
ViewportActionBar,
|
ViewportActionBar,
|
||||||
useViewportGrid,
|
useViewportGrid,
|
||||||
useViewportDialog,
|
|
||||||
LoadingIndicatorTotalPercent,
|
LoadingIndicatorTotalPercent,
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
|
||||||
@ -47,7 +45,6 @@ function OHIFCornerstoneRTViewport(props) {
|
|||||||
const rtDisplaySet = displaySets[0];
|
const rtDisplaySet = displaySets[0];
|
||||||
|
|
||||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||||
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
|
|
||||||
|
|
||||||
// States
|
// States
|
||||||
const [isToolGroupCreated, setToolGroupCreated] = useState(false);
|
const [isToolGroupCreated, setToolGroupCreated] = useState(false);
|
||||||
@ -363,18 +360,6 @@ function OHIFCornerstoneRTViewport(props) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{getCornerstoneViewport()}
|
{getCornerstoneViewport()}
|
||||||
<div className="absolute w-full">
|
|
||||||
{viewportDialogState.viewportIndex === viewportIndex && (
|
|
||||||
<Notification
|
|
||||||
id="viewport-notification"
|
|
||||||
message={viewportDialogState.message}
|
|
||||||
type={viewportDialogState.type}
|
|
||||||
actions={viewportDialogState.actions}
|
|
||||||
onSubmit={viewportDialogState.onSubmit}
|
|
||||||
onOutsideClick={viewportDialogState.onOutsideClick}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{childrenWithProps}
|
{childrenWithProps}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -4,8 +4,6 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import OHIF, { utils } from '@ohif/core';
|
import OHIF, { utils } from '@ohif/core';
|
||||||
import {
|
import {
|
||||||
LoadingIndicatorTotalPercent,
|
LoadingIndicatorTotalPercent,
|
||||||
Notification,
|
|
||||||
useViewportDialog,
|
|
||||||
useViewportGrid,
|
useViewportGrid,
|
||||||
ViewportActionBar,
|
ViewportActionBar,
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
@ -48,7 +46,6 @@ function OHIFCornerstoneSEGViewport(props) {
|
|||||||
const segDisplaySet = displaySets[0];
|
const segDisplaySet = displaySets[0];
|
||||||
|
|
||||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||||
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
|
|
||||||
|
|
||||||
// States
|
// States
|
||||||
const [isToolGroupCreated, setToolGroupCreated] = useState(false);
|
const [isToolGroupCreated, setToolGroupCreated] = useState(false);
|
||||||
@ -366,18 +363,6 @@ function OHIFCornerstoneSEGViewport(props) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{getCornerstoneViewport()}
|
{getCornerstoneViewport()}
|
||||||
<div className="absolute w-full">
|
|
||||||
{viewportDialogState.viewportIndex === viewportIndex && (
|
|
||||||
<Notification
|
|
||||||
id="viewport-notification"
|
|
||||||
message={viewportDialogState.message}
|
|
||||||
type={viewportDialogState.type}
|
|
||||||
actions={viewportDialogState.actions}
|
|
||||||
onSubmit={viewportDialogState.onSubmit}
|
|
||||||
onOutsideClick={viewportDialogState.onOutsideClick}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{childrenWithProps}
|
{childrenWithProps}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -401,17 +401,6 @@ function OHIFCornerstoneSRViewport(props) {
|
|||||||
|
|
||||||
<div className="relative flex flex-row w-full h-full overflow-hidden">
|
<div className="relative flex flex-row w-full h-full overflow-hidden">
|
||||||
{getCornerstoneViewport()}
|
{getCornerstoneViewport()}
|
||||||
<div className="absolute w-full">
|
|
||||||
{viewportDialogState.viewportIndex === viewportIndex && (
|
|
||||||
<Notification
|
|
||||||
message={viewportDialogState.message}
|
|
||||||
type={viewportDialogState.type}
|
|
||||||
actions={viewportDialogState.actions}
|
|
||||||
onSubmit={viewportDialogState.onSubmit}
|
|
||||||
onOutsideClick={viewportDialogState.onOutsideClick}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{childrenWithProps}
|
{childrenWithProps}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -8,9 +8,14 @@ import {
|
|||||||
getEnabledElement,
|
getEnabledElement,
|
||||||
StackViewport,
|
StackViewport,
|
||||||
utilities as csUtils,
|
utilities as csUtils,
|
||||||
CONSTANTS,
|
|
||||||
} from '@cornerstonejs/core';
|
} from '@cornerstonejs/core';
|
||||||
import { CinePlayer, useCine, useViewportGrid } from '@ohif/ui';
|
import {
|
||||||
|
CinePlayer,
|
||||||
|
useCine,
|
||||||
|
useViewportGrid,
|
||||||
|
Notification,
|
||||||
|
useViewportDialog,
|
||||||
|
} from '@ohif/ui';
|
||||||
import {
|
import {
|
||||||
IStackViewport,
|
IStackViewport,
|
||||||
IVolumeViewport,
|
IVolumeViewport,
|
||||||
@ -132,6 +137,8 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
|||||||
stateSyncService,
|
stateSyncService,
|
||||||
} = servicesManager.services as CornerstoneServices;
|
} = servicesManager.services as CornerstoneServices;
|
||||||
|
|
||||||
|
const [viewportDialogState] = useViewportDialog();
|
||||||
|
|
||||||
const cineHandler = () => {
|
const cineHandler = () => {
|
||||||
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
|
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
|
||||||
return;
|
return;
|
||||||
@ -455,50 +462,64 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
|||||||
}, [displaySets, elementRef, viewportIndex]);
|
}, [displaySets, elementRef, viewportIndex]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="viewport-wrapper">
|
<React.Fragment>
|
||||||
<ReactResizeDetector
|
<div className="viewport-wrapper">
|
||||||
handleWidth
|
<ReactResizeDetector
|
||||||
handleHeight
|
handleWidth
|
||||||
skipOnMount={true} // Todo: make these configurable
|
handleHeight
|
||||||
refreshMode={'debounce'}
|
skipOnMount={true} // Todo: make these configurable
|
||||||
refreshRate={200} // transition amount in side panel
|
refreshMode={'debounce'}
|
||||||
onResize={onResize}
|
refreshRate={200} // transition amount in side panel
|
||||||
targetRef={elementRef.current}
|
onResize={onResize}
|
||||||
/>
|
targetRef={elementRef.current}
|
||||||
<div
|
|
||||||
className="cornerstone-viewport-element"
|
|
||||||
style={{ height: '100%', width: '100%' }}
|
|
||||||
onContextMenu={e => e.preventDefault()}
|
|
||||||
onMouseDown={e => e.preventDefault()}
|
|
||||||
ref={elementRef}
|
|
||||||
></div>
|
|
||||||
<CornerstoneOverlays
|
|
||||||
viewportIndex={viewportIndex}
|
|
||||||
toolbarService={toolbarService}
|
|
||||||
element={elementRef.current}
|
|
||||||
scrollbarHeight={scrollbarHeight}
|
|
||||||
servicesManager={servicesManager}
|
|
||||||
/>
|
|
||||||
{isCineEnabled && (
|
|
||||||
<CinePlayer
|
|
||||||
className="absolute left-1/2 -translate-x-1/2 bottom-3"
|
|
||||||
isPlaying={isPlaying}
|
|
||||||
onClose={handleCineClose}
|
|
||||||
onPlayPauseChange={isPlaying =>
|
|
||||||
cineService.setCine({
|
|
||||||
id: activeViewportIndex,
|
|
||||||
isPlaying,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onFrameRateChange={frameRate =>
|
|
||||||
cineService.setCine({
|
|
||||||
id: activeViewportIndex,
|
|
||||||
frameRate,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)}
|
<div
|
||||||
</div>
|
className="cornerstone-viewport-element"
|
||||||
|
style={{ height: '100%', width: '100%' }}
|
||||||
|
onContextMenu={e => e.preventDefault()}
|
||||||
|
onMouseDown={e => e.preventDefault()}
|
||||||
|
ref={elementRef}
|
||||||
|
></div>
|
||||||
|
<CornerstoneOverlays
|
||||||
|
viewportIndex={viewportIndex}
|
||||||
|
toolBarService={toolbarService}
|
||||||
|
element={elementRef.current}
|
||||||
|
scrollbarHeight={scrollbarHeight}
|
||||||
|
servicesManager={servicesManager}
|
||||||
|
/>
|
||||||
|
{isCineEnabled && (
|
||||||
|
<CinePlayer
|
||||||
|
className="absolute left-1/2 -translate-x-1/2 bottom-3"
|
||||||
|
isPlaying={isPlaying}
|
||||||
|
onClose={handleCineClose}
|
||||||
|
onPlayPauseChange={isPlaying =>
|
||||||
|
cineService.setCine({
|
||||||
|
id: activeViewportIndex,
|
||||||
|
isPlaying,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onFrameRateChange={frameRate =>
|
||||||
|
cineService.setCine({
|
||||||
|
id: activeViewportIndex,
|
||||||
|
frameRate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="absolute w-full">
|
||||||
|
{viewportDialogState.viewportIndex === viewportIndex && (
|
||||||
|
<Notification
|
||||||
|
id="viewport-notification"
|
||||||
|
message={viewportDialogState.message}
|
||||||
|
type={viewportDialogState.type}
|
||||||
|
actions={viewportDialogState.actions}
|
||||||
|
onSubmit={viewportDialogState.onSubmit}
|
||||||
|
onOutsideClick={viewportDialogState.onOutsideClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}, areEqual);
|
}, areEqual);
|
||||||
|
|
||||||
|
|||||||
@ -159,18 +159,6 @@ function TrackedCornerstoneViewport(props) {
|
|||||||
{/* TODO: Viewport interface to accept stack or layers of content like this? */}
|
{/* TODO: Viewport interface to accept stack or layers of content like this? */}
|
||||||
<div className="relative flex flex-row w-full h-full overflow-hidden">
|
<div className="relative flex flex-row w-full h-full overflow-hidden">
|
||||||
{getCornerstoneViewport()}
|
{getCornerstoneViewport()}
|
||||||
<div className="absolute w-full">
|
|
||||||
{viewportDialogState.viewportIndex === viewportIndex && (
|
|
||||||
<Notification
|
|
||||||
id={viewportDialogState.id}
|
|
||||||
message={viewportDialogState.message}
|
|
||||||
type={viewportDialogState.type}
|
|
||||||
actions={viewportDialogState.actions}
|
|
||||||
onSubmit={viewportDialogState.onSubmit}
|
|
||||||
onOutsideClick={viewportDialogState.onOutsideClick}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -9,10 +9,10 @@ import classNames from 'classnames';
|
|||||||
export type CinePlayerProps = {
|
export type CinePlayerProps = {
|
||||||
className: string;
|
className: string;
|
||||||
isPlaying: boolean;
|
isPlaying: boolean;
|
||||||
minFrameRate: number;
|
minFrameRate?: number;
|
||||||
maxFrameRate: number;
|
maxFrameRate?: number;
|
||||||
stepFrameRate: number;
|
stepFrameRate?: number;
|
||||||
frameRate: number;
|
frameRate?: number;
|
||||||
onFrameRateChange: (value: number) => void;
|
onFrameRateChange: (value: number) => void;
|
||||||
onPlayPauseChange: (value: boolean) => void;
|
onPlayPauseChange: (value: boolean) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -116,12 +116,12 @@ CinePlayer.defaultProps = {
|
|||||||
|
|
||||||
CinePlayer.propTypes = {
|
CinePlayer.propTypes = {
|
||||||
/** Minimum value for range slider */
|
/** Minimum value for range slider */
|
||||||
minFrameRate: PropTypes.number.isRequired,
|
minFrameRate: PropTypes.number,
|
||||||
/** Maximum value for range slider */
|
/** Maximum value for range slider */
|
||||||
maxFrameRate: PropTypes.number.isRequired,
|
maxFrameRate: PropTypes.number,
|
||||||
/** Increment range slider can "step" in either direction */
|
/** Increment range slider can "step" in either direction */
|
||||||
stepFrameRate: PropTypes.number.isRequired,
|
stepFrameRate: PropTypes.number,
|
||||||
frameRate: PropTypes.number.isRequired,
|
frameRate: PropTypes.number,
|
||||||
/** 'true' if playing, 'false' if paused */
|
/** 'true' if playing, 'false' if paused */
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
isPlaying: PropTypes.bool.isRequired,
|
||||||
onPlayPauseChange: PropTypes.func,
|
onPlayPauseChange: PropTypes.func,
|
||||||
|
|||||||
@ -111,12 +111,8 @@ describe('OHIF Cornerstone Toolbar', () => {
|
|||||||
it('checks if Length annotation can be added to viewport and shows up in the measurements panel', () => {
|
it('checks if Length annotation can be added to viewport and shows up in the measurements panel', () => {
|
||||||
//Click on button and verify if icon is active on toolbar
|
//Click on button and verify if icon is active on toolbar
|
||||||
cy.addLengthMeasurement();
|
cy.addLengthMeasurement();
|
||||||
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
|
cy.get('[data-cy="viewport-notification"]').should('exist');
|
||||||
'exist'
|
cy.get('[data-cy="viewport-notification"]').should('be.visible');
|
||||||
);
|
|
||||||
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
||||||
|
|
||||||
//Verify the measurement exists in the table
|
//Verify the measurement exists in the table
|
||||||
|
|||||||
@ -25,12 +25,8 @@ describe('OHIF Measurement Panel', function() {
|
|||||||
it('checks if measurement item can be Relabeled under Measurements panel', function() {
|
it('checks if measurement item can be Relabeled under Measurements panel', function() {
|
||||||
// Add length measurement
|
// Add length measurement
|
||||||
cy.addLengthMeasurement();
|
cy.addLengthMeasurement();
|
||||||
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
|
cy.get('[data-cy="viewport-notification"]').should('exist');
|
||||||
'exist'
|
cy.get('[data-cy="viewport-notification"]').should('be.visible');
|
||||||
);
|
|
||||||
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
|
||||||
cy.get('[data-cy="measurement-item"]').click();
|
cy.get('[data-cy="measurement-item"]').click();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user