feat: Automate tracking prompts for a less disruptive annotation workflow (#4822)

Co-authored-by: Devu Jayalekshmi <devu.jayalekshmi@trenser.com>
This commit is contained in:
nithin-trenserandDevu Jayalekshmi authored and GitHub committed 2025-04-04 12:02:13 -04:00
1 parent c0391cea1b
commit 54fded554e
42 files changed
+948 -70

No files matched your search

@@ -1,4 +1,5 @@
import React from 'react';
import { Dialog, ButtonEnums } from '@ohif/ui';
import { utils } from '@ohif/core';
import { AccordionTrigger, MeasurementTable, useViewportGrid } from '@ohif/ui-next';
import {
@@ -11,18 +12,40 @@ import {
} from '@ohif/extension-cornerstone';
import { useTrackedMeasurements } from '../getContextModule';
import { UntrackSeriesModal } from './PanelStudyBrowserTracking/untrackSeriesModal';
const { filterAnd, filterPlanarMeasurement, filterMeasurementsBySeriesUID } =
utils.MeasurementFilters;
function PanelMeasurementTableTracking(props) {
const [viewportGrid] = useViewportGrid();
const { measurementService, uiModalService } = props.servicesManager.services;
const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements();
const { trackedStudy, trackedSeries } = trackedMeasurements.context;
const measurementFilter = trackedStudy
? filterAnd(filterPlanarMeasurement, filterMeasurementsBySeriesUID(trackedSeries))
: filterPlanarMeasurement;
const onUntrackConfirm = () => {
sendTrackedMeasurementsEvent('UNTRACK_ALL', {});
};
const onDelete = () => {
const hasDirtyMeasurements = measurementService
.getMeasurements()
.some(measurement => measurement.isDirty);
hasDirtyMeasurements
? uiModalService.show({
title: 'Untrack Study',
content: UntrackSeriesModal,
contentProps: {
onConfirm: onUntrackConfirm,
message: 'Are you sure you want to untrack study and delete all measurements?',
},
})
: onUntrackConfirm();
};
const EmptyComponent = () => (
<div data-cy="trackedMeasurements-panel">
<MeasurementTable
@@ -43,6 +66,7 @@ function PanelMeasurementTableTracking(props) {
measurementFilter,
});
},
onDelete,
};
const Header = props => (
@@ -51,7 +75,10 @@ function PanelMeasurementTableTracking(props) {
className="px-0"
>
<div data-cy="TrackingHeader">
<StudySummaryFromMetadata {...props} />
<StudySummaryFromMetadata
{...props}
actions={actions}
/>
</div>
</AccordionTrigger>
);
@@ -68,7 +95,7 @@ function PanelMeasurementTableTracking(props) {
key="trackingMeasurementsHeader"
asChild={true}
>
<Header key="trackingHeadChild" />
<Header key="trackingHeadChild" />
</AccordionGroup.Trigger>
<MeasurementsOrAdditionalFindings
key="measurementsOrAdditionalFindings"
@@ -1,9 +1,10 @@
import React from 'react';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useSystem } from '@ohif/core';
import PanelStudyBrowser from '@ohif/extension-default/src/Panels/StudyBrowser/PanelStudyBrowser';
import { UntrackSeriesModal } from './untrackSeriesModal';
import { useTrackedMeasurements } from '../../getContextModule';
import { useViewportGrid } from '@ohif/ui-next';
const thumbnailNoImageModalities = [
'SR',
@@ -27,10 +28,34 @@ export default function PanelStudyBrowserTracking({
dataSource,
}) {
const { servicesManager } = useSystem();
const { displaySetService, uiModalService, measurementService } = servicesManager.services;
const { displaySetService, uiModalService, measurementService, viewportGridService } =
servicesManager.services;
const [trackedMeasurements, sendTrackedMeasurementsEvent] = useTrackedMeasurements();
const { trackedSeries } = trackedMeasurements.context;
const checkDirtyMeasurements = displaySetInstanceUID => {
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
if (displaySet.Modality === 'SR') {
const activeViewportId = viewportGridService.getActiveViewportId();
sendTrackedMeasurementsEvent('CHECK_DIRTY', {
viewportId: activeViewportId,
displaySetInstanceUID: displaySetInstanceUID,
});
}
};
useEffect(() => {
const subscriptionOndropFired = viewportGridService.subscribe(
viewportGridService.EVENTS.VIEWPORT_ONDROP_HANDLED,
({ eventData }) => {
checkDirtyMeasurements(eventData.displaySetInstanceUID);
}
);
return () => {
subscriptionOndropFired.unsubscribe();
};
}, []);
const onClickUntrack = displaySetInstanceUID => {
const onConfirm = () => {
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
@@ -50,6 +75,7 @@ export default function PanelStudyBrowserTracking({
content: UntrackSeriesModal,
contentProps: {
onConfirm,
message: 'Are you sure you want to untrack this series?',
},
});
};
@@ -115,6 +141,7 @@ export default function PanelStudyBrowserTracking({
dataSource={dataSource}
customMapDisplaySets={mapDisplaySetsWithTracking}
onClickUntrack={onClickUntrack}
onDoubleClickThumbnailHandlerCallBack={checkDirtyMeasurements}
/>
);
}
@@ -1,11 +1,11 @@
import React from 'react';
import { FooterAction } from '@ohif/ui-next';
export function UntrackSeriesModal({ hide, onConfirm }) {
export function UntrackSeriesModal({ hide, onConfirm, message }) {
return (
<div className="text-foreground">
<div>
<p>Are you sure you want to untrack this series?</p>
<p>{message}</p>
<p className="mt-2">
This action cannot be undone and will delete all your existing measurements.
</p>