@@ -504,7 +376,6 @@ export default function GeneralPage() {
onValueChange={(value) =>
handleFilterChange("type", value)
}
- // placeholder=""
searchPlaceholder="Search..."
emptyMessage="None found"
/>
@@ -522,7 +393,7 @@ export default function GeneralPage() {
},
{
accessorKey: "actor",
- header: ({ column }) => {
+ header: () => {
return (
{t("actor")}
@@ -535,7 +406,6 @@ export default function GeneralPage() {
onValueChange={(value) =>
handleFilterChange("actor", value)
}
- // placeholder=""
searchPlaceholder="Search..."
emptyMessage="None found"
/>
@@ -563,16 +433,12 @@ export default function GeneralPage() {
},
{
accessorKey: "actorId",
- header: ({ column }) => {
- return t("actorId");
- },
- cell: ({ row }) => {
- return (
-
- {row.original.actorId || "-"}
-
- );
- }
+ header: () => t("actorId"),
+ cell: ({ row }) => (
+
+ {row.original.actorId || "-"}
+
+ )
}
];
@@ -618,13 +484,10 @@ export default function GeneralPage() {
columns={columns}
data={rows}
title={t("accessLogs")}
- onRefresh={refreshData}
- isRefreshing={isRefreshing}
+ onRefresh={() => refetch()}
+ isRefreshing={isFetching}
onExport={() => startTransition(exportData)}
isExporting={isExporting}
- // isExportDisabled={ // not disabling this because the user should be able to click the button and get the feedback about needing to upgrade the plan
- // !isPaidUser(tierMatrix.accessLogs) || build === "oss"
- // }
onDateRangeChange={handleDateRangeChange}
dateRange={{
start: dateRange.startDate,
@@ -634,14 +497,12 @@ export default function GeneralPage() {
id: "timestamp",
desc: true
}}
- // Server-side pagination props
totalCount={totalCount}
currentPage={currentPage}
pageSize={pageSize}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
isLoading={isLoading}
- // Row expansion props
expandable={true}
renderExpandedRow={renderExpandedRow}
disabled={!isPaidUser(tierMatrix.accessLogs) || build === "oss"}
@@ -649,3 +510,41 @@ export default function GeneralPage() {
>
);
}
+
+function generateSampleAccessLogs(): QueryAccessAuditLogResponse["log"] {
+ const locations = ["US", "DE", "GB", "FR", "JP", "CA", "AU"];
+ const types = ["password", "pincode", "login", "whitelistedEmail", "ssh"];
+ const actors = [
+ "alice@example.com",
+ "bob@example.com",
+ "carol@example.com",
+ null
+ ];
+
+ const now = Math.floor(Date.now() / 1000);
+ const sevenDaysAgo = now - 7 * 24 * 60 * 60;
+
+ return Array.from({ length: 10 }, (_, i) => {
+ const action = Math.random() > 0.3;
+ const actor = actors[Math.floor(Math.random() * actors.length)];
+
+ return {
+ timestamp: Math.floor(
+ sevenDaysAgo + Math.random() * (now - sevenDaysAgo)
+ ),
+ action,
+ orgId: "sample-org",
+ actorType: actor ? "user" : null,
+ actor,
+ actorId: actor ? `user-${i}` : null,
+ resourceId: Math.floor(Math.random() * 5) + 1,
+ resourceNiceId: `resource-${(i % 3) + 1}`,
+ resourceName: `Resource ${(i % 3) + 1}`,
+ ip: `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`,
+ location: locations[Math.floor(Math.random() * locations.length)],
+ userAgent: "Mozilla/5.0",
+ metadata: null,
+ type: types[Math.floor(Math.random() * types.length)]
+ };
+ });
+}
diff --git a/src/app/[orgId]/settings/logs/action/page.tsx b/src/app/[orgId]/settings/logs/action/page.tsx
index 1c2408df0..7ccce8877 100644
--- a/src/app/[orgId]/settings/logs/action/page.tsx
+++ b/src/app/[orgId]/settings/logs/action/page.tsx
@@ -10,14 +10,17 @@ import { useStoredPageSize } from "@app/hooks/useStoredPageSize";
import { toast } from "@app/hooks/useToast";
import { createApiClient } from "@app/lib/api";
import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo";
+import { logQueries } from "@app/lib/queries";
import { build } from "@server/build";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
+import type { QueryActionAuditLogResponse } from "@server/routers/auditLogs/types";
+import { useQuery } from "@tanstack/react-query";
import { ColumnDef } from "@tanstack/react-table";
import axios from "axios";
import { Key, User } from "lucide-react";
import { useTranslations } from "next-intl";
import { useParams, useRouter, useSearchParams } from "next/navigation";
-import { useEffect, useState, useTransition } from "react";
+import { useMemo, useState, useTransition } from "react";
export default function GeneralPage() {
const router = useRouter();
@@ -28,18 +31,8 @@ export default function GeneralPage() {
const { isPaidUser } = usePaidStatus();
- const [rows, setRows] = useState
([]);
- const [isRefreshing, setIsRefreshing] = useState(false);
const [isExporting, startTransition] = useTransition();
- const [filterAttributes, setFilterAttributes] = useState<{
- actors: string[];
- actions: string[];
- }>({
- actors: [],
- actions: []
- });
- // Filter states - unified object for all filters
const [filters, setFilters] = useState<{
action?: string;
actor?: string;
@@ -48,40 +41,21 @@ export default function GeneralPage() {
actor: searchParams.get("actor") || undefined
});
- // Pagination state
- const [totalCount, setTotalCount] = useState(0);
const [currentPage, setCurrentPage] = useState(0);
- const [isLoading, setIsLoading] = useState(false);
-
- // Initialize page size from storage or default
const [pageSize, setPageSize] = useStoredPageSize("action-audit-logs", 20);
- // Set default date range to last 24 hours
const getDefaultDateRange = () => {
- // if the time is in the url params, use that instead
const startParam = searchParams.get("start");
const endParam = searchParams.get("end");
if (startParam && endParam) {
return {
- startDate: {
- date: new Date(startParam)
- },
- endDate: {
- date: new Date(endParam)
- }
+ startDate: { date: new Date(startParam) },
+ endDate: { date: new Date(endParam) }
};
}
-
- const now = new Date();
- const lastWeek = getSevenDaysAgo();
-
return {
- startDate: {
- date: lastWeek
- },
- endDate: {
- date: now
- }
+ startDate: { date: getSevenDaysAgo() },
+ endDate: { date: new Date() }
};
};
@@ -90,78 +64,90 @@ export default function GeneralPage() {
endDate: DateTimeValue;
}>(getDefaultDateRange());
- // Trigger search with default values on component mount
- useEffect(() => {
- if (build === "oss") {
- return;
+ const queryFilters = useMemo(() => {
+ let timeStart: string | undefined;
+ let timeEnd: string | undefined;
+
+ if (dateRange.startDate?.date) {
+ const dt = new Date(dateRange.startDate.date);
+ if (dateRange.startDate.time) {
+ const [h, m, s] = dateRange.startDate.time
+ .split(":")
+ .map(Number);
+ dt.setHours(h, m, s || 0);
+ }
+ timeStart = dt.toISOString();
}
- const defaultRange = getDefaultDateRange();
- queryDateTime(
- defaultRange.startDate,
- defaultRange.endDate,
- 0,
- pageSize
- );
- }, [orgId]); // Re-run if orgId changes
+
+ if (dateRange.endDate?.date) {
+ const dt = new Date(dateRange.endDate.date);
+ if (dateRange.endDate.time) {
+ const [h, m, s] = dateRange.endDate.time.split(":").map(Number);
+ dt.setHours(h, m, s || 0);
+ } else {
+ const now = new Date();
+ dt.setHours(
+ now.getHours(),
+ now.getMinutes(),
+ now.getSeconds(),
+ now.getMilliseconds()
+ );
+ }
+ timeEnd = dt.toISOString();
+ }
+
+ return {
+ timeStart,
+ timeEnd,
+ page: currentPage,
+ pageSize,
+ ...filters
+ };
+ }, [dateRange, currentPage, pageSize, filters]);
+
+ const { data, isFetching, isLoading, refetch } = useQuery({
+ ...logQueries.action({
+ orgId: orgId as string,
+ filters: queryFilters
+ }),
+ enabled: isPaidUser(tierMatrix.actionLogs) && build !== "oss"
+ });
+
+ const rows = isLoading ? generateSampleActionLogs() : (data?.log ?? []);
+ const totalCount = data?.pagination?.total ?? 0;
+ const filterAttributes = {
+ actors: data?.filterAttributes?.actors ?? []
+ };
const handleDateRangeChange = (
startDate: DateTimeValue,
endDate: DateTimeValue
) => {
setDateRange({ startDate, endDate });
- setCurrentPage(0); // Reset to first page when filtering
- // put the search params in the url for the time
+ setCurrentPage(0);
updateUrlParamsForAllFilters({
start: startDate.date?.toISOString() || "",
end: endDate.date?.toISOString() || ""
});
-
- queryDateTime(startDate, endDate, 0, pageSize);
};
- // Handle page changes
const handlePageChange = (newPage: number) => {
setCurrentPage(newPage);
- queryDateTime(
- dateRange.startDate,
- dateRange.endDate,
- newPage,
- pageSize
- );
};
- // Handle page size changes
const handlePageSizeChange = (newPageSize: number) => {
setPageSize(newPageSize);
- setCurrentPage(0); // Reset to first page when changing page size
- queryDateTime(dateRange.startDate, dateRange.endDate, 0, newPageSize);
+ setCurrentPage(0);
};
- // Handle filter changes generically
const handleFilterChange = (
filterType: keyof typeof filters,
value: string | undefined
) => {
- // Create new filters object with updated value
- const newFilters = {
- ...filters,
- [filterType]: value
- };
-
+ const newFilters = { ...filters, [filterType]: value };
setFilters(newFilters);
- setCurrentPage(0); // Reset to first page when filtering
-
- // Update URL params
+ setCurrentPage(0);
updateUrlParamsForAllFilters(newFilters);
-
- // Trigger new query with updated filters (pass directly to avoid async state issues)
- queryDateTime(
- dateRange.startDate,
- dateRange.endDate,
- 0,
- pageSize,
- newFilters
- );
};
const updateUrlParamsForAllFilters = (
@@ -183,114 +169,8 @@ export default function GeneralPage() {
router.replace(`?${params.toString()}`, { scroll: false });
};
- const queryDateTime = async (
- startDate: DateTimeValue,
- endDate: DateTimeValue,
- page: number = currentPage,
- size: number = pageSize,
- filtersParam?: {
- action?: string;
- actor?: string;
- }
- ) => {
- console.log("Date range changed:", { startDate, endDate, page, size });
- if (!isPaidUser(tierMatrix.actionLogs)) {
- console.log(
- "Access denied: subscription inactive or license locked"
- );
- return;
- }
- setIsLoading(true);
-
- try {
- // Use the provided filters or fall back to current state
- const activeFilters = filtersParam || filters;
-
- // Convert the date/time values to API parameters
- const params: any = {
- limit: size,
- offset: page * size,
- ...activeFilters
- };
-
- if (startDate?.date) {
- const startDateTime = new Date(startDate.date);
- if (startDate.time) {
- const [hours, minutes, seconds] = startDate.time
- .split(":")
- .map(Number);
- startDateTime.setHours(hours, minutes, seconds || 0);
- }
- params.timeStart = startDateTime.toISOString();
- }
-
- if (endDate?.date) {
- const endDateTime = new Date(endDate.date);
- if (endDate.time) {
- const [hours, minutes, seconds] = endDate.time
- .split(":")
- .map(Number);
- endDateTime.setHours(hours, minutes, seconds || 0);
- } else {
- // If no time is specified, set to NOW
- const now = new Date();
- endDateTime.setHours(
- now.getHours(),
- now.getMinutes(),
- now.getSeconds(),
- now.getMilliseconds()
- );
- }
- params.timeEnd = endDateTime.toISOString();
- }
-
- const res = await api.get(`/org/${orgId}/logs/action`, { params });
- if (res.status === 200) {
- setRows(res.data.data.log || []);
- setTotalCount(res.data.data.pagination?.total || 0);
- setFilterAttributes(res.data.data.filterAttributes);
- console.log("Fetched logs:", res.data);
- }
- } catch (error) {
- toast({
- title: t("error"),
- description: t("Failed to filter logs"),
- variant: "destructive"
- });
- } finally {
- setIsLoading(false);
- }
- };
-
- const refreshData = async () => {
- console.log("Data refreshed");
- setIsRefreshing(true);
- try {
- const endDate = searchParams.get("end")
- ? dateRange.endDate
- : { date: new Date() };
- setDateRange((current) => ({ ...current, endDate }));
- // Refresh data with current date range and pagination
- await queryDateTime(
- dateRange.startDate,
- endDate,
- currentPage,
- pageSize
- );
- } catch (error) {
- toast({
- title: t("error"),
- description: t("refreshError"),
- variant: "destructive"
- });
- } finally {
- setIsRefreshing(false);
- }
- };
-
const exportData = async () => {
try {
- // Prepare query params for export
const params: any = {
timeStart: dateRange.startDate?.date
? new Date(dateRange.startDate.date).toISOString()
@@ -306,7 +186,6 @@ export default function GeneralPage() {
params
});
- // Create a URL for the blob and trigger a download
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
@@ -324,7 +203,6 @@ export default function GeneralPage() {
const data = error.response.data;
if (data instanceof Blob && data.type === "application/json") {
- // Parse the Blob as JSON
const text = await data.text();
const errorData = JSON.parse(text);
apiErrorMessage = errorData.message;
@@ -341,7 +219,7 @@ export default function GeneralPage() {
const columns: ColumnDef[] = [
{
accessorKey: "timestamp",
- header: ({ column }) => {
+ header: () => {
return t("timestamp");
},
cell: ({ row }) => {
@@ -356,22 +234,16 @@ export default function GeneralPage() {
},
{
accessorKey: "action",
- header: ({ column }) => {
+ header: () => {
return (
{t("action")}
({
- label:
- action.charAt(0).toUpperCase() +
- action.slice(1),
- value: action
- }))}
+ options={[]}
selectedValue={filters.action}
onValueChange={(value) =>
handleFilterChange("action", value)
}
- // placeholder=""
searchPlaceholder="Search..."
emptyMessage="None found"
/>
@@ -389,7 +261,7 @@ export default function GeneralPage() {
},
{
accessorKey: "actor",
- header: ({ column }) => {
+ header: () => {
return (
{t("actor")}
@@ -402,7 +274,6 @@ export default function GeneralPage() {
onValueChange={(value) =>
handleFilterChange("actor", value)
}
- // placeholder=""
searchPlaceholder="Search..."
emptyMessage="None found"
/>
@@ -424,7 +295,7 @@ export default function GeneralPage() {
},
{
accessorKey: "actorId",
- header: ({ column }) => {
+ header: () => {
return t("actorId");
},
cell: ({ row }) => {
@@ -473,12 +344,9 @@ export default function GeneralPage() {
title={t("actionLogs")}
searchPlaceholder={t("searchLogs")}
searchColumn="action"
- onRefresh={refreshData}
- isRefreshing={isRefreshing}
+ onRefresh={() => refetch()}
+ isRefreshing={isFetching}
onExport={() => startTransition(exportData)}
- // isExportDisabled={ // not disabling this because the user should be able to click the button and get the feedback about needing to upgrade the plan
- // !isPaidUser(tierMatrix.logExport) || build === "oss"
- // }
isExporting={isExporting}
onDateRangeChange={handleDateRangeChange}
dateRange={{
@@ -489,14 +357,12 @@ export default function GeneralPage() {
id: "timestamp",
desc: true
}}
- // Server-side pagination props
totalCount={totalCount}
currentPage={currentPage}
pageSize={pageSize}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
isLoading={isLoading}
- // Row expansion props
expandable={true}
renderExpandedRow={renderExpandedRow}
disabled={!isPaidUser(tierMatrix.actionLogs) || build === "oss"}
@@ -504,3 +370,39 @@ export default function GeneralPage() {
>
);
}
+
+function generateSampleActionLogs(): QueryActionAuditLogResponse["log"] {
+ const actions = [
+ "createResource",
+ "deleteResource",
+ "updateResource",
+ "createSite",
+ "deleteSite",
+ "inviteUser",
+ "removeUser"
+ ];
+ const actors = [
+ "alice@example.com",
+ "bob@example.com",
+ "carol@example.com"
+ ];
+
+ const now = Math.floor(Date.now() / 1000);
+ const sevenDaysAgo = now - 7 * 24 * 60 * 60;
+
+ return Array.from({ length: 10 }, (_, i) => {
+ const actor = actors[Math.floor(Math.random() * actors.length)];
+
+ return {
+ timestamp: Math.floor(
+ sevenDaysAgo + Math.random() * (now - sevenDaysAgo)
+ ),
+ action: actions[Math.floor(Math.random() * actions.length)],
+ orgId: "sample-org",
+ actorType: "user",
+ actor,
+ actorId: `user-${i}`,
+ metadata: null
+ };
+ });
+}
diff --git a/src/app/[orgId]/settings/logs/connection/page.tsx b/src/app/[orgId]/settings/logs/connection/page.tsx
index 737277eb6..be408edb1 100644
--- a/src/app/[orgId]/settings/logs/connection/page.tsx
+++ b/src/app/[orgId]/settings/logs/connection/page.tsx
@@ -11,24 +11,18 @@ import { useStoredPageSize } from "@app/hooks/useStoredPageSize";
import { toast } from "@app/hooks/useToast";
import { createApiClient } from "@app/lib/api";
import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo";
+import { logQueries } from "@app/lib/queries";
import { build } from "@server/build";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
+import type { QueryConnectionAuditLogResponse } from "@server/routers/auditLogs/types";
+import { useQuery } from "@tanstack/react-query";
import { ColumnDef } from "@tanstack/react-table";
import axios from "axios";
import { ArrowUpRight, Laptop, User } from "lucide-react";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { useParams, useRouter, useSearchParams } from "next/navigation";
-import { useEffect, useState, useTransition } from "react";
-
-function formatBytes(bytes: number | null): string {
- if (bytes === null || bytes === undefined) return "-";
- if (bytes === 0) return "0 B";
- const units = ["B", "KB", "MB", "GB", "TB"];
- const i = Math.floor(Math.log(bytes) / Math.log(1024));
- const value = bytes / Math.pow(1024, i);
- return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
-}
+import { useMemo, useState, useTransition } from "react";
function formatDuration(startedAt: number, endedAt: number | null): string {
if (endedAt === null || endedAt === undefined) return "Active";
@@ -54,24 +48,8 @@ export default function ConnectionLogsPage() {
const { isPaidUser } = usePaidStatus();
- const [rows, setRows] = useState
([]);
- const [isRefreshing, setIsRefreshing] = useState(false);
const [isExporting, startTransition] = useTransition();
- const [filterAttributes, setFilterAttributes] = useState<{
- protocols: string[];
- destAddrs: string[];
- clients: { id: number; name: string }[];
- resources: { id: number; name: string | null }[];
- users: { id: string; email: string | null }[];
- }>({
- protocols: [],
- destAddrs: [],
- clients: [],
- resources: [],
- users: []
- });
- // Filter states - unified object for all filters
const [filters, setFilters] = useState<{
protocol?: string;
destAddr?: string;
@@ -86,43 +64,24 @@ export default function ConnectionLogsPage() {
userId: searchParams.get("userId") || undefined
});
- // Pagination state
- const [totalCount, setTotalCount] = useState(0);
const [currentPage, setCurrentPage] = useState(0);
- const [isLoading, setIsLoading] = useState(false);
-
- // Initialize page size from storage or default
const [pageSize, setPageSize] = useStoredPageSize(
"connection-audit-logs",
20
);
- // Set default date range to last 7 days
const getDefaultDateRange = () => {
- // if the time is in the url params, use that instead
const startParam = searchParams.get("start");
const endParam = searchParams.get("end");
if (startParam && endParam) {
return {
- startDate: {
- date: new Date(startParam)
- },
- endDate: {
- date: new Date(endParam)
- }
+ startDate: { date: new Date(startParam) },
+ endDate: { date: new Date(endParam) }
};
}
-
- const now = new Date();
- const lastWeek = getSevenDaysAgo();
-
return {
- startDate: {
- date: lastWeek
- },
- endDate: {
- date: now
- }
+ startDate: { date: getSevenDaysAgo() },
+ endDate: { date: new Date() }
};
};
@@ -131,78 +90,98 @@ export default function ConnectionLogsPage() {
endDate: DateTimeValue;
}>(getDefaultDateRange());
- // Trigger search with default values on component mount
- useEffect(() => {
- if (build === "oss") {
- return;
+ const queryFilters = useMemo(() => {
+ let timeStart: string | undefined;
+ let timeEnd: string | undefined;
+
+ if (dateRange.startDate?.date) {
+ const dt = new Date(dateRange.startDate.date);
+ if (dateRange.startDate.time) {
+ const [h, m, s] = dateRange.startDate.time
+ .split(":")
+ .map(Number);
+ dt.setHours(h, m, s || 0);
+ }
+ timeStart = dt.toISOString();
}
- const defaultRange = getDefaultDateRange();
- queryDateTime(
- defaultRange.startDate,
- defaultRange.endDate,
- 0,
- pageSize
- );
- }, [orgId]); // Re-run if orgId changes
+
+ if (dateRange.endDate?.date) {
+ const dt = new Date(dateRange.endDate.date);
+ if (dateRange.endDate.time) {
+ const [h, m, s] = dateRange.endDate.time.split(":").map(Number);
+ dt.setHours(h, m, s || 0);
+ } else {
+ const now = new Date();
+ dt.setHours(
+ now.getHours(),
+ now.getMinutes(),
+ now.getSeconds(),
+ now.getMilliseconds()
+ );
+ }
+ timeEnd = dt.toISOString();
+ }
+
+ return {
+ timeStart,
+ timeEnd,
+ page: currentPage,
+ pageSize,
+ ...filters,
+ clientId: filters.clientId ? Number(filters.clientId) : undefined,
+ siteResourceId: filters.siteResourceId
+ ? Number(filters.siteResourceId)
+ : undefined
+ };
+ }, [dateRange, currentPage, pageSize, filters]);
+
+ const { data, isFetching, isLoading, refetch } = useQuery({
+ ...logQueries.connection({
+ orgId: orgId as string,
+ filters: queryFilters
+ }),
+ enabled: isPaidUser(tierMatrix.connectionLogs) && build !== "oss"
+ });
+
+ const rows = isLoading ? generateSampleConnectionLogs() : (data?.log ?? []);
+ const totalCount = data?.pagination?.total ?? 0;
+ const filterAttributes = data?.filterAttributes ?? {
+ protocols: [],
+ destAddrs: [],
+ clients: [],
+ resources: [],
+ users: []
+ };
const handleDateRangeChange = (
startDate: DateTimeValue,
endDate: DateTimeValue
) => {
setDateRange({ startDate, endDate });
- setCurrentPage(0); // Reset to first page when filtering
- // put the search params in the url for the time
+ setCurrentPage(0);
updateUrlParamsForAllFilters({
start: startDate.date?.toISOString() || "",
end: endDate.date?.toISOString() || ""
});
-
- queryDateTime(startDate, endDate, 0, pageSize);
};
- // Handle page changes
const handlePageChange = (newPage: number) => {
setCurrentPage(newPage);
- queryDateTime(
- dateRange.startDate,
- dateRange.endDate,
- newPage,
- pageSize
- );
};
- // Handle page size changes
const handlePageSizeChange = (newPageSize: number) => {
setPageSize(newPageSize);
- setCurrentPage(0); // Reset to first page when changing page size
- queryDateTime(dateRange.startDate, dateRange.endDate, 0, newPageSize);
+ setCurrentPage(0);
};
- // Handle filter changes generically
const handleFilterChange = (
filterType: keyof typeof filters,
value: string | undefined
) => {
- // Create new filters object with updated value
- const newFilters = {
- ...filters,
- [filterType]: value
- };
-
+ const newFilters = { ...filters, [filterType]: value };
setFilters(newFilters);
- setCurrentPage(0); // Reset to first page when filtering
-
- // Update URL params
+ setCurrentPage(0);
updateUrlParamsForAllFilters(newFilters);
-
- // Trigger new query with updated filters (pass directly to avoid async state issues)
- queryDateTime(
- dateRange.startDate,
- dateRange.endDate,
- 0,
- pageSize,
- newFilters
- );
};
const updateUrlParamsForAllFilters = (
@@ -224,113 +203,8 @@ export default function ConnectionLogsPage() {
router.replace(`?${params.toString()}`, { scroll: false });
};
- const queryDateTime = async (
- startDate: DateTimeValue,
- endDate: DateTimeValue,
- page: number = currentPage,
- size: number = pageSize,
- filtersParam?: typeof filters
- ) => {
- console.log("Date range changed:", { startDate, endDate, page, size });
- if (!isPaidUser(tierMatrix.connectionLogs)) {
- console.log(
- "Access denied: subscription inactive or license locked"
- );
- return;
- }
- setIsLoading(true);
-
- try {
- // Use the provided filters or fall back to current state
- const activeFilters = filtersParam || filters;
-
- // Convert the date/time values to API parameters
- const params: any = {
- limit: size,
- offset: page * size,
- ...activeFilters
- };
-
- if (startDate?.date) {
- const startDateTime = new Date(startDate.date);
- if (startDate.time) {
- const [hours, minutes, seconds] = startDate.time
- .split(":")
- .map(Number);
- startDateTime.setHours(hours, minutes, seconds || 0);
- }
- params.timeStart = startDateTime.toISOString();
- }
-
- if (endDate?.date) {
- const endDateTime = new Date(endDate.date);
- if (endDate.time) {
- const [hours, minutes, seconds] = endDate.time
- .split(":")
- .map(Number);
- endDateTime.setHours(hours, minutes, seconds || 0);
- } else {
- // If no time is specified, set to NOW
- const now = new Date();
- endDateTime.setHours(
- now.getHours(),
- now.getMinutes(),
- now.getSeconds(),
- now.getMilliseconds()
- );
- }
- params.timeEnd = endDateTime.toISOString();
- }
-
- const res = await api.get(`/org/${orgId}/logs/connection`, {
- params
- });
- if (res.status === 200) {
- setRows(res.data.data.log || []);
- setTotalCount(res.data.data.pagination?.total || 0);
- setFilterAttributes(res.data.data.filterAttributes);
- console.log("Fetched connection logs:", res.data);
- }
- } catch (error) {
- toast({
- title: t("error"),
- description: t("Failed to filter logs"),
- variant: "destructive"
- });
- } finally {
- setIsLoading(false);
- }
- };
-
- const refreshData = async () => {
- console.log("Data refreshed");
- setIsRefreshing(true);
- try {
- const endDate = searchParams.get("end")
- ? dateRange.endDate
- : { date: new Date() };
- setDateRange((current) => ({ ...current, endDate }));
- // Refresh data with current date range and pagination
- await queryDateTime(
- dateRange.startDate,
- endDate,
- currentPage,
- pageSize
- );
- } catch (error) {
- toast({
- title: t("error"),
- description: t("refreshError"),
- variant: "destructive"
- });
- } finally {
- setIsRefreshing(false);
- }
- };
-
const exportData = async () => {
try {
- // Prepare query params for export
const params: any = {
timeStart: dateRange.startDate?.date
? new Date(dateRange.startDate.date).toISOString()
@@ -349,7 +223,6 @@ export default function ConnectionLogsPage() {
}
);
- // Create a URL for the blob and trigger a download
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
@@ -367,7 +240,6 @@ export default function ConnectionLogsPage() {
const data = error.response.data;
if (data instanceof Blob && data.type === "application/json") {
- // Parse the Blob as JSON
const text = await data.text();
const errorData = JSON.parse(text);
apiErrorMessage = errorData.message;
@@ -384,7 +256,7 @@ export default function ConnectionLogsPage() {
const columns: ColumnDef[] = [
{
accessorKey: "startedAt",
- header: ({ column }) => {
+ header: () => {
return t("timestamp");
},
cell: ({ row }) => {
@@ -399,7 +271,7 @@ export default function ConnectionLogsPage() {
},
{
accessorKey: "protocol",
- header: ({ column }) => {
+ header: () => {
return (
{t("protocol")}
@@ -430,7 +302,7 @@ export default function ConnectionLogsPage() {
},
{
accessorKey: "resourceName",
- header: ({ column }) => {
+ header: () => {
return (
{t("resource")}
@@ -453,7 +325,7 @@ export default function ConnectionLogsPage() {
if (row.original.resourceName && row.original.resourceNiceId) {
return (