diff --git a/server/routers/auditLogs/queryRequestAnalytics.ts b/server/routers/auditLogs/queryRequestAnalytics.ts index 9e4ea17e..944160da 100644 --- a/server/routers/auditLogs/queryRequestAnalytics.ts +++ b/server/routers/auditLogs/queryRequestAnalytics.ts @@ -2,7 +2,7 @@ import { db, requestAuditLog, driver } from "@server/db"; import { registry } from "@server/openApi"; import { NextFunction } from "express"; import { Request, Response } from "express"; -import { eq, gt, lt, and, count, sql, desc, not, isNull } from "drizzle-orm"; +import { eq, gte, lte, and, count, sql, desc, not, isNull } from "drizzle-orm"; import { OpenAPITags } from "@server/openApi"; import { z } from "zod"; import createHttpError from "http-errors"; @@ -11,6 +11,14 @@ import { fromError } from "zod-validation-error"; import response from "@server/lib/response"; import logger from "@server/logger"; +function getSevenDaysAgo() { + const today = new Date(); + today.setHours(0, 0, 0, 0); // Set to midnight + const sevenDaysAgo = new Date(today); + sevenDaysAgo.setDate(today.getDate() - 7); + return sevenDaysAgo.toISOString(); +} + const queryAccessAuditLogsQuery = z.object({ // iso string just validate its a parseable date timeStart: z @@ -19,7 +27,8 @@ const queryAccessAuditLogsQuery = z.object({ error: "timeStart must be a valid ISO date string" }) .transform((val) => Math.floor(new Date(val).getTime() / 1000)) - .optional(), + .optional() + .prefault(getSevenDaysAgo), timeEnd: z .string() .refine((val) => !isNaN(Date.parse(val)), { @@ -55,15 +64,10 @@ type Q = z.infer; async function query(query: Q) { let baseConditions = and( eq(requestAuditLog.orgId, query.orgId), - lt(requestAuditLog.timestamp, query.timeEnd) + gte(requestAuditLog.timestamp, query.timeStart), + lte(requestAuditLog.timestamp, query.timeEnd) ); - if (query.timeStart) { - baseConditions = and( - baseConditions, - gt(requestAuditLog.timestamp, query.timeStart) - ); - } if (query.resourceId) { baseConditions = and( baseConditions, diff --git a/src/components/LogAnalyticsData.tsx b/src/components/LogAnalyticsData.tsx index 2fd30189..e5df48e1 100644 --- a/src/components/LogAnalyticsData.tsx +++ b/src/components/LogAnalyticsData.tsx @@ -1,22 +1,27 @@ "use client"; -import { useEnvContext } from "@app/hooks/useEnvContext"; -import { createApiClient } from "@app/lib/api"; +import { cn } from "@app/lib/cn"; import { logAnalyticsFiltersSchema, logQueries, resourceQueries } from "@app/lib/queries"; import { useQuery } from "@tanstack/react-query"; -import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { useState } from "react"; -import { Card, CardContent, CardHeader } from "./ui/card"; import { LoaderIcon, RefreshCw, XIcon } from "lucide-react"; +import { useTranslations } from "next-intl"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { DateRangePicker, type DateTimeValue } from "./DateTimePicker"; import { Button } from "./ui/button"; -import { cn } from "@app/lib/cn"; -import { useTranslations } from "next-intl"; +import { Card, CardContent, CardHeader } from "./ui/card"; +import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji"; +import { + InfoSection, + InfoSectionContent, + InfoSections, + InfoSectionTitle +} from "./InfoSection"; +import { Label } from "./ui/label"; import { Select, SelectContent, @@ -24,23 +29,10 @@ import { SelectTrigger, SelectValue } from "./ui/select"; -import { Label } from "./ui/label"; import { Separator } from "./ui/separator"; -import { - InfoSection, - InfoSectionContent, - InfoSections, - InfoSectionTitle -} from "./InfoSection"; import { WorldMap } from "./WorldMap"; -import { countryCodeToFlagEmoji } from "@app/lib/countryCodeToFlagEmoji"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger -} from "./ui/tooltip"; +import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts"; import { ChartContainer, ChartLegend, @@ -49,12 +41,25 @@ import { ChartTooltipContent, type ChartConfig } from "./ui/chart"; -import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from "./ui/tooltip"; export type AnalyticsContentProps = { orgId: string; }; +function getSevenDaysAgo() { + const today = new Date(); + today.setHours(0, 0, 0, 0); // Set to midnight + const sevenDaysAgo = new Date(today); + sevenDaysAgo.setDate(today.getDate() - 7); + return sevenDaysAgo; +} + export function LogAnalyticsData(props: AnalyticsContentProps) { const searchParams = useSearchParams(); const path = usePathname(); @@ -67,17 +72,18 @@ export function LogAnalyticsData(props: AnalyticsContentProps) { const isEmptySearchParams = !filters.resourceId && !filters.timeStart && !filters.timeEnd; - const env = useEnvContext(); - const [api] = useState(() => createApiClient(env)); const router = useRouter(); + console.log({ filters }); const dateRange = { - startDate: filters.timeStart ? new Date(filters.timeStart) : undefined, - endDate: filters.timeEnd ? new Date(filters.timeEnd) : undefined + startDate: filters.timeStart + ? new Date(filters.timeStart) + : getSevenDaysAgo(), + endDate: filters.timeEnd ? new Date(filters.timeEnd) : new Date() }; const { data: resources = [], isFetching: isFetchingResources } = useQuery( - resourceQueries.listNamesPerOrg(props.orgId, api) + resourceQueries.listNamesPerOrg(props.orgId) ); const { @@ -88,7 +94,6 @@ export function LogAnalyticsData(props: AnalyticsContentProps) { } = useQuery( logQueries.requestAnalytics({ orgId: props.orgId, - api, filters }) ); diff --git a/src/lib/queries.ts b/src/lib/queries.ts index 2a19f3f9..5fe85078 100644 --- a/src/lib/queries.ts +++ b/src/lib/queries.ts @@ -168,17 +168,15 @@ export type LogAnalyticsFilters = z.TypeOf; export const logQueries = { requestAnalytics: ({ orgId, - filters, - api + filters }: { orgId: string; filters: LogAnalyticsFilters; - api: AxiosInstance; }) => queryOptions({ queryKey: ["REQUEST_LOG_ANALYTICS", orgId, filters] as const, - queryFn: async ({ signal }) => { - const res = await api.get< + queryFn: async ({ signal, meta }) => { + const res = await meta!.api.get< AxiosResponse >(`/org/${orgId}/logs/analytics`, { params: filters, @@ -228,11 +226,11 @@ export const resourceQueries = { return res.data.data.clients; } }), - listNamesPerOrg: (orgId: string, api: AxiosInstance) => + listNamesPerOrg: (orgId: string) => queryOptions({ queryKey: ["RESOURCES_NAMES", orgId] as const, - queryFn: async ({ signal }) => { - const res = await api.get< + queryFn: async ({ signal, meta }) => { + const res = await meta!.api.get< AxiosResponse >(`/org/${orgId}/resource-names`, { signal