From 2e4517afcb7fe9b2604f9c884f69cb2b50b2a4b5 Mon Sep 17 00:00:00 2001 From: Maximilian Kaske <56969857+mxkaske@users.noreply.github.com> Date: Tue, 13 May 2025 22:02:55 +0200 Subject: [PATCH] feat: copy id for api visibility (#1250) * chore: add copy id buttons * fix: order * feat: tooltip --- .../(dashboard)/monitors/[id]/layout.tsx | 2 ++ .../(dashboard)/notifications/[id]/layout.tsx | 2 ++ .../(dashboard)/status-pages/[id]/layout.tsx | 10 +++--- .../maintenance/data-table-row-actions.tsx | 11 ++++++ .../monitor/data-table-row-actions.tsx | 11 ++++++ .../notification/data-table-row-actions.tsx | 11 ++++++ .../status-page/data-table-row-actions.tsx | 9 +++++ .../status-report/data-table-row-actions.tsx | 11 ++++++ .../components/layout/header/copy-button.tsx | 36 +++++++++++++++++++ apps/web/src/hooks/use-copy-to-clipboard.ts | 8 +++-- 10 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 apps/web/src/components/layout/header/copy-button.tsx diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/layout.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/layout.tsx index 9033319cb..cc2214d62 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/layout.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/layout.tsx @@ -4,6 +4,7 @@ import { Badge } from "@openstatus/ui/src/components/badge"; import { Header } from "@/components/dashboard/header"; import AppPageWithSidebarLayout from "@/components/layout/app-page-with-sidebar-layout"; +import { CopyButton } from "@/components/layout/header/copy-button"; import { JobTypeIconWithTooltip } from "@/components/monitor/job-type-icon-with-tooltip"; import { NotificationIconWithTooltip } from "@/components/monitor/notification-icon-with-tooltip"; import { StatusDotWithTooltip } from "@/components/monitor/status-dot-with-tooltip"; @@ -82,6 +83,7 @@ export default async function Layout(props: { /> } + actions={} /> {children} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/[id]/layout.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/[id]/layout.tsx index 84b31f950..966081fe7 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/[id]/layout.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/[id]/layout.tsx @@ -2,6 +2,7 @@ import { notFound } from "next/navigation"; import { Header } from "@/components/dashboard/header"; import AppPageWithSidebarLayout from "@/components/layout/app-page-with-sidebar-layout"; +import { CopyButton } from "@/components/layout/header/copy-button"; import { api } from "@/trpc/server"; export default async function Layout(props: { @@ -27,6 +28,7 @@ export default async function Layout(props: {
{notification.provider}} + actions={} /> {children} diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/layout.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/layout.tsx index 8ea399ab6..73740598d 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/layout.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/layout.tsx @@ -6,6 +6,7 @@ import { Button } from "@openstatus/ui/src/components/button"; import { getBaseUrl } from "@/app/status-page/[domain]/utils"; import { Header } from "@/components/dashboard/header"; import AppPageWithSidebarLayout from "@/components/layout/app-page-with-sidebar-layout"; +import { CopyButton } from "@/components/layout/header/copy-button"; import { api } from "@/trpc/server"; export default async function Layout(props: { @@ -31,8 +32,9 @@ export default async function Layout(props: {
+ actions={[ + , + - } + , + ]} /> {children} diff --git a/apps/web/src/components/data-table/maintenance/data-table-row-actions.tsx b/apps/web/src/components/data-table/maintenance/data-table-row-actions.tsx index 9b4cf0afe..6d30ded01 100644 --- a/apps/web/src/components/data-table/maintenance/data-table-row-actions.tsx +++ b/apps/web/src/components/data-table/maintenance/data-table-row-actions.tsx @@ -25,6 +25,7 @@ import { } from "@openstatus/ui"; import { LoadingAnimation } from "@/components/loading-animation"; +import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; import { toastAction } from "@/lib/toast"; import { api } from "@/trpc/client"; @@ -39,6 +40,7 @@ export function DataTableRowActions({ const router = useRouter(); const [alertOpen, setAlertOpen] = React.useState(false); const [isPending, startTransition] = React.useTransition(); + const { copy } = useCopyToClipboard(); async function onDelete() { startTransition(async () => { @@ -70,6 +72,15 @@ export function DataTableRowActions({ Edit + + copy(`${maintenance.id}`, { + withToast: `Copied ID '${maintenance.id}'`, + }) + } + > + Copy ID + Delete diff --git a/apps/web/src/components/data-table/monitor/data-table-row-actions.tsx b/apps/web/src/components/data-table/monitor/data-table-row-actions.tsx index 8a5069c1a..609540a26 100644 --- a/apps/web/src/components/data-table/monitor/data-table-row-actions.tsx +++ b/apps/web/src/components/data-table/monitor/data-table-row-actions.tsx @@ -32,6 +32,7 @@ import { toast, toastAction } from "@/lib/toast"; import { api } from "@/trpc/client"; import type { TCPResponse } from "@/app/api/checker/test/tcp/schema"; +import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; interface DataTableRowActionsProps { row: Row; @@ -46,6 +47,7 @@ export function DataTableRowActions({ const router = useRouter(); const [alertOpen, setAlertOpen] = useState(false); const [isPending, startTransition] = useTransition(); + const { copy } = useCopyToClipboard(); async function onDelete() { startTransition(async () => { @@ -155,6 +157,15 @@ export function DataTableRowActions({ Clone Test + + copy(`${monitor.id}`, { + withToast: `Copied ID '${monitor.id}'`, + }) + } + > + Copy ID + diff --git a/apps/web/src/components/data-table/notification/data-table-row-actions.tsx b/apps/web/src/components/data-table/notification/data-table-row-actions.tsx index c0547f221..a55e58a61 100644 --- a/apps/web/src/components/data-table/notification/data-table-row-actions.tsx +++ b/apps/web/src/components/data-table/notification/data-table-row-actions.tsx @@ -26,6 +26,7 @@ import { } from "@openstatus/ui"; import { LoadingAnimation } from "@/components/loading-animation"; +import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; import { toastAction } from "@/lib/toast"; import { api } from "@/trpc/client"; @@ -40,6 +41,7 @@ export function DataTableRowActions({ const router = useRouter(); const [alertOpen, setAlertOpen] = React.useState(false); const [isPending, startTransition] = React.useTransition(); + const { copy } = useCopyToClipboard(); async function onDelete() { startTransition(async () => { @@ -73,6 +75,15 @@ export function DataTableRowActions({ Edit + + copy(`${notification.id}`, { + withToast: `Copied ID '${notification.id}'`, + }) + } + > + Copy ID + diff --git a/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx b/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx index 9a2939145..34ecf1bca 100644 --- a/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx +++ b/apps/web/src/components/data-table/status-page/data-table-row-actions.tsx @@ -105,6 +105,15 @@ export function DataTableRowActions({ > Visit + + copy(`${page.id}`, { + withToast: `Copied ID '${page.id}'`, + }) + } + > + Copy ID + Create Report diff --git a/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx b/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx index 944272c55..fe2148f67 100644 --- a/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx +++ b/apps/web/src/components/data-table/status-report/data-table-row-actions.tsx @@ -25,6 +25,7 @@ import { } from "@openstatus/ui"; import { LoadingAnimation } from "@/components/loading-animation"; +import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; import { toastAction } from "@/lib/toast"; import { api } from "@/trpc/client"; @@ -39,6 +40,7 @@ export function DataTableRowActions({ const router = useRouter(); const [alertOpen, setAlertOpen] = React.useState(false); const [isPending, startTransition] = React.useTransition(); + const { copy } = useCopyToClipboard(); async function onDelete() { startTransition(async () => { @@ -75,6 +77,15 @@ export function DataTableRowActions({ View + + copy(`${statusReport.id}`, { + withToast: `Copied ID '${statusReport.id}'`, + }) + } + > + Copy ID + Delete diff --git a/apps/web/src/components/layout/header/copy-button.tsx b/apps/web/src/components/layout/header/copy-button.tsx new file mode 100644 index 000000000..c0198bb6c --- /dev/null +++ b/apps/web/src/components/layout/header/copy-button.tsx @@ -0,0 +1,36 @@ +"use client"; + +import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; +import { + Button, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@openstatus/ui"; +import { Copy } from "lucide-react"; + +export function CopyButton({ id }: { id: string | number }) { + const { copy } = useCopyToClipboard(); + return ( + + + + + + Copy ID for API usage + + + ); +} diff --git a/apps/web/src/hooks/use-copy-to-clipboard.ts b/apps/web/src/hooks/use-copy-to-clipboard.ts index 121d01c1f..612304fe0 100644 --- a/apps/web/src/hooks/use-copy-to-clipboard.ts +++ b/apps/web/src/hooks/use-copy-to-clipboard.ts @@ -10,7 +10,7 @@ export function useCopyToClipboard() { { timeout = 3000, withToast = false, - }: { timeout?: number; withToast?: boolean }, + }: { timeout?: number; withToast?: boolean | string }, ) => { if (!navigator?.clipboard) { console.warn("Clipboard not supported"); @@ -28,7 +28,11 @@ export function useCopyToClipboard() { } if (withToast) { - toast.success("Copied to clipboard"); + if (typeof withToast === "string") { + toast.success(withToast); + } else { + toast.success("Copied to clipboard"); + } } return true; -- 2.51.2