Skip to content

Commit 42f6d84

Browse files
committed
feat: webhook analytics tab
1 parent 26c080f commit 42f6d84

22 files changed

+1132
-149
lines changed

apps/dashboard/.storybook/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ function getAbsolutePath(value: string): string {
99
return dirname(require.resolve(join(value, "package.json")));
1010
}
1111
const config: StorybookConfig = {
12-
stories: ["../src/**/*.stories.tsx"],
1312
addons: [
1413
getAbsolutePath("@storybook/addon-onboarding"),
1514
getAbsolutePath("@storybook/addon-links"),
1615
getAbsolutePath("@chromatic-com/storybook"),
1716
getAbsolutePath("@storybook/addon-docs"),
1817
],
18+
features: {
19+
experimentalRSC: true,
20+
},
1921
framework: {
2022
name: getAbsolutePath("@storybook/nextjs"),
2123
options: {},
@@ -26,8 +28,6 @@ const config: StorybookConfig = {
2628
},
2729
},
2830
staticDirs: ["../public"],
29-
features: {
30-
experimentalRSC: true,
31-
},
31+
stories: ["../src/**/*.stories.tsx"],
3232
};
3333
export default config;

apps/dashboard/.storybook/preview.tsx

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import type { Preview } from "@storybook/nextjs";
22
import "../src/global.css";
33
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
44
import { MoonIcon, SunIcon } from "lucide-react";
5-
import { ThemeProvider, useTheme } from "next-themes";
65
import { Inter as interFont } from "next/font/google";
6+
import { ThemeProvider, useTheme } from "next-themes";
77
// biome-ignore lint/style/useImportType: <explanation>
8-
import React from "react";
9-
import { useEffect } from "react";
8+
import React, { useEffect } from "react";
109
import { Toaster } from "sonner";
1110
import { Button } from "../src/@/components/ui/button";
1211

@@ -18,45 +17,33 @@ const fontSans = interFont({
1817
});
1918

