Files
claude code agent 0bf4e71b79 fix(stacks): keep the stack breadcrumb trail on container attribute sub-tabs
When a container is opened from a stack, the detail tab kept the stack
trail (PR #7) but the attribute sub-tabs (Logs, Stats, Inspect, Console,
Attach) dropped it: those tabs were registered only under the global
docker.containers.container.* tree, so navigating to one left the stack
state (and its inherited params) behind, and each sub-view set a hardcoded
"Containers > ..." breadcrumb.

- Register stack-scoped child states docker.stacks.stack.container.{attach,
  exec,inspect,logs,stats} mirroring the global ones, so the inherited stack
  params survive and the trail can be kept.
- Centralize the breadcrumb logic in containerBreadcrumbs.ts (moved out of
  ItemView, which re-exports it) and add isStackContainerState +
  getContainerSubTabBreadcrumbs + buildStackContainerLinkParams.
- ActionLinksRow links sub-tabs into the stack tree (with stack+container
  params) when opened from a stack, else the global states unchanged.
- InspectView + the logs/stats/console controllers render the stack-aware
  trail; set up-front (no name) so it survives the load window and errors.

Covers regular/external/orphaned stacks and the non-stack fallback,
matching the existing ItemView breadcrumb behavior. New unit tests in
containerBreadcrumbs.test.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 02:25:04 +03:00

132 lines
3.8 KiB
TypeScript

import { FileText, Info, BarChart2, Terminal, Paperclip } from 'lucide-react';
import { useCurrentStateAndParams } from '@uirouter/react';
import { ContainerId } from '@/react/docker/containers/types';
import { useAuthorizations } from '@/react/hooks/useUser';
import { Icon } from '@@/Icon';
import { Button, ButtonGroup } from '@@/buttons';
import { Link } from '@@/Link';
import {
STACK_CONTAINER_STATE_NAME,
buildStackContainerLinkParams,
isStackContainerState,
} from '../containerBreadcrumbs';
interface Props {
containerId: ContainerId;
}
export function ActionLinksRow({ containerId }: Props) {
const { state, params } = useCurrentStateAndParams();
// When the container was opened from a stack, keep the sub-tab links inside
// the stack tree (docker.stacks.stack.container.*) so the stack params are
// preserved and the breadcrumb keeps the stack trail. Otherwise use the
// global container states.
const fromStack = isStackContainerState(state?.name);
const baseState = fromStack
? STACK_CONTAINER_STATE_NAME
: 'docker.containers.container';
const linkParams = fromStack
? buildStackContainerLinkParams(params, containerId)
: { id: containerId };
const { authorized: canLogs } = useAuthorizations(['DockerContainerLogs']);
const { authorized: canInspect } = useAuthorizations([
'DockerContainerInspect',
]);
const { authorized: canStats } = useAuthorizations(['DockerContainerStats']);
const { authorized: canExec } = useAuthorizations(['DockerExecStart']);
const { authorized: canAttach } = useAuthorizations([
'DockerContainerAttach',
]);
const hasAnyAuthorization =
canLogs || canInspect || canStats || canExec || canAttach;
if (!hasAnyAuthorization) {
return null;
}
return (
<tr>
<td colSpan={2}>
<ButtonGroup>
{canLogs && (
<Button
as={Link}
props={{
to: `${baseState}.logs`,
params: linkParams,
}}
data-cy="container-logs-link"
color="link"
>
<Icon icon={FileText} className="lucide space-right" />
Logs
</Button>
)}
{canInspect && (
<Button
as={Link}
props={{
to: `${baseState}.inspect`,
params: linkParams,
}}
data-cy="container-inspect-link"
color="link"
>
<Icon icon={Info} className="lucide space-right" />
Inspect
</Button>
)}
{canStats && (
<Button
as={Link}
props={{
to: `${baseState}.stats`,
params: linkParams,
}}
data-cy="container-stats-link"
color="link"
>
<Icon icon={BarChart2} className="lucide space-right" />
Stats
</Button>
)}
{canExec && (
<Button
as={Link}
props={{
to: `${baseState}.exec`,
params: linkParams,
}}
data-cy="container-console-link"
color="link"
>
<Icon icon={Terminal} className="lucide space-right" />
Console
</Button>
)}
{canAttach && (
<Button
as={Link}
props={{
to: `${baseState}.attach`,
params: linkParams,
}}
data-cy="container-attach-link"
color="link"
>
<Icon icon={Paperclip} className="lucide space-right" />
Attach
</Button>
)}
</ButtonGroup>
</td>
</tr>
);
}