Просмотр исходного кода

feat(dashboard): Add page size controls to asset list

Michael Bromley 3 месяцев назад
Родитель
Сommit
8dc3c92cc6

+ 17 - 1
packages/dashboard/src/app/routes/_authenticated/_assets/assets.tsx

@@ -1,15 +1,29 @@
 import { AssetGallery } from '@/vdb/components/shared/asset/asset-gallery.js';
 import { Page, PageBlock, PageTitle } from '@/vdb/framework/layout-engine/page-layout.js';
 import { Trans } from '@lingui/react/macro';
-import { createFileRoute } from '@tanstack/react-router';
+import { createFileRoute, useNavigate } from '@tanstack/react-router';
 import { DeleteAssetsBulkAction } from './components/asset-bulk-actions.js';
 
 export const Route = createFileRoute('/_authenticated/_assets/assets')({
     component: RouteComponent,
     loader: () => ({ breadcrumb: () => <Trans>Assets</Trans> }),
+    validateSearch: (search: Record<string, unknown>) => {
+        return {
+            perPage: (search.perPage as number) || 24,
+        };
+    },
 });
 
 function RouteComponent() {
+    const navigate = useNavigate({ from: Route.fullPath });
+    const { perPage } = Route.useSearch();
+
+    const handlePageSizeChange = (newPageSize: number) => {
+        navigate({
+            search: (prev: any) => ({ ...prev, perPage: newPageSize }),
+        });
+    };
+
     return (
         <Page pageId="asset-list">
             <PageTitle>
@@ -19,6 +33,8 @@ function RouteComponent() {
                 <AssetGallery
                     selectable={true}
                     multiSelect="manual"
+                    pageSize={perPage}
+                    onPageSizeChange={handlePageSizeChange}
                     bulkActions={[
                         {
                             order: 10,

+ 126 - 91
packages/dashboard/src/lib/components/shared/asset/asset-gallery.tsx

@@ -131,6 +131,11 @@ export interface AssetGalleryProps {
      * Whether the gallery should display bulk actions.
      */
     displayBulkActions?: boolean;
+    /**
+     * @description
+     * The function to call when the page size changes.
+     */
+    onPageSizeChange?: (pageSize: number) => void;
 }
 
 /**
@@ -164,6 +169,7 @@ export function AssetGallery({
     onFilesDropped,
     bulkActions,
     displayBulkActions = true,
+    onPageSizeChange,
 }: AssetGalleryProps) {
     // State
     const [page, setPage] = useState(1);
@@ -469,119 +475,148 @@ export function AssetGallery({
                 </div>
             </div>
 
-            {totalPages > 1 && (
-                <Pagination className="mt-4 flex-shrink-0">
-                    <PaginationContent>
-                        <PaginationItem>
-                            <PaginationPrevious
-                                href="#"
-                                size="default"
-                                onClick={e => {
-                                    e.preventDefault();
-                                    goToPage(page - 1);
-                                }}
-                                className={page === 1 ? 'pointer-events-none opacity-50' : ''}
-                            />
-                        </PaginationItem>
+            <div className="flex flex-col md:flex-row items-center md:justify-between gap-4 mt-4 flex-shrink-0">
+                <div className="mt-2 text-xs text-muted-foreground flex-shrink-0">
+                    {totalItems} {totalItems === 1 ? 'asset' : 'assets'} found
+                    {selected.length > 0 && `, ${selected.length} selected`}
+                </div>
+                <div className="flex-1"></div>
+                {/* Items per page selector */}
+                {onPageSizeChange && (
+                    <div className="flex items-center gap-2">
+                        <span className="text-sm text-muted-foreground">Items per page</span>
+                        <Select
+                            value={pageSize.toString()}
+                            onValueChange={value => {
+                                const newPageSize = parseInt(value, 10);
+                                onPageSizeChange(newPageSize);
+                                setPage(1); // Reset to first page when changing page size
+                            }}
+                        >
+                            <SelectTrigger className="h-8 w-[70px]">
+                                <SelectValue />
+                            </SelectTrigger>
+                            <SelectContent side="top">
+                                {[12, 24, 48, 96].map(size => (
+                                    <SelectItem key={size} value={`${size}`}>
+                                        {size}
+                                    </SelectItem>
+                                ))}
+                            </SelectContent>
+                        </Select>
+                    </div>
+                )}
 
-                        {/* First page */}
-                        {page > 2 && (
+                {/* Pagination */}
+                {totalPages > 1 && (
+                    <Pagination className="w-auto">
+                        <PaginationContent>
                             <PaginationItem>
-                                <PaginationLink
+                                <PaginationPrevious
                                     href="#"
+                                    size="default"
                                     onClick={e => {
                                         e.preventDefault();
-                                        goToPage(1);
+                                        goToPage(page - 1);
                                     }}
-                                >
-                                    1
-                                </PaginationLink>
+                                    className={page === 1 ? 'pointer-events-none opacity-50' : ''}
+                                />
                             </PaginationItem>
-                        )}
 
-                        {/* Ellipsis if needed */}
-                        {page > 3 && (
-                            <PaginationItem>
-                                <PaginationEllipsis />
-                            </PaginationItem>
-                        )}
+                            {/* First page */}
+                            {page > 2 && (
+                                <PaginationItem>
+                                    <PaginationLink
+                                        href="#"
+                                        onClick={e => {
+                                            e.preventDefault();
+                                            goToPage(1);
+                                        }}
+                                    >
+                                        1
+                                    </PaginationLink>
+                                </PaginationItem>
+                            )}
 
-                        {/* Previous page */}
-                        {page > 1 && (
-                            <PaginationItem>
-                                <PaginationLink
-                                    href="#"
-                                    onClick={e => {
-                                        e.preventDefault();
-                                        goToPage(page - 1);
-                                    }}
-                                >
-                                    {page - 1}
-                                </PaginationLink>
-                            </PaginationItem>
-                        )}
+                            {/* Ellipsis if needed */}
+                            {page > 3 && (
+                                <PaginationItem>
+                                    <PaginationEllipsis />
+                                </PaginationItem>
+                            )}
 
-                        {/* Current page */}
-                        <PaginationItem>
-                            <PaginationLink href="#" isActive>
-                                {page}
-                            </PaginationLink>
-                        </PaginationItem>
+                            {/* Previous page */}
+                            {page > 1 && (
+                                <PaginationItem>
+                                    <PaginationLink
+                                        href="#"
+                                        onClick={e => {
+                                            e.preventDefault();
+                                            goToPage(page - 1);
+                                        }}
+                                    >
+                                        {page - 1}
+                                    </PaginationLink>
+                                </PaginationItem>
+                            )}
 
-                        {/* Next page */}
-                        {page < totalPages && (
+                            {/* Current page */}
                             <PaginationItem>
-                                <PaginationLink
-                                    href="#"
-                                    onClick={e => {
-                                        e.preventDefault();
-                                        goToPage(page + 1);
-                                    }}
-                                >
-                                    {page + 1}
+                                <PaginationLink href="#" isActive>
+                                    {page}
                                 </PaginationLink>
                             </PaginationItem>
-                        )}
 
-                        {/* Ellipsis if needed */}
-                        {page < totalPages - 2 && (
-                            <PaginationItem>
-                                <PaginationEllipsis />
-                            </PaginationItem>
-                        )}
+                            {/* Next page */}
+                            {page < totalPages && (
+                                <PaginationItem>
+                                    <PaginationLink
+                                        href="#"
+                                        onClick={e => {
+                                            e.preventDefault();
+                                            goToPage(page + 1);
+                                        }}
+                                    >
+                                        {page + 1}
+                                    </PaginationLink>
+                                </PaginationItem>
+                            )}
+
+                            {/* Ellipsis if needed */}
+                            {page < totalPages - 2 && (
+                                <PaginationItem>
+                                    <PaginationEllipsis />
+                                </PaginationItem>
+                            )}
+
+                            {/* Last page */}
+                            {page < totalPages - 1 && (
+                                <PaginationItem>
+                                    <PaginationLink
+                                        href="#"
+                                        onClick={e => {
+                                            e.preventDefault();
+                                            goToPage(totalPages);
+                                        }}
+                                    >
+                                        {totalPages}
+                                    </PaginationLink>
+                                </PaginationItem>
+                            )}
 
-                        {/* Last page */}
-                        {page < totalPages - 1 && (
                             <PaginationItem>
-                                <PaginationLink
+                                <PaginationNext
                                     href="#"
                                     onClick={e => {
                                         e.preventDefault();
-                                        goToPage(totalPages);
+                                        goToPage(page + 1);
                                     }}
-                                >
-                                    {totalPages}
-                                </PaginationLink>
+                                    className={page === totalPages ? 'pointer-events-none opacity-50' : ''}
+                                />
                             </PaginationItem>
-                        )}
-
-                        <PaginationItem>
-                            <PaginationNext
-                                href="#"
-                                onClick={e => {
-                                    e.preventDefault();
-                                    goToPage(page + 1);
-                                }}
-                                className={page === totalPages ? 'pointer-events-none opacity-50' : ''}
-                            />
-                        </PaginationItem>
-                    </PaginationContent>
-                </Pagination>
-            )}
-
-            <div className="mt-2 text-xs text-muted-foreground flex-shrink-0">
-                {totalItems} {totalItems === 1 ? 'asset' : 'assets'} found
-                {selected.length > 0 && `, ${selected.length} selected`}
+                        </PaginationContent>
+                    </Pagination>
+                )}
             </div>
         </div>
     );