Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: date select issue on logs page #2764

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"use client";

import { RequestResponseDetails } from "@/app/(app)/logs/components/table/log-details/components/request-response-details";
import { TimestampInfo } from "@/components/timestamp-info";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { FunctionSquare, KeySquare } from "lucide-react";
import type { Data } from "./table/types";

type Props = {
log: Data;
};

export const LogFooter = ({ log }: Props) => {
return (
<RequestResponseDetails
fields={[
{
label: "Time",
description: (content) => (
<TimestampInfo value={content} className="text-[13px] underline decoration-dotted" />
),
content: log.auditLog.time,
tooltipContent: "Copy Time",
tooltipSuccessMessage: "Time copied to clipboard",
},
{
label: "Location",
description: (content) => <span className="text-[13px] font-mono">{content}</span>,
content: log.auditLog.location,
tooltipContent: "Copy Location",
tooltipSuccessMessage: "Location copied to clipboard",
},
{
label: "Actor Details",
description: (content) => {
const { log, user } = content;
return log.actor.type === "user" && user?.imageUrl ? (
<div className="flex justify-end items-center w-full gap-2 max-sm:m-0 max-sm:gap-1 max-sm:text-xs md:flex-grow">
<Avatar className="w-6 h-6">
<AvatarImage src={user.imageUrl} />
<AvatarFallback>{user?.username?.slice(0, 2)}</AvatarFallback>
</Avatar>
<span className="text-sm text-content whitespace-nowrap">
{`${user?.firstName ?? ""} ${user?.lastName ?? ""}`}
</span>
</div>
) : log.actor.type === "key" ? (
<div className="flex items-center w-full gap-2 max-sm:m-0 max-sm:gap-1 max-sm:text-xs md:flex-grow">
<KeySquare className="w-4 h-4" />
<span className="font-mono text-xs text-content">{log.actor.id}</span>
</div>
) : (
<div className="flex items-center w-full gap-2 max-sm:m-0 max-sm:gap-1 max-sm:text-xs md:flex-grow">
<FunctionSquare className="w-4 h-4" />
<span className="font-mono text-xs text-content">{log.actor.id}</span>
</div>
);
},
content: { log: log.auditLog, user: log.user },
className: "whitespace-pre",
tooltipContent: "Copy Actor",
tooltipSuccessMessage: "Actor copied to clipboard",
},
{
label: "User Agent",
description: (content) => (
<span className="text-[13px] font-mono w-[100px] truncate">{content}</span>
),
content: log.auditLog.userAgent,
tooltipContent: "Copy User Agent",
tooltipSuccessMessage: "User Agent copied to clipboard",
},
{
label: "Event",
description: (content) => <span className="text-[13px] font-mono">{content}</span>,
content: log.auditLog.event,
tooltipContent: "Copy Event",
tooltipSuccessMessage: "Event copied to clipboard",
},
{
label: "Description",
description: (content) => (
<span className="text-[13px] font-mono text-end">{content}</span>
),
content: log.auditLog.description,
tooltipContent: "Copy Description",
tooltipSuccessMessage: "Description copied to clipboard",
},
{
label: "Workspace Id",
description: (content) => <span className="text-[13px] font-mono">{content}</span>,
content: log.auditLog.workspaceId,
tooltipContent: "Copy Workspace Id",
tooltipSuccessMessage: "Workspace Id copied to clipboard",
},
]}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Badge } from "@/components/ui/badge";
import { Button } from "@unkey/ui";
import { X } from "lucide-react";
import type { Data } from "./table/types";

type Props = {
log: Data;
onClose: () => void;
};

export const LogHeader = ({ onClose, log }: Props) => {
return (
<div className="border-b-[1px] px-3 py-4 flex justify-between border-border items-center">
<div className="flex gap-2 items-center overflow-hidden">
<Badge variant="secondary" className="bg-transparent shrink-0">
{log.auditLog.event}
</Badge>
</div>
<div className="flex gap-1 items-center shrink-0">
<Button shape="square" variant="ghost" onClick={onClose}>
<X size="22" strokeWidth="1.5" className="text-content/65 cursor-pointer" />
</Button>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { TimestampInfo } from "@/components/timestamp-info";
import { Badge } from "@/components/ui/badge";
import type { Column } from "@/components/virtual-table";
import { cn } from "@unkey/ui/src/lib/utils";
import { FunctionSquare, KeySquare } from "lucide-react";
import type { Data } from "./types";
import { getEventType } from "./utils";

export const columns: Column<Data>[] = [
{
key: "time",
header: "Time",
width: "130px",
render: (log) => (
<TimestampInfo
value={log.auditLog.time}
className="font-mono group-hover:underline decoration-dotted"
/>
),
},
{
key: "actor",
header: "Actor",
width: "10%",
render: (log) => (
<div className="flex items-center">
{log.auditLog.actor.type === "user" && log.user ? (
<div className="flex items-center w-full gap-2 max-sm:m-0 max-sm:gap-1 max-sm:text-xs">
<span className="text-xs whitespace-nowrap">{`${log.user.firstName ?? ""} ${
log.user.lastName ?? ""
}`}</span>
</div>
) : log.auditLog.actor.type === "key" ? (
<div className="flex items-center w-full gap-2 max-sm:m-0 max-sm:gap-1 max-sm:text-xs">
<KeySquare className="w-4 h-4" />
<span className="font-mono text-xs">{log.auditLog.actor.id}</span>
</div>
) : (
<div className="flex items-center w-full gap-2 max-sm:m-0 max-sm:gap-1 max-sm:text-xs">
<FunctionSquare className="w-4 h-4" />
<span className="font-mono text-xs">{log.auditLog.actor.id}</span>
</div>
)}
</div>
),
},
{
key: "action",
header: "Action",
width: "72px",
render: (log) => {
const eventType = getEventType(log.auditLog.event);
const badgeClassName = cn("font-mono capitalize", {
"bg-error-3 text-error-11 hover:bg-error-4": eventType === "delete",
"bg-warning-3 text-warning-11 hover:bg-warning-4": eventType === "update",
"bg-success-3 text-success-11 hover:bg-success-4": eventType === "create",
"bg-accent-3 text-accent-11 hover:bg-accent-4": eventType === "other",
});
return <Badge className={badgeClassName}>{eventType}</Badge>;
},
},
{
key: "event",
header: "Event",
width: "20%",
render: (log) => (
<div className="flex items-center gap-2 text-current font-mono text-xs">
<span>{log.auditLog.event}</span>
</div>
),
},
{
key: "event-description",
header: "Description",
width: "auto",
render: (log) => (
<div className="text-current font-mono px-2 text-xs">{log.auditLog.description}</div>
),
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export const DEFAULT_FETCH_COUNT = 50;

export const eventGroups = {
create: [
"workspace.create",
"gateway.create",
"llmGateway.create",
"api.create",
"key.create",
"ratelimitNamespace.create",
"vercelIntegration.create",
"vercelBinding.create",
"role.create",
"permission.create",
"secret.create",
"webhook.create",
"reporter.create",
"identity.create",
"ratelimit.create",
"auditLogBucket.create",
],
delete: [
"workspace.delete",
"llmGateway.delete",
"api.delete",
"key.delete",
"ratelimitNamespace.delete",
"vercelIntegration.delete",
"vercelBinding.delete",
"role.delete",
"permission.delete",
"webhook.delete",
"identity.delete",
"ratelimit.delete",
"ratelimit.delete_override",
],
update: [
"workspace.update",
"api.update",
"key.update",
"ratelimitNamespace.update",
"vercelIntegration.update",
"vercelBinding.update",
"role.update",
"permission.update",
"secret.update",
"webhook.update",
"identity.update",
"ratelimit.update",
"authorization.connect_role_and_permission",
"authorization.disconnect_role_and_permissions",
"authorization.connect_role_and_key",
"authorization.disconnect_role_and_key",
"authorization.connect_permission_and_key",
"authorization.disconnect_permission_and_key",
"ratelimit.set_override",
],
other: ["workspace.opt_in", "secret.decrypt", "ratelimit.read_override"],
} as const;
Loading
Loading