diff --git a/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx b/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx
index f618694..72134eb 100644
--- a/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx
+++ b/frontend-modern/src/components/Docker/DockerUnifiedTable.tsx
@@ -46,18 +46,18 @@ type SearchToken = { key?: string; value: string };
type DockerRow =
| {
- kind: 'container';
- id: string;
- host: DockerHost;
- container: DockerContainer;
- }
+ kind: 'container';
+ id: string;
+ host: DockerHost;
+ container: DockerContainer;
+ }
| {
- kind: 'service';
- id: string;
- host: DockerHost;
- service: DockerService;
- tasks: DockerTask[];
- };
+ kind: 'service';
+ id: string;
+ host: DockerHost;
+ service: DockerService;
+ tasks: DockerTask[];
+ };
interface DockerUnifiedTableProps {
hosts: DockerHost[];
@@ -283,36 +283,36 @@ const PODMAN_METADATA_GROUPS: Array<{
prefixes?: string[];
keys?: string[];
}> = [
- {
- title: 'Pod',
- prefixes: ['io.podman.annotations.pod.', 'io.podman.pod.', 'net.containers.podman.pod.'],
- },
- {
- title: 'Compose',
- prefixes: ['io.podman.compose.'],
- },
- {
- title: 'Auto Update',
- prefixes: ['io.containers.autoupdate.'],
- keys: ['io.containers.autoupdate'],
- },
- {
- title: 'User Namespace',
- keys: ['io.podman.annotations.userns', 'io.containers.userns'],
- },
- {
- title: 'Capabilities',
- keys: ['io.containers.capabilities', 'io.containers.selinux', 'io.containers.seccomp'],
- },
- {
- title: 'Podman Annotations',
- prefixes: ['io.podman.annotations.'],
- },
- {
- title: 'Container Settings',
- prefixes: ['io.containers.'],
- },
-];
+ {
+ title: 'Pod',
+ prefixes: ['io.podman.annotations.pod.', 'io.podman.pod.', 'net.containers.podman.pod.'],
+ },
+ {
+ title: 'Compose',
+ prefixes: ['io.podman.compose.'],
+ },
+ {
+ title: 'Auto Update',
+ prefixes: ['io.containers.autoupdate.'],
+ keys: ['io.containers.autoupdate'],
+ },
+ {
+ title: 'User Namespace',
+ keys: ['io.podman.annotations.userns', 'io.containers.userns'],
+ },
+ {
+ title: 'Capabilities',
+ keys: ['io.containers.capabilities', 'io.containers.selinux', 'io.containers.seccomp'],
+ },
+ {
+ title: 'Podman Annotations',
+ prefixes: ['io.podman.annotations.'],
+ },
+ {
+ title: 'Container Settings',
+ prefixes: ['io.containers.'],
+ },
+ ];
const humanizePodmanKey = (raw: string): string => {
if (!raw) return 'Value';
@@ -1049,9 +1049,8 @@ const DockerContainerRow: Component<{
return (
<>
@@ -1539,11 +1538,10 @@ const DockerContainerRow: Component<{
{rw}
@@ -1819,13 +1817,11 @@ const DockerServiceRow: Component<{
return (
<>
@@ -2356,6 +2352,31 @@ const DockerUnifiedTable: Component = (props) => {
}, 0),
);
+ const degradedContainers = createMemo(() =>
+ groupedRows().reduce((acc, group) => {
+ return (
+ acc +
+ group.rows
+ .filter((row): row is Extract => row.kind === 'container')
+ .filter((row) => {
+ const state = toLower(row.container.state);
+ const health = toLower(row.container.health);
+
+ // Explicitly degraded/error states
+ if (ERROR_CONTAINER_STATES.has(state)) return true;
+
+ // Running but unhealthy
+ if (state === 'running' && health === 'unhealthy') return true;
+
+ // Any other state that is NOT running and NOT stopped
+ if (state !== 'running' && !STOPPED_CONTAINER_STATES.has(state)) return true;
+
+ return false;
+ }).length
+ );
+ }, 0),
+ );
+
const renderRow = (row: DockerRow, grouped: boolean) => {
const resourceId =
row.kind === 'container'
@@ -2579,6 +2600,13 @@ const DockerUnifiedTable: Component = (props) => {
{runningContainers()} running
+ 0}>
+ |
+
+
+ {degradedContainers()} degraded
+
+
|