From 42e481d049762212f397c6e868d1479c430da5b0 Mon Sep 17 00:00:00 2001 From: ogzhanolguncu Date: Sat, 28 Sep 2024 17:21:20 +0300 Subject: [PATCH] refactor: log details section --- .../logs/log-details/components/log-body.tsx | 46 +++ .../log-details/components/log-footer.tsx | 132 +++++++++ .../log-details/components/log-header.tsx | 40 +++ .../components/request-response-details.tsx | 74 +++++ .../app/(app)/logs/log-details/index.tsx | 267 +----------------- apps/dashboard/app/(app)/logs/page.tsx | 2 +- 6 files changed, 303 insertions(+), 258 deletions(-) create mode 100644 apps/dashboard/app/(app)/logs/log-details/components/log-body.tsx create mode 100644 apps/dashboard/app/(app)/logs/log-details/components/log-footer.tsx create mode 100644 apps/dashboard/app/(app)/logs/log-details/components/log-header.tsx create mode 100644 apps/dashboard/app/(app)/logs/log-details/components/request-response-details.tsx diff --git a/apps/dashboard/app/(app)/logs/log-details/components/log-body.tsx b/apps/dashboard/app/(app)/logs/log-details/components/log-body.tsx new file mode 100644 index 0000000000..2e6a5c875d --- /dev/null +++ b/apps/dashboard/app/(app)/logs/log-details/components/log-body.tsx @@ -0,0 +1,46 @@ +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { toast } from "@/components/ui/toaster"; +import { Copy } from "lucide-react"; +import { highlighter } from ".."; +import type { Log } from "../../data"; +import { getObjectsFromLogs } from "../../utils"; + +type Props = { + log: Log; +}; + +export const LogBody = ({ log }: Props) => { + return ( +
+ + +
+ +
+
+
+ ); +}; diff --git a/apps/dashboard/app/(app)/logs/log-details/components/log-footer.tsx b/apps/dashboard/app/(app)/logs/log-details/components/log-footer.tsx new file mode 100644 index 0000000000..2617bec40e --- /dev/null +++ b/apps/dashboard/app/(app)/logs/log-details/components/log-footer.tsx @@ -0,0 +1,132 @@ +import { Badge } from "@/components/ui/badge"; +import { Card, CardContent } from "@/components/ui/card"; +import { cn } from "@/lib/utils"; +import { format } from "date-fns"; +import { highlighter } from ".."; +import { RED_STATES, YELLOW_STATES } from "../../constants"; +import type { Log } from "../../data"; +import { getRequestHeader, getResponseBodyFieldOutcome } from "../../utils"; +import { RequestResponseDetails } from "./request-response-details"; + +type Props = { + log: Log; +}; +export const LogFooter = ({ log }: Props) => { + return ( + ( + {content} + ), + content: format(log.time, "MMM dd HH:mm:ss.SS"), + tooltipContent: "Copy Time", + tooltipSuccessMessage: "Time copied to clipboard", + }, + { + label: "Host", + description: (content) => ( + {content} + ), + content: log.host, + tooltipContent: "Copy Host", + tooltipSuccessMessage: "Host copied to clipboard", + }, + { + label: "Request Path", + description: (content) => ( + {content} + ), + content: log.path, + tooltipContent: "Copy Request Path", + tooltipSuccessMessage: "Request path copied to clipboard", + }, + { + label: "Request ID", + description: (content) => ( + {content} + ), + content: log.request_id, + tooltipContent: "Copy Request ID", + tooltipSuccessMessage: "Request ID copied to clipboard", + }, + { + label: "Request User Agent", + description: (content) => ( + {content} + ), + content: getRequestHeader(log, "user-agent") ?? "", + tooltipContent: "Copy Request User Agent", + tooltipSuccessMessage: "Request user agent copied to clipboard", + }, + { + label: "Outcome", + description: (content) => { + let contentCopy = content; + if (contentCopy == null) { + contentCopy = "VALID"; + } + return ( + + {content} + + ); + }, + content: getResponseBodyFieldOutcome(log, "code"), + tooltipContent: "Copy Outcome", + tooltipSuccessMessage: "Outcome copied to clipboard", + }, + { + label: "Permissions", + description: (content) => ( + + {content.map((permission) => ( + + {permission} + + ))} + + ), + content: getResponseBodyFieldOutcome(log, "permissions"), + tooltipContent: "Copy Permissions", + tooltipSuccessMessage: "Permissions copied to clipboard", + }, + { + label: "Meta", + description: (content) => ( + + + + ), + content: getResponseBodyFieldOutcome(log, "meta"), + tooltipContent: "Copy Meta", + tooltipSuccessMessage: "Meta copied to clipboard", + }, + ]} + /> + ); +}; diff --git a/apps/dashboard/app/(app)/logs/log-details/components/log-header.tsx b/apps/dashboard/app/(app)/logs/log-details/components/log-header.tsx new file mode 100644 index 0000000000..41df38bb13 --- /dev/null +++ b/apps/dashboard/app/(app)/logs/log-details/components/log-header.tsx @@ -0,0 +1,40 @@ +import { Badge } from "@/components/ui/badge"; +import { cn } from "@/lib/utils"; +import { X } from "lucide-react"; +import type { Log } from "../../data"; + +type Props = { + log: Log; + onClose: () => void; +}; +export const LogHeader = ({ onClose, log }: Props) => { + return ( +
+
+ + POST + +

{log.path}

+
+ +
+ = 400 && "border-red-6 text-red-11" + )} + > + {log.response_status} + + + | + +
+
+ ); +}; diff --git a/apps/dashboard/app/(app)/logs/log-details/components/request-response-details.tsx b/apps/dashboard/app/(app)/logs/log-details/components/request-response-details.tsx new file mode 100644 index 0000000000..cee13e0548 --- /dev/null +++ b/apps/dashboard/app/(app)/logs/log-details/components/request-response-details.tsx @@ -0,0 +1,74 @@ +import { toast } from "@/components/ui/toaster"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; +import type { ReactNode } from "react"; + +type Field = { + label: string; + description: (content: NonNullable) => ReactNode; + content: T | null; + tooltipContent: ReactNode; + tooltipSuccessMessage: string; + className?: string; +}; + +type Props = { + fields: { [K in keyof T]: Field }; + className?: string; +}; +//This function ensures that content is not nil, and if it's an object or array, it has some content. +const isNonEmpty = (content: unknown): boolean => { + if (Array.isArray(content)) { + return content.length > 0; + } + if (typeof content === "object" && content !== null) { + return Object.keys(content).length > 0; + } + return Boolean(content); +}; + +export const RequestResponseDetails = ({ + fields, + className, +}: Props) => { + return ( +
+ {fields.map( + (field, index) => + isNonEmpty(field.content) && ( + // biome-ignore lint/suspicious/noArrayIndexKey: + + + { + navigator.clipboard.writeText( + typeof field.content === "object" + ? JSON.stringify(field.content) + : String(field.content) + ); + toast.success(field.tooltipSuccessMessage); + }} + > + {field.label} + {field.description(field.content as NonNullable)} + + + {field.tooltipContent} + + + + ) + )} +
+ ); +}; diff --git a/apps/dashboard/app/(app)/logs/log-details/index.tsx b/apps/dashboard/app/(app)/logs/log-details/index.tsx index 22eafc5bdd..89cc9cf879 100644 --- a/apps/dashboard/app/(app)/logs/log-details/index.tsx +++ b/apps/dashboard/app/(app)/logs/log-details/index.tsx @@ -1,34 +1,14 @@ -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; -import { cn } from "@/lib/utils"; -import { format } from "date-fns"; -import { Copy, X } from "lucide-react"; import { useState } from "react"; import { createHighlighter } from "shiki"; -import { toast } from "sonner"; import { useDebounceCallback } from "usehooks-ts"; -import { - DEFAULT_DRAGGABLE_WIDTH, - RED_STATES, - YELLOW_STATES, -} from "../constants"; +import { DEFAULT_DRAGGABLE_WIDTH } from "../constants"; import type { Log } from "../data"; -import { - getObjectsFromLogs, - getOutcomeIfValid, - getRequestHeader, - getResponseBodyFieldOutcome, -} from "../utils"; +import { LogBody } from "./components/log-body"; +import { LogFooter } from "./components/log-footer"; +import { LogHeader } from "./components/log-header"; import ResizablePanel from "./resizable-panel"; -const highlighter = await createHighlighter({ +export const highlighter = await createHighlighter({ themes: ["github-light", "github-dark"], langs: ["json"], }); @@ -48,246 +28,19 @@ export const LogDetails = ({ log, onClose }: Props) => { return null; } - const outcome = getOutcomeIfValid(log); - return ( -
-
- - POST - -

/api/simple-test

-
- -
- - 400 - - | - -
-
-
- - -
- -
-
-
-
- - - { - navigator.clipboard.writeText(String(log.time)); - toast.success("Time copied to clipboard"); - }} - > - Time - - {format(log.time, "MMM dd HH:mm:ss.SS")} - - - Copy Time - - - - - - { - navigator.clipboard.writeText(String(log.host)); - toast.success("Host copied to clipboard"); - }} - > - Host - {log.host} - - Copy Host - - - - - - { - navigator.clipboard.writeText(log.path); - toast.success("Request path copied to clipboard"); - }} - > - Request Path - {log.path} - - Copy Request Path - - - - - { - navigator.clipboard.writeText(log.request_id); - toast.success("Request ID copied to clipboard"); - }} - > - Request ID - {log.request_id} - - Copy Request ID - - - - - { - navigator.clipboard.writeText( - getRequestHeader(log, "user-agent") ?? "" - ); - toast.success("Request user agent copied to clipboard"); - }} - > - - Request User Agent - - - {log.request_headers.at(-1)} - - - Copy Request User Agent - - - - - { - navigator.clipboard.writeText( - JSON.stringify(getResponseBodyFieldOutcome(log, "code")) - ); - toast.success("Request user agent copied to clipboard"); - }} - > - Outcome - - - {getResponseBodyFieldOutcome(log, "code")} - - - - Copy Outcome - - - - - { - navigator.clipboard.writeText( - JSON.stringify( - getResponseBodyFieldOutcome(log, "permissions") - ) - ); - toast.success("Request user agent copied to clipboard"); - }} - > - Permissions - - {( - getResponseBodyFieldOutcome(log, "permissions") as string[] - ).map((permission) => ( - {permission} - ))} - - - Copy Permissions - - - - - { - navigator.clipboard.writeText( - JSON.stringify(getResponseBodyFieldOutcome(log, "meta")) - ); - toast.success("Request user agent copied to clipboard"); - }} - > - Meta - - - - - - - Copy Meta - - -
+ + +
); }; diff --git a/apps/dashboard/app/(app)/logs/page.tsx b/apps/dashboard/app/(app)/logs/page.tsx index 10e6561b6b..6d675a84db 100644 --- a/apps/dashboard/app/(app)/logs/page.tsx +++ b/apps/dashboard/app/(app)/logs/page.tsx @@ -83,7 +83,7 @@ export default function Page() {
{log.host}
{log.path}
-
+
{log.response_body}