Skip to content

Commit

Permalink
[TOOL-3508] Dashboard: Engine general Page UI improvements, update en…
Browse files Browse the repository at this point in the history
…gine instance header layout (#6324)
  • Loading branch information
MananTank authored Feb 27, 2025
1 parent 566b5b9 commit 39a8afd
Show file tree
Hide file tree
Showing 24 changed files with 1,280 additions and 831 deletions.
2 changes: 1 addition & 1 deletion apps/dashboard/src/@/components/ui/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background selection:bg-foreground selection:text-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background selection:bg-foreground/10 file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className,
)}
ref={ref}
Expand Down
20 changes: 20 additions & 0 deletions apps/dashboard/src/@/components/ui/tracked-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useTrack } from "hooks/analytics/useTrack";
import Link from "next/link";
import type React from "react";
import { cn } from "../../lib/utils";

export type TrackedLinkProps = React.ComponentProps<typeof Link> & {
category: string;
Expand All @@ -24,3 +25,22 @@ export function TrackedLinkTW(props: TrackedLinkProps) {
/>
);
}

export function TrackedUnderlineLink(props: TrackedLinkProps) {
const trackEvent = useTrack();
const { category, label, trackingProps, ...restProps } = props;

return (
<Link
{...restProps}
onClick={(e) => {
trackEvent({ category, action: "click", label, ...trackingProps });
props.onClick?.(e);
}}
className={cn(
"underline decoration-muted-foreground/50 decoration-dotted underline-offset-[5px] hover:text-foreground hover:decoration-foreground hover:decoration-solid",
restProps.className,
)}
/>
);
}
2 changes: 1 addition & 1 deletion apps/dashboard/src/@/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
--link-foreground: 221.21deg 83.19% 53.33%;
--success-text: 142.09 70.56% 35.29%;
--warning-text: 38 92% 40%;
--destructive-text: 357.15deg 100% 68.72%;
--destructive-text: 360 72% 60%;

/* Borders */
--border: 0 0% 85%;
Expand Down
128 changes: 49 additions & 79 deletions apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,101 +230,71 @@ export function useEngineUpdateDeployment() {
});
}

export function useEngineRemoveFromDashboard() {
const address = useActiveAccount()?.address;
const queryClient = useQueryClient();

return useMutation({
mutationFn: async (instanceId: string) => {
invariant(instanceId, "instance is required");

const res = await apiServerProxy({
pathname: `/v1/engine/${instanceId}`,
method: "DELETE",
});

if (!res.ok) {
throw new Error(res.error);
}
},
export type RemoveEngineFromDashboardIParams = {
instanceId: string;
};

onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.instances(address || ""),
});
},
export async function removeEngineFromDashboard({
instanceId,
}: RemoveEngineFromDashboardIParams) {
const res = await apiServerProxy({
pathname: `/v1/engine/${instanceId}`,
method: "DELETE",
});

if (!res.ok) {
throw new Error(res.error);
}
}

export interface DeleteCloudHostedInput {
export type DeleteCloudHostedEngineParams = {
deploymentId: string;
reason: "USING_SELF_HOSTED" | "TOO_EXPENSIVE" | "MISSING_FEATURES" | "OTHER";
feedback: string;
}

export function useEngineDeleteCloudHosted() {
const address = useActiveAccount()?.address;
const queryClient = useQueryClient();

return useMutation({
mutationFn: async ({
deploymentId,
reason,
feedback,
}: DeleteCloudHostedInput) => {
const res = await apiServerProxy({
pathname: `/v2/engine/deployments/${deploymentId}/infrastructure/delete`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ reason, feedback }),
});

if (!res.ok) {
throw new Error(res.error);
}
},
};

onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.instances(address || ""),
});
},
export async function deleteCloudHostedEngine({
deploymentId,
reason,
feedback,
}: DeleteCloudHostedEngineParams) {
const res = await apiServerProxy({
pathname: `/v2/engine/deployments/${deploymentId}/infrastructure/delete`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ reason, feedback }),
});

if (!res.ok) {
throw new Error(res.error);
}
}

