Files
claude code agent ccd5897915 fix(automation): gate stack redeploy on PortainerStackUpdate + bulk/name polish (#10 review)
F1: single-container "Update now" and bulk "Update" now require
PortainerStackUpdate when the resolved path is a stack, disabling the
action with a tooltip / skipping it rather than letting the click 403.

F2: resolveContainerUpdatePath only matches a Docker Compose stack; a
same-named swarm/kubernetes stack is treated as external.

F3: SecondaryActions no longer renders an empty ButtonGroup when all of
recreate/duplicate/update-now are hidden.

F4: bulk update reports an explicit no-op toast and counts containers vs
stacks honestly in the success summary.

F5: bulk toasts use trimmed container names (no leading slash).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 09:42:33 +03:00

87 lines
2.5 KiB
TypeScript

import { Authorized } from '@/react/hooks/useUser';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { ButtonGroup } from '@@/buttons';
import { ContainerId } from '../../types';
import { RecreateButton } from './SecondaryActions/RecreateButton';
import { UpdateNowButton } from './SecondaryActions/UpdateNowButton';
import { DuplicateEditButton } from './SecondaryActions/DuplicateEditButton';
import { useCanRecreateContainer } from './SecondaryActions/useCanRecreateContainer';
import { useCanDuplicateEditContainer } from './SecondaryActions/useCanDuplicateEditContainer';
interface Props {
environmentId: EnvironmentId;
containerId: ContainerId;
nodeName?: string;
containerImage: string;
containerName: string;
containerLabels?: Record<string, string>;
containerAutoRemove: boolean | undefined;
isPortainer: boolean;
partOfSwarmService: boolean;
}
export function SecondaryActions({
environmentId,
containerId,
nodeName,
containerImage,
containerName,
containerLabels,
containerAutoRemove = false,
isPortainer,
partOfSwarmService,
}: Props) {
const displayRecreateButton = useCanRecreateContainer({
autoRemove: containerAutoRemove,
partOfSwarmService,
});
const displayDuplicateEditButton = useCanDuplicateEditContainer({
autoRemove: containerAutoRemove,
partOfSwarmService,
});
return (
<Authorized authorizations="DockerContainerCreate">
{/*
Self-hides unless the image is outdated; renders its own ButtonGroup so
the recreate/duplicate group never shows up empty when both are hidden.
*/}
<UpdateNowButton
environmentId={environmentId}
containerId={containerId}
nodeName={nodeName}
containerImage={containerImage}
containerName={containerName}
labels={containerLabels}
isPortainer={isPortainer}
/>
{(displayRecreateButton || displayDuplicateEditButton) && (
<ButtonGroup>
{displayRecreateButton && (
<RecreateButton
environmentId={environmentId}
containerId={containerId}
nodeName={nodeName}
containerImage={containerImage}
isPortainer={isPortainer}
/>
)}
{displayDuplicateEditButton && (
<DuplicateEditButton
containerId={containerId}
nodeName={nodeName}
isPortainer={isPortainer}
/>
)}
</ButtonGroup>
)}
</Authorized>
);
}