mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-22 12:36:24 +08:00
feat: pre-aggregation workspace stats
This commit is contained in:
@@ -17,10 +17,12 @@ import { useCallback, useTransition } from 'react';
|
||||
|
||||
interface DataTablePaginationProps<TData> {
|
||||
table: Table<TData>;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export function DataTablePagination<TData>({
|
||||
table,
|
||||
disabled = false,
|
||||
}: DataTablePaginationProps<TData>) {
|
||||
const [, startTransition] = useTransition();
|
||||
|
||||
@@ -63,6 +65,7 @@ export function DataTablePagination<TData>({
|
||||
<Select
|
||||
value={`${table.getState().pagination.pageSize}`}
|
||||
onValueChange={onPageSizeChange}
|
||||
disabled={disabled}
|
||||
>
|
||||
<SelectTrigger className="h-8 w-[70px]">
|
||||
<SelectValue placeholder={table.getState().pagination.pageSize} />
|
||||
@@ -86,7 +89,7 @@ export function DataTablePagination<TData>({
|
||||
variant="outline"
|
||||
className="hidden h-8 w-8 p-0 lg:flex"
|
||||
onClick={handleFirstPage}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
disabled={disabled || !table.getCanPreviousPage()}
|
||||
>
|
||||
<span className="sr-only">Go to first page</span>
|
||||
<ChevronsLeftIcon className="h-4 w-4" />
|
||||
@@ -95,7 +98,7 @@ export function DataTablePagination<TData>({
|
||||
variant="outline"
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={handlePreviousPage}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
disabled={disabled || !table.getCanPreviousPage()}
|
||||
>
|
||||
<span className="sr-only">Go to previous page</span>
|
||||
<ChevronLeftIcon className="h-4 w-4" />
|
||||
@@ -104,7 +107,7 @@ export function DataTablePagination<TData>({
|
||||
variant="outline"
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={handleNextPage}
|
||||
disabled={!table.getCanNextPage()}
|
||||
disabled={disabled || !table.getCanNextPage()}
|
||||
>
|
||||
<span className="sr-only">Go to next page</span>
|
||||
<ChevronRightIcon className="h-4 w-4" />
|
||||
@@ -113,7 +116,7 @@ export function DataTablePagination<TData>({
|
||||
variant="outline"
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={handleLastPage}
|
||||
disabled={!table.getCanNextPage()}
|
||||
disabled={disabled || !table.getCanNextPage()}
|
||||
>
|
||||
<span className="sr-only">Go to last page</span>
|
||||
<ChevronsRightIcon className="h-4 w-4" />
|
||||
|
||||
@@ -27,6 +27,8 @@ interface DataTableProps<TData, TValue> {
|
||||
totalCount: number;
|
||||
pagination: PaginationState;
|
||||
onPaginationChange: OnChangeFn<PaginationState>;
|
||||
loading?: boolean;
|
||||
disablePagination?: boolean;
|
||||
|
||||
// Row Selection
|
||||
rowSelection?: RowSelectionState;
|
||||
@@ -51,6 +53,8 @@ export function SharedDataTable<TData extends { id: string }, TValue>({
|
||||
totalCount,
|
||||
pagination,
|
||||
onPaginationChange,
|
||||
loading = false,
|
||||
disablePagination = false,
|
||||
rowSelection,
|
||||
onRowSelectionChange,
|
||||
renderToolbar,
|
||||
@@ -83,9 +87,34 @@ export function SharedDataTable<TData extends { id: string }, TValue>({
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 py-5 px-6 h-full overflow-auto">
|
||||
<div className="flex flex-col gap-4 py-5 px-6 h-full overflow-auto relative">
|
||||
{renderToolbar?.(table)}
|
||||
<div className="rounded-md border h-full flex flex-col overflow-auto">
|
||||
<div className="rounded-md border h-full flex flex-col overflow-auto relative">
|
||||
{loading ? (
|
||||
<div className="absolute inset-0 z-10 bg-gray-50/70 backdrop-blur-[1px] flex flex-col items-center justify-center gap-2 text-sm text-gray-600">
|
||||
<svg
|
||||
className="h-5 w-5 animate-spin text-gray-500"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
/>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Loading...</span>
|
||||
</div>
|
||||
) : null}
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map(headerGroup => (
|
||||
@@ -160,7 +189,10 @@ export function SharedDataTable<TData extends { id: string }, TValue>({
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
<DataTablePagination table={table} />
|
||||
<DataTablePagination
|
||||
table={table}
|
||||
disabled={disablePagination || loading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ type FeatureFilterPopoverProps = {
|
||||
onChange: (features: FeatureType[]) => void;
|
||||
align?: 'start' | 'center' | 'end';
|
||||
buttonLabel?: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const FeatureFilterPopover = ({
|
||||
@@ -22,29 +23,37 @@ export const FeatureFilterPopover = ({
|
||||
onChange,
|
||||
align = 'start',
|
||||
buttonLabel = 'Features',
|
||||
disabled = false,
|
||||
}: FeatureFilterPopoverProps) => {
|
||||
const handleFeatureToggle = useCallback(
|
||||
(feature: FeatureType, checked: boolean) => {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
if (checked) {
|
||||
onChange([...new Set([...selectedFeatures, feature])]);
|
||||
} else {
|
||||
onChange(selectedFeatures.filter(enabled => enabled !== feature));
|
||||
}
|
||||
},
|
||||
[onChange, selectedFeatures]
|
||||
[disabled, onChange, selectedFeatures]
|
||||
);
|
||||
|
||||
const handleClearFeatures = useCallback(() => {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
onChange([]);
|
||||
}, [onChange]);
|
||||
}, [disabled, onChange]);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<Popover open={disabled ? false : undefined}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 px-2 lg:px-3 space-x-1"
|
||||
disabled={disabled}
|
||||
>
|
||||
<span>{buttonLabel}</span>
|
||||
{selectedFeatures.length > 0 ? (
|
||||
@@ -70,6 +79,7 @@ export const FeatureFilterPopover = ({
|
||||
onCheckedChange={checked =>
|
||||
handleFeatureToggle(feature, !!checked)
|
||||
}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<span className="text-sm truncate">{feature}</span>
|
||||
</label>
|
||||
@@ -80,7 +90,7 @@ export const FeatureFilterPopover = ({
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleClearFeatures}
|
||||
disabled={selectedFeatures.length === 0}
|
||||
disabled={disabled || selectedFeatures.length === 0}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user