Explorar o código

feat(dashboard): Add refresh button to data tables

Michael Bromley hai 8 meses
pai
achega
891ff15ec6

+ 5 - 1
packages/dashboard/src/app/routes/_authenticated/_system/scheduled-tasks.tsx

@@ -70,9 +70,12 @@ function ScheduledTasksPage() {
     const { mutate: updateScheduledTask } = useMutation({
         mutationFn: api.mutate(updateScheduledTaskDocument),
         onSuccess: (result) => {
-            queryClient.invalidateQueries({ queryKey: ['scheduledTasks'] });
+            refreshScheduledTasks();
         },
     });
+    const refreshScheduledTasks = () => {
+        queryClient.invalidateQueries({ queryKey: ['scheduledTasks'] });
+    }
     const { mutate: runScheduledTask } = useMutation({
         mutationFn: api.mutate(runScheduledTaskDocument),
         onSuccess: (result) => {
@@ -223,6 +226,7 @@ function ScheduledTasksPage() {
             <PageLayout>
                 <FullWidthPageBlock blockId="list-table">
                     <DataTable
+                        onRefresh={refreshScheduledTasks}
                         columns={columns}
                         data={data?.scheduledTasks ?? []}
                         totalItems={data?.scheduledTasks?.length ?? 0}

+ 15 - 0
packages/dashboard/src/app/styles.css

@@ -76,6 +76,21 @@
     grid-column: span 2 / span 2;
 }
 
+@layer utilities {
+    @keyframes rotate {
+        0% {
+            transform: rotate(0deg);
+        }
+        100% {
+            transform: rotate(360deg);
+        }
+    }
+
+    .animate-rotate {
+        animation: rotate 0.5s linear;
+    }
+}
+
 /* Overrides for the react-grid-layout library */
 .react-grid-item {
     transition: none !important;

+ 1 - 1
packages/dashboard/src/lib/components/data-table/data-table-view-options.tsx

@@ -73,7 +73,7 @@ export function DataTableViewOptions<TData>({ table }: DataTableViewOptionsProps
         <div className="flex items-center gap-2">
             <DropdownMenu>
                 <DropdownMenuTrigger asChild>
-                    <Button variant="outline" size="sm" className="ml-auto hidden h-8 lg:flex">
+                    <Button variant="ghost" size="sm" className="ml-auto hidden h-8 lg:flex">
                         <Settings2 />
                         <Trans>Columns</Trans>
                     </Button>

+ 29 - 23
packages/dashboard/src/lib/components/data-table/data-table.tsx

@@ -23,6 +23,7 @@ import { AddFilterMenu } from './add-filter-menu.js';
 import { DataTableFacetedFilter, DataTableFacetedFilterOption } from './data-table-faceted-filter.js';
 import { DataTableFilterBadge } from './data-table-filter-badge.js';
 import { useChannel } from '@/hooks/use-channel.js';
+import { RefreshButton } from '@/components/data-table/refresh-button.js';
 
 export interface FacetedFilter {
     title: string;
@@ -52,26 +53,28 @@ interface DataTableProps<TData> {
      * when needed.
      */
     setTableOptions?: (table: TableOptions<TData>) => TableOptions<TData>;
+    onRefresh?: () => void;
 }
 
 export function DataTable<TData>({
-    columns,
-    data,
-    totalItems,
-    page,
-    itemsPerPage,
-    sorting: sortingInitialState,
-    columnFilters: filtersInitialState,
-    onPageChange,
-    onSortChange,
-    onFilterChange,
-    onSearchTermChange,
-    onColumnVisibilityChange,
-    defaultColumnVisibility,
-    facetedFilters,
-    disableViewOptions,
-    setTableOptions,
-}: DataTableProps<TData>) {
+                                     columns,
+                                     data,
+                                     totalItems,
+                                     page,
+                                     itemsPerPage,
+                                     sorting: sortingInitialState,
+                                     columnFilters: filtersInitialState,
+                                     onPageChange,
+                                     onSortChange,
+                                     onFilterChange,
+                                     onSearchTermChange,
+                                     onColumnVisibilityChange,
+                                     defaultColumnVisibility,
+                                     facetedFilters,
+                                     disableViewOptions,
+                                     setTableOptions,
+                                     onRefresh,
+                                 }: DataTableProps<TData>) {
     const [sorting, setSorting] = React.useState<SortingState>(sortingInitialState || []);
     const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(filtersInitialState || []);
     const { activeChannel } = useChannel();
@@ -160,15 +163,18 @@ export function DataTable<TData>({
                                 const column = table.getColumn(f.id);
                                 const currency = activeChannel?.defaultCurrencyCode ?? 'USD';
                                 return <DataTableFilterBadge
-                                            key={f.id}
-                                            filter={f}
-                                            currencyCode={currency}
-                                            dataType={(column?.columnDef.meta as any)?.fieldInfo?.type ?? 'String'}
-                                            onRemove={() => setColumnFilters(old => old.filter(x => x.id !== f.id))} />;
+                                    key={f.id}
+                                    filter={f}
+                                    currencyCode={currency}
+                                    dataType={(column?.columnDef.meta as any)?.fieldInfo?.type ?? 'String'}
+                                    onRemove={() => setColumnFilters(old => old.filter(x => x.id !== f.id))} />;
                             })}
                     </div>
                 </div>
-                {!disableViewOptions && <DataTableViewOptions table={table} />}
+                <div className="flex items-center justify-start gap-2">
+                    {!disableViewOptions && <DataTableViewOptions table={table} />}
+                    {onRefresh && <RefreshButton onRefresh={onRefresh} />}
+                </div>
             </div>
             <div className="rounded-md border my-2">
                 <Table>

+ 25 - 0
packages/dashboard/src/lib/components/data-table/refresh-button.tsx

@@ -0,0 +1,25 @@
+import React, { useState } from 'react';
+import { Button } from '@/components/ui/button.js';
+import { RefreshCw } from 'lucide-react';
+
+export function RefreshButton({ onRefresh }: { onRefresh: () => void }) {
+    const [isRotating, setIsRotating] = useState(false);
+
+    const handleClick = () => {
+        if (!isRotating) {
+            setIsRotating(true);
+            onRefresh();
+        }
+    };
+
+    return (
+        <Button
+            variant="ghost"
+            size="sm"
+            onClick={handleClick}
+        >
+            <RefreshCw onAnimationEnd={() => setIsRotating(false)}
+                       className={isRotating ? 'animate-rotate' : ''} />
+        </Button>
+    );
+}

+ 1 - 0
packages/dashboard/src/lib/components/shared/paginated-list-data-table.tsx

@@ -428,6 +428,7 @@ export function PaginatedListDataTable<
                 facetedFilters={facetedFilters}
                 disableViewOptions={disableViewOptions}
                 setTableOptions={setTableOptions}
+                onRefresh={refetchPaginatedList}
             />
         </PaginatedListContext.Provider>
     );