Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL Logs #207

Merged
merged 13 commits into from
Mar 6, 2024
31 changes: 31 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ export function DataTable<TData, TValue>({

return (
<div>
<div className="flex items-center py-4">
<h2 className="text-xl font-medium">Table Data</h2>
<div className="flex items-center">
{!!data.length && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
Expand Down Expand Up @@ -87,7 +86,7 @@ export function DataTable<TData, TValue>({
</DropdownMenu>
)}
</div>
<div className="rounded-md border">
<div className="mt-4 rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
Expand Down
2 changes: 1 addition & 1 deletion packages/web/app/_components/latest-projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Link from "next/link";
import TimeAgo from "javascript-time-ago";
import { useState } from "react";
import { Paginator } from "./paginator";
import { Paginator } from "@/components/paginator";
import { TypographyH3 } from "@/components/typography-h3";
import { type store } from "@/lib/store";
import TeamAvatar from "@/components/team-avatar";
Expand Down
3 changes: 2 additions & 1 deletion packages/web/app/_components/latest-tables.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Link from "next/link";
import TimeAgo from "javascript-time-ago";
import { useEffect, useState } from "react";
import { chainsMap } from "../../lib/chains-map";
import { Paginator } from "./paginator";
import { Paginator } from "@/components/paginator";
import { TypographyH3 } from "@/components/typography-h3";
import ChainSelector from "@/components/chain-selector";
import { Label } from "@/components/ui/label";
Expand Down Expand Up @@ -85,6 +85,7 @@ export function LatestTables({ initialData }: { initialData: Table[] }) {
pageSize={pageSize}
page={page}
setPage={setPage}
disabled={loading}
/>
</>
);
Expand Down
3 changes: 2 additions & 1 deletion packages/web/app/_components/popular-tables.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Link from "next/link";
import { useEffect, useState } from "react";
import { chainsMap } from "../../lib/chains-map";
import { Paginator } from "./paginator";
import { Paginator } from "@/components/paginator";
import { TypographyH3 } from "@/components/typography-h3";
import ChainSelector from "@/components/chain-selector";
import { Label } from "@/components/ui/label";
Expand Down Expand Up @@ -101,6 +101,7 @@ export function PopularTables({
pageSize={pageSize}
page={page}
setPage={setPage}
disabled={loading}
/>
</>
);
Expand Down
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Experimenting with my own Card component on the txn page just to have more control over how it looks. Still don't love using cards like this everywhere, but it's just a go-to for the time being.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You, @dtbuchholz, and I all independently opened PRs to fix/change the ShadCN Card. Maybe we combine them into a single component and start using that everywhere on the site?

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { type ComponentPropsWithoutRef } from "react";
import { cn } from "@/lib/utils";

export function Card({
children,
className,
...rest
}: ComponentPropsWithoutRef<"div">) {
return (
<div className="flex flex-col gap-4 rounded-sm border border-gray-200 p-4">
{children}
</div>
);
}

export function CardTitle({
children,
className,
...rest
}: ComponentPropsWithoutRef<"div">) {
return (
<div
className={cn("text-xs uppercase text-muted-foreground", className)}
{...rest}
>
{children}
</div>
);
}

export function CardContent({
children,
className,
...rest
}: ComponentPropsWithoutRef<"div">) {
return (
<div className="flex flex-col gap-2" {...rest}>
{children}
</div>
);
}

export function CardMainContent({
children,
className,
...rest
}: ComponentPropsWithoutRef<"div">) {
return (
<div
className={cn("self-center text-3xl font-medium", className)}
{...rest}
>
{children}
</div>
);
}

export function CardSubContent({
children,
className,
...rest
}: ComponentPropsWithoutRef<"div">) {
return (
<div
className={cn("self-center text-sm text-muted-foreground", className)}
{...rest}
>
{children}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use client";

import { ExternalLink } from "lucide-react";
import { Button } from "@/components/ui/button";

export default function ExplorerButton({
explorerName,
txnUrl,
}: {
explorerName: string;
txnUrl: string;
}) {
return (
<Button
variant="ghost"
size="default"
className="ml-auto gap-x-1"
onClick={() => window.open(txnUrl)}
>
<ExternalLink className="shrink-0" />
View on {explorerName}
</Button>
);
}
157 changes: 157 additions & 0 deletions packages/web/app/chain/[chainId]/txn/[txnHash]/page.tsx
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the react server component page that renders to view a single transaction.

Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import TimeAgo from "javascript-time-ago";
import { AlertCircle } from "lucide-react";
import { notFound } from "next/navigation";
import Link from "next/link";
import {
Card,
CardContent,
CardMainContent,
CardSubContent,
CardTitle,
} from "./_components/card";
import ExplorerButton from "./_components/explorer-button";
import AddressDisplay from "@/components/address-display";
import { chainsMap } from "@/lib/chains-map";
import { cn } from "@/lib/utils";
import { getSqlLog } from "@/lib/validator-queries";
import { blockExplorers } from "@/lib/block-explorers";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";

const timeAgo = new TimeAgo("en-US");

export default async function TxnPage({
params,
}: {
params: { chainId: string; txnHash: string };
}) {
const chainNumber = parseInt(params.chainId, 10);
const log = await getSqlLog(chainNumber, params.txnHash);

const chain = chainsMap.get(chainNumber);

if (!chain) {
notFound();
}

const explorer = blockExplorers.get(chainNumber);

return (
<div className="container flex flex-col gap-10 pt-10">
<div className="flex items-center gap-2">
{log.error && (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<AlertCircle />
</TooltipTrigger>
<TooltipContent>Txn Status: Error</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
<AddressDisplay
address={log.txHash}
name="txn hash"
numCharacters={8}
copy
className={cn("text-3xl font-bold", log.error && "text-red-500")}
/>
{explorer && (
<ExplorerButton
explorerName={explorer.explorer}
txnUrl={explorer.txUrl(params.txnHash)}
/>
)}
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3">
<Card>
<CardTitle>Sent by</CardTitle>
<CardContent>
<CardMainContent>
<AddressDisplay
address={log.caller}
copy
className="self-center text-3xl font-medium text-black"
/>
</CardMainContent>
</CardContent>
</Card>
<Card>
<CardTitle>Timestamp</CardTitle>
<CardContent>
<CardMainContent>
{timeAgo.format(log.timestamp * 1000)}
</CardMainContent>
<CardSubContent>
{new Date(log.timestamp * 1000).toLocaleString()}
</CardSubContent>
</CardContent>
</Card>
<Card>
<CardTitle>Status</CardTitle>
<CardContent>
<CardMainContent>{log.error ? "Error" : "Success"}</CardMainContent>
</CardContent>
</Card>
<Card>
<CardTitle>Chain ID</CardTitle>
<CardContent>
<CardMainContent>{chainNumber}</CardMainContent>
<CardSubContent>{chain.name}</CardSubContent>
</CardContent>
</Card>
<Card>
<CardTitle>Block Number</CardTitle>
<CardContent>
<CardMainContent>{log.blockNumber}</CardMainContent>
{explorer && (
<CardSubContent>
<Link href={explorer.blockUrl(log.blockNumber)}>
View on {explorer.explorer}
</Link>
</CardSubContent>
)}
</CardContent>
</Card>
<Card>
<CardTitle>Event Index</CardTitle>
<CardContent>
<CardMainContent>{log.eventIndex}</CardMainContent>
</CardContent>
</Card>
<Card>
<CardTitle>Event Type</CardTitle>
<CardContent>
<CardMainContent>
{log.eventType === "ContractCreateTable"
? "Create Table"
: "Run SQL"}
</CardMainContent>
</CardContent>
</Card>
</div>
<div>
<label className="text-sm uppercase text-muted-foreground">
Statement:
</label>
<pre className="whitespace-break-spaces rounded-sm border border-gray-300 bg-gray-100 p-4">
{log.statement}
</pre>
</div>
{log.error && (
<div>
<label className="text-sm uppercase text-muted-foreground">
Error:
</label>
<pre className="whitespace-break-spaces rounded-sm border border-gray-300 bg-gray-100 p-4">
{log.error}
</pre>
</div>
)}
</div>
);
}
Loading
Loading