feat(segmentation): Enhance dropdown menu functionality in SegmentationTable (#4553)

This commit is contained in:
Alireza authored and GitHub committed 2024-11-28 12:41:08 -05:00
1 parent 144ec791a2
commit 397fd85653
6 files changed
+153 -167

No files matched your search

@@ -26,10 +26,7 @@ export const SegmentationExpanded: React.FC<{ children?: React.ReactNode }> = ({
representation: segmentationInfo.representation,
})
) : (
<SegmentationHeader
segmentation={segmentationInfo.segmentation}
representation={segmentationInfo.representation}
/>
<SegmentationHeader segmentation={segmentationInfo.segmentation} />
)}
</PanelSection.Header>
<PanelSection.Content>
@@ -38,7 +35,6 @@ export const SegmentationExpanded: React.FC<{ children?: React.ReactNode }> = ({
React.isValidElement(child)
? React.cloneElement(child, {
segmentation: segmentationInfo.segmentation,
representation: segmentationInfo.representation,
})
: child
)}
@@ -1,39 +1,31 @@
import React from 'react';
import { Button } from '../Button';
import { Icons } from '../Icons/Icons';
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
DropdownMenuPortal,
} from '../DropdownMenu';
import { DropdownMenu, DropdownMenuTrigger } from '../DropdownMenu';
import { Tooltip, TooltipTrigger, TooltipContent } from '../Tooltip/Tooltip';
import { useSegmentationTableContext } from './SegmentationTableContext';
import { useTranslation } from 'react-i18next';
export const SegmentationHeader: React.FC<{
children?: React.ReactNode;
segmentation?: any;
}> = ({ segmentation }) => {
}> = ({ children, segmentation }) => {
const { t } = useTranslation('SegmentationTable');
const {
onSegmentAdd,
onSegmentationRemoveFromViewport,
onSegmentationEdit,
onSegmentationDelete,
onSegmentationDownload,
onSegmentationDownloadRTSS,
storeSegmentation,
} = useSegmentationTableContext('SegmentationHeader');
const { ...contextProps } = useSegmentationTableContext('SegmentationHeader');
if (!segmentation) {
return null;
}
const childrenWithProps = React.Children.map(children, child =>
React.isValidElement(child)
? React.cloneElement(child, {
t,
...contextProps,
})
: child
);
return (
<div className="text-foreground flex h-8 w-full items-center justify-between">
<div className="flex items-center space-x-1">
@@ -48,79 +40,7 @@ export const SegmentationHeader: React.FC<{
<Icons.More />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem
onClick={e => {
e.stopPropagation();
onSegmentAdd(segmentation.segmentationId);
}}
>
<Icons.Add className="text-foreground" />
<span className="pl-2">{t('Add Segment')}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={e => {
e.stopPropagation();
onSegmentationRemoveFromViewport(segmentation.segmentationId);
}}
>
<Icons.Series className="text-foreground" />
<span className="pl-2">{t('Remove from Viewport')}</span>
</DropdownMenuItem>
<DropdownMenuItem
onClick={e => {
e.stopPropagation();
onSegmentationEdit(segmentation.segmentationId);
}}
>
<Icons.Rename className="text-foreground" />
<span className="pl-2">{t('Rename')}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={e => e.stopPropagation()}>
<Icons.Hide className="text-foreground" />
<span className="pl-2">{t('Hide or Show all Segments')}</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger onClick={e => e.stopPropagation()}>
<Icons.Export className="text-foreground" />
<span className="pl-2">{t('Export & Download')}</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem
onClick={e => {
e.stopPropagation();
storeSegmentation(segmentation.segmentationId);
}}
>
{t('Export DICOM SEG')}
</DropdownMenuItem>
<DropdownMenuItem
onClick={e => {
e.stopPropagation();
onSegmentationDownload(segmentation.segmentationId);
}}
>
{t('Download DICOM SEG')}
</DropdownMenuItem>
<DropdownMenuItem
onClick={e => {
e.stopPropagation();
onSegmentationDownloadRTSS(segmentation.segmentationId);
}}
>
{t('Download DICOM RTSTRUCT')}
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => onSegmentationDelete(segmentation.segmentationId)}>
<Icons.Delete className="text-red-600" />
<span className="pl-2 text-red-600">{t('Delete')}</span>
</DropdownMenuItem>
</DropdownMenuContent>
{childrenWithProps}
</DropdownMenu>
<div className="pl-1.5">{segmentation.label}</div>
</div>
@@ -4,17 +4,9 @@ import {
Button,
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuItem,
DropdownMenuContent,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuPortal,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
Tooltip,
TooltipTrigger,
TooltipContent,
DropdownMenuLabel,
} from '../../components';
import { useTranslation } from 'react-i18next';
@@ -26,20 +18,8 @@ export const SegmentationSelectorHeader: React.FC<{ children?: React.ReactNode }
}) => {
const { t } = useTranslation('SegmentationTable.HeaderCollapsed');
const {
data,
activeSegmentationId,
mode,
onSegmentationClick,
onSegmentationAdd,
onSegmentationRemoveFromViewport,
onSegmentationEdit,
onSegmentationDelete,
onSegmentationDownload,
onSegmentationDownloadRTSS,
storeSegmentation,
exportOptions,
} = useSegmentationTableContext('SegmentationTable.HeaderCollapsed');
const { data, activeSegmentationId, mode, onSegmentationClick, exportOptions, ...contextProps } =
useSegmentationTableContext('SegmentationTable.HeaderCollapsed');
if (mode !== 'collapsed' || !data?.length) {
return null;
@@ -65,6 +45,17 @@ export const SegmentationSelectorHeader: React.FC<{ children?: React.ReactNode }
({ segmentationId }) => segmentationId === activeSegmentation.id
)?.isExportable;
const childrenWithProps = React.Children.map(children, child =>
React.isValidElement(child)
? React.cloneElement(child, {
activeSegmentation,
allowExport,
t,
...contextProps,
})
: child
);
return (
<div className="bg-primary-dark flex h-10 w-full items-center space-x-1 rounded-t px-1.5">
<DropdownMenu>
@@ -76,49 +67,7 @@ export const SegmentationSelectorHeader: React.FC<{ children?: React.ReactNode }
<Icons.More className="h-6 w-6" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem onClick={() => onSegmentationAdd(activeSegmentation.id)}>
<Icons.Add className="text-foreground" />
<span className="pl-2">{t('Create New Segmentation')}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>{t('Manage Current Segmentation')}</DropdownMenuLabel>
<DropdownMenuItem onClick={() => onSegmentationRemoveFromViewport(activeSegmentation.id)}>
<Icons.Series className="text-foreground" />
<span className="pl-2">{t('Remove from Viewport')}</span>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onSegmentationEdit(activeSegmentation.id)}>
<Icons.Rename className="text-foreground" />
<span className="pl-2">{t('Rename')}</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger
disabled={!allowExport}
className="pl-1"
>
<Icons.Export className="text-foreground" />
<span className="pl-2">{t('Export & Download')}</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem onClick={() => storeSegmentation(activeSegmentation.id)}>
{t('Export DICOM SEG')}
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onSegmentationDownload(activeSegmentation.id)}>
{t('Download DICOM SEG')}
</DropdownMenuItem>
<DropdownMenuItem onClick={() => onSegmentationDownloadRTSS(activeSegmentation.id)}>
{t('Download DICOM RTSTRUCT')}
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => onSegmentationDelete(activeSegmentation.id)}>
<Icons.Delete className="text-red-600" />
<span className="pl-2 text-red-600">{t('Delete')}</span>
</DropdownMenuItem>
</DropdownMenuContent>
{childrenWithProps}
</DropdownMenu>
<Select
onValueChange={value => onSegmentationClick(value)}