more ui/ux enhancements around labels and tables

This commit is contained in:
miloschwartz
2026-05-26 22:26:54 -07:00
parent 05e4ad3200
commit 938e9b0d49
13 changed files with 246 additions and 276 deletions

View File

@@ -27,20 +27,18 @@ export default function SiteInfoCard({}: ClientInfoCardProps) {
return (
<Alert>
<AlertDescription>
<InfoSections cols={3}>
<InfoSections cols={userDisplayName ? 3 : 2}>
<InfoSection>
<InfoSectionTitle>{t("name")}</InfoSectionTitle>
<InfoSectionContent>{client.name}</InfoSectionContent>
</InfoSection>
<InfoSection>
<InfoSectionTitle>
{userDisplayName ? t("user") : t("identifier")}
</InfoSectionTitle>
<InfoSectionContent>
<div className="flex flex-wrap items-center gap-2">
<span>{userDisplayName || client.niceId}</span>
{userDisplayName &&
(client.userType ?? "internal") !==
{userDisplayName ? (
<InfoSection>
<InfoSectionTitle>{t("user")}</InfoSectionTitle>
<InfoSectionContent>
<div className="flex flex-wrap items-center gap-2">
<span>{userDisplayName}</span>
{(client.userType ?? "internal") !==
"internal" && (
<IdpTypeBadge
type={client.userType ?? "oidc"}
@@ -54,9 +52,10 @@ export default function SiteInfoCard({}: ClientInfoCardProps) {
}
/>
)}
</div>
</InfoSectionContent>
</InfoSection>
</div>
</InfoSectionContent>
</InfoSection>
) : null}
<InfoSection>
<InfoSectionTitle>{t("status")}</InfoSectionTitle>
<InfoSectionContent>

View File

@@ -29,8 +29,7 @@ import {
ChevronDown,
ChevronsUpDownIcon,
Funnel,
MoreHorizontal,
PlusIcon
MoreHorizontal
} from "lucide-react";
import { useTranslations } from "next-intl";
import Link from "next/link";
@@ -40,7 +39,6 @@ import {
startTransition,
useEffect,
useMemo,
useOptimistic,
useState,
useTransition
} from "react";
@@ -62,10 +60,10 @@ import { ResourceAccessCertIndicator } from "@app/components/ResourceAccessCertI
import { build } from "@server/build";
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { LabelBadge } from "./label-badge";
import { LabelOverflowBadge } from "./label-overflow-badge";
import { LabelsSelector, type SelectedLabel } from "./labels-selector";
import { type SelectedLabel } from "./labels-selector";
import { TableLabelsCell } from "./TableLabelsCell";
import { LabelColumnFilterButton } from "./LabelColumnFilterButton";
import { useLocalLabels } from "@app/hooks/useLocalLabels";
export type InternalResourceSiteRow = ResourceSiteRow;
@@ -164,12 +162,12 @@ export default function ClientResourcesTable({
const { isPaidUser } = usePaidStatus();
const isLabelFeatureEnabled = isPaidUser(tierMatrix.labels);
useEffect(() => {
const interval = setInterval(() => {
router.refresh();
}, 30_000);
return () => clearInterval(interval);
}, [router]);
// useEffect(() => {
// const interval = setInterval(() => {
// router.refresh();
// }, 30_000);
// return () => clearInterval(interval);
// }, [router]);
const siteIdQ = searchParams.get("siteId");
const siteIdNum = siteIdQ ? parseInt(siteIdQ, 10) : NaN;
@@ -700,27 +698,28 @@ function ClientResourceLabelCell({
}: ClientResourceLabelCellProps) {
const t = useTranslations();
const api = createApiClient(useEnvContext());
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const router = useRouter();
const labels = resource.labels ?? [];
const [optimisticLabels, setOptimisticLabels] = useOptimistic(labels);
const [localLabels, setLocalLabels] = useLocalLabels(
resource.labels,
resource.id
);
function toggleResourceLabel(
label: SelectedLabel,
action: "attach" | "detach"
) {
startTransition(async () => {
const previousLabels = localLabels;
void (async () => {
try {
if (action === "attach") {
setOptimisticLabels([...optimisticLabels, label]);
setLocalLabels([...previousLabels, label]);
await api.put(
`/org/${orgId}/label/${label.labelId}/attach`,
{ siteResourceId: resource.id }
);
} else {
setOptimisticLabels(
optimisticLabels.filter(
setLocalLabels(
previousLabels.filter(
(lb) => lb.labelId !== label.labelId
)
);
@@ -730,54 +729,21 @@ function ClientResourceLabelCell({
);
}
} catch (e) {
setLocalLabels(previousLabels);
toast({
title: t("error"),
description: formatAxiosError(e, t("errorOccurred")),
variant: "destructive"
});
} finally {
router.refresh();
}
});
})();
}
const visibleLabels = optimisticLabels.slice(0, 3);
const overflowLabels = optimisticLabels.slice(3);
return (
<div className="inline-flex w-full min-w-0 flex-nowrap items-center gap-1 overflow-hidden">
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
<PopoverTrigger asChild>
<Button
size="icon"
variant="outline"
className="size-auto shrink-0 rounded-full p-1"
title={t("addLabels")}
>
<span className="sr-only">{t("addLabels")}</span>
<PlusIcon className="size-3" />
</Button>
</PopoverTrigger>
<PopoverContent align="center" className="p-0 w-full">
<LabelsSelector
orgId={orgId}
selectedLabels={optimisticLabels}
toggleLabel={toggleResourceLabel}
/>
</PopoverContent>
</Popover>
{visibleLabels.map((label) => (
<LabelBadge
key={label.labelId}
className="shrink-0"
onClick={() => setIsPopoverOpen(true)}
{...label}
/>
))}
<LabelOverflowBadge
labels={overflowLabels}
onClick={() => setIsPopoverOpen(true)}
/>
</div>
<TableLabelsCell
orgId={orgId}
localLabels={localLabels}
toggleLabel={toggleResourceLabel}
/>
);
}

View File

@@ -122,7 +122,7 @@ export default function ExitNodesTable({
},
{
accessorKey: "online",
friendlyName: t("online"),
friendlyName: t("status"),
header: ({ column }) => {
return (
<Button
@@ -131,7 +131,7 @@ export default function ExitNodesTable({
column.toggleSorting(column.getIsSorted() === "asc")
}
>
{t("online")}
{t("status")}
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);

View File

@@ -163,12 +163,12 @@ export default function HealthChecksTable({
});
}
useEffect(() => {
const interval = setInterval(() => {
router.refresh();
}, 30_000);
return () => clearInterval(interval);
}, [router]);
// useEffect(() => {
// const interval = setInterval(() => {
// router.refresh();
// }, 30_000);
// return () => clearInterval(interval);
// }, [router]);
const handlePaginationChange = (newState: PaginationState) => {
searchParams.set("page", (newState.pageIndex + 1).toString());

View File

@@ -25,7 +25,6 @@ import {
ChevronsUpDownIcon,
CircleSlash,
MoreHorizontal,
PlusIcon
} from "lucide-react";
import { useTranslations } from "next-intl";
import Link from "next/link";
@@ -33,20 +32,18 @@ import { useRouter } from "next/navigation";
import {
startTransition,
useMemo,
useOptimistic,
useState,
useTransition
} from "react";
import { useDebouncedCallback } from "use-debounce";
import z from "zod";
import { ColumnFilterButton } from "./ColumnFilterButton";
import { LabelBadge } from "./label-badge";
import { LabelOverflowBadge } from "./label-overflow-badge";
import { LabelsSelector, type SelectedLabel } from "./labels-selector";
import { type SelectedLabel } from "./labels-selector";
import { TableLabelsCell } from "./TableLabelsCell";
import { Badge } from "./ui/badge";
import { ControlledDataTable } from "./ui/controlled-data-table";
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
import { LabelColumnFilterButton } from "./LabelColumnFilterButton";
import { useLocalLabels } from "@app/hooks/useLocalLabels";
export type ClientRow = {
id: number;
@@ -277,7 +274,7 @@ export default function MachineClientsTable({
},
{
accessorKey: "online",
friendlyName: t("online"),
friendlyName: t("status"),
header: () => {
return (
<ColumnFilterButton
@@ -299,7 +296,7 @@ export default function MachineClientsTable({
}
searchPlaceholder={t("searchPlaceholder")}
emptyMessage={t("emptySearchOptions")}
label={t("online")}
label={t("status")}
className="p-3"
/>
);
@@ -617,27 +614,25 @@ function MachineClientLabelCell({
}: MachineClientLabelCellProps) {
const t = useTranslations();
const api = createApiClient(useEnvContext());
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const router = useRouter();
const labels = client.labels ?? [];
const [optimisticLabels, setOptimisticLabels] = useOptimistic(labels);
const [localLabels, setLocalLabels] = useLocalLabels(client.labels, client.id);
function toggleClientLabel(
label: SelectedLabel,
action: "attach" | "detach"
) {
startTransition(async () => {
const previousLabels = localLabels;
void (async () => {
try {
if (action === "attach") {
setOptimisticLabels([...optimisticLabels, label]);
setLocalLabels([...previousLabels, label]);
await api.put(
`/org/${orgId}/label/${label.labelId}/attach`,
{ clientId: client.id }
);
} else {
setOptimisticLabels(
optimisticLabels.filter(
setLocalLabels(
previousLabels.filter(
(lb) => lb.labelId !== label.labelId
)
);
@@ -647,54 +642,21 @@ function MachineClientLabelCell({
);
}
} catch (e) {
setLocalLabels(previousLabels);
toast({
title: t("error"),
description: formatAxiosError(e, t("errorOccurred")),
variant: "destructive"
});
} finally {
router.refresh();
}
});
})();
}
const visibleLabels = optimisticLabels.slice(0, 3);
const overflowLabels = optimisticLabels.slice(3);
return (
<div className="inline-flex w-full min-w-0 flex-nowrap items-center gap-1 overflow-hidden">
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
<PopoverTrigger asChild>
<Button
size="icon"
variant="outline"
className="size-auto shrink-0 rounded-full p-1"
title={t("addLabels")}
>
<span className="sr-only">{t("addLabels")}</span>
<PlusIcon className="size-3" />
</Button>
</PopoverTrigger>
<PopoverContent align="center" className="p-0 w-full">
<LabelsSelector
orgId={orgId}
selectedLabels={optimisticLabels}
toggleLabel={toggleClientLabel}
/>
</PopoverContent>
</Popover>
{visibleLabels.map((label) => (
<LabelBadge
key={label.labelId}
className="shrink-0"
onClick={() => setIsPopoverOpen(true)}
{...label}
/>
))}
<LabelOverflowBadge
labels={overflowLabels}
onClick={() => setIsPopoverOpen(true)}
/>
</div>
<TableLabelsCell
orgId={orgId}
localLabels={localLabels}
toggleLabel={toggleClientLabel}
/>
);
}

View File

@@ -70,10 +70,10 @@ import z from "zod";
import { ColumnFilterButton } from "./ColumnFilterButton";
import { ControlledDataTable } from "./ui/controlled-data-table";
import UptimeMiniBar from "./UptimeMiniBar";
import { LabelsSelector, type SelectedLabel } from "./labels-selector";
import { LabelBadge } from "./label-badge";
import { LabelOverflowBadge } from "./label-overflow-badge";
import { type SelectedLabel } from "./labels-selector";
import { LabelColumnFilterButton } from "./LabelColumnFilterButton";
import { useLocalLabels } from "@app/hooks/useLocalLabels";
import { TableLabelsCell } from "./TableLabelsCell";
export type TargetHealth = {
targetId: number;
@@ -171,12 +171,12 @@ export default function ProxyResourcesTable({
};
}, [initialFilterSite, siteIdQ, siteIdNum, t]);
useEffect(() => {
const interval = setInterval(() => {
router.refresh();
}, 30_000);
return () => clearInterval(interval);
}, [router]);
// useEffect(() => {
// const interval = setInterval(() => {
// router.refresh();
// }, 30_000);
// return () => clearInterval(interval);
// }, [router]);
const refreshData = () => {
startTransition(() => {
@@ -766,29 +766,29 @@ function ResourceLabelCell({ resource, orgId }: ResourceLabelCellProps) {
const api = createApiClient(useEnvContext());
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const router = useRouter();
const labels = resource.labels ?? [];
const [optimisticLabels, setOptimisticLabels] = useOptimistic(labels);
const [localLabels, setLocalLabels] = useLocalLabels(
resource.labels,
resource.id
);
function toggleSiteLabel(
label: SelectedLabel,
action: "attach" | "detach"
) {
startTransition(async () => {
const previousLabels = localLabels;
void (async () => {
try {
if (action === "attach") {
setOptimisticLabels([...optimisticLabels, label]);
setLocalLabels([...previousLabels, label]);
await api.put(
`/org/${orgId}/label/${label.labelId}/attach`,
{ resourceId: resource.id }
);
} else {
setOptimisticLabels(
optimisticLabels.filter(
setLocalLabels(
previousLabels.filter(
(lb) => lb.labelId !== label.labelId
)
);
@@ -798,55 +798,22 @@ function ResourceLabelCell({ resource, orgId }: ResourceLabelCellProps) {
);
}
} catch (e) {
setLocalLabels(previousLabels);
toast({
title: t("error"),
description: formatAxiosError(e, t("errorOccurred")),
variant: "destructive"
});
} finally {
router.refresh();
}
});
})();
}
const visibleLabels = optimisticLabels.slice(0, 3);
const overflowLabels = optimisticLabels.slice(3);
return (
<div className="inline-flex w-full min-w-0 flex-nowrap items-center gap-1 overflow-hidden">
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
<PopoverTrigger asChild>
<Button
size="icon"
variant="outline"
className="size-auto shrink-0 rounded-full p-1"
title={t("addLabels")}
>
<span className="sr-only">{t("addLabels")}</span>
<PlusIcon className="size-3" />
</Button>
</PopoverTrigger>
<PopoverContent align="center" className="p-0 w-full">
<LabelsSelector
orgId={orgId}
selectedLabels={optimisticLabels}
toggleLabel={toggleSiteLabel}
/>
</PopoverContent>
</Popover>
{visibleLabels.map((label) => (
<LabelBadge
key={label.labelId}
className="shrink-0"
onClick={() => setIsPopoverOpen(true)}
{...label}
/>
))}
<LabelOverflowBadge
labels={overflowLabels}
onClick={() => setIsPopoverOpen(true)}
/>
</div>
<TableLabelsCell
orgId={orgId}
localLabels={localLabels}
toggleLabel={toggleSiteLabel}
/>
);
}

View File

@@ -36,15 +36,7 @@ export default function ResourceInfoBox({}: ResourceInfoBoxType) {
<Alert>
<AlertDescription>
{/* 4 cols because of the certs */}
<InfoSections cols={resource.http && build != "oss" ? 6 : 5}>
<InfoSection>
<InfoSectionTitle>{t("identifier")}</InfoSectionTitle>
<InfoSectionContent>
<span className="inline-flex items-center">
{resource.niceId}
</span>
</InfoSectionContent>
</InfoSection>
<InfoSections cols={resource.http && build != "oss" ? 5 : 4}>
{resource.http ? (
<>
<InfoSection>

View File

@@ -61,8 +61,7 @@ export default function SiteInfoCard({}: SiteInfoCardProps) {
return (
<Alert>
<AlertDescription>
<InfoSections cols={site.endpoint ? 5 : 4}>
{identifierSection}
<InfoSections cols={site.endpoint ? 4 : 3}>
{statusSection}
<InfoSection>
<InfoSectionTitle>

View File

@@ -37,7 +37,6 @@ import {
ChevronDown,
ChevronsUpDownIcon,
MoreHorizontal,
PlusIcon
} from "lucide-react";
import { useTranslations } from "next-intl";
import Link from "next/link";
@@ -46,7 +45,6 @@ import {
startTransition,
useEffect,
useMemo,
useOptimistic,
useState,
useTransition
} from "react";
@@ -61,11 +59,10 @@ import {
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { cn } from "@app/lib/cn";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { LabelBadge } from "./label-badge";
import { LabelOverflowBadge } from "./label-overflow-badge";
import { LabelsSelector, type SelectedLabel } from "./labels-selector";
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
import { type SelectedLabel } from "./labels-selector";
import { LabelColumnFilterButton } from "./LabelColumnFilterButton";
import { useLocalLabels } from "@app/hooks/useLocalLabels";
import { TableLabelsCell } from "./TableLabelsCell";
export type SiteRow = {
id: number;
@@ -124,12 +121,12 @@ export default function SitesTable({
const api = createApiClient(useEnvContext());
const t = useTranslations();
useEffect(() => {
const interval = setInterval(() => {
router.refresh();
}, 30_000);
return () => clearInterval(interval);
}, []);
// useEffect(() => {
// const interval = setInterval(() => {
// router.refresh();
// }, 30_000);
// return () => clearInterval(interval);
// }, []);
const booleanSearchFilterSchema = z
.enum(["true", "false"])
@@ -225,7 +222,7 @@ export default function SitesTable({
},
{
accessorKey: "online",
friendlyName: t("online"),
friendlyName: t("status"),
header: () => {
return (
<ColumnFilterButton
@@ -241,7 +238,7 @@ export default function SitesTable({
}
searchPlaceholder={t("searchPlaceholder")}
emptyMessage={t("emptySearchOptions")}
label={t("online")}
label={t("status")}
className="p-3"
/>
);
@@ -693,29 +690,26 @@ function SiteLabelCell({ site, orgId }: SiteLabelCellProps) {
const api = createApiClient(useEnvContext());
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const router = useRouter();
const labels = site.labels ?? [];
const [optimisticLabels, setOptimisticLabels] = useOptimistic(labels);
const [localLabels, setLocalLabels] = useLocalLabels(site.labels, site.id);
function toggleSiteLabel(
label: SelectedLabel,
action: "attach" | "detach"
) {
startTransition(async () => {
const previousLabels = localLabels;
void (async () => {
try {
if (action === "attach") {
setOptimisticLabels([...optimisticLabels, label]);
setLocalLabels([...previousLabels, label]);
await api.put(
`/org/${orgId}/label/${label.labelId}/attach`,
{ siteId: site.id }
);
} else {
setOptimisticLabels(
optimisticLabels.filter(
setLocalLabels(
previousLabels.filter(
(lb) => lb.labelId !== label.labelId
)
);
@@ -725,54 +719,21 @@ function SiteLabelCell({ site, orgId }: SiteLabelCellProps) {
);
}
} catch (e) {
setLocalLabels(previousLabels);
toast({
title: t("error"),
description: formatAxiosError(e, t("errorOccurred")),
variant: "destructive"
});
} finally {
router.refresh();
}
});
})();
}
const visibleLabels = optimisticLabels.slice(0, 3);
const overflowLabels = optimisticLabels.slice(3);
return (
<div className="inline-flex w-full min-w-0 flex-nowrap items-center gap-1 overflow-hidden">
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
<PopoverTrigger asChild>
<Button
size="icon"
variant="outline"
className="size-auto shrink-0 rounded-full p-1"
title={t("addLabels")}
>
<span className="sr-only">{t("addLabels")}</span>
<PlusIcon className="size-3" />
</Button>
</PopoverTrigger>
<PopoverContent align="center" className="p-0 w-full">
<LabelsSelector
orgId={orgId}
selectedLabels={optimisticLabels}
toggleLabel={toggleSiteLabel}
/>
</PopoverContent>
</Popover>
{visibleLabels.map((label) => (
<LabelBadge
key={label.labelId}
className="shrink-0"
onClick={() => setIsPopoverOpen(true)}
{...label}
/>
))}
<LabelOverflowBadge
labels={overflowLabels}
onClick={() => setIsPopoverOpen(true)}
/>
</div>
<TableLabelsCell
orgId={orgId}
localLabels={localLabels}
toggleLabel={toggleSiteLabel}
/>
);
}

View File

@@ -0,0 +1,97 @@
"use client";
import { dataTableFilterPopoverContentClassName } from "@app/lib/dataTableFilterPopover";
import type { Measurable } from "@radix-ui/rect";
import { PlusIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { useRef, useState } from "react";
import { LabelBadge } from "./label-badge";
import { LabelOverflowBadge } from "./label-overflow-badge";
import { LabelsSelector, type SelectedLabel } from "./labels-selector";
import { Button } from "./ui/button";
import {
Popover,
PopoverAnchor,
PopoverContent,
PopoverTrigger
} from "./ui/popover";
const MAX_VISIBLE_LABELS = 3;
type TableLabelsCellProps = {
orgId: string;
localLabels: SelectedLabel[];
toggleLabel: (label: SelectedLabel, action: "attach" | "detach") => void;
};
export function TableLabelsCell({
orgId,
localLabels,
toggleLabel
}: TableLabelsCellProps) {
const t = useTranslations();
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const triggerRef = useRef<HTMLButtonElement>(null);
const frozenAnchorRef = useRef<Measurable>({
getBoundingClientRect: () => new DOMRect()
});
const visibleLabels = localLabels.slice(0, MAX_VISIBLE_LABELS);
const overflowLabels = localLabels.slice(MAX_VISIBLE_LABELS);
function handleOpenChange(open: boolean) {
if (open && triggerRef.current) {
const rect = triggerRef.current.getBoundingClientRect();
frozenAnchorRef.current = {
getBoundingClientRect: () => rect
};
}
setIsPopoverOpen(open);
}
return (
<div className="grid w-full min-w-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-1">
<Popover open={isPopoverOpen} onOpenChange={handleOpenChange}>
<PopoverAnchor virtualRef={frozenAnchorRef} />
<PopoverTrigger asChild>
<Button
ref={triggerRef}
size="icon"
variant="outline"
className="size-auto shrink-0 rounded-full p-1"
title={t("addLabels")}
>
<span className="sr-only">{t("addLabels")}</span>
<PlusIcon className="size-3" />
</Button>
</PopoverTrigger>
<PopoverContent
align="start"
side="bottom"
className={`${dataTableFilterPopoverContentClassName} p-0`}
updatePositionStrategy="optimized"
>
<LabelsSelector
orgId={orgId}
selectedLabels={localLabels}
toggleLabel={toggleLabel}
/>
</PopoverContent>
</Popover>
<div className="flex min-w-0 flex-nowrap items-center justify-start gap-1 overflow-hidden">
{visibleLabels.map((label) => (
<LabelBadge
key={label.labelId}
className="shrink-0"
onClick={() => handleOpenChange(true)}
{...label}
/>
))}
<LabelOverflowBadge
labels={overflowLabels}
onClick={() => handleOpenChange(true)}
/>
</div>
</div>
);
}

View File

@@ -405,7 +405,7 @@ export default function UserDevicesTable({
},
{
accessorKey: "online",
friendlyName: t("connected"),
friendlyName: t("status"),
header: () => {
return (
<ColumnFilterButton
@@ -427,7 +427,7 @@ export default function UserDevicesTable({
}
searchPlaceholder={t("searchPlaceholder")}
emptyMessage={t("emptySearchOptions")}
label={t("connected")}
label={t("status")}
className="p-3"
/>
);

View File

@@ -0,0 +1,21 @@
import type { SelectedLabel } from "@app/components/labels-selector";
import { useEffect, useState } from "react";
export function useLocalLabels(
serverLabels: SelectedLabel[] | undefined,
entityId: number
) {
const labels = serverLabels ?? [];
const [localLabels, setLocalLabels] = useState(labels);
const serverLabelIds = labels
.map((label) => label.labelId)
.sort((a, b) => a - b)
.join(",");
useEffect(() => {
setLocalLabels(serverLabels ?? []);
}, [entityId, serverLabelIds]);
return [localLabels, setLocalLabels] as const;
}

View File

@@ -759,7 +759,13 @@ export const logQueries = {
}
}),
access: ({ orgId, filters }: { orgId: string; filters: AccessLogFilters }) =>
access: ({
orgId,
filters
}: {
orgId: string;
filters: AccessLogFilters;
}) =>
queryOptions({
queryKey: ["ACCESS_LOGS", orgId, "ALL", filters] as const,
queryFn: async ({ signal, meta }) => {