Merge branch 'dev' into bubble-errors-up

This commit is contained in:
miloschwartz
2026-01-17 12:00:55 -08:00
2 changed files with 50 additions and 6 deletions

View File

@@ -1308,6 +1308,7 @@
"setupErrorCreateAdmin": "An error occurred while creating the server admin account.", "setupErrorCreateAdmin": "An error occurred while creating the server admin account.",
"certificateStatus": "Certificate Status", "certificateStatus": "Certificate Status",
"loading": "Loading", "loading": "Loading",
"loadingAnalytics": "Loading Analytics",
"restart": "Restart", "restart": "Restart",
"domains": "Domains", "domains": "Domains",
"domainsDescription": "Create and manage domains available in the organization", "domainsDescription": "Create and manage domains available in the organization",

View File

@@ -48,6 +48,7 @@ import {
TooltipTrigger TooltipTrigger
} from "./ui/tooltip"; } from "./ui/tooltip";
import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo"; import { getSevenDaysAgo } from "@app/lib/getSevenDaysAgo";
import type { QueryRequestAnalyticsResponse } from "@server/routers/auditLogs";
export type AnalyticsContentProps = { export type AnalyticsContentProps = {
orgId: string; orgId: string;
@@ -276,13 +277,32 @@ export function LogAnalyticsData(props: AnalyticsContentProps) {
</CardHeader> </CardHeader>
</Card> </Card>
<Card className="w-full h-full flex flex-col gap-8"> <Card className="w-full h-full flex flex-col gap-8 relative">
{isLoadingAnalytics && (
<div className="absolute z-20 left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border border-border rounded-md bg-muted">
<div className="flex items-center gap-2 p-6">
<LoaderIcon className="size-4 animate-spin" />
{t("loadingAnalytics")}
</div>
</div>
)}
<CardHeader> <CardHeader>
<h3 className="font-semibold">{t("requestsByDay")}</h3> <h3 className="font-semibold">{t("requestsByDay")}</h3>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="relative">
{isLoadingAnalytics && (
<div className="backdrop-blur-[2px] z-10 absolute inset-0"></div>
)}
<RequestChart <RequestChart
data={stats?.requestsPerDay ?? []} className={cn(
isLoadingAnalytics &&
"opacity-50 pointer-events-none"
)}
data={
stats?.requestsPerDay ??
generateSampleDailyRequests()
}
isLoading={isLoadingAnalytics} isLoading={isLoadingAnalytics}
/> />
</CardContent> </CardContent>
@@ -323,6 +343,28 @@ export function LogAnalyticsData(props: AnalyticsContentProps) {
); );
} }
function generateSampleDailyRequests(): QueryRequestAnalyticsResponse["requestsPerDay"] {
const today = new Date();
// generate sample data for the last 7 days
const requestsPerDay = Array.from({ length: 7 }, (_, i) => {
const date = new Date(today);
date.setDate(date.getDate() - (6 - i));
// generate a random number of requests between 1 and 100
const totalCount = Math.floor(Math.random() * 100) + 1;
// generate a random number of requests between 1 and totalCount
const blockedCount = Math.floor(Math.random() * (totalCount + 1));
return {
day: date.toISOString().split("T")[0],
allowedCount: totalCount - blockedCount,
blockedCount,
totalCount
};
});
return requestsPerDay;
}
type RequestChartProps = { type RequestChartProps = {
data: { data: {
day: string; day: string;
@@ -331,6 +373,7 @@ type RequestChartProps = {
totalCount: number; totalCount: number;
}[]; }[];
isLoading: boolean; isLoading: boolean;
className?: string;
}; };
function RequestChart(props: RequestChartProps) { function RequestChart(props: RequestChartProps) {
@@ -359,7 +402,7 @@ function RequestChart(props: RequestChartProps) {
return ( return (
<ChartContainer <ChartContainer
config={chartConfig} config={chartConfig}
className="min-h-[200px] w-full h-80" className={cn("min-h-50 w-full h-80", props.className)}
> >
<LineChart accessibilityLayer data={props.data}> <LineChart accessibilityLayer data={props.data}>
<ChartLegend content={<ChartLegendContent />} /> <ChartLegend content={<ChartLegendContent />} />
@@ -467,7 +510,7 @@ function TopCountriesList(props: TopCountriesListProps) {
</div> </div>
)} )}
{/* `aspect-475/335` is the same aspect ratio as the world map component */} {/* `aspect-475/335` is the same aspect ratio as the world map component */}
<ol className="w-full overflow-auto grid gap-1 aspect-475/335"> <ol className="w-full overflow-auto gap-1 aspect-475/335 flex flex-col">
{props.countries.length === 0 && ( {props.countries.length === 0 && (
<div className="flex items-center justify-center size-full text-muted-foreground gap-1"> <div className="flex items-center justify-center size-full text-muted-foreground gap-1">
{props.isLoading ? ( {props.isLoading ? (
@@ -485,7 +528,7 @@ function TopCountriesList(props: TopCountriesListProps) {
return ( return (
<li <li
key={country.code} key={country.code}
className="grid grid-cols-7 rounded-xs hover:bg-muted relative items-center text-sm" className="w-full grid grid-cols-7 rounded-xs hover:bg-muted relative items-center text-sm"
> >
<div <div
className={cn( className={cn(