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

feat: refactor typing, add ColumnFormat.HoverCard #275

Merged
merged 1 commit into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/[query]/merges/merge-performance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const mergePerformanceConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/merges/merges.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const mergesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/merges/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const mutationsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/asynchronous-metrics.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const asynchronousMetricsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/backups.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const backupsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/count-across-replicas.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const countAcrossReplicasConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/mergetree-settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const mergeTreeSettingsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/metrics.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const metricsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const settingsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/top-usage-columns.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const topUsageColumnsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/top-usage-tables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const topUsageTablesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/more/zookeeper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const zookeeperConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/queries/common-errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const commonErrorsConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/queries/expensive-queries-by-memory.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const expensiveQueriesByMemoryConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/queries/expensive-queries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const expensiveQueriesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/queries/failed-queries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const failedQueriesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/queries/history-queries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const historyQueriesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/queries/running-queries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const runningQueriesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/tables/distributed-ddl-queue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const distributedDdlQueueConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/tables/readonly-tables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const readOnlyTablesConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/tables/replicas.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const replicasConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/tables/replication-queue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const replicationQueueConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/[query]/tables/table-overview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export const tablesOverviewConfig: QueryConfig = {
Expand Down
2 changes: 1 addition & 1 deletion app/clusters/[cluster]/count-across-replicas/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { DataTable } from '@/components/data-table/data-table'
import { fetchData } from '@/lib/clickhouse'
import { ColumnFormat } from '@/lib/types/column-format'

import type { QueryConfig } from '@/lib/types/query-config'

Expand Down
2 changes: 1 addition & 1 deletion app/clusters/[cluster]/parts-across-replicas/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { DataTable } from '@/components/data-table/data-table'
import { fetchData } from '@/lib/clickhouse'
import { ColumnFormat } from '@/lib/types/column-format'

import type { QueryConfig } from '@/lib/types/query-config'

Expand Down
2 changes: 1 addition & 1 deletion app/clusters/[cluster]/replicas-status/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export type Row = {
Expand Down
2 changes: 1 addition & 1 deletion app/clusters/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export type Row = {
Expand Down
3 changes: 2 additions & 1 deletion app/database/[database]/[table]/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export type Row = {
Expand Down Expand Up @@ -70,6 +70,7 @@ export const config: QueryConfig = {
'comment',
],
columnFormats: {
column: [ColumnFormat.HoverCard, { content: 'Column note: [comment]' }],
type: ColumnFormat.Code,
codec: ColumnFormat.Code,
part_count: ColumnFormat.Number,
Expand Down
9 changes: 2 additions & 7 deletions app/database/[database]/[table]/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { UpdateIcon } from '@radix-ui/react-icons'
import { TableSkeleton } from '@/components/skeleton'

export default function Loading() {
return (
<div className="flex flex-row items-center gap-3">
<UpdateIcon className="size-4 animate-spin" />
Loading table detail ...
</div>
)
return <TableSkeleton className="mb-4" />
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Consider adding a fallback for TableSkeleton

In case TableSkeleton fails to load or render, consider adding a fallback UI to improve user experience.

Suggested change
return <TableSkeleton className="mb-4" />
return (
<React.Suspense fallback={<div>Loading table detail ...</div>}>
<TableSkeleton className="mb-4" />
</React.Suspense>
)

}
15 changes: 11 additions & 4 deletions app/database/[database]/breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface DatabaseCount {
export async function DatabaseBreadcrumb({ database }: Props) {
// Default
let databases: { name: string; count: number }[] = [
{ name: database, count: 0 },
{ name: database, count: -1 },
Copy link
Contributor

Choose a reason for hiding this comment

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

issue: Negative count value might be confusing

Using -1 as a placeholder for loading state might be confusing. Consider using a more explicit value or a separate flag to indicate loading state.

]

try {
Expand Down Expand Up @@ -64,8 +64,8 @@ export async function DatabaseBreadcrumbSkeleton({ database }: Props) {
<Internal
current={database}
databases={[
{ name: database, count: 0 },
{ name: 'Loading ...', count: 0 },
{ name: database, count: -1 },
{ name: 'Loading ...', count: -1 },
]}
/>
)
Expand Down Expand Up @@ -93,7 +93,7 @@ function Internal({

<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
{current} ({currentCount} {currentCount == 1 ? 'table' : 'tables'})
{current} (<Count count={currentCount} />)
<ChevronDownIcon />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
Expand All @@ -114,3 +114,10 @@ function Internal({
</Breadcrumb>
)
}

function Count({ count }: { count?: number }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (performance): Consider memoizing the Count component

To avoid unnecessary re-renders, consider memoizing the Count component using React.memo.

Suggested change
function Count({ count }: { count?: number }) {
import React from 'react';
const Count = React.memo(({ count }: { count?: number }) => {
if (count == undefined || count == -1) return 'loading ...';
if (count == 0) return '0 table';
});

if (count == undefined || count == -1) return 'loading ...'
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (count == undefined || count == -1) return 'loading ...'
if (count == undefined || count == -1) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

if (count == 0) return '0 table'
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (count == 0) return '0 table'
if (count == 0) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

if (count == 1) return '1 table'
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (count == 1) return '1 table'
if (count == 1) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

return `${count} tables`
}
2 changes: 1 addition & 1 deletion app/database/[database]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { DataTable } from '@/components/data-table/data-table'
import { fetchData } from '@/lib/clickhouse'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'
import { type RowData } from '@tanstack/react-table'

Expand Down
2 changes: 1 addition & 1 deletion app/disks/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export type Row = {
Expand Down
2 changes: 1 addition & 1 deletion app/replica/[replica]/tables/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnFormat } from '@/components/data-table/column-defs'
import { ColumnFormat } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export type Row = {
Expand Down
50 changes: 50 additions & 0 deletions components/data-table/cells/hover-card-format.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from '@/components/ui/hover-card'
import React from 'react'

export type HoverCardContent = string | React.ReactNode

export type HoverCardOptions = {
content: HoverCardContent
}

interface HoverCardProps {
row: any
value: any
options?: HoverCardOptions
}

export function HoverCardFormat({ row, value, options }: HoverCardProps) {
let { content } = options || {}

if (!content) {
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Default content assignment

Consider using a more explicit default value for content to avoid potential issues with falsy values.

Suggested change
if (!content) {
if (content === undefined || content === null) {

content = value
}

// Content replacement, e.g. "Hover content: [column_name]"
if (
typeof content === 'string' &&
content.includes('[') &&
content.includes(']')
) {
const matches = content.match(/\[(.*?)\]/g)
if (matches) {
matches.forEach((match) => {
const key = match.replace('[', '').replace(']', '').trim()
const replacementValue = row.getValue(key)
if (typeof content === 'string') {
content = content.replace(match, replacementValue)
}
})
}
}
return (
<HoverCard>
<HoverCardTrigger>{value}</HoverCardTrigger>
<HoverCardContent>{content}</HoverCardContent>
</HoverCard>
)
}
24 changes: 2 additions & 22 deletions components/data-table/column-defs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,12 @@ import {
CaretUpIcon,
} from '@radix-ui/react-icons'
import type { ColumnDef, Row, RowData, Table } from '@tanstack/react-table'
import { LinkProps } from 'next/link'

import { formatCell } from '@/components/data-table/cell'
import { type Action } from '@/components/data-table/cells/actions/types'
import { formatCell } from '@/components/data-table/format-cell'
import { Button } from '@/components/ui/button'
import { ColumnFormat, ColumnFormatOptions } from '@/lib/types/column-format'
import { type QueryConfig } from '@/lib/types/query-config'

export enum ColumnFormat {
BackgroundBar = 'background-bar',
ColoredBadge = 'colored-badge',
RelatedTime = 'related-time',
NumberShort = 'number-short',
CodeToggle = 'code-toggle',
Duration = 'duration',
Boolean = 'boolean',
Action = 'action',
Number = 'number',
Badge = 'badge',
Code = 'code',
Link = 'link',
None = 'none',
}

// Union of all possible format options
export type ColumnFormatOptions = Action[] | LinkProps

export type ColumnType = { [key: string]: string }

const formatHeader = (name: string, format: ColumnFormat) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import type { Row, RowData, Table } from '@tanstack/react-table'
import { type LinkProps } from 'next/link'

import {
ColumnFormat,
ColumnFormatOptions,
} from '@/components/data-table/column-defs'
import { formatReadableQuantity } from '@/lib/format-readable'
import { ColumnFormat, ColumnFormatOptions } from '@/lib/types/column-format'

import { ActionFormat } from './cells/action-format'
import { type Action } from './cells/actions/types'
Expand All @@ -15,6 +12,7 @@ import { BooleanFormat } from './cells/boolean-format'
import { CodeToggleFormat } from './cells/code-toggle-format'
import { ColoredBadgeFormat } from './cells/colored-badge-format'
import { DurationFormat } from './cells/duration-format'
import { HoverCardFormat, HoverCardOptions } from './cells/hover-card-format'
import { LinkFormat } from './cells/link-format'
import { RelatedTimeFormat } from './cells/related-time-format'

Expand Down Expand Up @@ -82,6 +80,15 @@ export const formatCell = <TData extends RowData, TValue>(
/>
)

case ColumnFormat.HoverCard:
return (
<HoverCardFormat
row={row}
value={value}
options={columnFormatOptions as unknown as HoverCardOptions}
/>
)

default:
return <span className="text-nowrap">{value as string}</span>
}
Expand Down
Loading