diff --git a/apps/dokploy/components/dashboard/projects/show.tsx b/apps/dokploy/components/dashboard/projects/show.tsx index 783c5bb32..5369a544e 100644 --- a/apps/dokploy/components/dashboard/projects/show.tsx +++ b/apps/dokploy/components/dashboard/projects/show.tsx @@ -14,6 +14,7 @@ import { useEffect, useMemo, useState } from "react"; import { toast } from "sonner"; import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar"; import { DateTooltip } from "@/components/shared/date-tooltip"; +import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input"; import { StatusTooltip } from "@/components/shared/status-tooltip"; import { AlertDialog, @@ -44,7 +45,6 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { FocusShortcutInput } from "@/components/shared/focus-shortcut-input"; import { Select, SelectContent, @@ -52,12 +52,14 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { TimeBadge } from "@/components/ui/time-badge"; import { api } from "@/utils/api"; import { HandleProject } from "./handle-project"; import { ProjectEnvironment } from "./project-environment"; export const ShowProjects = () => { const utils = api.useUtils(); + const { data: isCloud } = api.settings.isCloud.useQuery(); const { data, isLoading } = api.project.all.useQuery(); const { data: auth } = api.user.get.useQuery(); const { mutateAsync } = api.project.remove.useMutation(); @@ -135,6 +137,11 @@ export const ShowProjects = () => { + {!isCloud && ( +
+ +
+ )}
@@ -148,7 +155,6 @@ export const ShowProjects = () => { Create and manage your projects - {(auth?.role === "owner" || auth?.canCreateProjects) && (
@@ -298,7 +304,13 @@ export const ShowProjects = () => { {domain.host} @@ -340,7 +352,13 @@ export const ShowProjects = () => { {domain.host} diff --git a/apps/dokploy/components/layouts/side.tsx b/apps/dokploy/components/layouts/side.tsx index 8d84e260c..7473fe586 100644 --- a/apps/dokploy/components/layouts/side.tsx +++ b/apps/dokploy/components/layouts/side.tsx @@ -83,6 +83,7 @@ import { AddOrganization } from "../dashboard/organization/handle-organization"; import { DialogAction } from "../shared/dialog-action"; import { Logo } from "../shared/logo"; import { Button } from "../ui/button"; +import { TimeBadge } from "../ui/time-badge"; import { UpdateServerButton } from "./update-server"; import { UserNav } from "./user-nav"; @@ -1125,6 +1126,7 @@ export default function Page({ children }: Props) {
+ {!isCloud && }
)} diff --git a/apps/dokploy/components/ui/time-badge.tsx b/apps/dokploy/components/ui/time-badge.tsx new file mode 100644 index 000000000..ea7f1f84e --- /dev/null +++ b/apps/dokploy/components/ui/time-badge.tsx @@ -0,0 +1,58 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { api } from "@/utils/api"; + +export function TimeBadge() { + const { data: serverTime } = api.server.getServerTime.useQuery(undefined); + const [time, setTime] = useState(null); + + useEffect(() => { + if (serverTime?.time) { + setTime(new Date(serverTime.time)); + } + }, [serverTime]); + + useEffect(() => { + const timer = setInterval(() => { + setTime((prevTime) => { + if (!prevTime) return null; + const newTime = new Date(prevTime.getTime() + 1000); + return newTime; + }); + }, 1000); + + return () => { + clearInterval(timer); + }; + }, []); + + if (!time || !serverTime?.timezone) { + return null; + } + + const getUtcOffset = (timeZone: string) => { + const date = new Date(); + const utcDate = new Date(date.toLocaleString("en-US", { timeZone: "UTC" })); + const tzDate = new Date(date.toLocaleString("en-US", { timeZone })); + const offset = (tzDate.getTime() - utcDate.getTime()) / (1000 * 60 * 60); + const sign = offset >= 0 ? "+" : "-"; + const hours = Math.floor(Math.abs(offset)); + const minutes = (Math.abs(offset) * 60) % 60; + return `UTC${sign}${hours.toString().padStart(2, "0")}:${minutes + .toString() + .padStart(2, "0")}`; + }; + + return ( +
+ Server Time: + + {time.toLocaleTimeString()} + + + ({serverTime.timezone} | {getUtcOffset(serverTime.timezone)}) + +
+ ); +} diff --git a/apps/dokploy/server/api/routers/server.ts b/apps/dokploy/server/api/routers/server.ts index d6904a7ec..8a01228f8 100644 --- a/apps/dokploy/server/api/routers/server.ts +++ b/apps/dokploy/server/api/routers/server.ts @@ -383,6 +383,15 @@ export const serverRouter = createTRPCRouter({ const ip = await getPublicIpWithFallback(); return ip; }), + getServerTime: protectedProcedure.query(() => { + if (IS_CLOUD) { + return null; + } + return { + time: new Date(), + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }; + }), getServerMetrics: protectedProcedure .input( z.object({