2019
const customViewports = {
21-
xs: {
22-
// Regular sized phones (iphone 15 / 15 pro)
23-
name: "iPhone",
24-
styles: {
25-
width: "390px",
26-
height: "844px",
27-
},
28-
},
2920
sm: {
3021
// Larger phones (iphone 15 plus / 15 pro max)
3122
name: "iPhone Plus",
3223
styles: {
33-
width: "430px",
3424
height: "932px",
25+
width: "430px",
3526
},
3627
},
37-
};
38-
39-
const preview: Preview = {
40-
parameters: {
41-
viewport: {
42-
viewports: customViewports,
43-
},
44-
controls: {
45-
matchers: {
46-
color: /(background|color)$/i,
47-
date: /Date$/i,
48-
},
28+
xs: {
29+
// Regular sized phones (iphone 15 / 15 pro)
30+
name: "iPhone",
31+
styles: {
32+
height: "844px",
33+
width: "390px",
4934
},
5035
},
36+
};
5137

38+
const preview: Preview = {
5239
decorators: [
5340
(Story) => {
5441
return (
5542
<ThemeProvider
5643
attribute="class"
44+
defaultTheme="dark"
5745
disableTransitionOnChange
5846
enableSystem={false}
59-
defaultTheme="dark"
6047
>
6148
<StoryLayout>
6249
<Story />
@@ -65,13 +52,22 @@ const preview: Preview = {
6552
);
6653
},
6754
],
55+
parameters: {
56+
controls: {
57+
matchers: {
58+
color: /(background|color)$/i,
59+
date: /Date$/i,
60+
},
61+
},
62+
viewport: {
63+
viewports: customViewports,
64+
},
65+
},
6866
};
6967

7068
export default preview;
7169

72-
function StoryLayout(props: {
73-
children: React.ReactNode;
74-
}) {
70+
function StoryLayout(props: { children: React.ReactNode }) {
7571
const { setTheme, theme } = useTheme();
7672

7773
useEffect(() => {
@@ -83,10 +79,10 @@ function StoryLayout(props: {
8379
<div className="flex min-h-dvh min-w-0 flex-col bg-background text-foreground">
8480
<div className="fixed right-0 bottom-0 z-50 flex justify-end gap-2 p-4">
8581
<Button
82+
className="h-auto w-auto shrink-0 rounded-full p-2"
8683
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
8784
size="sm"
8885
variant="outline"
89-
className="h-auto w-auto shrink-0 rounded-full p-2"
9086
>
9187
{theme === "dark" ? (
9288
<MoonIcon className="size-4" />

apps/dashboard/public/assets/examples/example.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
[
22
{
3-
"name": "Your Collection #1",
4-
"description": "Remember to replace this description",
5-
"image": "ipfs://NewUriToReplace/1.png",
63
"attributes": [
74
{
85
"trait_type": "Background",
@@ -32,12 +29,12 @@
3229
"trait_type": "Top lid",
3330
"value": "High"
3431
}
35-
]
32+
],
33+
"description": "Remember to replace this description",
34+
"image": "ipfs://NewUriToReplace/1.png",
35+
"name": "Your Collection #1"
3636
},
3737
{
38-
"name": "Your Collection #2",
39-
"description": "Remember to replace this description",
40-
"image": "ipfs://NewUriToReplace/2.png",
4138
"attributes": [
4239
{
4340
"trait_type": "Background",
@@ -67,6 +64,9 @@
6764
"trait_type": "Top lid",
6865
"value": "Middle"
6966
}
70-
]
67+
],
68+
"description": "Remember to replace this description",
69+
"image": "ipfs://NewUriToReplace/2.png",
70+
"name": "Your Collection #2"
7171
}
7272
]

apps/dashboard/src/@/api/analytics.ts

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import type {
1313
UserOpStats,
1414
WalletStats,
1515
WalletUserStats,
16+
WebhookLatencyStats,
17+
WebhookRequestStats,
1618
WebhookSummaryStats,
1719
} from "@/types/analytics";
1820
import { getAuthToken } from "./auth-token";
@@ -426,44 +428,56 @@ export async function getEngineCloudMethodUsage(
426428
return json.data as EngineCloudStats[];
427429
}
428430

429-
export async function getWebhookMetrics(params: {
430-
teamId: string;
431-
projectId: string;
432-
webhookId: string;
433-
period?: "day" | "week" | "month" | "year" | "all";
434-
from?: Date;
435-
to?: Date;
436-
}): Promise<{ data: WebhookSummaryStats[] } | { error: string }> {
437-
const searchParams = new URLSearchParams();
438-
439-
// Required params
440-
searchParams.append("teamId", params.teamId);
441-
searchParams.append("projectId", params.projectId);
431+
export async function getWebhookSummary(
432+
params: AnalyticsQueryParams & { webhookId: string },
433+
): Promise<{ data: WebhookSummaryStats[] } | { error: string }> {
434+
const searchParams = buildSearchParams(params);
442435
searchParams.append("webhookId", params.webhookId);
443436

444-
// Optional params
445-
if (params.period) {
446-
searchParams.append("period", params.period);
447-
}
448-
if (params.from) {
449-
searchParams.append("from", params.from.toISOString());
437+
const res = await fetchAnalytics(
438+
`v2/webhook/summary?${searchParams.toString()}`,
439+
);
440+
if (!res.ok) {
441+
const reason = await res.text();
442+
return { error: reason };
450443
}
451-
if (params.to) {
452-
searchParams.append("to", params.to.toISOString());
444+
445+
return (await res.json()) as { data: WebhookSummaryStats[] };
446+
}
447+
448+
export async function getWebhookRequests(
449+
params: AnalyticsQueryParams & { webhookId?: string },
450+
): Promise<{ data: WebhookRequestStats[] } | { error: string }> {
451+
const searchParams = buildSearchParams(params);
452+
if (params.webhookId) {
453+
searchParams.append("webhookId", params.webhookId);
453454
}
454455

455456
const res = await fetchAnalytics(
456-
`v2/webhook/summary?${searchParams.toString()}`,
457-
{
458-
method: "GET",
459-
},
457+
`v2/webhook/requests?${searchParams.toString()}`,
460458
);
459+
if (!res.ok) {
460+
const reason = await res.text();
461+
return { error: reason };
462+
}
461463

464+
return (await res.json()) as { data: WebhookRequestStats[] };
465+
}
466+
467+
export async function getWebhookLatency(
468+
params: AnalyticsQueryParams & { webhookId?: string },
469+
): Promise<{ data: WebhookLatencyStats[] } | { error: string }> {
470+
const searchParams = buildSearchParams(params);
471+
if (params.webhookId) {
472+
searchParams.append("webhookId", params.webhookId);
473+
}
474+
const res = await fetchAnalytics(
475+
`v2/webhook/latency?${searchParams.toString()}`,
476+
);
462477
if (!res.ok) {
463-
const reason = await res?.text();
478+
const reason = await res.text();
464479
return { error: reason };
465480
}
466-
return (await res.json()) as {
467-
data: WebhookSummaryStats[];
468-
};
481+
482+
return (await res.json()) as { data: WebhookLatencyStats[] };
469483
}

0 commit comments

Comments
 (0)