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:
Alireza 2023-04-28 11:06:03 -04:00 committed by GitHub
parent c9d3c08cb6
commit f377153b60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 78 additions and 118 deletions

View File

@ -2,10 +2,8 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import OHIF, { utils } from '@ohif/core';
import {
Notification,
ViewportActionBar,
useViewportGrid,
useViewportDialog,
LoadingIndicatorTotalPercent,
} from '@ohif/ui';
@ -47,7 +45,6 @@ function OHIFCornerstoneRTViewport(props) {
const rtDisplaySet = displaySets[0];
const [viewportGrid, viewportGridService] = useViewportGrid();
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
// States
const [isToolGroupCreated, setToolGroupCreated] = useState(false);
@ -363,18 +360,6 @@ function OHIFCornerstoneRTViewport(props) {
/>
)}
{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}
</div>
</>

View File

@ -4,8 +4,6 @@ import { useTranslation } from 'react-i18next';
import OHIF, { utils } from '@ohif/core';
import {
LoadingIndicatorTotalPercent,
Notification,
useViewportDialog,
useViewportGrid,
ViewportActionBar,
} from '@ohif/ui';
@ -48,7 +46,6 @@ function OHIFCornerstoneSEGViewport(props) {
const segDisplaySet = displaySets[0];
const [viewportGrid, viewportGridService] = useViewportGrid();
const [viewportDialogState, viewportDialogApi] = useViewportDialog();
// States
const [isToolGroupCreated, setToolGroupCreated] = useState(false);
@ -366,18 +363,6 @@ function OHIFCornerstoneSEGViewport(props) {
/>
)}
{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}
</div>
</>

View File

@ -401,17 +401,6 @@ function OHIFCornerstoneSRViewport(props) {
<div className="relative flex flex-row w-full h-full overflow-hidden">
{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}
</div>
</>

View File

@ -8,9 +8,14 @@ import {
getEnabledElement,
StackViewport,
utilities as csUtils,
CONSTANTS,
} from '@cornerstonejs/core';
import { CinePlayer, useCine, useViewportGrid } from '@ohif/ui';
import {
CinePlayer,
useCine,
useViewportGrid,
Notification,
useViewportDialog,
} from '@ohif/ui';
import {
IStackViewport,
IVolumeViewport,
@ -132,6 +137,8 @@ const OHIFCornerstoneViewport = React.memo(props => {
stateSyncService,
} = servicesManager.services as CornerstoneServices;
const [viewportDialogState] = useViewportDialog();
const cineHandler = () => {
if (!cines || !cines[viewportIndex] || !enabledVPElement) {
return;
@ -455,50 +462,64 @@ const OHIFCornerstoneViewport = React.memo(props => {
}, [displaySets, elementRef, viewportIndex]);
return (
<div className="viewport-wrapper">
<ReactResizeDetector
handleWidth
handleHeight
skipOnMount={true} // Todo: make these configurable
refreshMode={'debounce'}
refreshRate={200} // transition amount in side panel
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,
})
}
<React.Fragment>
<div className="viewport-wrapper">
<ReactResizeDetector
handleWidth
handleHeight
skipOnMount={true} // Todo: make these configurable
refreshMode={'debounce'}
refreshRate={200} // transition amount in side panel
onResize={onResize}
targetRef={elementRef.current}
/>
)}
</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);

View File

@ -159,18 +159,6 @@ function TrackedCornerstoneViewport(props) {
{/* TODO: Viewport interface to accept stack or layers of content like this? */}
<div className="relative flex flex-row w-full h-full overflow-hidden">
{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>
</>
);

View File

@ -9,10 +9,10 @@ import classNames from 'classnames';
export type CinePlayerProps = {
className: string;
isPlaying: boolean;
minFrameRate: number;
maxFrameRate: number;
stepFrameRate: number;
frameRate: number;
minFrameRate?: number;
maxFrameRate?: number;
stepFrameRate?: number;
frameRate?: number;
onFrameRateChange: (value: number) => void;
onPlayPauseChange: (value: boolean) => void;
onClose: () => void;
@ -116,12 +116,12 @@ CinePlayer.defaultProps = {
CinePlayer.propTypes = {
/** Minimum value for range slider */
minFrameRate: PropTypes.number.isRequired,
minFrameRate: PropTypes.number,
/** Maximum value for range slider */
maxFrameRate: PropTypes.number.isRequired,
maxFrameRate: PropTypes.number,
/** Increment range slider can "step" in either direction */
stepFrameRate: PropTypes.number.isRequired,
frameRate: PropTypes.number.isRequired,
stepFrameRate: PropTypes.number,
frameRate: PropTypes.number,
/** 'true' if playing, 'false' if paused */
isPlaying: PropTypes.bool.isRequired,
onPlayPauseChange: PropTypes.func,

View File

@ -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', () => {
//Click on button and verify if icon is active on toolbar
cy.addLengthMeasurement();
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
'exist'
);
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
'be.visible'
);
cy.get('[data-cy="viewport-notification"]').should('exist');
cy.get('[data-cy="viewport-notification"]').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
//Verify the measurement exists in the table

View File

@ -25,12 +25,8 @@ describe('OHIF Measurement Panel', function() {
it('checks if measurement item can be Relabeled under Measurements panel', function() {
// Add length measurement
cy.addLengthMeasurement();
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
'exist'
);
cy.get('[data-cy="measurement-tracking-prompt-begin-tracking"]').should(
'be.visible'
);
cy.get('[data-cy="viewport-notification"]').should('exist');
cy.get('[data-cy="viewport-notification"]').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes"]').click();
cy.get('[data-cy="measurement-item"]').click();