ccd5897915
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>
87 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|