Skip to content

Commit 0e1ee82

Browse files
committed
Dashboard: Migrate engine/metrics from chakra to tailwind (#7722)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on improving the layout and user interface of the `Healthcheck` and `EngineSystemMetrics` components in the dashboard. It enhances responsiveness and readability, while also introducing new loading states and alert messages. ### Detailed summary - Changed layout from row to column in `engine-contract-subscription.tsx`. - Added `tracking-tight` class to the `h2` header for better text spacing. - Refactored `Healthcheck` component to use a new loading indicator. - Updated `EngineSystemMetrics` to use `GenericLoadingPage` instead of `Spinner`. - Introduced `Alert` component for error messaging in `EngineSystemMetrics`. - Replaced `Card` components with divs for layout consistency. - Created a new `MetricRow` component for displaying metrics in a structured format. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 67abd0d commit 0e1ee82

File tree

3 files changed

+92
-100
lines changed

3 files changed

+92
-100
lines changed

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/contract-subscriptions/components/engine-contract-subscription.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ export function EngineContractSubscriptions({
2727
return (
2828
<div>
2929
{/* Header */}
30-
<div className="flex flex-row gap-2 justify-between mb-4">
30+
<div className="flex flex-col md:flex-row gap-4 justify-between mb-4">
3131
<div>
32-
<h2 className="text-2xl font-semibold mb-1">
32+
<h2 className="text-2xl font-semibold mb-1 tracking-tight">
3333
Contract Subscriptions
3434
</h2>
3535
<p className="text-muted-foreground text-sm">
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
"use client";
22

3-
import { Card } from "chakra/card";
4-
import { Heading } from "chakra/heading";
5-
import { Text } from "chakra/text";
6-
import { ChartAreaIcon, InfoIcon } from "lucide-react";
7-
import { Spinner } from "@/components/ui/Spinner/Spinner";
3+
import { CircleAlertIcon } from "lucide-react";
4+
import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage";
5+
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
86
import { UnderlineLink } from "@/components/ui/UnderlineLink";
97
import {
108
type EngineInstance,
@@ -15,19 +13,17 @@ import { ErrorRate } from "./ErrorRate";
1513
import { Healthcheck } from "./Healthcheck";
1614
import { StatusCodes } from "./StatusCodes";
1715

18-
interface EngineStatusProps {
19-
instance: EngineInstance;
20-
teamSlug: string;
21-
projectSlug: string;
22-
authToken: string;
23-
}
24-
25-
export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
16+
export function EngineSystemMetrics({
2617
instance,
2718
teamSlug,
2819
projectSlug,
2920
authToken,
30-
}) => {
21+
}: {
22+
instance: EngineInstance;
23+
teamSlug: string;
24+
projectSlug: string;
25+
authToken: string;
26+
}) {
3127
const systemMetricsQuery = useEngineSystemMetrics(
3228
instance.id,
3329
teamSlug,
@@ -39,58 +35,54 @@ export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
3935
pollInterval: 10_000,
4036
});
4137

42-
let systemMetricsPanel = <Spinner className="h-4 w-4" />;
38+
let systemMetricsPanel = <GenericLoadingPage />;
4339
if (!systemMetricsQuery.data || systemMetricsQuery.isError) {
4440
systemMetricsPanel = (
45-
<Card p={8}>
46-
<div className="flex flex-col gap-4">
47-
<div className="flex flex-row items-center gap-2">
48-
<InfoIcon className="size-4" />
49-
<Heading size="title.xs">
50-
System metrics are unavailable for self-hosted Engine.
51-
</Heading>
52-
</div>
53-
<Text>
41+
<div>
42+
<h2 className="text-2xl font-semibold tracking-tight mb-4">
43+
System Metrics
44+
</h2>
45+
46+
<Alert variant="warning">
47+
<CircleAlertIcon className="size-5" />
48+
<AlertTitle>
49+
System metrics are not available for self-hosted Engine
50+
</AlertTitle>
51+
<AlertDescription className="text-muted-foreground text-sm">
5452
Upgrade to a{" "}
5553
<UnderlineLink
56-
color="blue.500"
5754
href={`/team/${teamSlug}/${projectSlug}/engine/dedicated/create`}
5855
rel="noopener noreferrer"
5956
target="_blank"
6057
>
6158
Engine instance managed by thirdweb
6259
</UnderlineLink>{" "}
63-
to view these metrics.
64-
</Text>
65-
</div>
66-
</Card>
60+
to view system metrics
61+
</AlertDescription>
62+
</Alert>
63+
</div>
6764
);
6865
} else {
6966
systemMetricsPanel = (
70-
<Card p={16}>
71-
<div className="flex flex-col gap-4">
72-
<div className="-mb-2 flex flex-row items-center gap-2">
73-
<ChartAreaIcon className="size-4" />
74-
<Heading size="title.md">System Metrics</Heading>
75-
</div>
67+
<div>
68+
<div className="flex items-center gap-3 mb-4">
69+
<h2 className="text-2xl font-semibold tracking-tight">
70+
System Metrics
71+
</h2>
72+
<Healthcheck instance={instance} />
73+
</div>
7674

77-
<div className="mt-10 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
78-
<Healthcheck instance={instance} />
79-
</div>
75+
<div className="space-y-8">
8076
<StatusCodes
8177
datapoints={systemMetricsQuery.data.result.statusCodes}
8278
/>
8379
<ErrorRate datapoints={systemMetricsQuery.data.result.errorRate} />
8480
</div>
85-
</Card>
81+
</div>
8682
);
8783
}
8884

89-
let queueMetricsPanel = (
90-
<div className="flex min-h-[200px] items-center justify-center rounded-lg border border-border">
91-
<Spinner className="size-6" />
92-
</div>
93-
);
85+
let queueMetricsPanel = <GenericLoadingPage />;
9486

9587
if (
9688
!queueMetricsQuery.isPending &&
@@ -108,43 +100,39 @@ export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
108100
const msToMine = queueMetricsQuery.data.result.latency?.msToMine;
109101

110102
queueMetricsPanel = (
111-
<Card p={8}>
112-
<div className="flex flex-col gap-6">
113-
<div className="flex flex-row items-center gap-2">
114-
<Heading size="title.md">Queue Metrics</Heading>
115-
</div>
103+
<div className="bg-card p-4 rounded-lg border lg:p-6">
104+
<h2 className="text-lg tracking-tight font-semibold mb-3">
105+
Queue Metrics
106+
</h2>
116107

117-
<div className="flex flex-col gap-6 lg:flex-row lg:gap-12">
118-
<div className="flex-col gap-y-4">
119-
<h2 className="font-semibold"> Queued</h2>
120-
<p className="text-muted-foreground">{numQueued}</p>
121-
</div>
122-
<div className="flex-col gap-y-4">
123-
<h2 className="font-semibold">Pending</h2>
124-
<p className="text-muted-foreground">{numPending}</p>
125-
</div>
108+
<div className="space-y-2">
109+
<MetricRow label="Queued" value={numQueued} />
110+
<MetricRow label="Pending" value={numPending} />
126111

127-
{msToSend && (
128-
<div className="flex-col gap-y-4">
129-
<h2 className="font-semibold">Time to send</h2>
130-
<p className="text-muted-foreground">
112+
{msToSend && (
113+
<MetricRow
114+
label="Time to send"
115+
value={
116+
<span>
131117
p50 {(msToSend.p50 / 1000).toFixed(2)}s, p90{" "}
132118
{(msToSend.p90 / 1000).toFixed(2)}s
133-
</p>
134-
</div>
135-
)}
136-
{msToMine && (
137-
<div className="flex-col gap-y-4">
138-
<h2 className="font-semibold">Time to mine</h2>
139-
<p className="text-muted-foreground">
119+
</span>
120+
}
121+
/>
122+
)}
123+
{msToMine && (
124+
<MetricRow
125+
label="Time to mine"
126+
value={
127+
<span>
140128
p50 {(msToMine.p50 / 1000).toFixed(2)}s, p90{" "}
141129
{(msToMine.p90 / 1000).toFixed(2)}s
142-
</p>
143-
</div>
144-
)}
145-
</div>
130+
</span>
131+
}
132+
/>
133+
)}
146134
</div>
147-
</Card>
135+
</div>
148136
);
149137
}
150138

@@ -154,4 +142,19 @@ export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
154142
{queueMetricsPanel}
155143
</div>
156144
);
157-
};
145+
}
146+
147+
function MetricRow({
148+
label,
149+
value,
150+
}: {
151+
label: string;
152+
value: React.ReactNode;
153+
}) {
154+
return (
155+
<div className="grid grid-cols-2 w-[400px]">
156+
<h3 className="text-sm font-medium">{label}</h3>
157+
<p className="text-sm text-foreground">{value}</p>
158+
</div>
159+
);
160+
}

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/metrics/components/Healthcheck.tsx

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
22

3-
import { PrimaryInfoItem } from "app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/primary-info-item";
43
import { Skeleton } from "@/components/ui/skeleton";
54
import { ToolTipLabel } from "@/components/ui/tooltip";
65
import { type EngineInstance, useEngineSystemHealth } from "@/hooks/useEngine";
@@ -9,35 +8,25 @@ export function Healthcheck({ instance }: { instance: EngineInstance }) {
98
const query = useEngineSystemHealth(instance.url, 5_000);
109

1110
return (
12-
<>
13-
{/* Engine Reachability */}
14-
<PrimaryInfoItem title="Engine" titleIcon={<PulseDot />}>
15-
<div className="flex items-center gap-1">
16-
{query.isSuccess ? (
17-
<ToolTipLabel label="Working">
18-
<div className="text-lg text-success-text">Reachable</div>
19-
</ToolTipLabel>
20-
) : query.isError ? (
21-
<ToolTipLabel label="Not Working">
22-
<div className="text-destructive-text text-lg">Not Reachable</div>
23-
</ToolTipLabel>
24-
) : (
25-
<div className="flex h-[28px] w-[70px] py-1">
26-
<Skeleton className="h-full w-full" />
27-
</div>
28-
)}
29-
</div>
30-
</PrimaryInfoItem>
31-
</>
11+
<div className="rounded-full bg-card px-3 py-2 border flex items-center gap-2">
12+
<PulseDot />
13+
{query.isSuccess ? (
14+
<div className="text-sm">Reachable</div>
15+
) : query.isError ? (
16+
<div className="text-destructive-text text-sm">Not Reachable</div>
17+
) : (
18+
<Skeleton className="h-4 w-16" />
19+
)}
20+
</div>
3221
);
3322
}
3423

3524
function PulseDot() {
3625
return (
3726
<ToolTipLabel label="Live Data">
38-
<span className="relative flex size-3">
27+
<span className="relative flex size-2">
3928
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-sky-400 opacity-75" />
40-
<span className="relative inline-flex size-3 rounded-full bg-primary" />
29+
<span className="relative inline-flex size-2 rounded-full bg-primary" />
4130
</span>
4231
</ToolTipLabel>
4332
);

0 commit comments

Comments
 (0)