export interface EditEngineInstanceInput {
export type EditEngineInstanceParams = {
instanceId: string;
name: string;
url: string;
}

export function useEngineEditInstance() {
const address = useActiveAccount()?.address;
const queryClient = useQueryClient();

return useMutation({
mutationFn: async ({ instanceId, name, url }: EditEngineInstanceInput) => {
const res = await apiServerProxy({
pathname: `/v1/engine/${instanceId}`,
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name, url }),
});
};

if (!res.ok) {
throw new Error(res.error);
}
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: engineKeys.instances(address || ""),
});
},
export async function editEngineInstance({
instanceId,
name,
url,
}: EditEngineInstanceParams) {
const res = await apiServerProxy({
pathname: `/v1/engine/${instanceId}`,
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name, url }),
});

if (!res.ok) {
throw new Error(res.error);
}
}

export type Transaction = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { SidebarLayout } from "@/components/blocks/SidebarLayout";
import {} from "@/constants/cookie";
import { redirect } from "next/navigation";
import { getAuthToken } from "../../../../../../../../api/lib/getAuthToken";
import { fetchEcosystem } from "../../../utils/fetchEcosystem";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Button } from "@/components/ui/button";
import {} from "@/constants/cookie";
import { ArrowRightIcon, ExternalLinkIcon } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
"use client";

import { Button } from "@/components/ui/button";
import {
ArrowRightIcon,
DownloadIcon,
ExternalLinkIcon,
PlusIcon,
} from "lucide-react";
import Link from "next/link";
import { useTrack } from "../../../../../../../hooks/analytics/useTrack";

export function CreateEngineLink(props: {
label: string;
engineLinkPrefix: string;
}) {
const trackEvent = useTrack();

return (
<Button
asChild
variant="default"
size="sm"
onClick={() => {
trackEvent({
category: "engine",
action: "click",
label: "add-engine-instance",
});
}}
>
<Link href={`${props.engineLinkPrefix}/create`} className="gap-2">
<PlusIcon className="size-3" />
{props.label}
</Link>
</Button>
);
}

export function ImportEngineLink(props: {
label: string;
engineLinkPrefix: string;
}) {
const trackEvent = useTrack();

return (
<Button
asChild
variant="outline"
size="sm"
className="gap-2 bg-card"
onClick={() => {
trackEvent({
category: "engine",
action: "import",
});
}}
>
<Link href={`${props.engineLinkPrefix}/import`}>
<DownloadIcon className="size-3" />
{props.label}
</Link>
</Button>
);
}

export function EngineInfoCard(props: { team_slug: string }) {
const engineLinkPrefix = `/team/${props.team_slug}/~/engine`;
const trackEvent = useTrack();

return (
<div className=" rounded-lg border border-border bg-card">
<div className="p-6">
<h1 className="font-semibold text-xl tracking-tight">
Your scalable web3 backend server
</h1>

<div className="h-2" />

<ul className="list-disc space-y-2 pl-3 text-muted-foreground text-sm">
<li>Read, write, and deploy contracts at production scale</li>
<li>
Reliably parallelize and retry transactions with gas & nonce
management
</li>
<li>Securely manage backend wallets</li>
<li>Built-in support for account abstraction, relayers, and more</li>
</ul>
</div>

<div className="flex justify-end gap-3 border-border border-t p-4 lg:px-6">
<Button asChild variant="outline" size="sm">
<Link
href="https://portal.thirdweb.com/engine"
className="gap-2"
target="_blank"
>
Learn More
<ExternalLinkIcon className="size-3 text-muted-foreground" />
</Link>
</Button>

<Button
size="sm"
asChild
onClick={() => {
trackEvent({
category: "engine",
action: "try-demo",
label: "clicked-try-demo",
});
}}
variant="outline"
>
<Link href={`${engineLinkPrefix}/sandbox`} className="gap-2">
Try Demo Engine
<ArrowRightIcon className="size-3 text-muted-foreground" />
</Link>
</Button>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { EngineTierCard } from "./tier-card";

export default function Page() {
return (
<div>
<h1 className="mb-2 font-semibold text-2xl tracking-tight">
<div className="pb-20">
<h1 className="mb-1 font-semibold text-2xl tracking-tight">
Choose an Engine deployment
</h1>

<p className="mb-7 text-muted-foreground">
Host Engine on thirdweb with no setup or maintenance required.
<p className="mb-8 text-muted-foreground text-sm">
Host Engine on thirdweb with no setup or maintenance required
</p>

<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
<div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
<EngineTierCard tier="STARTER" />
<EngineTierCard tier="PREMIUM" isPrimaryCta />
<EngineTierCard tier="ENTERPRISE" previousTier="Premium Engine" />
Expand Down
Loading

0 comments on commit 39a8afd

Please sign in to comment.