feat(cluster): enhance swarm settings UI with tooltips and documentation links

- Added tooltips to menu items in the swarm settings for better user guidance.
- Included documentation URLs and descriptions for Health Check, Restart Policy, Placement, Update Config, Rollback Config, Mode, Labels, Stop Grace Period, and Endpoint Spec.
- Updated type assertions in rollback and update config forms for improved type safety.
This commit is contained in:
Mauricio Siu
2026-01-20 16:19:12 +01:00
parent 7e48b2cf29
commit a76147d820
3 changed files with 98 additions and 21 deletions

View File

@@ -1,4 +1,4 @@
import { Settings } from "lucide-react";
import { ExternalLink, Settings } from "lucide-react";
import { useState } from "react";
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
@@ -10,6 +10,12 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
import {
EndpointSpecForm,
@@ -27,6 +33,8 @@ type MenuItem = {
id: string;
label: string;
description: string;
docUrl?: string;
docDescription?: string;
};
const menuItems: MenuItem[] = [
@@ -34,38 +42,81 @@ const menuItems: MenuItem[] = [
id: "health-check",
label: "Health Check",
description: "Configure health check settings",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#healthcheck",
docDescription:
"Configure HEALTHCHECK to test a container's health. Determines if a container is healthy by running a command inside the container.",
},
{
id: "restart-policy",
label: "Restart Policy",
description: "Configure restart policy",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#restart-policy",
docDescription:
"Configure the restart policy for containers in the service. Controls when and how containers should be restarted.",
},
{
id: "placement",
label: "Placement",
description: "Configure placement constraints",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#placement-pref",
docDescription:
"Control which nodes service tasks can be scheduled on. Use constraints, preferences, and platform specifications.",
},
{
id: "update-config",
label: "Update Config",
description: "Configure update strategy",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#update-config",
docDescription:
"Configure how the service should be updated. Controls parallelism, delay, failure action, and order of updates.",
},
{
id: "rollback-config",
label: "Rollback Config",
description: "Configure rollback strategy",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#rollback-config",
docDescription:
"Configure automated rollback on update failure. Similar to update config but applies to rollback operations.",
},
{
id: "mode",
label: "Mode",
description: "Configure service mode",
docUrl: "https://docs.docker.com/reference/cli/docker/service/create/#mode",
docDescription:
"Set service mode to either 'replicated' (default) with a specified number of tasks, or 'global' (one task per node).",
},
{
id: "labels",
label: "Labels",
description: "Configure service labels",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#label",
docDescription:
"Add metadata to services using labels. Labels are key-value pairs for organizing and filtering services.",
},
{ id: "mode", label: "Mode", description: "Configure service mode" },
{ id: "labels", label: "Labels", description: "Configure service labels" },
{
id: "stop-grace-period",
label: "Stop Grace Period",
description: "Configure stop grace period",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#stop-grace-period",
docDescription:
"Time to wait before forcefully killing a container. Given in nanoseconds. Default is 10 seconds.",
},
{
id: "endpoint-spec",
label: "Endpoint Spec",
description: "Configure endpoint specification",
docUrl:
"https://docs.docker.com/reference/cli/docker/service/create/#endpoint-mode",
docDescription:
"Configure endpoint mode for service discovery. Choose between 'vip' (virtual IP) or 'dnsrr' (DNS round-robin).",
},
];
@@ -110,22 +161,48 @@ export const AddSwarmSettings = ({ id, type }: Props) => {
{/* Left Column - Menu */}
<div className="w-64 flex-shrink-0 border-r pr-4 overflow-y-auto">
<nav className="space-y-1">
{menuItems.map((item) => (
<button
key={item.id}
type="button"
onClick={() => setActiveMenu(item.id)}
className={cn(
"w-full text-left px-3 py-2 rounded-md text-sm transition-colors",
activeMenu === item.id
? "bg-primary text-primary-foreground"
: "hover:bg-muted",
)}
>
<div className="font-medium">{item.label}</div>
<div className="text-xs opacity-80">{item.description}</div>
</button>
))}
<TooltipProvider>
{menuItems.map((item) => (
<div key={item.id} className="relative group">
<button
type="button"
onClick={() => setActiveMenu(item.id)}
className={cn(
"w-full text-left px-3 py-2 rounded-md text-sm transition-colors",
activeMenu === item.id
? "bg-primary text-primary-foreground"
: "hover:bg-muted",
)}
>
<div className="flex items-center justify-between gap-2">
<div className="flex-1">
<div className="font-medium">{item.label}</div>
<div className="text-xs opacity-80">
{item.description}
</div>
</div>
{item.docUrl && (
<Tooltip>
<TooltipTrigger asChild>
<a
href={item.docUrl}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
>
<ExternalLink className="size-3.5" />
</a>
</TooltipTrigger>
<TooltipContent side="right" className="max-w-xs">
<p className="text-xs">{item.docDescription}</p>
</TooltipContent>
</Tooltip>
)}
</div>
</button>
</div>
))}
</TooltipProvider>
</nav>
</div>

View File

@@ -103,7 +103,7 @@ export const RollbackConfigForm = ({ id, type }: RollbackConfigFormProps) => {
mysqlId: id || "",
mariadbId: id || "",
mongoId: id || "",
rollbackConfigSwarm: hasAnyValue ? formData : null,
rollbackConfigSwarm: (hasAnyValue ? formData : null) as any,
});
toast.success("Rollback config updated successfully");

View File

@@ -109,7 +109,7 @@ export const UpdateConfigForm = ({ id, type }: UpdateConfigFormProps) => {
mysqlId: id || "",
mariadbId: id || "",
mongoId: id || "",
updateConfigSwarm: hasAnyValue ? formData : null,
updateConfigSwarm: (hasAnyValue ? formData : null) as any,
});
toast.success("Update config updated successfully");