From 01c33ad98b5f826b2a126515ab597018315db6c4 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:26:39 -0600 Subject: [PATCH] feat(ui): add tooltips to service action buttons for improved user guidance - Integrate tooltips for Deploy, Rebuild, Start, and Stop buttons across various service components - Provide context-specific explanations for each action button - Enhance user understanding of service management actions - Consistent tooltip styling and implementation using TooltipProvider --- .../dashboard/application/general/show.tsx | 266 ++++++++++------ .../dashboard/compose/general/actions.tsx | 205 +++++++----- .../mariadb/general/show-general-mariadb.tsx | 205 ++++++++---- .../mongo/general/show-general-mongo.tsx | 216 ++++++++----- .../mysql/general/show-general-mysql.tsx | 206 ++++++++---- .../general/show-general-postgres.tsx | 299 +++++++++++------- .../redis/general/show-general-redis.tsx | 208 ++++++++---- 7 files changed, 1047 insertions(+), 558 deletions(-) diff --git a/apps/dokploy/components/dashboard/application/general/show.tsx b/apps/dokploy/components/dashboard/application/general/show.tsx index 8989ca19..28a50a01 100644 --- a/apps/dokploy/components/dashboard/application/general/show.tsx +++ b/apps/dokploy/components/dashboard/application/general/show.tsx @@ -4,8 +4,22 @@ import { DialogAction } from "@/components/shared/dialog-action"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Switch } from "@/components/ui/switch"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { Ban, CheckCircle2, Hammer, RefreshCcw, Terminal } from "lucide-react"; +import { + Ban, + CheckCircle2, + Hammer, + HelpCircle, + RefreshCcw, + Terminal, +} from "lucide-react"; import { useRouter } from "next/router"; import { toast } from "sonner"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; @@ -41,128 +55,188 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => { Deploy Settings - { - await deploy({ - applicationId: applicationId, - }) - .then(() => { - toast.success("Application deployed successfully"); - refetch(); - router.push( - `/dashboard/project/${data?.projectId}/services/application/${applicationId}?tab=deployments`, - ); - }) - .catch(() => { - toast.error("Error deploying application"); - }); - }} - > - - - { - await reload({ - applicationId: applicationId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Application reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading application"); - }); - }} - > - - - { - await redeploy({ - applicationId: applicationId, - }) - .then(() => { - toast.success("Application rebuilt successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error rebuilding application"); - }); - }} - > - - - - {data?.applicationStatus === "idle" ? ( + { - await start({ + await deploy({ applicationId: applicationId, }) .then(() => { - toast.success("Application started successfully"); + toast.success("Application deployed successfully"); refetch(); + router.push( + `/dashboard/project/${data?.projectId}/services/application/${applicationId}?tab=deployments`, + ); }) .catch(() => { - toast.error("Error starting application"); + toast.error("Error deploying application"); }); }} > - - ) : ( { - await stop({ + await reload({ applicationId: applicationId, + appName: data?.appName || "", }) .then(() => { - toast.success("Application stopped successfully"); + toast.success("Application reloaded successfully"); refetch(); }) .catch(() => { - toast.error("Error stopping application"); + toast.error("Error reloading application"); }); }} > - - )} + { + await redeploy({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application rebuilt successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error rebuilding application"); + }); + }} + > + + + + {data?.applicationStatus === "idle" ? ( + { + await start({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting application"); + }); + }} + > + + + ) : ( + { + await stop({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping application"); + }); + }} + > + + + )} + { api.compose.stop.useMutation(); return (
- { - await deploy({ - composeId: composeId, - }) - .then(() => { - toast.success("Compose deployed successfully"); - refetch(); - router.push( - `/dashboard/project/${data?.project.projectId}/services/compose/${composeId}?tab=deployments`, - ); - }) - .catch(() => { - toast.error("Error deploying compose"); - }); - }} - > - - - { - await redeploy({ - composeId: composeId, - }) - .then(() => { - toast.success("Compose rebuilt successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error rebuilding compose"); - }); - }} - > - - - {data?.composeType === "docker-compose" && - data?.composeStatus === "idle" ? ( + { - await start({ + await deploy({ composeId: composeId, }) .then(() => { - toast.success("Compose started successfully"); + toast.success("Compose deployed successfully"); refetch(); + router.push( + `/dashboard/project/${data?.project.projectId}/services/compose/${composeId}?tab=deployments`, + ); }) .catch(() => { - toast.error("Error starting compose"); + toast.error("Error deploying compose"); }); }} > - - ) : ( { - await stop({ + await redeploy({ composeId: composeId, }) .then(() => { - toast.success("Compose stopped successfully"); + toast.success("Compose rebuilt successfully"); refetch(); }) .catch(() => { - toast.error("Error stopping compose"); + toast.error("Error rebuilding compose"); }); }} > - - )} - + {data?.composeType === "docker-compose" && + data?.composeStatus === "idle" ? ( + { + await start({ + composeId: composeId, + }) + .then(() => { + toast.success("Compose started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting compose"); + }); + }} + > + + + ) : ( + { + await stop({ + composeId: composeId, + }) + .then(() => { + toast.success("Compose stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping compose"); + }); + }} + > + + + )} + { Deploy Settings - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - mariadbId: mariadbId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Mariadb reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Mariadb"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( + { - await start({ - mariadbId: mariadbId, - }) - .then(() => { - toast.success("Mariadb started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Mariadb"); - }); + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); }} > - - ) : ( { - await stop({ + await reload({ mariadbId: mariadbId, + appName: data?.appName || "", }) .then(() => { - toast.success("Mariadb stopped successfully"); + toast.success("Mariadb reloaded successfully"); refetch(); }) .catch(() => { - toast.error("Error stopping Mariadb"); + toast.error("Error reloading Mariadb"); }); }} > - - )} + {data?.applicationStatus === "idle" ? ( + { + await start({ + mariadbId: mariadbId, + }) + .then(() => { + toast.success("Mariadb started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Mariadb"); + }); + }} + > + + + ) : ( + { + await stop({ + mariadbId: mariadbId, + }) + .then(() => { + toast.success("Mariadb stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Mariadb"); + }); + }} + > + + + )} + { Deploy Settings - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - mongoId: mongoId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Mongo reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Mongo"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( + { - await start({ + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); + }} + > + + + { + await reload({ mongoId: mongoId, + appName: data?.appName || "", }) .then(() => { - toast.success("Mongo started successfully"); + toast.success("Mongo reloaded successfully"); refetch(); }) .catch(() => { - toast.error("Error starting Mongo"); + toast.error("Error reloading Mongo"); }); }} > - - ) : ( - { - await stop({ - mongoId: mongoId, - }) - .then(() => { - toast.success("Mongo stopped successfully"); - refetch(); + {data?.applicationStatus === "idle" ? ( + { + await start({ + mongoId: mongoId, }) - .catch(() => { - toast.error("Error stopping Mongo"); - }); - }} - > - - - )} + .then(() => { + toast.success("Mongo started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Mongo"); + }); + }} + > + + + ) : ( + { + await stop({ + mongoId: mongoId, + }) + .then(() => { + toast.success("Mongo stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Mongo"); + }); + }} + > + + + )} + { Deploy Settings - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - mysqlId: mysqlId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Mysql reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Mysql"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( + { - await start({ - mysqlId: mysqlId, - }) - .then(() => { - toast.success("Mysql started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Mysql"); - }); + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); }} > - - ) : ( { - await stop({ + await reload({ mysqlId: mysqlId, + appName: data?.appName || "", }) .then(() => { - toast.success("Mysql stopped successfully"); + toast.success("Mysql reloaded successfully"); refetch(); }) .catch(() => { - toast.error("Error stopping Mysql"); + toast.error("Error reloading Mysql"); }); }} > - - )} - + {data?.applicationStatus === "idle" ? ( + { + await start({ + mysqlId: mysqlId, + }) + .then(() => { + toast.success("Mysql started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Mysql"); + }); + }} + > + + + ) : ( + { + await stop({ + mysqlId: mysqlId, + }) + .then(() => { + toast.success("Mysql stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Mysql"); + }); + }} + > + + + )} + { ); return ( -
- - - General - - - { - setIsDeploying(true); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - - { - await reload({ - postgresId: postgresId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Postgres reloaded successfully"); + <> +
+ + + Deploy Settings + + + + { + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); refetch(); - }) - .catch(() => { - toast.error("Error reloading Postgres"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( - { - await start({ - postgresId: postgresId, - }) - .then(() => { - toast.success("Postgres started successfully"); - refetch(); + }} + > + + + { + await reload({ + postgresId: postgresId, + appName: data?.appName || "", }) - .catch(() => { - toast.error("Error starting Postgres"); - }); - }} + .then(() => { + toast.success("Postgres reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading Postgres"); + }); + }} + > + + + {data?.applicationStatus === "idle" ? ( + { + await start({ + postgresId: postgresId, + }) + .then(() => { + toast.success("Postgres started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Postgres"); + }); + }} + > + + + ) : ( + { + await stop({ + postgresId: postgresId, + }) + .then(() => { + toast.success("Postgres stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Postgres"); + }); + }} + > + + + )} + + - - - ) : ( - { - await stop({ - postgresId: postgresId, - }) - .then(() => { - toast.success("Postgres stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping Postgres"); - }); - }} - > - - - )} - - - - - - - { - setIsDrawerOpen(false); - setFilteredLogs([]); - setIsDeploying(false); - refetch(); - }} - filteredLogs={filteredLogs} - /> -
+ +
+
+ { + setIsDrawerOpen(false); + setFilteredLogs([]); + setIsDeploying(false); + refetch(); + }} + filteredLogs={filteredLogs} + /> +
+ ); }; diff --git a/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx b/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx index e309ef49..d9c2e10a 100644 --- a/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx +++ b/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx @@ -2,12 +2,26 @@ import { DialogAction } from "@/components/shared/dialog-action"; import { DrawerLogs } from "@/components/shared/drawer-logs"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { Ban, CheckCircle2, RefreshCcw, Terminal } from "lucide-react"; +import { + Ban, + CheckCircle2, + HelpCircle, + RefreshCcw, + Terminal, +} from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { type LogLine, parseLogs } from "../../docker/logs/utils"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; + interface Props { redisId: string; } @@ -63,94 +77,150 @@ export const ShowGeneralRedis = ({ redisId }: Props) => { Deploy Settings - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - redisId: redisId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Redis reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Redis"); - }); - }} - > - - - {/* */} - {data?.applicationStatus === "idle" ? ( + { - await start({ - redisId: redisId, - }) - .then(() => { - toast.success("Redis started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Redis"); - }); + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); }} > - - ) : ( { - await stop({ + await reload({ redisId: redisId, + appName: data?.appName || "", }) .then(() => { - toast.success("Redis stopped successfully"); + toast.success("Redis reloaded successfully"); refetch(); }) .catch(() => { - toast.error("Error stopping Redis"); + toast.error("Error reloading Redis"); }); }} > - - )} - + {data?.applicationStatus === "idle" ? ( + { + await start({ + redisId: redisId, + }) + .then(() => { + toast.success("Redis started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Redis"); + }); + }} + > + + + ) : ( + { + await stop({ + redisId: redisId, + }) + .then(() => { + toast.success("Redis stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Redis"); + }); + }} + > + + + )} +