Skip to content

Commit

Permalink
Merge pull request #258 from duyet/chore/ui
Browse files Browse the repository at this point in the history
feat(ui): cluster layout breakdown and skeleton
  • Loading branch information
duyet authored May 28, 2024
2 parents 5d4e4c4 + 046cf72 commit b895f02
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 73 deletions.
109 changes: 109 additions & 0 deletions app/clusters/[cluster]/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { ChevronDownIcon, SlashIcon } from '@radix-ui/react-icons'
import Link from 'next/link'

import { ErrorAlert } from '@/components/error-alert'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
} from '@/components/ui/breadcrumb'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { fetchDataWithCache } from '@/lib/clickhouse'

import { config, type Row } from '../config'

interface Props {
cluster: string
}

export async function ClusterListBreadcrumb({ cluster }: Props) {
let clusters: Row[] = []

try {
// Lists cluster names.
clusters = await fetchDataWithCache()<Row[]>({ query: config.sql })

if (!clusters.length) {
return (
<ErrorAlert
title="Message"
message="No cluster found on system.clusters"
/>
)
}
} catch (e: any) {
return (
<ErrorAlert
title="Unable to retrieve the list of clusters"
message={`${e}`}
/>
)
}

return <Internal cluster={cluster} clusters={clusters} />
}

export function ClusterListBreadcrumbSkeleton({ cluster }: Props) {
return (
<Internal
cluster={cluster}
clusters={[
{
cluster: cluster,
replica_count: 0,
count_replica: '0',
shard_count: 0,
},
{
cluster: 'Loading ...',
replica_count: 0,
count_replica: '0',
shard_count: 0,
},
]}
/>
)
}

function Internal({ cluster, clusters }: Props & { clusters: Row[] }) {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/clusters">Clusters</BreadcrumbLink>
</BreadcrumbItem>

<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>

<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
{cluster}
<ChevronDownIcon />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
{clusters.map(({ cluster: name, replica_count }) => (
<DropdownMenuItem key={name}>
<Link
href={`/clusters/${name}/replicas-status`}
className={name == cluster ? 'font-bold' : ''}
>
{name} ({replica_count}{' '}
{replica_count > 1 ? 'replicas' : 'replica'})
</Link>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbList>
</Breadcrumb>
)
}
80 changes: 7 additions & 73 deletions app/clusters/[cluster]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
import { ChevronDownIcon, SlashIcon } from '@radix-ui/react-icons'
import Link from 'next/link'

import { ErrorAlert } from '@/components/error-alert'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
} from '@/components/ui/breadcrumb'
import { Suspense } from 'react'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { fetchDataWithCache } from '@/lib/clickhouse'

import { config, type Row } from '../config'
ClusterListBreadcrumb,
ClusterListBreadcrumbSkeleton,
} from './breadcrumb'

interface ClusterListProps {
params: {
Expand All @@ -32,62 +17,11 @@ export default async function ClusterTabListLayout({
params: { cluster },
children,
}: ClusterListProps) {
let clusters: Row[] = []

try {
// Lists cluster names.
clusters = await fetchDataWithCache()<Row[]>({ query: config.sql })

if (!clusters.length) {
return (
<ErrorAlert
title="Message"
message="No cluster found on system.clusters"
/>
)
}
} catch (e: any) {
return (
<ErrorAlert
title="Unable to retrieve the list of clusters"
message={`${e}`}
/>
)
}

return (
<div className="flex flex-col gap-5">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/clusters">Clusters</BreadcrumbLink>
</BreadcrumbItem>

<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>

<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
{cluster}
<ChevronDownIcon />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
{clusters.map(({ cluster: name, replica_count }) => (
<DropdownMenuItem key={name}>
<Link
href={`/clusters/${name}/replicas-status`}
className={name == cluster ? 'font-bold' : ''}
>
{name} ({replica_count}{' '}
{replica_count > 1 ? 'replicas' : 'replica'})
</Link>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbList>
</Breadcrumb>
<Suspense fallback={<ClusterListBreadcrumbSkeleton cluster={cluster} />}>
<ClusterListBreadcrumb cluster={cluster} />
</Suspense>

{children}
</div>
Expand Down

0 comments on commit b895f02

Please sign in to comment.