Skip to content

Commit ab71cef

Browse files
committed
Insight Dashboard
1 parent a7d0ecb commit ab71cef

File tree

13 files changed

+1139
-134
lines changed

13 files changed

+1139
-134
lines changed

apps/dashboard/src/@/components/ui/code/CodeBlockContainer.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export function CodeBlockContainer(props: {
1111
children: React.ReactNode;
1212
className?: string;
1313
scrollableClassName?: string;
14+
scrollableContainerClassName?: string;
1415
copyButtonClassName?: string;
1516
}) {
1617
const { hasCopied, onCopy } = useClipboard(props.codeToCopy);
@@ -24,7 +25,10 @@ export function CodeBlockContainer(props: {
2425
>
2526
<ScrollShadow
2627
scrollableClassName={cn("p-4", props.scrollableClassName)}
27-
className="text-xs md:text-sm [&_*]:leading-relaxed"
28+
className={cn(
29+
"text-xs md:text-sm [&_*]:leading-relaxed",
30+
props.scrollableContainerClassName,
31+
)}
2832
shadowColor="hsl(var(--muted))"
2933
>
3034
{props.children}

apps/dashboard/src/@/components/ui/code/RenderCode.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ export function RenderCode(props: {
66
className?: string;
77
scrollableClassName?: string;
88
copyButtonClassName?: string;
9+
scrollableContainerClassName?: string;
910
}) {
1011
return (
1112
<CodeBlockContainer
1213
codeToCopy={props.code}
1314
className={props.className}
1415
copyButtonClassName={props.copyButtonClassName}
1516
scrollableClassName={props.scrollableClassName}
17+
scrollableContainerClassName={props.scrollableContainerClassName}
1618
>
1719
<div
1820
// biome-ignore lint/security/noDangerouslySetInnerHtml: we know what we're doing here

apps/dashboard/src/@/components/ui/code/code.client.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type CodeProps = {
1212
scrollableClassName?: string;
1313
keepPreviousDataOnCodeChange?: boolean;
1414
copyButtonClassName?: string;
15+
scrollableContainerClassName?: string;
1516
};
1617

1718
export const CodeClient: React.FC<CodeProps> = ({
@@ -21,6 +22,7 @@ export const CodeClient: React.FC<CodeProps> = ({
2122
scrollableClassName,
2223
keepPreviousDataOnCodeChange = false,
2324
copyButtonClassName,
25+
scrollableContainerClassName,
2426
}) => {
2527
const codeQuery = useQuery({
2628
queryKey: ["html", code],
@@ -38,6 +40,7 @@ export const CodeClient: React.FC<CodeProps> = ({
3840
className={className}
3941
scrollableClassName={scrollableClassName}
4042
copyButtonClassName={copyButtonClassName}
43+
scrollableContainerClassName={scrollableContainerClassName}
4144
/>
4245
);
4346
}
@@ -49,6 +52,7 @@ export const CodeClient: React.FC<CodeProps> = ({
4952
className={className}
5053
scrollableClassName={scrollableClassName}
5154
copyButtonClassName={copyButtonClassName}
55+
scrollableContainerClassName={scrollableContainerClassName}
5256
/>
5357
);
5458
};

apps/dashboard/src/@/components/ui/code/getCodeHtml.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ function isPrettierSupportedLang(lang: BundledLanguage) {
1010
lang === "ts" ||
1111
lang === "tsx" ||
1212
lang === "javascript" ||
13-
lang === "typescript" ||
14-
lang === "css" ||
15-
lang === "json"
13+
lang === "typescript"
1614
);
1715
}
1816

apps/dashboard/src/@/components/ui/code/plaintext-code.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ export function PlainTextCodeBlock(props: {
77
className?: string;
88
scrollableClassName?: string;
99
codeClassName?: string;
10+
scrollableContainerClassName?: string;
1011
}) {
1112
return (
1213
<CodeBlockContainer
1314
codeToCopy={props.code}
1415
className={props.className}
1516
copyButtonClassName={props.copyButtonClassName}
1617
scrollableClassName={props.scrollableClassName}
18+
scrollableContainerClassName={props.scrollableContainerClassName}
1719
>
1820
<code className={cn("block whitespace-pre", props.codeClassName)}>
1921
{props.code}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { useMutation } from "@tanstack/react-query";
3+
import { useState } from "react";
4+
import { mobileViewport } from "../../../../../../stories/utils";
5+
import { BluePrintPlaygroundUI } from "./BluePrintPlayground";
6+
import type { BluePrintMetadata } from "./utils";
7+
8+
const meta = {
9+
title: "Insight/BluePrintPlayground",
10+
component: Story,
11+
parameters: {
12+
nextjs: {
13+
appDirectory: true,
14+
},
15+
},
16+
} satisfies Meta<typeof Story>;
17+
18+
export default meta;
19+
type Story = StoryObj<typeof meta>;
20+
21+
export const Desktop: Story = {
22+
args: {
23+
metadata: getBlueprintMetadata().transactionsMetadata,
24+
},
25+
};
26+
27+
export const Mobile: Story = {
28+
args: {
29+
metadata: getBlueprintMetadata().transactionsMetadata,
30+
},
31+
parameters: {
32+
viewport: mobileViewport("iphone14"),
33+
},
34+
};
35+
36+
function Story() {
37+
return (
38+
<div className="flex flex-col gap-10">
39+
<Variant metadata={getBlueprintMetadata().transactionsMetadata} />
40+
<Variant metadata={getBlueprintMetadata().eventsMetadata} />
41+
<Variant metadata={getBlueprintMetadata().tokensMetadata} />
42+
</div>
43+
);
44+
}
45+
46+
function Variant(props: {
47+
metadata: BluePrintMetadata;
48+
}) {
49+
const [abortController, setAbortController] =
50+
useState<AbortController | null>(null);
51+
52+
const mutation = useMutation({
53+
mutationFn: async () => {
54+
const controller = new AbortController();
55+
setAbortController(controller);
56+
const start = performance.now();
57+
const promise = new Promise((resolve) =>
58+
setTimeout(resolve, Math.random() * 4000),
59+
);
60+
await Promise.race([
61+
promise,
62+
new Promise((_, reject) =>
63+
controller.signal.addEventListener("abort", reject),
64+
),
65+
]);
66+
67+
const dummyResponse = {
68+
data: {
69+
title: "This is a dummy response",
70+
content: crypto.getRandomValues(new Uint8Array(100)),
71+
},
72+
};
73+
74+
return {
75+
data: JSON.stringify(dummyResponse, null, 2),
76+
status: 200,
77+
time: performance.now() - start,
78+
};
79+
},
80+
});
81+
return (
82+
<div className="flex min-h-[800px] flex-col">
83+
<BluePrintPlaygroundUI
84+
metadata={props.metadata}
85+
backLink="/"
86+
isPending={mutation.isPending}
87+
onRun={async () => {
88+
mutation.mutateAsync();
89+
}}
90+
response={mutation.data}
91+
clientId="68665db28327c771c9a1bd5fc4580a0a"
92+
abortRequest={() => {
93+
abortController?.abort();
94+
}}
95+
/>
96+
</div>
97+
);
98+
}
99+
100+
function getBlueprintMetadata() {
101+
const transactionsMetadata: BluePrintMetadata = {
102+
domain: "https://{chainId}.insight.thirdweb.com",
103+
path: "/v1/{clientId}/transactions",
104+
parameters: [
105+
{
106+
name: "chainId",
107+
in: "path",
108+
required: true,
109+
description: "Chain ID",
110+
type: "string",
111+
},
112+
{
113+
name: "filter",
114+
in: "query",
115+
description: "Filter parameters",
116+
type: "string",
117+
},
118+
{
119+
name: "group_by",
120+
in: "query",
121+
description: "Field to group results by",
122+
type: "string",
123+
},
124+
{
125+
name: "sort_by",
126+
in: "query",
127+
description: "Field to sort results by",
128+
type: "string",
129+
},
130+
{
131+
name: "sort_order",
132+
in: "query",
133+
description: "Sort order (asc or desc)",
134+
type: "string",
135+
},
136+
{
137+
name: "page",
138+
in: "query",
139+
description: "Page number for pagination",
140+
type: "integer",
141+
},
142+
{
143+
name: "limit",
144+
in: "query",
145+
description: "Number of items per page",
146+
type: "integer",
147+
},
148+
{
149+
name: "aggregate",
150+
in: "query",
151+
description: "List of aggregate functions to apply",
152+
type: "array",
153+
},
154+
],
155+
title: "Transactions",
156+
description: "Retrieve all transactions across all contracts",
157+
};
158+
159+
const eventsMetadata: BluePrintMetadata = {
160+
domain: "https://{chainId}.insight.thirdweb.com",
161+
path: "/v1/{clientId}/events",
162+
parameters: [
163+
{
164+
name: "chainId",
165+
in: "path",
166+
required: true,
167+
description: "Chain ID",
168+
type: "string",
169+
},
170+
{
171+
name: "filter",
172+
in: "query",
173+
description: "Filter parameters",
174+
type: "string",
175+
},
176+
{
177+
name: "group_by",
178+
in: "query",
179+
description: "Field to group results by",
180+
type: "string",
181+
},
182+
{
183+
name: "sort_by",
184+
in: "query",
185+
description: "Field to sort results by",
186+
type: "string",
187+
},
188+
{
189+
name: "sort_order",
190+
in: "query",
191+
description: "Sort order (asc or desc)",
192+
type: "string",
193+
},
194+
{
195+
name: "page",
196+
in: "query",
197+
description: "Page number for pagination",
198+
type: "integer",
199+
},
200+
{
201+
name: "limit",
202+
in: "query",
203+
description: "Number of items per page",
204+
type: "integer",
205+
},
206+
{
207+
name: "aggregate",
208+
in: "query",
209+
description: "List of aggregate functions to apply",
210+
type: "array",
211+
},
212+
],
213+
title: "Events",
214+
description: "Retrieve all logs across all contracts",
215+
};
216+
217+
const tokensMetadata: BluePrintMetadata = {
218+
domain: "https://{chainId}.insight.thirdweb.com",
219+
path: "/v1/{clientId}/tokens/erc20/:ownerAddress",
220+
parameters: [
221+
{
222+
name: "ownerAddress",
223+
in: "path",
224+
required: true,
225+
type: "string",
226+
},
227+
{
228+
name: "clientId",
229+
in: "path",
230+
required: false,
231+
type: "string",
232+
},
233+
],
234+
title: "Tokens",
235+
description: "Retrieve tokens balances for a given owner address",
236+
};
237+
238+
return {
239+
transactionsMetadata,
240+
eventsMetadata,
241+
tokensMetadata,
242+
};
243+
}

0 commit comments

Comments
 (0)