149 lines
4.3 KiB
TypeScript
149 lines
4.3 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import debounce from 'lodash.debounce';
|
|
import { roundNumber } from '@ohif/core/src/utils';
|
|
import { SegmentationData } from '../services/SegmentationService/SegmentationService';
|
|
|
|
function mapSegmentationToDisplay(segmentation, customizationService) {
|
|
const { label, segments } = segmentation;
|
|
|
|
// Get the readable text mapping once
|
|
const { readableText: readableTextMap } = customizationService.getCustomization(
|
|
'PanelSegmentation.readableText',
|
|
{}
|
|
);
|
|
|
|
// Helper function to recursively map cachedStats to readable display text
|
|
function mapStatsToDisplay(stats, indent = 0) {
|
|
const primary = [];
|
|
const indentation = ' '.repeat(indent);
|
|
|
|
for (const key in stats) {
|
|
if (Object.prototype.hasOwnProperty.call(stats, key)) {
|
|
const value = stats[key];
|
|
const readableText = readableTextMap?.[key];
|
|
|
|
if (!readableText) {
|
|
continue;
|
|
}
|
|
|
|
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
// Add empty row before category (except for the first category)
|
|
if (primary.length > 0) {
|
|
primary.push('');
|
|
}
|
|
// Add category title
|
|
primary.push(`${indentation}${readableText}`);
|
|
// Recursively handle nested objects
|
|
primary.push(...mapStatsToDisplay(value, indent + 1));
|
|
} else {
|
|
// For non-nested values, don't add empty rows
|
|
primary.push(`${indentation}${readableText}: ${roundNumber(value, 2)}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
return primary;
|
|
}
|
|
|
|
// Get customization for display text mapping
|
|
const displayTextMapper = segment => {
|
|
const defaultDisplay = {
|
|
primary: [],
|
|
secondary: [],
|
|
};
|
|
|
|
// If the segment has cachedStats, map it to readable text
|
|
if (segment.cachedStats) {
|
|
const primary = mapStatsToDisplay(segment.cachedStats);
|
|
defaultDisplay.primary = primary;
|
|
}
|
|
|
|
return defaultDisplay;
|
|
};
|
|
|
|
const updatedSegments = {};
|
|
|
|
Object.entries(segments).forEach(([segmentIndex, segment]) => {
|
|
updatedSegments[segmentIndex] = {
|
|
...segment,
|
|
displayText: displayTextMapper(segment),
|
|
};
|
|
});
|
|
|
|
// Map the segments and apply the display text mapper
|
|
return {
|
|
...segmentation,
|
|
label,
|
|
segments: updatedSegments,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Custom hook that provides segmentation data.
|
|
* @param options - The options object.
|
|
* @param options.servicesManager - The services manager object.
|
|
* @param options.subscribeToDataModified - Whether to subscribe to segmentation data modifications.
|
|
* @param options.debounceTime - Debounce time in milliseconds for updates.
|
|
* @returns An array of segmentation data.
|
|
*/
|
|
export function useSegmentations({
|
|
servicesManager,
|
|
subscribeToDataModified = false,
|
|
debounceTime = 0,
|
|
}: withAppTypes<{ debounceTime?: number }>): SegmentationData[] {
|
|
const { segmentationService, customizationService } = servicesManager.services;
|
|
|
|
const [segmentations, setSegmentations] = useState<SegmentationData[]>([]);
|
|
|
|
useEffect(() => {
|
|
const update = () => {
|
|
const segmentations = segmentationService.getSegmentations();
|
|
|
|
if (!segmentations?.length) {
|
|
setSegmentations([]);
|
|
return;
|
|
}
|
|
|
|
const mappedSegmentations = segmentations.map(segmentation =>
|
|
mapSegmentationToDisplay(segmentation, customizationService)
|
|
);
|
|
|
|
setSegmentations(mappedSegmentations);
|
|
};
|
|
|
|
const debouncedUpdate =
|
|
debounceTime > 0 ? debounce(update, debounceTime, { leading: true, trailing: true }) : update;
|
|
|
|
update();
|
|
|
|
const subscriptions = [
|
|
segmentationService.subscribe(
|
|
segmentationService.EVENTS.SEGMENTATION_MODIFIED,
|
|
debouncedUpdate
|
|
),
|
|
segmentationService.subscribe(
|
|
segmentationService.EVENTS.SEGMENTATION_REMOVED,
|
|
debouncedUpdate
|
|
),
|
|
];
|
|
|
|
if (subscribeToDataModified) {
|
|
subscriptions.push(
|
|
segmentationService.subscribe(
|
|
segmentationService.EVENTS.SEGMENTATION_DATA_MODIFIED,
|
|
debouncedUpdate
|
|
)
|
|
);
|
|
}
|
|
|
|
return () => {
|
|
subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
if (debounceTime > 0) {
|
|
debouncedUpdate.cancel();
|
|
}
|
|
};
|
|
}, [segmentationService, customizationService, debounceTime, subscribeToDataModified]);
|
|
|
|
return segmentations;
|
|
}
|