diff --git a/frontend/src/components/resources/swarm/index.tsx b/frontend/src/components/resources/swarm/index.tsx
index d88e6c0fc..c45cd8361 100644
--- a/frontend/src/components/resources/swarm/index.tsx
+++ b/frontend/src/components/resources/swarm/index.tsx
@@ -14,6 +14,8 @@ import { SwarmTable } from "./table";
import {
swarm_state_intention,
stroke_color_class_by_intention,
+ swarm_node_state_intention,
+ swarm_task_state_intention,
} from "@lib/color";
import { cn, updateLogToHtml } from "@lib/utils";
import { Types } from "komodo_client";
@@ -143,26 +145,89 @@ export type SwarmResourceType =
| "Stack";
export const SWARM_ICONS: {
- [type in SwarmResourceType]: React.FC<{ size?: number; className?: string }>;
+ [type in SwarmResourceType]: React.FC<{
+ swarm_id?: string;
+ resource_id?: string;
+ size?: number;
+ className?: string;
+ }>;
} = {
- Node: ({ size, className }) => (
-
- ),
- Service: ({ size, className }) => (
-
- ),
- Task: ({ size, className }) => (
-
- ),
+ Node: ({ swarm_id, resource_id, size, className }) => {
+ const state = useRead(
+ "ListSwarmNodes",
+ { swarm: swarm_id! },
+ { enabled: !!swarm_id }
+ ).data?.find((node) => resource_id && node.ID === resource_id)?.State;
+ return (
+
+ );
+ },
+ Stack: ({ swarm_id, resource_id, size, className }) => {
+ const state = useRead(
+ "ListSwarmStacks",
+ { swarm: swarm_id! },
+ { enabled: !!swarm_id }
+ ).data?.find((stack) => resource_id && stack.Name === resource_id)?.State;
+ return (
+
+ );
+ },
+ Service: ({ swarm_id, resource_id, size, className }) => {
+ const state = useRead(
+ "ListSwarmServices",
+ { swarm: swarm_id! },
+ { enabled: !!swarm_id }
+ ).data?.find(
+ (service) =>
+ resource_id &&
+ (service.ID === resource_id || service.Name === resource_id)
+ )?.State;
+ return (
+
+ );
+ },
+ Task: ({ swarm_id, resource_id, size, className }) => {
+ const task = useRead(
+ "ListSwarmTasks",
+ { swarm: swarm_id! },
+ { enabled: !!swarm_id }
+ ).data?.find((task) => resource_id && task.ID === resource_id);
+ return (
+
+ );
+ },
Secret: ({ size, className }) => (
),
Config: ({ size, className }) => (
),
- Stack: ({ size, className }) => (
-
- ),
};
export const SwarmResourceLink = ({
@@ -180,10 +245,15 @@ export const SwarmResourceLink = ({
return (
-
- {name ?? "Unknown"}
+
+
+ {name ?? "Unknown"}
+
);
};
diff --git a/frontend/src/components/util.tsx b/frontend/src/components/util.tsx
index 33f8b3647..caa1398f8 100644
--- a/frontend/src/components/util.tsx
+++ b/frontend/src/components/util.tsx
@@ -726,7 +726,7 @@ export const DockerResourceLink = ({
server_id: string;
name: string | undefined;
id?: string;
- type: "container" | "network" | "image" | "volume";
+ type: DockerResourceType;
extra?: ReactNode;
muted?: boolean;
}) => {
@@ -745,7 +745,7 @@ export const DockerResourceLink = ({
{name}
diff --git a/frontend/src/lib/color.ts b/frontend/src/lib/color.ts
index 7a3c76134..d406d68e6 100644
--- a/frontend/src/lib/color.ts
+++ b/frontend/src/lib/color.ts
@@ -144,6 +144,55 @@ export const swarm_state_intention: (
}
};
+export const swarm_node_state_intention: (
+ state?: Types.NodeState
+) => ColorIntention = (state) => {
+ switch (state) {
+ case Types.NodeState.READY:
+ return "Good";
+ case Types.NodeState.DOWN:
+ return "Warning";
+ case Types.NodeState.DISCONNECTED:
+ return "Critical";
+ case Types.NodeState.UNKNOWN:
+ return "Neutral";
+ case undefined:
+ return "None";
+ }
+};
+
+export const swarm_task_state_intention: (
+ state?: Types.TaskState,
+ desired?: Types.TaskState
+) => ColorIntention = (state, desired) => {
+ // Case when its desired running
+ if (desired === Types.TaskState.RUNNING) {
+ if (state === Types.TaskState.RUNNING) {
+ return "Good";
+ } else {
+ return "Critical";
+ }
+ }
+
+ // Case when its desired shutdown
+ if (desired === Types.TaskState.SHUTDOWN) {
+ // If you want it shutdown, then running is critical.
+ if (state === Types.TaskState.RUNNING) {
+ return "Critical";
+ } else {
+ // Otherwise, it is "Down", give neutral color
+ return "Neutral";
+ }
+ }
+
+ // Others
+ if (state === desired) {
+ return "Good";
+ } else {
+ return "Critical";
+ }
+};
+
export const server_state_intention: (
state?: Types.ServerState,
hasVersionMismatch?: boolean
@@ -217,6 +266,8 @@ export const container_state_intention: (
return "Warning";
case Types.ContainerStateStatusEnum.Empty:
return "Unknown";
+ case undefined:
+ return "Unknown";
default:
return "Critical";
}