2025-03-17 22:34:34 -04:00
|
|
|
import React, { ReactNode, useState, Children, isValidElement } from 'react';
|
2024-11-06 07:15:27 -05:00
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
import { PanelSection } from '../PanelSection';
|
2026-01-13 15:57:44 -05:00
|
|
|
import {
|
|
|
|
|
SegmentationTableProvider,
|
|
|
|
|
SegmentationTableContextType,
|
|
|
|
|
} from './contexts/SegmentationTableContext';
|
2024-11-06 07:15:27 -05:00
|
|
|
import { SegmentationSegments } from './SegmentationSegments';
|
2025-03-17 22:34:34 -04:00
|
|
|
import { SegmentStatistics } from './SegmentStatistics';
|
2024-11-06 07:15:27 -05:00
|
|
|
import { SegmentationTableConfig } from './SegmentationTableConfig';
|
|
|
|
|
import { AddSegmentRow } from './AddSegmentRow';
|
|
|
|
|
import { AddSegmentationRow } from './AddSegmentationRow';
|
|
|
|
|
import { SegmentationHeader } from './SegmentationHeader';
|
|
|
|
|
import { SegmentationCollapsed } from './SegmentationCollapsed';
|
|
|
|
|
import { SegmentationExpanded } from './SegmentationExpanded';
|
2025-03-17 22:34:34 -04:00
|
|
|
import Icons from '../Icons';
|
2024-11-06 07:15:27 -05:00
|
|
|
|
2025-03-17 22:34:34 -04:00
|
|
|
// Only include props that aren't part of the context
|
|
|
|
|
interface SegmentationTableProps extends Omit<SegmentationTableContextType, 'setShowConfig'> {
|
2024-11-06 07:15:27 -05:00
|
|
|
title?: string;
|
|
|
|
|
children?: ReactNode;
|
2025-03-17 22:34:34 -04:00
|
|
|
setShowConfig?: (value: boolean) => void;
|
2024-11-06 07:15:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface SegmentationTableComponent extends React.FC<SegmentationTableProps> {
|
|
|
|
|
Segments: typeof SegmentationSegments;
|
|
|
|
|
Config: typeof SegmentationTableConfig;
|
|
|
|
|
AddSegmentRow: typeof AddSegmentRow;
|
|
|
|
|
AddSegmentationRow: typeof AddSegmentationRow;
|
|
|
|
|
Header: typeof SegmentationHeader;
|
|
|
|
|
Collapsed: typeof SegmentationCollapsed;
|
|
|
|
|
Expanded: typeof SegmentationExpanded;
|
2025-03-17 22:34:34 -04:00
|
|
|
SegmentStatistics: typeof SegmentStatistics;
|
2024-11-06 07:15:27 -05:00
|
|
|
}
|
|
|
|
|
|
2025-03-17 22:34:34 -04:00
|
|
|
export const SegmentationTableRoot = (props: SegmentationTableProps) => {
|
2025-12-12 16:46:56 +01:00
|
|
|
const { t } = useTranslation('SegmentationPanel');
|
2025-03-17 22:34:34 -04:00
|
|
|
const {
|
|
|
|
|
data = [],
|
|
|
|
|
mode,
|
|
|
|
|
title,
|
|
|
|
|
disableEditing = false,
|
|
|
|
|
disabled = false,
|
|
|
|
|
children,
|
|
|
|
|
showConfig: externalShowConfig,
|
2025-11-19 17:55:53 -05:00
|
|
|
selectedSegmentationIdForType,
|
2025-03-17 22:34:34 -04:00
|
|
|
...contextProps
|
|
|
|
|
} = props;
|
2024-11-06 07:15:27 -05:00
|
|
|
|
2025-03-17 22:34:34 -04:00
|
|
|
const [internalShowConfig, setInternalShowConfig] = useState(false);
|
|
|
|
|
const showConfig = externalShowConfig !== undefined ? externalShowConfig : internalShowConfig;
|
|
|
|
|
|
|
|
|
|
// Find the active segmentation info based on which representation is active
|
2024-11-06 07:15:27 -05:00
|
|
|
const activeSegmentationInfo = data.find(info => info.representation?.active);
|
|
|
|
|
|
2025-03-17 22:34:34 -04:00
|
|
|
// Get the active segmentation ID
|
|
|
|
|
const activeSegmentationId =
|
|
|
|
|
props.activeSegmentationId || activeSegmentationInfo?.segmentation?.segmentationId;
|
|
|
|
|
const activeRepresentation = props.activeRepresentation || activeSegmentationInfo?.representation;
|
|
|
|
|
const activeSegmentation = props.activeSegmentation || activeSegmentationInfo?.segmentation;
|
|
|
|
|
|
2025-11-19 17:55:53 -05:00
|
|
|
const selectedSegmentationForTypeInfo = data.find(
|
|
|
|
|
info => info.segmentation?.segmentationId === selectedSegmentationIdForType
|
|
|
|
|
);
|
|
|
|
|
const selectedSegmentationForTypeRepresentation = selectedSegmentationForTypeInfo?.representation;
|
|
|
|
|
|
2025-03-17 22:34:34 -04:00
|
|
|
// Extract style properties or use defaults
|
|
|
|
|
const {
|
|
|
|
|
fillAlpha = props.fillAlpha || 0.5,
|
|
|
|
|
fillAlphaInactive = props.fillAlphaInactive || 0.2,
|
|
|
|
|
outlineWidth = props.outlineWidth || 1,
|
|
|
|
|
renderFill = props.renderFill !== undefined ? props.renderFill : true,
|
|
|
|
|
renderOutline = props.renderOutline !== undefined ? props.renderOutline : true,
|
2025-11-19 17:55:53 -05:00
|
|
|
} = selectedSegmentationForTypeRepresentation?.styles ?? {};
|
2025-03-17 22:34:34 -04:00
|
|
|
|
|
|
|
|
// Check if SegmentationTableConfig is present in children
|
|
|
|
|
const hasConfigComponent = Children.toArray(children).some(
|
|
|
|
|
child => isValidElement(child) && child.type === SegmentationTableConfig
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Process children to conditionally render the config component based on showConfig
|
|
|
|
|
const processedChildren = Children.map(children, child => {
|
|
|
|
|
if (isValidElement(child) && child.type === SegmentationTableConfig) {
|
|
|
|
|
// Only render the Config component if showConfig is true
|
|
|
|
|
return showConfig ? child : null;
|
|
|
|
|
}
|
|
|
|
|
return child;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const toggleShowConfig = () => {
|
|
|
|
|
if (props.setShowConfig) {
|
|
|
|
|
props.setShowConfig(!showConfig);
|
|
|
|
|
} else {
|
|
|
|
|
setInternalShowConfig(!internalShowConfig);
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-11-06 07:15:27 -05:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<SegmentationTableProvider
|
2025-03-17 22:34:34 -04:00
|
|
|
value={{
|
|
|
|
|
data,
|
|
|
|
|
mode,
|
|
|
|
|
showConfig,
|
|
|
|
|
disabled,
|
|
|
|
|
disableEditing,
|
|
|
|
|
fillAlpha,
|
|
|
|
|
fillAlphaInactive,
|
|
|
|
|
outlineWidth,
|
|
|
|
|
renderFill,
|
|
|
|
|
renderOutline,
|
|
|
|
|
activeSegmentationId,
|
|
|
|
|
activeSegmentation,
|
|
|
|
|
activeRepresentation,
|
2025-11-19 17:55:53 -05:00
|
|
|
selectedSegmentationIdForType,
|
2025-03-17 22:34:34 -04:00
|
|
|
...contextProps,
|
|
|
|
|
setShowConfig: toggleShowConfig,
|
|
|
|
|
}}
|
2024-11-06 07:15:27 -05:00
|
|
|
>
|
|
|
|
|
<PanelSection defaultOpen={true}>
|
2025-03-17 22:34:34 -04:00
|
|
|
<PanelSection.Header className="flex items-center justify-between">
|
2024-11-06 07:15:27 -05:00
|
|
|
<span>{t(title)}</span>
|
2025-03-17 22:34:34 -04:00
|
|
|
{hasConfigComponent && (
|
|
|
|
|
<div className="ml-auto mr-2">
|
|
|
|
|
<Icons.Settings
|
2025-04-04 12:11:29 -04:00
|
|
|
className="text-primary h-4 w-4"
|
2025-03-17 22:34:34 -04:00
|
|
|
onClick={e => {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
toggleShowConfig();
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2024-11-06 07:15:27 -05:00
|
|
|
</PanelSection.Header>
|
2025-03-17 22:34:34 -04:00
|
|
|
<PanelSection.Content>{processedChildren}</PanelSection.Content>
|
2024-11-06 07:15:27 -05:00
|
|
|
</PanelSection>
|
|
|
|
|
</SegmentationTableProvider>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-17 22:34:34 -04:00
|
|
|
const SegmentationTable = Object.assign(SegmentationTableRoot, {
|
|
|
|
|
Segments: SegmentationSegments,
|
|
|
|
|
Config: SegmentationTableConfig,
|
|
|
|
|
AddSegmentRow: AddSegmentRow,
|
|
|
|
|
AddSegmentationRow: AddSegmentationRow,
|
|
|
|
|
Collapsed: SegmentationCollapsed,
|
|
|
|
|
Expanded: SegmentationExpanded,
|
|
|
|
|
SegmentStatistics: SegmentStatistics,
|
|
|
|
|
Header: SegmentationHeader,
|
|
|
|
|
}) as SegmentationTableComponent;
|
|
|
|
|
|
|
|
|
|
export { SegmentationTable };
|