Skip to content

Commit b895f02

Browse files
authored
Merge pull request #258 from duyet/chore/ui
feat(ui): cluster layout breakdown and skeleton
2 parents 5d4e4c4 + 046cf72 commit b895f02

File tree

2 files changed

+116
-73
lines changed

2 files changed

+116
-73
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { ChevronDownIcon, SlashIcon } from '@radix-ui/react-icons'
2+
import Link from 'next/link'
3+
4+
import { ErrorAlert } from '@/components/error-alert'
5+
import {
6+
Breadcrumb,
7+
BreadcrumbItem,
8+
BreadcrumbLink,
9+
BreadcrumbList,
10+
BreadcrumbSeparator,
11+
} from '@/components/ui/breadcrumb'
12+
import {
13+
DropdownMenu,
14+
DropdownMenuContent,
15+
DropdownMenuItem,
16+
DropdownMenuTrigger,
17+
} from '@/components/ui/dropdown-menu'
18+
import { fetchDataWithCache } from '@/lib/clickhouse'
19+
20+
import { config, type Row } from '../config'
21+
22+
interface Props {
23+
cluster: string
24+
}
25+
26+
export async function ClusterListBreadcrumb({ cluster }: Props) {
27+
let clusters: Row[] = []
28+
29+
try {
30+
// Lists cluster names.
31+
clusters = await fetchDataWithCache()<Row[]>({ query: config.sql })
32+
33+
if (!clusters.length) {
34+
return (
35+
<ErrorAlert
36+
title="Message"
37+
message="No cluster found on system.clusters"
38+
/>
39+
)
40+
}
41+
} catch (e: any) {
42+
return (
43+
<ErrorAlert
44+
title="Unable to retrieve the list of clusters"
45+
message={`${e}`}
46+
/>
47+
)
48+
}
49+
50+
return <Internal cluster={cluster} clusters={clusters} />
51+
}
52+
53+
export function ClusterListBreadcrumbSkeleton({ cluster }: Props) {
54+
return (
55+
<Internal
56+
cluster={cluster}
57+
clusters={[
58+
{
59+
cluster: cluster,
60+
replica_count: 0,
61+
count_replica: '0',
62+
shard_count: 0,
63+
},
64+
{
65+
cluster: 'Loading ...',
66+
replica_count: 0,
67+
count_replica: '0',
68+
shard_count: 0,
69+
},
70+
]}
71+
/>
72+
)
73+
}
74+
75+
function Internal({ cluster, clusters }: Props & { clusters: Row[] }) {
76+
return (
77+
<Breadcrumb>
78+
<BreadcrumbList>
79+
<BreadcrumbItem>
80+
<BreadcrumbLink href="/clusters">Clusters</BreadcrumbLink>
81+
</BreadcrumbItem>
82+
83+
<BreadcrumbSeparator>
84+
<SlashIcon />
85+
</BreadcrumbSeparator>
86+
87+
<DropdownMenu>
88+
<DropdownMenuTrigger className="flex items-center gap-1">
89+
{cluster}
90+
<ChevronDownIcon />
91+
</DropdownMenuTrigger>
92+
<DropdownMenuContent align="start">
93+
{clusters.map(({ cluster: name, replica_count }) => (
94+
<DropdownMenuItem key={name}>
95+
<Link
96+
href={`/clusters/${name}/replicas-status`}
97+
className={name == cluster ? 'font-bold' : ''}
98+
>
99+
{name} ({replica_count}{' '}
100+
{replica_count > 1 ? 'replicas' : 'replica'})
101+
</Link>
102+
</DropdownMenuItem>
103+
))}
104+
</DropdownMenuContent>
105+
</DropdownMenu>
106+
</BreadcrumbList>
107+
</Breadcrumb>
108+
)
109+
}

app/clusters/[cluster]/layout.tsx

Lines changed: 7 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,8 @@
1-
import { ChevronDownIcon, SlashIcon } from '@radix-ui/react-icons'
2-
import Link from 'next/link'
3-
4-
import { ErrorAlert } from '@/components/error-alert'
5-
import {
6-
Breadcrumb,
7-
BreadcrumbItem,
8-
BreadcrumbLink,
9-
BreadcrumbList,
10-
BreadcrumbSeparator,
11-
} from '@/components/ui/breadcrumb'
1+
import { Suspense } from 'react'
122
import {
13-
DropdownMenu,
14-
DropdownMenuContent,
15-
DropdownMenuItem,
16-
DropdownMenuTrigger,
17-
} from '@/components/ui/dropdown-menu'
18-
import { fetchDataWithCache } from '@/lib/clickhouse'
19-
20-
import { config, type Row } from '../config'
3+
ClusterListBreadcrumb,
4+
ClusterListBreadcrumbSkeleton,
5+
} from './breadcrumb'
216

227
interface ClusterListProps {
238
params: {
@@ -32,62 +17,11 @@ export default async function ClusterTabListLayout({
3217
params: { cluster },
3318
children,
3419
}: ClusterListProps) {
35-
let clusters: Row[] = []
36-
37-
try {
38-
// Lists cluster names.
39-
clusters = await fetchDataWithCache()<Row[]>({ query: config.sql })
40-
41-
if (!clusters.length) {
42-
return (
43-
<ErrorAlert
44-
title="Message"
45-
message="No cluster found on system.clusters"
46-
/>
47-
)
48-
}
49-
} catch (e: any) {
50-
return (
51-
<ErrorAlert
52-
title="Unable to retrieve the list of clusters"
53-
message={`${e}`}
54-
/>
55-
)
56-
}
57-
5820
return (
5921
<div className="flex flex-col gap-5">
60-
<Breadcrumb>
61-
<BreadcrumbList>
62-
<BreadcrumbItem>
63-
<BreadcrumbLink href="/clusters">Clusters</BreadcrumbLink>
64-
</BreadcrumbItem>
65-
66-
<BreadcrumbSeparator>
67-
<SlashIcon />
68-
</BreadcrumbSeparator>
69-
70-
<DropdownMenu>
71-
<DropdownMenuTrigger className="flex items-center gap-1">
72-
{cluster}
73-
<ChevronDownIcon />
74-
</DropdownMenuTrigger>
75-
<DropdownMenuContent align="start">
76-
{clusters.map(({ cluster: name, replica_count }) => (
77-
<DropdownMenuItem key={name}>
78-
<Link
79-
href={`/clusters/${name}/replicas-status`}
80-
className={name == cluster ? 'font-bold' : ''}
81-
>
82-
{name} ({replica_count}{' '}
83-
{replica_count > 1 ? 'replicas' : 'replica'})
84-
</Link>
85-
</DropdownMenuItem>
86-
))}
87-
</DropdownMenuContent>
88-
</DropdownMenu>
89-
</BreadcrumbList>
90-
</Breadcrumb>
22+
<Suspense fallback={<ClusterListBreadcrumbSkeleton cluster={cluster} />}>
23+
<ClusterListBreadcrumb cluster={cluster} />
24+
</Suspense>
9125

9226
{children}
9327
</div>

0 commit comments

Comments
 (0)