feat(web): enhance ResourcePage and AgentsPage with table layout and column pinning
- Updated ResourcePage to support customizable table layout and column pinning, improving data presentation and user interaction. - Introduced a new `formatAgentSeen` function in AgentsPage for better date formatting of agent last seen timestamps. - Adjusted column sizes and added min/max size constraints for various columns in AgentsPage to enhance layout consistency. - Enhanced the tooltip functionality for displaying agent last seen timestamps, improving user experience.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { useCallback, useMemo, useState, type ReactNode } from 'react'
|
||||
import { useCallback, useMemo, useState, type ComponentProps, type ReactNode } from 'react'
|
||||
import {
|
||||
getCoreRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
type ColumnDef,
|
||||
type ColumnPinningState,
|
||||
type PaginationState,
|
||||
type RowSelectionState,
|
||||
type SortingState,
|
||||
@@ -46,6 +47,10 @@ import {
|
||||
import { EmptyState } from '@/components/empty-state'
|
||||
import { applyFiltersToData } from './filter-utils'
|
||||
|
||||
type DataGridTableLayout = NonNullable<
|
||||
ComponentProps<typeof DataGrid>['tableLayout']
|
||||
>
|
||||
|
||||
export interface ResourcePageTab {
|
||||
id: string
|
||||
label: string
|
||||
@@ -88,6 +93,10 @@ export interface ResourcePageProps<T extends object> {
|
||||
onSearchChange?: (query: string) => void
|
||||
searchPlaceholder?: string
|
||||
getSearchText?: (item: T) => string
|
||||
/** Merge over defaults: dense + headerSticky + width fixed */
|
||||
tableLayout?: Partial<DataGridTableLayout>
|
||||
/** Pin columns (e.g. `{ right: ['actions'] }`) — enables column pinning */
|
||||
columnPinning?: ColumnPinningState
|
||||
}
|
||||
|
||||
function ResourcePageSkeleton() {
|
||||
@@ -140,12 +149,17 @@ export function ResourcePage<T extends object>({
|
||||
onSearchChange,
|
||||
searchPlaceholder = 'Поиск…',
|
||||
getSearchText,
|
||||
tableLayout: tableLayoutProp,
|
||||
columnPinning: columnPinningProp,
|
||||
}: ResourcePageProps<T>) {
|
||||
const [internalTab, setInternalTab] = useState(tabs?.[0]?.id ?? 'all')
|
||||
const activeTab = controlledTab ?? internalTab
|
||||
|
||||
const [sorting, setSorting] = useState<SortingState>([])
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
|
||||
const [columnPinning, setColumnPinning] = useState<ColumnPinningState>(
|
||||
() => columnPinningProp ?? {},
|
||||
)
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize,
|
||||
@@ -213,15 +227,32 @@ export function ResourcePage<T extends object>({
|
||||
setRowSelection({})
|
||||
}, [])
|
||||
|
||||
const tableLayout = useMemo(
|
||||
() => ({
|
||||
dense: true,
|
||||
headerSticky: true,
|
||||
width: 'fixed' as const,
|
||||
...tableLayoutProp,
|
||||
...(columnPinningProp || Object.keys(columnPinning).length > 0
|
||||
? { columnsPinnable: true }
|
||||
: {}),
|
||||
}),
|
||||
[tableLayoutProp, columnPinningProp, columnPinning],
|
||||
)
|
||||
|
||||
const table = useReactTable({
|
||||
data: filteredData,
|
||||
columns,
|
||||
getRowId,
|
||||
state: { sorting, rowSelection, pagination },
|
||||
state: { sorting, rowSelection, pagination, columnPinning },
|
||||
enableRowSelection,
|
||||
enableColumnPinning: Boolean(
|
||||
tableLayout.columnsPinnable || columnPinningProp,
|
||||
),
|
||||
onSortingChange: setSorting,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
onColumnPinningChange: setColumnPinning,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
@@ -338,7 +369,7 @@ export function ResourcePage<T extends object>({
|
||||
table={table}
|
||||
recordCount={filteredData.length}
|
||||
emptyMessage={emptyMessage}
|
||||
tableLayout={{ dense: true }}
|
||||
tableLayout={tableLayout}
|
||||
onRowClick={onRowClick}
|
||||
>
|
||||
<Frame dense variant="default" spacing="sm" className="w-full">
|
||||
|
||||
Reference in New Issue
Block a user