Skip to content

Commit

Permalink
feat: add alternative tables and show ddl sql of the table
Browse files Browse the repository at this point in the history
  • Loading branch information
duyet committed Nov 27, 2023
1 parent b401968 commit fafe21c
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 23 deletions.
72 changes: 72 additions & 0 deletions app/tables/[database]/[table]/alternative-tables.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Link from 'next/link'
import { CardStackMinusIcon, DotFilledIcon } from '@radix-ui/react-icons'
import { ChevronDownIcon, TableIcon } from 'lucide-react'

import { fetchData } from '@/lib/clickhouse'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'

interface AlternativeTablesProps {
database: string
table: string
}

export async function AlternativeTables({
database,
table,
}: AlternativeTablesProps) {
let anotherTables: { name: string }[] = []
try {
anotherTables = await fetchData(
`SELECT name FROM system.tables WHERE database = {database: String}`,
{ database }
)
} catch (error) {
console.log(error)

return null
}

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size="sm"
className="text-muted-foreground group flex flex-row gap-2"
>
<CardStackMinusIcon className="h-3 w-3" />
{database}
<ChevronDownIcon
className="h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180"
aria-hidden="true"
/>
</Button>
</DropdownMenuTrigger>

<DropdownMenuContent>
{anotherTables.map(({ name }) => (
<DropdownMenuItem key={name}>
<Link
href={`/tables/${database}/${name}`}
className="flex flex-row items-center gap-2"
>
{name == table ? (
<DotFilledIcon className="h-3 w-3" />
) : (
<div className="h-3 w-3" />
)}
<TableIcon className="h-3 w-3" />
{name}
</Link>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)
}
28 changes: 20 additions & 8 deletions app/tables/[database]/[table]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import Link from 'next/link'
import { ArrowLeftIcon } from 'lucide-react'

import { fetchData } from '@/lib/clickhouse'
import type { QueryConfig } from '@/lib/types/query-config'
import { type QueryConfig } from '@/lib/types/query-config'
import { Button } from '@/components/ui/button'
import { ColumnFormat } from '@/components/data-table/columns'
import { DataTable } from '@/components/data-table/data-table'

import { AlternativeTables } from './alternative-tables'
import { ShowDDL } from './show-ddl-button'

const config: QueryConfig = {
name: 'columns',
sql: `
Expand Down Expand Up @@ -64,13 +68,21 @@ export default async function ColumnsPage({
return (
<div className="flex flex-col">
<div>
<Link
href="/tables"
className="text-muted-foreground flex flex-row items-center gap-2 text-xs hover:underline hover:decoration-1 hover:underline-offset-4"
>
<ArrowLeftIcon className="h-3 w-3" />
Back to tables
</Link>
<div className="mb-3 flex flex-row gap-3">
<Link href="/tables">
<Button
variant="outline"
size="sm"
className="text-muted-foreground flex flex-row gap-2"
>
<ArrowLeftIcon className="h-3 w-3" />
Back to tables
</Button>
</Link>

<AlternativeTables database={database} table={table} />
<ShowDDL database={database} table={table} />
</div>

<DataTable
title={`${database}.${table}`}
Expand Down
71 changes: 71 additions & 0 deletions app/tables/[database]/[table]/show-ddl-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { CodeIcon } from '@radix-ui/react-icons'

import { fetchData } from '@/lib/clickhouse'
import { cn, dedent } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'

interface ShowSQLButtonProps {
database: string
table: string
className?: string
}

export async function ShowDDL({
database,
table,
className,
}: ShowSQLButtonProps) {
let showCreateTable: { statement: string }[] = []
try {
showCreateTable = await fetchData(`SHOW CREATE TABLE ${database}.${table}`)
} catch (error) {
console.log(error)

return null
}

if (!showCreateTable?.length || !showCreateTable[0]?.statement) {
return null
}

const sql = showCreateTable[0].statement

return (
<Dialog>
<DialogTrigger asChild>
<Button
variant="outline"
size="sm"
className={cn(
'text-muted-foreground flex flex-row items-center gap-2',
className
)}
aria-label="Show DDL"
title="Show Table DDL Table Definition"
>
<CodeIcon className="h-3 w-3" />
Show DDL
</Button>
</DialogTrigger>
<DialogContent className="max-w-max">
<DialogHeader>
<DialogTitle>SQL DDL Code</DialogTitle>
<DialogDescription>
CREATE query used for creating this table
</DialogDescription>
</DialogHeader>
<div className="w-fit overflow-auto">
<pre className="text-sm">{dedent(sql)}</pre>
</div>
</DialogContent>
</Dialog>
)
}
33 changes: 18 additions & 15 deletions components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const DialogOverlay = React.forwardRef<
ref={ref}
className={cn(
'bg-background/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 backdrop-blur-sm',
'grid place-items-center overflow-y-auto',
className
)}
{...props}
Expand All @@ -34,21 +35,23 @@ const DialogContent = React.forwardRef<
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
className
)}
{...props}
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
<DialogOverlay>
<DialogPrimitive.Content
ref={ref}
className={cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
'max-h-screen overflow-auto',
className
)}
{...props}
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogOverlay>
</DialogPortal>
))
DialogContent.displayName = DialogPrimitive.Content.displayName
Expand Down

0 comments on commit fafe21c

Please sign in to comment.