@burdenoff/fluidgrids-fe-sdk 2026.1007.2 → 2026.1007.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -1
- package/dist/index.js +282 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -777,7 +777,12 @@ declare function useDataTables(search?: string): {
|
|
|
777
777
|
error: Error | null;
|
|
778
778
|
refetch: () => Promise<void>;
|
|
779
779
|
};
|
|
780
|
-
|
|
780
|
+
interface DataTableRowsPaging {
|
|
781
|
+
/** Zero-based page index. */
|
|
782
|
+
page: number;
|
|
783
|
+
pageSize: number;
|
|
784
|
+
}
|
|
785
|
+
declare function useDataTableRows(tableId: string | null, paging: DataTableRowsPaging): {
|
|
781
786
|
rows: DataTableRow$1[];
|
|
782
787
|
total: number;
|
|
783
788
|
loading: boolean;
|
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ import { Button } from '@burdenoff/fe-libs/button';
|
|
|
49
49
|
import { Tabs, TabsList, TabsTrigger, TabsContent, Card, CardContent, PagePurpose, NextSteps, CardHeader, CardTitle, Badge, Input, IllustratedEmptyState, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Label, Switch, CardDescription, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea } from '@burdenoff/fe-libs/ui';
|
|
50
50
|
import { toast } from 'sonner';
|
|
51
51
|
import { gql } from '@apollo/client';
|
|
52
|
-
import { ChevronRight, Check, Circle, Database, ArrowLeft, Plus, Table2, RefreshCw, Search,
|
|
52
|
+
import { ChevronRight, Check, Circle, Database, ArrowLeft, Plus, Table2, RefreshCw, Search, ChevronDown, ChevronUp, Pencil, Trash2, ArrowUpFromLine, ArrowDownToLine, ChevronLeft } from 'lucide-react';
|
|
53
53
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
54
54
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
55
55
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
@@ -1745,7 +1745,38 @@ function useDataTables(search) {
|
|
|
1745
1745
|
}, [fetchTables]);
|
|
1746
1746
|
return { tables, total, loading, error, refetch: fetchTables };
|
|
1747
1747
|
}
|
|
1748
|
-
|
|
1748
|
+
var DATA_TABLE_MAX_PAGE_SIZE = 5e3;
|
|
1749
|
+
async function queryRowsPage(tableId, limit, offset) {
|
|
1750
|
+
const result = throwIfResultError(
|
|
1751
|
+
await getFluidGridsClient().query({
|
|
1752
|
+
query: GET_DATA_TABLE_ROWS,
|
|
1753
|
+
variables: { input: { tableId, limit, offset } },
|
|
1754
|
+
fetchPolicy: "network-only"
|
|
1755
|
+
})
|
|
1756
|
+
);
|
|
1757
|
+
const response = result.data?.dataTableRows;
|
|
1758
|
+
return {
|
|
1759
|
+
rows: response?.rows.map(toRow) ?? [],
|
|
1760
|
+
total: response?.total ?? 0
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
async function fetchAllDataTableRows(tableId) {
|
|
1764
|
+
const collected = [];
|
|
1765
|
+
let total = Number.POSITIVE_INFINITY;
|
|
1766
|
+
while (collected.length < total) {
|
|
1767
|
+
const page = await queryRowsPage(
|
|
1768
|
+
tableId,
|
|
1769
|
+
DATA_TABLE_MAX_PAGE_SIZE,
|
|
1770
|
+
collected.length
|
|
1771
|
+
);
|
|
1772
|
+
total = page.total;
|
|
1773
|
+
if (page.rows.length === 0) break;
|
|
1774
|
+
collected.push(...page.rows);
|
|
1775
|
+
}
|
|
1776
|
+
return collected;
|
|
1777
|
+
}
|
|
1778
|
+
function useDataTableRows(tableId, paging) {
|
|
1779
|
+
const { page, pageSize } = paging;
|
|
1749
1780
|
const [rows, setRows] = useState([]);
|
|
1750
1781
|
const [total, setTotal] = useState(0);
|
|
1751
1782
|
const [loading, setLoading] = useState(false);
|
|
@@ -1761,22 +1792,15 @@ function useDataTableRows(tableId) {
|
|
|
1761
1792
|
setLoading(true);
|
|
1762
1793
|
setError(null);
|
|
1763
1794
|
try {
|
|
1764
|
-
const
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
variables: { input: { tableId, limit: 5e3, offset: 0 } },
|
|
1768
|
-
fetchPolicy: "network-only"
|
|
1769
|
-
})
|
|
1770
|
-
);
|
|
1771
|
-
const response = result.data?.dataTableRows;
|
|
1772
|
-
setRows(response?.rows.map(toRow) ?? []);
|
|
1773
|
-
setTotal(response?.total ?? 0);
|
|
1795
|
+
const response = await queryRowsPage(tableId, pageSize, page * pageSize);
|
|
1796
|
+
setRows(response.rows);
|
|
1797
|
+
setTotal(response.total);
|
|
1774
1798
|
} catch (err) {
|
|
1775
1799
|
setError(operationError(err, "Failed to load data table rows"));
|
|
1776
1800
|
} finally {
|
|
1777
1801
|
setLoading(false);
|
|
1778
1802
|
}
|
|
1779
|
-
}, [tableId]);
|
|
1803
|
+
}, [tableId, page, pageSize]);
|
|
1780
1804
|
useEffect(() => {
|
|
1781
1805
|
void fetchRows();
|
|
1782
1806
|
}, [fetchRows]);
|
|
@@ -2030,6 +2054,22 @@ function rowsToCsv(columns, rows) {
|
|
|
2030
2054
|
);
|
|
2031
2055
|
return [header, ...values].join("\r\n");
|
|
2032
2056
|
}
|
|
2057
|
+
|
|
2058
|
+
// src/modules/data-tables/utils/paging.ts
|
|
2059
|
+
var ROW_PAGE_SIZES = [50, 100, 250];
|
|
2060
|
+
var DEFAULT_ROW_PAGE_SIZE = ROW_PAGE_SIZES[0];
|
|
2061
|
+
function pageCount(total, pageSize) {
|
|
2062
|
+
if (pageSize <= 0) return 1;
|
|
2063
|
+
return Math.max(1, Math.ceil(total / pageSize));
|
|
2064
|
+
}
|
|
2065
|
+
function clampPage(page, total, pageSize) {
|
|
2066
|
+
return Math.min(Math.max(page, 0), pageCount(total, pageSize) - 1);
|
|
2067
|
+
}
|
|
2068
|
+
function pageRange(page, pageSize, shown) {
|
|
2069
|
+
if (shown <= 0) return { from: 0, to: 0 };
|
|
2070
|
+
const from = page * pageSize + 1;
|
|
2071
|
+
return { from, to: from + shown - 1 };
|
|
2072
|
+
}
|
|
2033
2073
|
var COLUMN_TYPES = [
|
|
2034
2074
|
"STRING",
|
|
2035
2075
|
"NUMBER",
|
|
@@ -2440,15 +2480,35 @@ function RowFormDialog({
|
|
|
2440
2480
|
] })
|
|
2441
2481
|
] }) });
|
|
2442
2482
|
}
|
|
2443
|
-
function TableRowsPanel({
|
|
2483
|
+
function TableRowsPanel({
|
|
2484
|
+
table,
|
|
2485
|
+
onTableChanged,
|
|
2486
|
+
onEditTable,
|
|
2487
|
+
onDeleteTable,
|
|
2488
|
+
deletingTable
|
|
2489
|
+
}) {
|
|
2444
2490
|
const tr = useTr();
|
|
2445
|
-
const
|
|
2491
|
+
const [page, setPage] = useState(0);
|
|
2492
|
+
const [pageSize, setPageSize] = useState(DEFAULT_ROW_PAGE_SIZE);
|
|
2493
|
+
const { rows, total, loading, error, refetch } = useDataTableRows(table.id, {
|
|
2494
|
+
page,
|
|
2495
|
+
pageSize
|
|
2496
|
+
});
|
|
2446
2497
|
const { deleteDataTableRows, loading: deleting } = useDeleteDataTableRows();
|
|
2447
2498
|
const { insertDataTableRow } = useInsertDataTableRow();
|
|
2448
2499
|
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
2449
2500
|
const [rowDialogOpen, setRowDialogOpen] = useState(false);
|
|
2450
2501
|
const [editingRow, setEditingRow] = useState(null);
|
|
2502
|
+
const [exporting, setExporting] = useState(false);
|
|
2503
|
+
const [importProgress, setImportProgress] = useState(null);
|
|
2451
2504
|
const fileInputRef = useRef(null);
|
|
2505
|
+
const pages = pageCount(total, pageSize);
|
|
2506
|
+
const range = pageRange(page, pageSize, rows.length);
|
|
2507
|
+
useEffect(() => {
|
|
2508
|
+
if (loading) return;
|
|
2509
|
+
const clamped = clampPage(page, total, pageSize);
|
|
2510
|
+
if (clamped !== page) setPage(clamped);
|
|
2511
|
+
}, [loading, page, pageSize, total]);
|
|
2452
2512
|
useEffect(() => {
|
|
2453
2513
|
setSelectedIds((current) => {
|
|
2454
2514
|
const visible = new Set(rows.map((row) => row.id));
|
|
@@ -2488,43 +2548,68 @@ function TableRowsPanel({ table, onTableChanged }) {
|
|
|
2488
2548
|
);
|
|
2489
2549
|
}
|
|
2490
2550
|
}, [deleteDataTableRows, onTableChanged, refetch, selectedIds, table.id, tr]);
|
|
2491
|
-
const handleExport = useCallback(() => {
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2551
|
+
const handleExport = useCallback(async () => {
|
|
2552
|
+
setExporting(true);
|
|
2553
|
+
try {
|
|
2554
|
+
const allRows = await fetchAllDataTableRows(table.id);
|
|
2555
|
+
const csv = rowsToCsv(table.columns, allRows);
|
|
2556
|
+
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
|
|
2557
|
+
const url = URL.createObjectURL(blob);
|
|
2558
|
+
const anchor = document.createElement("a");
|
|
2559
|
+
anchor.href = url;
|
|
2560
|
+
anchor.download = `${table.name}.csv`;
|
|
2561
|
+
anchor.click();
|
|
2562
|
+
URL.revokeObjectURL(url);
|
|
2563
|
+
toast.success(
|
|
2564
|
+
tr(
|
|
2565
|
+
"fluidgrids.dataTables.exported",
|
|
2566
|
+
`${allRows.length} row(s) exported to CSV`
|
|
2567
|
+
)
|
|
2568
|
+
);
|
|
2569
|
+
} catch (error2) {
|
|
2570
|
+
toast.error(
|
|
2571
|
+
describeOperationError(
|
|
2572
|
+
error2,
|
|
2573
|
+
tr("fluidgrids.dataTables.exportFailed", "Failed to export CSV")
|
|
2574
|
+
)
|
|
2575
|
+
);
|
|
2576
|
+
} finally {
|
|
2577
|
+
setExporting(false);
|
|
2578
|
+
}
|
|
2579
|
+
}, [table.columns, table.id, table.name, tr]);
|
|
2504
2580
|
const handleImport = useCallback(
|
|
2505
2581
|
async (event) => {
|
|
2506
2582
|
const file = event.target.files?.[0];
|
|
2507
2583
|
event.target.value = "";
|
|
2508
2584
|
if (!file) return;
|
|
2585
|
+
let inserted = 0;
|
|
2509
2586
|
try {
|
|
2510
2587
|
const importedRows = csvToRows(await file.text(), table.columns);
|
|
2511
|
-
|
|
2588
|
+
setImportProgress({ done: 0, total: importedRows.length });
|
|
2512
2589
|
for (const data of importedRows) {
|
|
2513
2590
|
await insertDataTableRow(table.id, data);
|
|
2514
2591
|
inserted += 1;
|
|
2592
|
+
setImportProgress({ done: inserted, total: importedRows.length });
|
|
2515
2593
|
}
|
|
2516
2594
|
toast.success(
|
|
2517
2595
|
tr("fluidgrids.dataTables.imported", `${inserted} row(s) imported`)
|
|
2518
2596
|
);
|
|
2519
|
-
await refetch();
|
|
2520
|
-
onTableChanged();
|
|
2521
2597
|
} catch (error2) {
|
|
2598
|
+
const reason = describeOperationError(
|
|
2599
|
+
error2,
|
|
2600
|
+
tr("fluidgrids.dataTables.importFailed", "Failed to import CSV")
|
|
2601
|
+
);
|
|
2522
2602
|
toast.error(
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
)
|
|
2603
|
+
inserted > 0 ? tr(
|
|
2604
|
+
"fluidgrids.dataTables.importPartial",
|
|
2605
|
+
`Import stopped after ${inserted} row(s): ${reason}`
|
|
2606
|
+
) : reason
|
|
2527
2607
|
);
|
|
2608
|
+
} finally {
|
|
2609
|
+
setImportProgress(null);
|
|
2610
|
+
setPage(0);
|
|
2611
|
+
await refetch();
|
|
2612
|
+
onTableChanged();
|
|
2528
2613
|
}
|
|
2529
2614
|
},
|
|
2530
2615
|
[insertDataTableRow, onTableChanged, refetch, table.columns, table.id, tr]
|
|
@@ -2538,14 +2623,14 @@ function TableRowsPanel({ table, onTableChanged }) {
|
|
|
2538
2623
|
setRowDialogOpen(true);
|
|
2539
2624
|
}, []);
|
|
2540
2625
|
return /* @__PURE__ */ jsxs(Card, { className: "min-w-0 border-border-secondary", children: [
|
|
2541
|
-
/* @__PURE__ */ jsxs(CardHeader, { className: "gap-
|
|
2542
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-
|
|
2543
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
2626
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "gap-4 border-b border-border-secondary p-4 sm:p-5", children: [
|
|
2627
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
2628
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 basis-64", children: [
|
|
2544
2629
|
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 text-lg", children: [
|
|
2545
2630
|
/* @__PURE__ */ jsx(
|
|
2546
2631
|
Table2,
|
|
2547
2632
|
{
|
|
2548
|
-
className: "size-5 text-text-secondary",
|
|
2633
|
+
className: "size-5 shrink-0 text-text-secondary",
|
|
2549
2634
|
"aria-hidden": "true"
|
|
2550
2635
|
}
|
|
2551
2636
|
),
|
|
@@ -2553,20 +2638,95 @@ function TableRowsPanel({ table, onTableChanged }) {
|
|
|
2553
2638
|
] }),
|
|
2554
2639
|
/* @__PURE__ */ jsx(CardDescription, { className: "mt-1", children: table.description || tr("fluidgrids.dataTables.noDescription", "No description") })
|
|
2555
2640
|
] }),
|
|
2556
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
2557
|
-
/* @__PURE__ */ jsxs(
|
|
2558
|
-
|
|
2559
|
-
|
|
2641
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
2642
|
+
/* @__PURE__ */ jsxs(
|
|
2643
|
+
Button,
|
|
2644
|
+
{
|
|
2645
|
+
variant: "outline",
|
|
2646
|
+
size: "sm",
|
|
2647
|
+
className: "whitespace-nowrap",
|
|
2648
|
+
onClick: onEditTable,
|
|
2649
|
+
children: [
|
|
2650
|
+
/* @__PURE__ */ jsx(Pencil, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2651
|
+
tr("fluidgrids.dataTables.editTable", "Edit table")
|
|
2652
|
+
]
|
|
2653
|
+
}
|
|
2654
|
+
),
|
|
2655
|
+
/* @__PURE__ */ jsxs(
|
|
2656
|
+
Button,
|
|
2657
|
+
{
|
|
2658
|
+
variant: "outline",
|
|
2659
|
+
size: "sm",
|
|
2660
|
+
className: "whitespace-nowrap",
|
|
2661
|
+
onClick: onDeleteTable,
|
|
2662
|
+
disabled: deletingTable,
|
|
2663
|
+
children: [
|
|
2664
|
+
/* @__PURE__ */ jsx(Trash2, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2665
|
+
deletingTable ? tr("fluidgrids.dataTables.deleting", "Deleting\u2026") : tr("fluidgrids.dataTables.deleteTable", "Delete table")
|
|
2666
|
+
]
|
|
2667
|
+
}
|
|
2668
|
+
)
|
|
2669
|
+
] })
|
|
2670
|
+
] }),
|
|
2671
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
|
|
2672
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-text-secondary", children: [
|
|
2673
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
|
|
2674
|
+
total,
|
|
2675
|
+
" ",
|
|
2676
|
+
tr("fluidgrids.dataTables.rows", "rows")
|
|
2677
|
+
] }),
|
|
2678
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
|
|
2679
|
+
table.columns.length,
|
|
2680
|
+
" ",
|
|
2681
|
+
tr("fluidgrids.dataTables.columns", "columns")
|
|
2560
2682
|
] }),
|
|
2683
|
+
/* @__PURE__ */ jsx(Badge, { variant: "outline", children: formatBytes(table.sizeBytes) }),
|
|
2684
|
+
selectedIds.size > 0 && /* @__PURE__ */ jsxs(
|
|
2685
|
+
Button,
|
|
2686
|
+
{
|
|
2687
|
+
variant: "outline",
|
|
2688
|
+
size: "sm",
|
|
2689
|
+
className: "whitespace-nowrap",
|
|
2690
|
+
onClick: handleDeleteRows,
|
|
2691
|
+
disabled: deleting,
|
|
2692
|
+
children: [
|
|
2693
|
+
/* @__PURE__ */ jsx(Trash2, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2694
|
+
deleting ? tr("fluidgrids.dataTables.deleting", "Deleting\u2026") : tr(
|
|
2695
|
+
"fluidgrids.dataTables.deleteSelected",
|
|
2696
|
+
`Delete ${selectedIds.size} selected`
|
|
2697
|
+
)
|
|
2698
|
+
]
|
|
2699
|
+
}
|
|
2700
|
+
)
|
|
2701
|
+
] }),
|
|
2702
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2703
|
+
/* @__PURE__ */ jsxs(
|
|
2704
|
+
Button,
|
|
2705
|
+
{
|
|
2706
|
+
size: "sm",
|
|
2707
|
+
className: "whitespace-nowrap",
|
|
2708
|
+
onClick: openNewRow,
|
|
2709
|
+
disabled: importProgress !== null,
|
|
2710
|
+
children: [
|
|
2711
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2712
|
+
tr("fluidgrids.dataTables.addRow", "Add row")
|
|
2713
|
+
]
|
|
2714
|
+
}
|
|
2715
|
+
),
|
|
2561
2716
|
/* @__PURE__ */ jsxs(
|
|
2562
2717
|
Button,
|
|
2563
2718
|
{
|
|
2564
2719
|
variant: "outline",
|
|
2565
2720
|
size: "sm",
|
|
2721
|
+
className: "whitespace-nowrap",
|
|
2566
2722
|
onClick: () => fileInputRef.current?.click(),
|
|
2723
|
+
disabled: importProgress !== null,
|
|
2567
2724
|
children: [
|
|
2568
2725
|
/* @__PURE__ */ jsx(ArrowUpFromLine, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2569
|
-
tr(
|
|
2726
|
+
importProgress ? tr(
|
|
2727
|
+
"fluidgrids.dataTables.importing",
|
|
2728
|
+
`Importing ${importProgress.done} / ${importProgress.total}\u2026`
|
|
2729
|
+
) : tr("fluidgrids.dataTables.import", "Import CSV")
|
|
2570
2730
|
]
|
|
2571
2731
|
}
|
|
2572
2732
|
),
|
|
@@ -2585,44 +2745,16 @@ function TableRowsPanel({ table, onTableChanged }) {
|
|
|
2585
2745
|
{
|
|
2586
2746
|
variant: "outline",
|
|
2587
2747
|
size: "sm",
|
|
2748
|
+
className: "whitespace-nowrap",
|
|
2588
2749
|
onClick: handleExport,
|
|
2589
|
-
disabled:
|
|
2750
|
+
disabled: total === 0 || exporting,
|
|
2590
2751
|
children: [
|
|
2591
2752
|
/* @__PURE__ */ jsx(ArrowDownToLine, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2592
|
-
tr("fluidgrids.dataTables.export", "Export CSV")
|
|
2753
|
+
exporting ? tr("fluidgrids.dataTables.exporting", "Exporting\u2026") : tr("fluidgrids.dataTables.export", "Export CSV")
|
|
2593
2754
|
]
|
|
2594
2755
|
}
|
|
2595
2756
|
)
|
|
2596
2757
|
] })
|
|
2597
|
-
] }),
|
|
2598
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-text-secondary", children: [
|
|
2599
|
-
/* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
|
|
2600
|
-
total,
|
|
2601
|
-
" ",
|
|
2602
|
-
tr("fluidgrids.dataTables.rows", "rows")
|
|
2603
|
-
] }),
|
|
2604
|
-
/* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
|
|
2605
|
-
table.columns.length,
|
|
2606
|
-
" ",
|
|
2607
|
-
tr("fluidgrids.dataTables.columns", "columns")
|
|
2608
|
-
] }),
|
|
2609
|
-
/* @__PURE__ */ jsx(Badge, { variant: "outline", children: formatBytes(table.sizeBytes) }),
|
|
2610
|
-
selectedIds.size > 0 && /* @__PURE__ */ jsxs(
|
|
2611
|
-
Button,
|
|
2612
|
-
{
|
|
2613
|
-
variant: "outline",
|
|
2614
|
-
size: "sm",
|
|
2615
|
-
onClick: handleDeleteRows,
|
|
2616
|
-
disabled: deleting,
|
|
2617
|
-
children: [
|
|
2618
|
-
/* @__PURE__ */ jsx(Trash2, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
2619
|
-
deleting ? tr("fluidgrids.dataTables.deleting", "Deleting\u2026") : tr(
|
|
2620
|
-
"fluidgrids.dataTables.deleteSelected",
|
|
2621
|
-
`Delete ${selectedIds.size} selected`
|
|
2622
|
-
)
|
|
2623
|
-
]
|
|
2624
|
-
}
|
|
2625
|
-
)
|
|
2626
2758
|
] })
|
|
2627
2759
|
] }),
|
|
2628
2760
|
/* @__PURE__ */ jsxs(CardContent, { className: "p-0", children: [
|
|
@@ -2637,7 +2769,7 @@ function TableRowsPanel({ table, onTableChanged }) {
|
|
|
2637
2769
|
onChange: toggleAll,
|
|
2638
2770
|
"aria-label": tr(
|
|
2639
2771
|
"fluidgrids.dataTables.selectAll",
|
|
2640
|
-
"Select all rows"
|
|
2772
|
+
"Select all rows on this page"
|
|
2641
2773
|
)
|
|
2642
2774
|
}
|
|
2643
2775
|
) }),
|
|
@@ -2710,10 +2842,64 @@ function TableRowsPanel({ table, onTableChanged }) {
|
|
|
2710
2842
|
] }, row.id))
|
|
2711
2843
|
] })
|
|
2712
2844
|
] }) }),
|
|
2713
|
-
total >
|
|
2714
|
-
"
|
|
2715
|
-
|
|
2716
|
-
|
|
2845
|
+
total > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-t border-border-secondary px-4 py-3 text-xs text-text-secondary", children: [
|
|
2846
|
+
/* @__PURE__ */ jsx("span", { "aria-live": "polite", children: tr(
|
|
2847
|
+
"fluidgrids.dataTables.showingRange",
|
|
2848
|
+
`Showing ${range.from}\u2013${range.to} of ${total}`
|
|
2849
|
+
) }),
|
|
2850
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
2851
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
|
|
2852
|
+
/* @__PURE__ */ jsx("span", { children: tr("fluidgrids.dataTables.rowsPerPage", "Rows per page") }),
|
|
2853
|
+
/* @__PURE__ */ jsx(
|
|
2854
|
+
"select",
|
|
2855
|
+
{
|
|
2856
|
+
className: "h-8 rounded-md border border-input bg-background px-2 text-xs text-text-primary",
|
|
2857
|
+
value: pageSize,
|
|
2858
|
+
onChange: (event) => {
|
|
2859
|
+
setPageSize(Number(event.target.value));
|
|
2860
|
+
setPage(0);
|
|
2861
|
+
},
|
|
2862
|
+
children: ROW_PAGE_SIZES.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
2863
|
+
}
|
|
2864
|
+
)
|
|
2865
|
+
] }),
|
|
2866
|
+
/* @__PURE__ */ jsx("span", { children: tr(
|
|
2867
|
+
"fluidgrids.dataTables.pageOf",
|
|
2868
|
+
`Page ${page + 1} of ${pages}`
|
|
2869
|
+
) }),
|
|
2870
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2871
|
+
/* @__PURE__ */ jsx(
|
|
2872
|
+
Button,
|
|
2873
|
+
{
|
|
2874
|
+
variant: "outline",
|
|
2875
|
+
size: "icon",
|
|
2876
|
+
className: "size-8",
|
|
2877
|
+
onClick: () => setPage((current) => Math.max(current - 1, 0)),
|
|
2878
|
+
disabled: page === 0 || loading,
|
|
2879
|
+
title: tr("fluidgrids.dataTables.prevPage", "Previous page"),
|
|
2880
|
+
"aria-label": tr(
|
|
2881
|
+
"fluidgrids.dataTables.prevPage",
|
|
2882
|
+
"Previous page"
|
|
2883
|
+
),
|
|
2884
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": "true" })
|
|
2885
|
+
}
|
|
2886
|
+
),
|
|
2887
|
+
/* @__PURE__ */ jsx(
|
|
2888
|
+
Button,
|
|
2889
|
+
{
|
|
2890
|
+
variant: "outline",
|
|
2891
|
+
size: "icon",
|
|
2892
|
+
className: "size-8",
|
|
2893
|
+
onClick: () => setPage((current) => Math.min(current + 1, pages - 1)),
|
|
2894
|
+
disabled: page >= pages - 1 || loading,
|
|
2895
|
+
title: tr("fluidgrids.dataTables.nextPage", "Next page"),
|
|
2896
|
+
"aria-label": tr("fluidgrids.dataTables.nextPage", "Next page"),
|
|
2897
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": "true" })
|
|
2898
|
+
}
|
|
2899
|
+
)
|
|
2900
|
+
] })
|
|
2901
|
+
] })
|
|
2902
|
+
] })
|
|
2717
2903
|
] }),
|
|
2718
2904
|
/* @__PURE__ */ jsx(
|
|
2719
2905
|
RowFormDialog,
|
|
@@ -2890,7 +3076,7 @@ function DataTablesPage() {
|
|
|
2890
3076
|
]
|
|
2891
3077
|
}
|
|
2892
3078
|
),
|
|
2893
|
-
/* @__PURE__ */ jsxs("div", { className: "grid gap-5
|
|
3079
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-5 xl:grid-cols-[minmax(16rem,22rem)_minmax(0,1fr)]", children: [
|
|
2894
3080
|
/* @__PURE__ */ jsxs(Card, { className: "h-fit border-border-secondary", children: [
|
|
2895
3081
|
/* @__PURE__ */ jsxs(CardHeader, { className: "gap-3 border-b border-border-secondary p-4", children: [
|
|
2896
3082
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
@@ -2926,7 +3112,7 @@ function DataTablesPage() {
|
|
|
2926
3112
|
/* @__PURE__ */ jsx(Button, { type: "submit", variant: "outline", size: "sm", children: tr("fluidgrids.dataTables.searchAction", "Search") })
|
|
2927
3113
|
] })
|
|
2928
3114
|
] }),
|
|
2929
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "p-2", children: [
|
|
3115
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "max-h-72 overflow-y-auto p-2 xl:max-h-[36rem]", children: [
|
|
2930
3116
|
loading && /* @__PURE__ */ jsx("p", { className: "p-4 text-sm text-text-secondary", children: tr("fluidgrids.dataTables.loading", "Loading tables\u2026") }),
|
|
2931
3117
|
!loading && tables.length === 0 && /* @__PURE__ */ jsx(
|
|
2932
3118
|
IllustratedEmptyState,
|
|
@@ -3025,39 +3211,20 @@ function DataTablesPage() {
|
|
|
3025
3211
|
"Choose a table to view and edit its rows, or create your first table."
|
|
3026
3212
|
) })
|
|
3027
3213
|
] }) }),
|
|
3028
|
-
selectedTable && /* @__PURE__ */
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
]
|
|
3043
|
-
}
|
|
3044
|
-
),
|
|
3045
|
-
/* @__PURE__ */ jsxs(
|
|
3046
|
-
Button,
|
|
3047
|
-
{
|
|
3048
|
-
variant: "outline",
|
|
3049
|
-
size: "sm",
|
|
3050
|
-
onClick: handleDeleteTable,
|
|
3051
|
-
disabled: deleting,
|
|
3052
|
-
children: [
|
|
3053
|
-
/* @__PURE__ */ jsx(Trash2, { className: "mr-1.5 size-4", "aria-hidden": "true" }),
|
|
3054
|
-
deleting ? tr("fluidgrids.dataTables.deleting", "Deleting\u2026") : tr("fluidgrids.dataTables.deleteTable", "Delete table")
|
|
3055
|
-
]
|
|
3056
|
-
}
|
|
3057
|
-
)
|
|
3058
|
-
] }),
|
|
3059
|
-
/* @__PURE__ */ jsx(TableRowsPanel, { table: selectedTable, onTableChanged: refresh })
|
|
3060
|
-
] })
|
|
3214
|
+
selectedTable && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx(
|
|
3215
|
+
TableRowsPanel,
|
|
3216
|
+
{
|
|
3217
|
+
table: selectedTable,
|
|
3218
|
+
onTableChanged: refresh,
|
|
3219
|
+
onEditTable: () => {
|
|
3220
|
+
setEditingTable(selectedTable);
|
|
3221
|
+
setTableDialogOpen(true);
|
|
3222
|
+
},
|
|
3223
|
+
onDeleteTable: handleDeleteTable,
|
|
3224
|
+
deletingTable: deleting
|
|
3225
|
+
},
|
|
3226
|
+
selectedTable.id
|
|
3227
|
+
) })
|
|
3061
3228
|
] })
|
|
3062
3229
|
] }),
|
|
3063
3230
|
/* @__PURE__ */ jsx(
|