@questpie/admin 3.0.3 → 3.0.5
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/README.md +34 -5
- package/dist/client/blocks/block-renderer.d.mts +2 -2
- package/dist/client/blocks/block-renderer.mjs +4 -1
- package/dist/client/builder/types/action-types.d.mts +31 -3
- package/dist/client/builder/types/collection-types.d.mts +140 -0
- package/dist/client/builder/types/ui-config.d.mts +16 -2
- package/dist/client/builder/types/views.d.mts +57 -0
- package/dist/client/builder/types/widget-types.d.mts +5 -0
- package/dist/client/components/actions/action-button.mjs +137 -199
- package/dist/client/components/actions/action-dialog.mjs +198 -156
- package/dist/client/components/actions/confirmation-dialog.mjs +2 -2
- package/dist/client/components/actions/header-actions.mjs +52 -53
- package/dist/client/components/admin-link.d.mts +2 -2
- package/dist/client/components/auth/auth-loading.mjs +41 -18
- package/dist/client/components/blocks/block-editor-layout.mjs +2 -2
- package/dist/client/components/blocks/block-fields-renderer.mjs +64 -28
- package/dist/client/components/blocks/block-insert-button.mjs +4 -4
- package/dist/client/components/blocks/block-item.mjs +2 -2
- package/dist/client/components/blocks/block-library-sidebar.mjs +91 -63
- package/dist/client/components/component-renderer.mjs +1 -1
- package/dist/client/components/fields/array-field.mjs +14 -14
- package/dist/client/components/fields/asset-preview-field.mjs +1 -1
- package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
- package/dist/client/components/fields/json-field.mjs +2 -2
- package/dist/client/components/fields/object-array-field.mjs +22 -22
- package/dist/client/components/fields/object-field.mjs +5 -5
- package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
- package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
- package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
- package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
- package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
- package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
- package/dist/client/components/fields/relation-picker.mjs +7 -6
- package/dist/client/components/fields/relation-select.mjs +71 -47
- package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
- package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
- package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
- package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
- package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
- package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
- package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
- package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
- package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
- package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
- package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
- package/dist/client/components/fields/upload-field.mjs +45 -49
- package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
- package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
- package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
- package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
- package/dist/client/components/history-sidebar.mjs +850 -340
- package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
- package/dist/client/components/locale-switcher.mjs +8 -8
- package/dist/client/components/media/media-grid.mjs +106 -86
- package/dist/client/components/media/media-picker-dialog.mjs +242 -230
- package/dist/client/components/preview/live-preview-mode.mjs +1 -1
- package/dist/client/components/primitives/asset-preview.mjs +37 -22
- package/dist/client/components/primitives/date-input.mjs +212 -249
- package/dist/client/components/primitives/dropzone.mjs +192 -159
- package/dist/client/components/primitives/field-select-control.mjs +93 -0
- package/dist/client/components/primitives/select-multi.mjs +406 -365
- package/dist/client/components/primitives/select-single.mjs +391 -323
- package/dist/client/components/primitives/time-input.mjs +2 -2
- package/dist/client/components/sheets/resource-sheet.mjs +2 -0
- package/dist/client/components/ui/accordion.mjs +4 -4
- package/dist/client/components/ui/alert.mjs +3 -3
- package/dist/client/components/ui/badge.mjs +4 -4
- package/dist/client/components/ui/button.mjs +47 -37
- package/dist/client/components/ui/card.mjs +2 -2
- package/dist/client/components/ui/checkbox.mjs +1 -1
- package/dist/client/components/ui/command.mjs +5 -5
- package/dist/client/components/ui/dialog.mjs +3 -3
- package/dist/client/components/ui/drawer.mjs +1 -1
- package/dist/client/components/ui/dropdown-menu.mjs +157 -15
- package/dist/client/components/ui/empty-state.mjs +88 -59
- package/dist/client/components/ui/field.mjs +2 -2
- package/dist/client/components/ui/input-group.mjs +3 -3
- package/dist/client/components/ui/input.mjs +1 -1
- package/dist/client/components/ui/kbd.mjs +1 -1
- package/dist/client/components/ui/label.mjs +1 -1
- package/dist/client/components/ui/popover.mjs +19 -11
- package/dist/client/components/ui/scroll-fade.mjs +170 -0
- package/dist/client/components/ui/search-input.mjs +1 -1
- package/dist/client/components/ui/select.mjs +129 -27
- package/dist/client/components/ui/sheet.mjs +54 -34
- package/dist/client/components/ui/sidebar.mjs +15 -14
- package/dist/client/components/ui/skeleton.mjs +28 -12
- package/dist/client/components/ui/switch.mjs +2 -2
- package/dist/client/components/ui/table.mjs +82 -74
- package/dist/client/components/ui/tabs.mjs +26 -31
- package/dist/client/components/ui/textarea.mjs +1 -1
- package/dist/client/components/ui/tooltip.mjs +1 -1
- package/dist/client/components/widgets/chart-widget.mjs +154 -100
- package/dist/client/components/widgets/progress-widget.mjs +63 -36
- package/dist/client/components/widgets/quick-actions-widget.mjs +207 -115
- package/dist/client/components/widgets/recent-items-widget.mjs +147 -103
- package/dist/client/components/widgets/stats-widget.mjs +91 -72
- package/dist/client/components/widgets/table-widget.mjs +161 -247
- package/dist/client/components/widgets/timeline-widget.mjs +119 -78
- package/dist/client/components/widgets/value-widget.mjs +286 -157
- package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
- package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
- package/dist/client/contexts/focus-context.d.mts +2 -2
- package/dist/client/hooks/use-action.mjs +63 -55
- package/dist/client/hooks/use-audit-history.mjs +1 -65
- package/dist/client/hooks/use-collection-validation.mjs +36 -23
- package/dist/client/hooks/use-collection.mjs +96 -1
- package/dist/client/hooks/use-saved-views.mjs +70 -49
- package/dist/client/hooks/use-server-actions.mjs +70 -46
- package/dist/client/hooks/use-server-validation.mjs +156 -41
- package/dist/client/hooks/use-server-widget-data.mjs +1 -1
- package/dist/client/hooks/use-setup-status.d.mts +3 -3
- package/dist/client/hooks/use-setup-status.mjs +2 -2
- package/dist/client/hooks/use-transition-stage.mjs +2 -10
- package/dist/client/hooks/use-validation-error-map.mjs +31 -13
- package/dist/client/hooks/use-view-state.mjs +238 -174
- package/dist/client/i18n/date-locale.mjs +33 -0
- package/dist/client/i18n/hooks.mjs +17 -1
- package/dist/client/lib/utils.mjs +3 -2
- package/dist/client/preview/block-scope-context.d.mts +2 -2
- package/dist/client/preview/preview-banner.d.mts +2 -2
- package/dist/client/preview/preview-banner.mjs +75 -46
- package/dist/client/preview/preview-field.d.mts +4 -4
- package/dist/client/preview/preview-field.mjs +2 -2
- package/dist/client/runtime/provider.mjs +8 -1
- package/dist/client/runtime/translations-provider.mjs +1 -1
- package/dist/client/scope/picker.d.mts +2 -2
- package/dist/client/scope/provider.d.mts +2 -2
- package/dist/client/styles/base.css +1022 -0
- package/dist/client/styles/index.css +3 -589
- package/dist/client/utils/auto-expand-fields.mjs +4 -2
- package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
- package/dist/client/utils/use-lazy-component.mjs +80 -0
- package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
- package/dist/client/views/auth/auth-layout.d.mts +17 -10
- package/dist/client/views/auth/auth-layout.mjs +291 -80
- package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
- package/dist/client/views/auth/forgot-password-form.mjs +2 -2
- package/dist/client/views/auth/login-form.d.mts +2 -2
- package/dist/client/views/auth/login-form.mjs +1 -1
- package/dist/client/views/auth/reset-password-form.d.mts +2 -2
- package/dist/client/views/auth/reset-password-form.mjs +2 -2
- package/dist/client/views/auth/setup-form.d.mts +2 -2
- package/dist/client/views/collection/auto-form-fields.mjs +11 -9
- package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
- package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
- package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
- package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
- package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
- package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
- package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
- package/dist/client/views/collection/columns/build-columns.mjs +29 -9
- package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
- package/dist/client/views/collection/field-renderer.mjs +50 -89
- package/dist/client/views/collection/form-view.mjs +237 -227
- package/dist/client/views/collection/table-view.mjs +1167 -234
- package/dist/client/views/collection/view-skeletons.mjs +222 -79
- package/dist/client/views/common/global-search.mjs +29 -18
- package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
- package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
- package/dist/client/views/dashboard/widget-card.mjs +23 -14
- package/dist/client/views/globals/global-form-view.mjs +634 -589
- package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
- package/dist/client/views/layout/admin-layout.d.mts +3 -6
- package/dist/client/views/layout/admin-layout.mjs +152 -155
- package/dist/client/views/layout/admin-router.mjs +936 -616
- package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
- package/dist/client/views/layout/admin-sidebar.mjs +762 -592
- package/dist/client/views/layout/admin-theme.d.mts +10 -0
- package/dist/client/views/layout/admin-theme.mjs +84 -0
- package/dist/client/views/layout/admin-view-layout.mjs +161 -0
- package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
- package/dist/client/views/pages/accept-invite-page.mjs +49 -26
- package/dist/client/views/pages/dashboard-page.d.mts +2 -2
- package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
- package/dist/client/views/pages/forgot-password-page.mjs +2 -19
- package/dist/client/views/pages/invite-page.d.mts +2 -2
- package/dist/client/views/pages/invite-page.mjs +2 -19
- package/dist/client/views/pages/login-page.d.mts +3 -3
- package/dist/client/views/pages/login-page.mjs +4 -21
- package/dist/client/views/pages/reset-password-page.d.mts +2 -2
- package/dist/client/views/pages/reset-password-page.mjs +3 -20
- package/dist/client/views/pages/setup-page.d.mts +2 -2
- package/dist/client/views/pages/setup-page.mjs +70 -71
- package/dist/client.d.mts +6 -2
- package/dist/client.mjs +2 -1
- package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.mjs +2 -1
- package/dist/server/augmentation/dashboard.d.mts +67 -3
- package/dist/server/augmentation/form-layout.d.mts +21 -0
- package/dist/server/augmentation/index.d.mts +1 -1
- package/dist/server/codegen/admin-client-template.mjs +4 -0
- package/dist/server/fields/blocks.d.mts +1 -1
- package/dist/server/fields/blocks.mjs +12 -0
- package/dist/server/fields/rich-text.d.mts +1 -1
- package/dist/server/fields/rich-text.mjs +8 -0
- package/dist/server/i18n/index.mjs +29 -7
- package/dist/server/i18n/messages/cs.mjs +414 -1
- package/dist/server/i18n/messages/de.mjs +412 -1
- package/dist/server/i18n/messages/en.mjs +166 -1
- package/dist/server/i18n/messages/es.mjs +412 -1
- package/dist/server/i18n/messages/fr.mjs +412 -1
- package/dist/server/i18n/messages/pl.mjs +416 -1
- package/dist/server/i18n/messages/pt.mjs +409 -1
- package/dist/server/i18n/messages/sk.mjs +216 -2
- package/dist/server/modules/admin/block/introspection.mjs +4 -1
- package/dist/server/modules/admin/block/prefetch.mjs +12 -2
- package/dist/server/modules/admin/collections/account.d.mts +2 -2
- package/dist/server/modules/admin/collections/admin-locks.d.mts +2 -2
- package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
- package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
- package/dist/server/modules/admin/collections/apikey.d.mts +42 -42
- package/dist/server/modules/admin/collections/assets.d.mts +20 -20
- package/dist/server/modules/admin/collections/assets.mjs +0 -1
- package/dist/server/modules/admin/collections/session.d.mts +42 -42
- package/dist/server/modules/admin/collections/user.d.mts +40 -28
- package/dist/server/modules/admin/collections/user.mjs +40 -9
- package/dist/server/modules/admin/collections/verification.d.mts +36 -36
- package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
- package/dist/server/modules/admin/factories.mjs +7 -18
- package/dist/server/modules/admin/index.d.mts +1 -1
- package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
- package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
- package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
- package/dist/server/modules/admin/routes/execute-action.mjs +67 -28
- package/dist/server/modules/admin/routes/i18n-helpers.mjs +34 -0
- package/dist/server/modules/admin/routes/locales.d.mts +2 -2
- package/dist/server/modules/admin/routes/preview.mjs +25 -17
- package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
- package/dist/server/modules/admin/routes/route-helpers.mjs +1 -1
- package/dist/server/modules/admin/routes/setup.d.mts +10 -10
- package/dist/server/modules/admin/routes/setup.mjs +16 -13
- package/dist/server/modules/admin/routes/translations.d.mts +4 -4
- package/dist/server/modules/admin/routes/translations.mjs +5 -1
- package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
- package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +2 -2
- package/dist/server/modules/audit/.generated/module.d.mts +1 -1
- package/dist/server/modules/audit/.generated/module.mjs +1 -1
- package/dist/server/modules/audit/collections/audit-log.d.mts +2 -2
- package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
- package/dist/server/modules/audit/config/app.mjs +99 -42
- package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
- package/dist/server/plugin.mjs +4 -2
- package/dist/server/proxy-factories.d.mts +4 -3
- package/dist/server/proxy-factories.mjs +34 -8
- package/dist/shared/types/saved-views.types.d.mts +2 -0
- package/package.json +6 -4
- package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
- package/dist/client/components/ui/spinner.mjs +0 -52
- package/dist/client/components/ui/toolbar.mjs +0 -136
- package/dist/client/contexts/breadcrumb-context.mjs +0 -60
- package/dist/client/views/layout/admin-topbar.mjs +0 -236
|
@@ -5,39 +5,53 @@ import { useSafeContentLocales } from "../../runtime/content-locales-provider.mj
|
|
|
5
5
|
import { useScopedLocale } from "../../runtime/locale-scope.mjs";
|
|
6
6
|
import { Button } from "../../components/ui/button.mjs";
|
|
7
7
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../components/ui/select.mjs";
|
|
8
|
+
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle } from "../../components/ui/sheet.mjs";
|
|
9
|
+
import { sanitizeFilename } from "../../components/fields/field-utils.mjs";
|
|
10
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../../components/ui/tooltip.mjs";
|
|
8
11
|
import { LocaleSwitcher } from "../../components/locale-switcher.mjs";
|
|
9
12
|
import { Checkbox } from "../../components/ui/checkbox.mjs";
|
|
10
13
|
import { flattenOptions } from "../../components/primitives/types.mjs";
|
|
11
14
|
import { createActionRegistryProxy } from "../../builder/types/action-registry.mjs";
|
|
15
|
+
import { ActionButton } from "../../components/actions/action-button.mjs";
|
|
12
16
|
import { useCollectionFields } from "../../hooks/use-collection-fields.mjs";
|
|
13
17
|
import { useSuspenseCollectionMeta } from "../../hooks/use-collection-meta.mjs";
|
|
14
18
|
import { ActionDialog } from "../../components/actions/action-dialog.mjs";
|
|
19
|
+
import { EmptyState } from "../../components/ui/empty-state.mjs";
|
|
20
|
+
import { ScrollFade } from "../../components/ui/scroll-fade.mjs";
|
|
15
21
|
import { useSidebarSearchParam } from "../../hooks/use-sidebar-search-param.mjs";
|
|
16
|
-
import { useCollectionDelete, useCollectionList, useCollectionRestore } from "../../hooks/use-collection.mjs";
|
|
22
|
+
import { useCollectionDelete, useCollectionList, useCollectionRestore, useCollectionUpdateBatch } from "../../hooks/use-collection.mjs";
|
|
17
23
|
import { useSessionState } from "../../hooks/use-current-user.mjs";
|
|
18
24
|
import { getLockUser, useLocks } from "../../hooks/use-locks.mjs";
|
|
19
25
|
import { mergeServerActions, useServerActions } from "../../hooks/use-server-actions.mjs";
|
|
26
|
+
import { AdminViewHeader, AdminViewLayout } from "../layout/admin-view-layout.mjs";
|
|
27
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../components/ui/table.mjs";
|
|
20
28
|
import { TableViewSkeleton } from "./view-skeletons.mjs";
|
|
29
|
+
import { ResourceSheet } from "../../components/sheets/resource-sheet.mjs";
|
|
30
|
+
import { useUploadCollection } from "../../hooks/use-upload-collection.mjs";
|
|
31
|
+
import { useUpload } from "../../hooks/use-upload.mjs";
|
|
32
|
+
import { AssetPreview } from "../../components/primitives/asset-preview.mjs";
|
|
33
|
+
import { Dropzone } from "../../components/primitives/dropzone.mjs";
|
|
21
34
|
import { useDebouncedValue, useSearch } from "../../hooks/use-search.mjs";
|
|
35
|
+
import { autoExpandFields, hasFieldsToExpand } from "../../utils/auto-expand-fields.mjs";
|
|
36
|
+
import { computeDefaultColumns, getAllAvailableFields } from "./columns/column-defaults.mjs";
|
|
37
|
+
import { buildColumns } from "./columns/build-columns.mjs";
|
|
22
38
|
import { HeaderActions } from "../../components/actions/header-actions.mjs";
|
|
23
39
|
import { FilterBuilderSheet } from "../../components/filter-builder/filter-builder-sheet.mjs";
|
|
24
|
-
import { EmptyState } from "../../components/ui/empty-state.mjs";
|
|
25
40
|
import { SearchInput } from "../../components/ui/search-input.mjs";
|
|
26
|
-
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../components/ui/table.mjs";
|
|
27
|
-
import { Toolbar, ToolbarSection, ToolbarSeparator } from "../../components/ui/toolbar.mjs";
|
|
28
41
|
import { useActions } from "../../hooks/use-action.mjs";
|
|
29
42
|
import { useRealtimeHighlight } from "../../hooks/use-realtime-highlight.mjs";
|
|
30
43
|
import { useDeleteSavedView, useSaveView, useSavedViews } from "../../hooks/use-saved-views.mjs";
|
|
31
44
|
import { useViewState } from "../../hooks/use-view-state.mjs";
|
|
32
|
-
import { autoExpandFields, hasFieldsToExpand } from "../../utils/auto-expand-fields.mjs";
|
|
33
45
|
import { BulkActionToolbar } from "./bulk-action-toolbar.mjs";
|
|
34
|
-
import { computeDefaultColumns, getAllAvailableFields } from "./columns/column-defaults.mjs";
|
|
35
|
-
import { buildColumns } from "./columns/build-columns.mjs";
|
|
36
46
|
import { c } from "react/compiler-runtime";
|
|
37
47
|
import { Icon } from "@iconify/react";
|
|
38
48
|
import * as React from "react";
|
|
39
49
|
import { Suspense, useMemo, useState } from "react";
|
|
40
50
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
51
|
+
import { DndContext, DragOverlay, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
|
|
52
|
+
import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
|
53
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
54
|
+
import { toast } from "sonner";
|
|
41
55
|
import { flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
|
42
56
|
|
|
43
57
|
//#region src/client/views/collection/table-view.tsx
|
|
@@ -48,8 +62,198 @@ import { flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from "@
|
|
|
48
62
|
* This is the default list view registered in the admin view registry.
|
|
49
63
|
*/
|
|
50
64
|
const actionRegistry = createActionRegistryProxy();
|
|
65
|
+
const STICKY_TABLE_COLUMN_COUNT = 2;
|
|
66
|
+
const REORDER_DROP_DURATION = 160;
|
|
67
|
+
const REORDER_MOVE_EASING = "cubic-bezier(0.25, 1, 0.5, 1)";
|
|
68
|
+
const REORDER_DROP_ANIMATION = {
|
|
69
|
+
duration: REORDER_DROP_DURATION,
|
|
70
|
+
easing: REORDER_MOVE_EASING
|
|
71
|
+
};
|
|
72
|
+
function UploadCollectionButton(t0) {
|
|
73
|
+
const $ = c(13);
|
|
74
|
+
const { collection, onUploaded } = t0;
|
|
75
|
+
const { t } = useTranslation();
|
|
76
|
+
const [open, setOpen] = React.useState(false);
|
|
77
|
+
let t1;
|
|
78
|
+
let t2;
|
|
79
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
80
|
+
t1 = () => setOpen(true);
|
|
81
|
+
t2 = /* @__PURE__ */ jsx(Icon, {
|
|
82
|
+
icon: "ph:cloud-arrow-up",
|
|
83
|
+
className: "size-3.5"
|
|
84
|
+
});
|
|
85
|
+
$[0] = t1;
|
|
86
|
+
$[1] = t2;
|
|
87
|
+
} else {
|
|
88
|
+
t1 = $[0];
|
|
89
|
+
t2 = $[1];
|
|
90
|
+
}
|
|
91
|
+
let t3;
|
|
92
|
+
if ($[2] !== t) {
|
|
93
|
+
t3 = t("common.upload");
|
|
94
|
+
$[2] = t;
|
|
95
|
+
$[3] = t3;
|
|
96
|
+
} else t3 = $[3];
|
|
97
|
+
let t4;
|
|
98
|
+
if ($[4] !== t3) {
|
|
99
|
+
t4 = /* @__PURE__ */ jsxs(Button, {
|
|
100
|
+
variant: "default",
|
|
101
|
+
size: "sm",
|
|
102
|
+
className: "gap-2",
|
|
103
|
+
onClick: t1,
|
|
104
|
+
children: [t2, t3]
|
|
105
|
+
});
|
|
106
|
+
$[4] = t3;
|
|
107
|
+
$[5] = t4;
|
|
108
|
+
} else t4 = $[5];
|
|
109
|
+
let t5;
|
|
110
|
+
if ($[6] !== collection || $[7] !== onUploaded || $[8] !== open) {
|
|
111
|
+
t5 = /* @__PURE__ */ jsx(UploadCollectionSheet, {
|
|
112
|
+
open,
|
|
113
|
+
onOpenChange: setOpen,
|
|
114
|
+
collection,
|
|
115
|
+
onUploaded
|
|
116
|
+
});
|
|
117
|
+
$[6] = collection;
|
|
118
|
+
$[7] = onUploaded;
|
|
119
|
+
$[8] = open;
|
|
120
|
+
$[9] = t5;
|
|
121
|
+
} else t5 = $[9];
|
|
122
|
+
let t6;
|
|
123
|
+
if ($[10] !== t4 || $[11] !== t5) {
|
|
124
|
+
t6 = /* @__PURE__ */ jsxs(Fragment, { children: [t4, t5] });
|
|
125
|
+
$[10] = t4;
|
|
126
|
+
$[11] = t5;
|
|
127
|
+
$[12] = t6;
|
|
128
|
+
} else t6 = $[12];
|
|
129
|
+
return t6;
|
|
130
|
+
}
|
|
131
|
+
function UploadCollectionSheet({ open, onOpenChange, collection, onUploaded }) {
|
|
132
|
+
const { t } = useTranslation();
|
|
133
|
+
const { uploadMany, isUploading, progress } = useUpload();
|
|
134
|
+
const [uploadedAssets, setUploadedAssets] = React.useState([]);
|
|
135
|
+
const [editAssetId, setEditAssetId] = React.useState(null);
|
|
136
|
+
React.useEffect(() => {
|
|
137
|
+
if (!open) {
|
|
138
|
+
setUploadedAssets([]);
|
|
139
|
+
setEditAssetId(null);
|
|
140
|
+
}
|
|
141
|
+
}, [open]);
|
|
142
|
+
const handleValidationError = React.useCallback((errors) => {
|
|
143
|
+
for (const validationError of errors) toast.error(validationError.message);
|
|
144
|
+
}, []);
|
|
145
|
+
const handleDrop = React.useCallback(async (files) => {
|
|
146
|
+
if (files.length === 0 || isUploading) return;
|
|
147
|
+
const sanitizedFiles = files.map((file) => new File([file], sanitizeFilename(file.name), {
|
|
148
|
+
type: file.type,
|
|
149
|
+
lastModified: file.lastModified
|
|
150
|
+
}));
|
|
151
|
+
try {
|
|
152
|
+
const uploaded = await uploadMany(sanitizedFiles, { to: collection });
|
|
153
|
+
setUploadedAssets((current) => [...uploaded, ...current]);
|
|
154
|
+
toast.success(t("upload.bulkSuccess", { count: uploaded.length }));
|
|
155
|
+
await onUploaded?.();
|
|
156
|
+
} catch (error) {
|
|
157
|
+
toast.error(error instanceof Error ? error.message : t("upload.error"));
|
|
158
|
+
}
|
|
159
|
+
}, [
|
|
160
|
+
collection,
|
|
161
|
+
isUploading,
|
|
162
|
+
onUploaded,
|
|
163
|
+
t,
|
|
164
|
+
uploadMany
|
|
165
|
+
]);
|
|
166
|
+
return /* @__PURE__ */ jsx(Sheet, {
|
|
167
|
+
open,
|
|
168
|
+
onOpenChange,
|
|
169
|
+
modal: false,
|
|
170
|
+
children: /* @__PURE__ */ jsxs(SheetContent, {
|
|
171
|
+
side: "right",
|
|
172
|
+
showOverlay: false,
|
|
173
|
+
className: "qa-upload-sheet w-full p-0 data-[side=right]:sm:max-w-xl",
|
|
174
|
+
children: [
|
|
175
|
+
/* @__PURE__ */ jsxs(SheetHeader, {
|
|
176
|
+
className: "border-b px-6 py-5",
|
|
177
|
+
children: [/* @__PURE__ */ jsx(SheetTitle, { children: t("upload.bulkTitle") }), /* @__PURE__ */ jsx(SheetDescription, { children: t("upload.bulkDescription") })]
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ jsxs("div", {
|
|
180
|
+
className: "flex flex-1 flex-col gap-5 overflow-y-auto px-6 py-5",
|
|
181
|
+
children: [/* @__PURE__ */ jsx(Dropzone, {
|
|
182
|
+
onDrop: handleDrop,
|
|
183
|
+
multiple: true,
|
|
184
|
+
loading: isUploading,
|
|
185
|
+
progress: isUploading ? progress : void 0,
|
|
186
|
+
label: t("upload.dropzone"),
|
|
187
|
+
hint: t("upload.bulkHint"),
|
|
188
|
+
onValidationError: handleValidationError
|
|
189
|
+
}), uploadedAssets.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
190
|
+
className: "space-y-3",
|
|
191
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
192
|
+
className: "text-muted-foreground font-chrome chrome-meta text-xs font-medium",
|
|
193
|
+
children: t("upload.uploadedCount", { count: uploadedAssets.length })
|
|
194
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
195
|
+
className: "grid gap-2",
|
|
196
|
+
children: uploadedAssets.map((asset) => /* @__PURE__ */ jsx(AssetPreview, {
|
|
197
|
+
asset,
|
|
198
|
+
variant: "compact",
|
|
199
|
+
onEdit: () => setEditAssetId(asset.id)
|
|
200
|
+
}, asset.id))
|
|
201
|
+
})]
|
|
202
|
+
})]
|
|
203
|
+
}),
|
|
204
|
+
/* @__PURE__ */ jsx(SheetFooter, {
|
|
205
|
+
className: "border-t px-6 py-4",
|
|
206
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
207
|
+
variant: "outline",
|
|
208
|
+
onClick: () => onOpenChange(false),
|
|
209
|
+
disabled: isUploading,
|
|
210
|
+
children: t("common.close")
|
|
211
|
+
})
|
|
212
|
+
}),
|
|
213
|
+
editAssetId && /* @__PURE__ */ jsx(ResourceSheet, {
|
|
214
|
+
type: "collection",
|
|
215
|
+
collection,
|
|
216
|
+
itemId: editAssetId,
|
|
217
|
+
open: !!editAssetId,
|
|
218
|
+
onOpenChange: (nextOpen) => {
|
|
219
|
+
if (!nextOpen) setEditAssetId(null);
|
|
220
|
+
},
|
|
221
|
+
onSave: () => {
|
|
222
|
+
onUploaded?.();
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
]
|
|
226
|
+
})
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function getColumnSizeStyle(width) {
|
|
230
|
+
return {
|
|
231
|
+
width,
|
|
232
|
+
minWidth: width,
|
|
233
|
+
maxWidth: width
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function getColumnSize(column, fallback = 120) {
|
|
237
|
+
return typeof column?.getSize === "function" ? column.getSize() : fallback;
|
|
238
|
+
}
|
|
239
|
+
function getStickyLeftOffset(columns, index) {
|
|
240
|
+
return columns.slice(0, index).reduce((left, column, columnIndex) => {
|
|
241
|
+
return left + getColumnSize(column, columnIndex === 0 ? 40 : 360);
|
|
242
|
+
}, 0);
|
|
243
|
+
}
|
|
244
|
+
function getActionReferenceType(reference) {
|
|
245
|
+
if (typeof reference === "string") return reference;
|
|
246
|
+
if (typeof reference === "function") {
|
|
247
|
+
const actionType = reference.type;
|
|
248
|
+
if (typeof actionType === "string") return actionType;
|
|
249
|
+
const resolved = reference();
|
|
250
|
+
return typeof resolved === "string" ? resolved : void 0;
|
|
251
|
+
}
|
|
252
|
+
return typeof reference?.type === "string" ? reference.type : void 0;
|
|
253
|
+
}
|
|
51
254
|
function resolveBuiltinListAction(reference) {
|
|
52
|
-
|
|
255
|
+
if (typeof reference === "object" && reference !== null && "id" in reference && "handler" in reference) return reference;
|
|
256
|
+
const type = getActionReferenceType(reference);
|
|
53
257
|
const config = typeof reference === "object" && reference !== null ? reference.config : void 0;
|
|
54
258
|
if (!type) return null;
|
|
55
259
|
switch (type) {
|
|
@@ -64,29 +268,302 @@ function mapActionReferencesToDefinitions(references) {
|
|
|
64
268
|
if (!Array.isArray(references)) return [];
|
|
65
269
|
return references.map((reference) => resolveBuiltinListAction(reference)).filter((action) => action !== null);
|
|
66
270
|
}
|
|
271
|
+
function mapListActionsToDefinitions(actions) {
|
|
272
|
+
if (!actions || typeof actions !== "object") return void 0;
|
|
273
|
+
const listActions = actions;
|
|
274
|
+
const header = listActions.header ? {
|
|
275
|
+
primary: mapActionReferencesToDefinitions(listActions.header.primary),
|
|
276
|
+
secondary: mapActionReferencesToDefinitions(listActions.header.secondary)
|
|
277
|
+
} : void 0;
|
|
278
|
+
const row = mapActionReferencesToDefinitions(listActions.row);
|
|
279
|
+
const bulk = mapActionReferencesToDefinitions(listActions.bulk);
|
|
280
|
+
if (!header && row.length === 0 && bulk.length === 0) return void 0;
|
|
281
|
+
return {
|
|
282
|
+
...header ? { header } : {},
|
|
283
|
+
...row.length > 0 ? { row } : {},
|
|
284
|
+
...bulk.length > 0 ? { bulk } : {}
|
|
285
|
+
};
|
|
286
|
+
}
|
|
67
287
|
function mapListSchemaToConfig(list) {
|
|
68
288
|
if (!list) return void 0;
|
|
69
289
|
const config = {};
|
|
70
290
|
if (list.columns?.length) config.columns = list.columns;
|
|
71
291
|
if (list.defaultSort) config.defaultSort = list.defaultSort;
|
|
292
|
+
if (list.orderable) config.orderable = list.orderable;
|
|
72
293
|
if (list.searchable?.length) {
|
|
73
294
|
config.searchFields = list.searchable;
|
|
74
295
|
config.searchable = true;
|
|
75
296
|
}
|
|
76
|
-
if (list.
|
|
77
|
-
|
|
78
|
-
const header = listActions.header ? {
|
|
79
|
-
primary: mapActionReferencesToDefinitions(listActions.header.primary),
|
|
80
|
-
secondary: mapActionReferencesToDefinitions(listActions.header.secondary)
|
|
81
|
-
} : void 0;
|
|
82
|
-
const bulk = mapActionReferencesToDefinitions(listActions.bulk);
|
|
83
|
-
if (header || bulk.length > 0) config.actions = {
|
|
84
|
-
...header ? { header } : {},
|
|
85
|
-
...bulk.length > 0 ? { bulk } : {}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
297
|
+
if (list.grouping?.fields?.length) config.grouping = list.grouping;
|
|
298
|
+
config.actions = mapListActionsToDefinitions(list.actions);
|
|
88
299
|
return config;
|
|
89
300
|
}
|
|
301
|
+
function stringifyGroupValue(value, field, resolveText, noValueLabel = "No value") {
|
|
302
|
+
if (value === null || value === void 0 || value === "") return noValueLabel;
|
|
303
|
+
if (Array.isArray(value)) return value.length > 0 ? value.map((item) => stringifyGroupValue(item, field, resolveText, noValueLabel)).join(", ") : noValueLabel;
|
|
304
|
+
const options = field?.options?.options;
|
|
305
|
+
if (options) {
|
|
306
|
+
const option = flattenOptions(options).find((item) => String(item.value) === String(value));
|
|
307
|
+
if (option) return resolveText?.(option.label, String(option.value)) ?? String(option.label);
|
|
308
|
+
}
|
|
309
|
+
if (typeof value === "object") {
|
|
310
|
+
const record = value;
|
|
311
|
+
const displayValue = record.title ?? record.name ?? record.label ?? record.id;
|
|
312
|
+
return resolveText?.(displayValue, "Object") ?? String(displayValue ?? "Object");
|
|
313
|
+
}
|
|
314
|
+
return String(value);
|
|
315
|
+
}
|
|
316
|
+
function getGroupSortIndex(value, field) {
|
|
317
|
+
const options = field?.options?.options;
|
|
318
|
+
if (!options) return Number.MAX_SAFE_INTEGER;
|
|
319
|
+
const compareValue = Array.isArray(value) ? value[0] : value;
|
|
320
|
+
const index = flattenOptions(options).findIndex((option) => String(option.value) === String(compareValue));
|
|
321
|
+
return index === -1 ? Number.MAX_SAFE_INTEGER : index;
|
|
322
|
+
}
|
|
323
|
+
const ReorderRowContext = React.createContext(null);
|
|
324
|
+
function ReorderHandle() {
|
|
325
|
+
const $ = c(9);
|
|
326
|
+
const sortable = React.useContext(ReorderRowContext);
|
|
327
|
+
const t0 = sortable?.setActivatorNodeRef;
|
|
328
|
+
let t1;
|
|
329
|
+
if ($[0] !== sortable?.attributes) {
|
|
330
|
+
t1 = sortable?.attributes ?? {};
|
|
331
|
+
$[0] = sortable?.attributes;
|
|
332
|
+
$[1] = t1;
|
|
333
|
+
} else t1 = $[1];
|
|
334
|
+
let t2;
|
|
335
|
+
if ($[2] !== sortable?.listeners) {
|
|
336
|
+
t2 = sortable?.listeners ?? {};
|
|
337
|
+
$[2] = sortable?.listeners;
|
|
338
|
+
$[3] = t2;
|
|
339
|
+
} else t2 = $[3];
|
|
340
|
+
let t3;
|
|
341
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
342
|
+
t3 = /* @__PURE__ */ jsx(Icon, {
|
|
343
|
+
icon: "ph:dots-six-vertical",
|
|
344
|
+
className: "size-3.5"
|
|
345
|
+
});
|
|
346
|
+
$[4] = t3;
|
|
347
|
+
} else t3 = $[4];
|
|
348
|
+
let t4;
|
|
349
|
+
if ($[5] !== t0 || $[6] !== t1 || $[7] !== t2) {
|
|
350
|
+
t4 = /* @__PURE__ */ jsx("button", {
|
|
351
|
+
type: "button",
|
|
352
|
+
ref: t0,
|
|
353
|
+
className: "text-muted-foreground/50 hover:text-muted-foreground focus-visible:ring-ring/40 flex h-8 w-full cursor-grab touch-none items-center justify-center rounded-md transition-colors select-none focus-visible:ring-2 focus-visible:outline-none active:cursor-grabbing",
|
|
354
|
+
"aria-label": "Drag to reorder",
|
|
355
|
+
...t1,
|
|
356
|
+
...t2,
|
|
357
|
+
children: t3
|
|
358
|
+
});
|
|
359
|
+
$[5] = t0;
|
|
360
|
+
$[6] = t1;
|
|
361
|
+
$[7] = t2;
|
|
362
|
+
$[8] = t4;
|
|
363
|
+
} else t4 = $[8];
|
|
364
|
+
return t4;
|
|
365
|
+
}
|
|
366
|
+
function ReorderDragOverlay(t0) {
|
|
367
|
+
const $ = c(24);
|
|
368
|
+
const { row, columns, rect } = t0;
|
|
369
|
+
if (!row) return null;
|
|
370
|
+
let t1;
|
|
371
|
+
let t2;
|
|
372
|
+
let t3;
|
|
373
|
+
let t4;
|
|
374
|
+
let t5;
|
|
375
|
+
if ($[0] !== columns || $[1] !== rect?.height || $[2] !== rect?.width || $[3] !== row) {
|
|
376
|
+
const cells = row.getVisibleCells?.() ?? [];
|
|
377
|
+
t4 = "bg-background text-foreground ring-border-strong pointer-events-none overflow-hidden rounded-md shadow-xl ring-1";
|
|
378
|
+
const t6$1 = rect?.width;
|
|
379
|
+
const t7$1 = rect?.height;
|
|
380
|
+
if ($[9] !== t6$1 || $[10] !== t7$1) {
|
|
381
|
+
t5 = {
|
|
382
|
+
width: t6$1,
|
|
383
|
+
height: t7$1
|
|
384
|
+
};
|
|
385
|
+
$[9] = t6$1;
|
|
386
|
+
$[10] = t7$1;
|
|
387
|
+
$[11] = t5;
|
|
388
|
+
} else t5 = $[11];
|
|
389
|
+
t1 = "grid h-full items-center";
|
|
390
|
+
let t8;
|
|
391
|
+
if ($[12] !== columns) {
|
|
392
|
+
t8 = columns.map(_temp3).join(" ");
|
|
393
|
+
$[12] = columns;
|
|
394
|
+
$[13] = t8;
|
|
395
|
+
} else t8 = $[13];
|
|
396
|
+
if ($[14] !== t8) {
|
|
397
|
+
t2 = { gridTemplateColumns: t8 };
|
|
398
|
+
$[14] = t8;
|
|
399
|
+
$[15] = t2;
|
|
400
|
+
} else t2 = $[15];
|
|
401
|
+
t3 = cells.map(_temp4);
|
|
402
|
+
$[0] = columns;
|
|
403
|
+
$[1] = rect?.height;
|
|
404
|
+
$[2] = rect?.width;
|
|
405
|
+
$[3] = row;
|
|
406
|
+
$[4] = t1;
|
|
407
|
+
$[5] = t2;
|
|
408
|
+
$[6] = t3;
|
|
409
|
+
$[7] = t4;
|
|
410
|
+
$[8] = t5;
|
|
411
|
+
} else {
|
|
412
|
+
t1 = $[4];
|
|
413
|
+
t2 = $[5];
|
|
414
|
+
t3 = $[6];
|
|
415
|
+
t4 = $[7];
|
|
416
|
+
t5 = $[8];
|
|
417
|
+
}
|
|
418
|
+
let t6;
|
|
419
|
+
if ($[16] !== t1 || $[17] !== t2 || $[18] !== t3) {
|
|
420
|
+
t6 = /* @__PURE__ */ jsx("div", {
|
|
421
|
+
className: t1,
|
|
422
|
+
style: t2,
|
|
423
|
+
children: t3
|
|
424
|
+
});
|
|
425
|
+
$[16] = t1;
|
|
426
|
+
$[17] = t2;
|
|
427
|
+
$[18] = t3;
|
|
428
|
+
$[19] = t6;
|
|
429
|
+
} else t6 = $[19];
|
|
430
|
+
let t7;
|
|
431
|
+
if ($[20] !== t4 || $[21] !== t5 || $[22] !== t6) {
|
|
432
|
+
t7 = /* @__PURE__ */ jsx("div", {
|
|
433
|
+
className: t4,
|
|
434
|
+
style: t5,
|
|
435
|
+
children: t6
|
|
436
|
+
});
|
|
437
|
+
$[20] = t4;
|
|
438
|
+
$[21] = t5;
|
|
439
|
+
$[22] = t6;
|
|
440
|
+
$[23] = t7;
|
|
441
|
+
} else t7 = $[23];
|
|
442
|
+
return t7;
|
|
443
|
+
}
|
|
444
|
+
function _temp4(cell, index) {
|
|
445
|
+
return /* @__PURE__ */ jsx("div", {
|
|
446
|
+
className: cn("min-w-0 truncate px-3 py-1.5 text-sm whitespace-nowrap tabular-nums", index === 0 && "px-1.5 text-center"),
|
|
447
|
+
children: index === 0 ? /* @__PURE__ */ jsx(Icon, {
|
|
448
|
+
icon: "ph:dots-six-vertical",
|
|
449
|
+
className: "text-muted-foreground mx-auto size-3.5"
|
|
450
|
+
}) : flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
451
|
+
}, cell.id);
|
|
452
|
+
}
|
|
453
|
+
function _temp3(column) {
|
|
454
|
+
return `${getColumnSize(column, 120)}px`;
|
|
455
|
+
}
|
|
456
|
+
function SortableTableRow(t0) {
|
|
457
|
+
const $ = c(33);
|
|
458
|
+
let children;
|
|
459
|
+
let className;
|
|
460
|
+
let id;
|
|
461
|
+
let props;
|
|
462
|
+
if ($[0] !== t0) {
|
|
463
|
+
({id, className, children, ...props} = t0);
|
|
464
|
+
$[0] = t0;
|
|
465
|
+
$[1] = children;
|
|
466
|
+
$[2] = className;
|
|
467
|
+
$[3] = id;
|
|
468
|
+
$[4] = props;
|
|
469
|
+
} else {
|
|
470
|
+
children = $[1];
|
|
471
|
+
className = $[2];
|
|
472
|
+
id = $[3];
|
|
473
|
+
props = $[4];
|
|
474
|
+
}
|
|
475
|
+
let t1;
|
|
476
|
+
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
|
477
|
+
t1 = {
|
|
478
|
+
duration: REORDER_DROP_DURATION,
|
|
479
|
+
easing: REORDER_MOVE_EASING
|
|
480
|
+
};
|
|
481
|
+
$[5] = t1;
|
|
482
|
+
} else t1 = $[5];
|
|
483
|
+
let t2;
|
|
484
|
+
if ($[6] !== id) {
|
|
485
|
+
t2 = {
|
|
486
|
+
id,
|
|
487
|
+
transition: t1
|
|
488
|
+
};
|
|
489
|
+
$[6] = id;
|
|
490
|
+
$[7] = t2;
|
|
491
|
+
} else t2 = $[7];
|
|
492
|
+
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable(t2);
|
|
493
|
+
const t3 = isDragging && "bg-muted/[0.18] opacity-35";
|
|
494
|
+
let t4;
|
|
495
|
+
if ($[8] !== className || $[9] !== t3) {
|
|
496
|
+
t4 = cn("select-none", t3, className);
|
|
497
|
+
$[8] = className;
|
|
498
|
+
$[9] = t3;
|
|
499
|
+
$[10] = t4;
|
|
500
|
+
} else t4 = $[10];
|
|
501
|
+
let t5;
|
|
502
|
+
if ($[11] !== isDragging || $[12] !== transform) {
|
|
503
|
+
t5 = isDragging ? void 0 : CSS.Transform.toString(transform);
|
|
504
|
+
$[11] = isDragging;
|
|
505
|
+
$[12] = transform;
|
|
506
|
+
$[13] = t5;
|
|
507
|
+
} else t5 = $[13];
|
|
508
|
+
const t6 = isDragging ? void 0 : transition;
|
|
509
|
+
let t7;
|
|
510
|
+
if ($[14] !== props.style) {
|
|
511
|
+
t7 = props.style ?? {};
|
|
512
|
+
$[14] = props.style;
|
|
513
|
+
$[15] = t7;
|
|
514
|
+
} else t7 = $[15];
|
|
515
|
+
let t8;
|
|
516
|
+
if ($[16] !== t5 || $[17] !== t6 || $[18] !== t7) {
|
|
517
|
+
t8 = {
|
|
518
|
+
transform: t5,
|
|
519
|
+
transition: t6,
|
|
520
|
+
...t7
|
|
521
|
+
};
|
|
522
|
+
$[16] = t5;
|
|
523
|
+
$[17] = t6;
|
|
524
|
+
$[18] = t7;
|
|
525
|
+
$[19] = t8;
|
|
526
|
+
} else t8 = $[19];
|
|
527
|
+
let t9;
|
|
528
|
+
if ($[20] !== attributes || $[21] !== listeners || $[22] !== setActivatorNodeRef) {
|
|
529
|
+
t9 = {
|
|
530
|
+
attributes,
|
|
531
|
+
listeners,
|
|
532
|
+
setActivatorNodeRef
|
|
533
|
+
};
|
|
534
|
+
$[20] = attributes;
|
|
535
|
+
$[21] = listeners;
|
|
536
|
+
$[22] = setActivatorNodeRef;
|
|
537
|
+
$[23] = t9;
|
|
538
|
+
} else t9 = $[23];
|
|
539
|
+
let t10;
|
|
540
|
+
if ($[24] !== children || $[25] !== t9) {
|
|
541
|
+
t10 = /* @__PURE__ */ jsx(ReorderRowContext.Provider, {
|
|
542
|
+
value: t9,
|
|
543
|
+
children
|
|
544
|
+
});
|
|
545
|
+
$[24] = children;
|
|
546
|
+
$[25] = t9;
|
|
547
|
+
$[26] = t10;
|
|
548
|
+
} else t10 = $[26];
|
|
549
|
+
let t11;
|
|
550
|
+
if ($[27] !== props || $[28] !== setNodeRef || $[29] !== t10 || $[30] !== t4 || $[31] !== t8) {
|
|
551
|
+
t11 = /* @__PURE__ */ jsx(TableRow, {
|
|
552
|
+
ref: setNodeRef,
|
|
553
|
+
className: t4,
|
|
554
|
+
style: t8,
|
|
555
|
+
...props,
|
|
556
|
+
children: t10
|
|
557
|
+
});
|
|
558
|
+
$[27] = props;
|
|
559
|
+
$[28] = setNodeRef;
|
|
560
|
+
$[29] = t10;
|
|
561
|
+
$[30] = t4;
|
|
562
|
+
$[31] = t8;
|
|
563
|
+
$[32] = t11;
|
|
564
|
+
} else t11 = $[32];
|
|
565
|
+
return t11;
|
|
566
|
+
}
|
|
90
567
|
/**
|
|
91
568
|
* TableView - Default table-based list view for collections
|
|
92
569
|
*
|
|
@@ -139,10 +616,12 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
139
616
|
"use no memo";
|
|
140
617
|
const globalRealtimeConfig = useAdminStore(selectRealtime);
|
|
141
618
|
const { fields: resolvedFields, schema } = useCollectionFields(collection, { fallbackFields: config?.fields });
|
|
619
|
+
const { collections: uploadCollections } = useUploadCollection();
|
|
142
620
|
const schemaListConfig = mapListSchemaToConfig(schema?.admin?.list);
|
|
143
621
|
const resolvedListConfig = viewConfig ?? (config?.list)?.["~config"] ?? config?.list ?? schemaListConfig;
|
|
144
622
|
const resolvedRealtime = realtime ?? resolvedListConfig?.realtime ?? globalRealtimeConfig.enabled;
|
|
145
|
-
const
|
|
623
|
+
const rawActionsConfig = actionsConfig ?? resolvedListConfig?.actions;
|
|
624
|
+
const resolvedActionsConfig = React.useMemo(() => mapListActionsToDefinitions(rawActionsConfig), [rawActionsConfig]);
|
|
146
625
|
const { serverActions } = useServerActions({ collection });
|
|
147
626
|
const mergedActionsConfig = React.useMemo(() => mergeServerActions(resolvedActionsConfig ?? {}, serverActions), [resolvedActionsConfig, serverActions]);
|
|
148
627
|
const { user } = useSessionState();
|
|
@@ -155,6 +634,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
155
634
|
collection,
|
|
156
635
|
actionsConfig: mergedActionsConfig
|
|
157
636
|
});
|
|
637
|
+
const canUploadToCollection = uploadCollections.includes(collection) && schema?.access?.operations?.create?.allowed === true;
|
|
158
638
|
const columns = useMemo(() => buildColumns({
|
|
159
639
|
config: {
|
|
160
640
|
fields: resolvedFields,
|
|
@@ -179,6 +659,32 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
179
659
|
]);
|
|
180
660
|
const [isSheetOpen, setIsSheetOpen] = useSidebarSearchParam("view-options", { legacyKey: "viewOptions" });
|
|
181
661
|
const [searchTerm, setSearchTerm] = useState("");
|
|
662
|
+
const [isSearchPanelOpen, setIsSearchPanelOpen] = useState(false);
|
|
663
|
+
const [isReorderMode, setIsReorderMode] = useState(false);
|
|
664
|
+
const [activeReorderId, setActiveReorderId] = useState(null);
|
|
665
|
+
const [activeReorderRect, setActiveReorderRect] = useState(null);
|
|
666
|
+
const [optimisticOrderIds, setOptimisticOrderIds] = useState(null);
|
|
667
|
+
const reorderStartOrderIdsRef = React.useRef(null);
|
|
668
|
+
const reorderOverlayCleanupRef = React.useRef(null);
|
|
669
|
+
const clearReorderOverlay = React.useCallback((delay = 0) => {
|
|
670
|
+
if (reorderOverlayCleanupRef.current !== null) {
|
|
671
|
+
window.clearTimeout(reorderOverlayCleanupRef.current);
|
|
672
|
+
reorderOverlayCleanupRef.current = null;
|
|
673
|
+
}
|
|
674
|
+
const clear = () => {
|
|
675
|
+
setActiveReorderId(null);
|
|
676
|
+
setActiveReorderRect(null);
|
|
677
|
+
reorderOverlayCleanupRef.current = null;
|
|
678
|
+
};
|
|
679
|
+
if (delay > 0) {
|
|
680
|
+
reorderOverlayCleanupRef.current = window.setTimeout(clear, delay);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
clear();
|
|
684
|
+
}, []);
|
|
685
|
+
React.useEffect(() => () => {
|
|
686
|
+
if (reorderOverlayCleanupRef.current !== null) window.clearTimeout(reorderOverlayCleanupRef.current);
|
|
687
|
+
}, []);
|
|
182
688
|
const defaultColumns = useMemo(() => computeDefaultColumns(resolvedFields, {
|
|
183
689
|
meta: collectionMeta,
|
|
184
690
|
configuredColumns: resolvedListConfig?.columns
|
|
@@ -187,11 +693,41 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
187
693
|
resolvedListConfig?.columns,
|
|
188
694
|
collectionMeta
|
|
189
695
|
]);
|
|
190
|
-
const
|
|
696
|
+
const groupingConfig = resolvedListConfig?.grouping;
|
|
697
|
+
const defaultGroupBy = groupingConfig?.defaultField ?? null;
|
|
698
|
+
const orderableConfig = resolvedListConfig?.orderable;
|
|
699
|
+
const isOrderableEnabled = !!orderableConfig;
|
|
700
|
+
const orderField = "order";
|
|
701
|
+
const orderDirection = typeof orderableConfig === "object" ? orderableConfig.direction ?? "asc" : "asc";
|
|
702
|
+
const orderStep = typeof orderableConfig === "object" ? orderableConfig.step ?? 10 : 10;
|
|
703
|
+
const viewState = useViewState(defaultColumns, {
|
|
704
|
+
realtime: resolvedRealtime,
|
|
705
|
+
groupBy: defaultGroupBy
|
|
706
|
+
}, collection, user?.id);
|
|
191
707
|
const effectiveRealtime = viewState.config.realtime ?? resolvedRealtime;
|
|
708
|
+
const isKnownSortField = React.useCallback((field) => !!field && (field === "_title" || !!resolvedFields?.[field]), [resolvedFields]);
|
|
709
|
+
const hasOrderField = isKnownSortField(orderField);
|
|
710
|
+
const canUseOrderableSort = isOrderableEnabled && hasOrderField;
|
|
711
|
+
const effectiveSort = useMemo(() => {
|
|
712
|
+
if (isKnownSortField(viewState.config.sortConfig?.field)) return viewState.config.sortConfig;
|
|
713
|
+
if (isKnownSortField(resolvedListConfig?.defaultSort?.field)) return resolvedListConfig.defaultSort;
|
|
714
|
+
if (canUseOrderableSort) return {
|
|
715
|
+
field: orderField,
|
|
716
|
+
direction: orderDirection
|
|
717
|
+
};
|
|
718
|
+
return null;
|
|
719
|
+
}, [
|
|
720
|
+
viewState.config.sortConfig,
|
|
721
|
+
resolvedListConfig?.defaultSort,
|
|
722
|
+
canUseOrderableSort,
|
|
723
|
+
orderField,
|
|
724
|
+
orderDirection,
|
|
725
|
+
isKnownSortField
|
|
726
|
+
]);
|
|
192
727
|
const queryOptions = useMemo(() => {
|
|
193
728
|
const options = {};
|
|
194
729
|
if (collectionMeta?.softDelete) options.includeDeleted = !!viewState.config.includeDeleted;
|
|
730
|
+
if (viewState.config.groupBy) options.groupBy = { field: viewState.config.groupBy };
|
|
195
731
|
if (hasFieldsToExpand(expandedFields)) options.with = expandedFields;
|
|
196
732
|
if (viewState.config.filters.length > 0) {
|
|
197
733
|
const whereConditions = { ...options.where };
|
|
@@ -248,12 +784,12 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
248
784
|
}
|
|
249
785
|
};
|
|
250
786
|
for (const filter of viewState.config.filters) {
|
|
251
|
-
const { field, operator: operator_0, value } = filter;
|
|
252
|
-
if (!
|
|
253
|
-
const fieldDef_0 = resolvedFields?.[
|
|
787
|
+
const { field: field_0, operator: operator_0, value } = filter;
|
|
788
|
+
if (!field_0 || field_0 === "_title") continue;
|
|
789
|
+
const fieldDef_0 = resolvedFields?.[field_0];
|
|
254
790
|
const fieldType_0 = fieldDef_0?.name ?? "text";
|
|
255
791
|
const fieldOptions_1 = fieldDef_0?.["~options"] ?? {};
|
|
256
|
-
const relationName = fieldType_0 === "relation" ? fieldOptions_1.relationName ??
|
|
792
|
+
const relationName = fieldType_0 === "relation" ? fieldOptions_1.relationName ?? field_0 : void 0;
|
|
257
793
|
const hasRelation = relationName && (relationNames.length === 0 || relationNames.includes(relationName));
|
|
258
794
|
const isRelationField = fieldType_0 === "relation" && !!hasRelation;
|
|
259
795
|
if (operator_0 !== "is_empty" && operator_0 !== "is_not_empty" && isEmptyValue(value)) continue;
|
|
@@ -265,55 +801,56 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
265
801
|
}
|
|
266
802
|
switch (operator_0) {
|
|
267
803
|
case "equals":
|
|
268
|
-
whereConditions[
|
|
804
|
+
whereConditions[field_0] = normalizedValue;
|
|
269
805
|
break;
|
|
270
806
|
case "not_equals":
|
|
271
|
-
whereConditions[
|
|
807
|
+
whereConditions[field_0] = { ne: normalizedValue };
|
|
272
808
|
break;
|
|
273
809
|
case "contains":
|
|
274
|
-
whereConditions[
|
|
810
|
+
whereConditions[field_0] = { contains: normalizedValue };
|
|
275
811
|
break;
|
|
276
812
|
case "not_contains":
|
|
277
|
-
whereConditions[
|
|
813
|
+
whereConditions[field_0] = { notIlike: `%${normalizedValue}%` };
|
|
278
814
|
break;
|
|
279
815
|
case "starts_with":
|
|
280
|
-
whereConditions[
|
|
816
|
+
whereConditions[field_0] = { startsWith: normalizedValue };
|
|
281
817
|
break;
|
|
282
818
|
case "ends_with":
|
|
283
|
-
whereConditions[
|
|
819
|
+
whereConditions[field_0] = { endsWith: normalizedValue };
|
|
284
820
|
break;
|
|
285
821
|
case "greater_than":
|
|
286
|
-
whereConditions[
|
|
822
|
+
whereConditions[field_0] = { gt: normalizedValue };
|
|
287
823
|
break;
|
|
288
824
|
case "less_than":
|
|
289
|
-
whereConditions[
|
|
825
|
+
whereConditions[field_0] = { lt: normalizedValue };
|
|
290
826
|
break;
|
|
291
827
|
case "greater_than_or_equal":
|
|
292
|
-
whereConditions[
|
|
828
|
+
whereConditions[field_0] = { gte: normalizedValue };
|
|
293
829
|
break;
|
|
294
830
|
case "less_than_or_equal":
|
|
295
|
-
whereConditions[
|
|
831
|
+
whereConditions[field_0] = { lte: normalizedValue };
|
|
296
832
|
break;
|
|
297
833
|
case "in":
|
|
298
|
-
whereConditions[
|
|
834
|
+
whereConditions[field_0] = { in: Array.isArray(normalizedValue) ? normalizedValue : [normalizedValue] };
|
|
299
835
|
break;
|
|
300
836
|
case "not_in":
|
|
301
|
-
whereConditions[
|
|
837
|
+
whereConditions[field_0] = { notIn: Array.isArray(normalizedValue) ? normalizedValue : [normalizedValue] };
|
|
302
838
|
break;
|
|
303
839
|
case "is_empty":
|
|
304
|
-
whereConditions[
|
|
840
|
+
whereConditions[field_0] = { isNull: true };
|
|
305
841
|
break;
|
|
306
842
|
case "is_not_empty":
|
|
307
|
-
whereConditions[
|
|
843
|
+
whereConditions[field_0] = { isNotNull: true };
|
|
308
844
|
break;
|
|
309
845
|
}
|
|
310
846
|
}
|
|
311
847
|
options.where = whereConditions;
|
|
312
848
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
849
|
+
const groupBy = viewState.config.groupBy;
|
|
850
|
+
const sortConfig = effectiveSort;
|
|
851
|
+
if (groupBy && sortConfig?.field && sortConfig.field !== groupBy) options.orderBy = [{ [groupBy]: "asc" }, { [sortConfig.field]: sortConfig.direction }];
|
|
852
|
+
else if (groupBy) options.orderBy = { [groupBy]: sortConfig?.direction ?? "asc" };
|
|
853
|
+
else if (sortConfig) options.orderBy = { [sortConfig.field]: sortConfig.direction };
|
|
317
854
|
const pageSize = viewState.config.pagination?.pageSize ?? 25;
|
|
318
855
|
const page = viewState.config.pagination?.page ?? 1;
|
|
319
856
|
options.limit = pageSize;
|
|
@@ -323,7 +860,8 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
323
860
|
expandedFields,
|
|
324
861
|
viewState.config.filters,
|
|
325
862
|
viewState.config.includeDeleted,
|
|
326
|
-
viewState.config.
|
|
863
|
+
viewState.config.groupBy,
|
|
864
|
+
effectiveSort,
|
|
327
865
|
viewState.config.pagination?.page,
|
|
328
866
|
viewState.config.pagination?.pageSize,
|
|
329
867
|
resolvedFields,
|
|
@@ -341,18 +879,34 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
341
879
|
const { data: listData, isLoading: listLoading, error: listError } = useCollectionList(collection, queryOptions, { enabled: !isSearching }, { realtime: effectiveRealtime });
|
|
342
880
|
const isLoading = isSearching ? searchLoading : listLoading;
|
|
343
881
|
const isSearchActive = isSearching && searchFetching;
|
|
344
|
-
const { data: savedViewsData, isLoading: savedViewsLoading } = useSavedViews(collection);
|
|
345
|
-
const saveViewMutation = useSaveView(collection);
|
|
346
|
-
const deleteViewMutation = useDeleteSavedView(collection);
|
|
882
|
+
const { data: savedViewsData, isLoading: savedViewsLoading } = useSavedViews(collection, user?.id);
|
|
883
|
+
const saveViewMutation = useSaveView(collection, user?.id);
|
|
884
|
+
const deleteViewMutation = useDeleteSavedView(collection, user?.id);
|
|
347
885
|
const deleteMutation = useCollectionDelete(collection);
|
|
348
886
|
const restoreMutation = useCollectionRestore(collection);
|
|
887
|
+
const updateBatchMutation = useCollectionUpdateBatch(collection);
|
|
349
888
|
const availableFields = useMemo(() => {
|
|
350
889
|
return getAllAvailableFields(resolvedFields, { meta: collectionMeta });
|
|
351
890
|
}, [resolvedFields, collectionMeta]);
|
|
891
|
+
const groupableFields = useMemo(() => {
|
|
892
|
+
const groupableNames = groupingConfig?.fields ?? [];
|
|
893
|
+
if (groupableNames.length === 0) return [];
|
|
894
|
+
const groupableSet = new Set(groupableNames);
|
|
895
|
+
return availableFields.filter((field_1) => groupableSet.has(field_1.name));
|
|
896
|
+
}, [availableFields, groupingConfig?.fields]);
|
|
352
897
|
const visibleColumnDefs = useMemo(() => {
|
|
353
898
|
const selectCol = {
|
|
354
899
|
id: "_select",
|
|
355
900
|
header: ({ table: t_0 }) => {
|
|
901
|
+
if (isReorderMode) return /* @__PURE__ */ jsx("div", {
|
|
902
|
+
className: "text-muted-foreground/60 flex h-8 items-center justify-center",
|
|
903
|
+
title: "Order",
|
|
904
|
+
"aria-label": "Order",
|
|
905
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
906
|
+
icon: "ph:dots-six-vertical",
|
|
907
|
+
className: "size-3.5"
|
|
908
|
+
})
|
|
909
|
+
});
|
|
356
910
|
const isAllSelected = t_0.getIsAllPageRowsSelected();
|
|
357
911
|
const isSomeSelected = t_0.getIsSomePageRowsSelected();
|
|
358
912
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -368,6 +922,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
368
922
|
});
|
|
369
923
|
},
|
|
370
924
|
cell: ({ row }) => {
|
|
925
|
+
if (isReorderMode) return /* @__PURE__ */ jsx(ReorderHandle, {});
|
|
371
926
|
return /* @__PURE__ */ jsx("div", {
|
|
372
927
|
role: "presentation",
|
|
373
928
|
onClick: (e_1) => e_1.stopPropagation(),
|
|
@@ -400,15 +955,46 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
400
955
|
const col = columnMap.get(colName);
|
|
401
956
|
if (col) orderedColumns.push(col);
|
|
402
957
|
}
|
|
958
|
+
if (actions.row.length > 0) orderedColumns.push({
|
|
959
|
+
id: "_actions",
|
|
960
|
+
header: () => /* @__PURE__ */ jsx("span", {
|
|
961
|
+
className: "sr-only",
|
|
962
|
+
children: t("common.actions")
|
|
963
|
+
}),
|
|
964
|
+
cell: ({ row: row_0 }) => /* @__PURE__ */ jsx("div", {
|
|
965
|
+
role: "presentation",
|
|
966
|
+
className: "flex justify-end gap-1",
|
|
967
|
+
onClick: (event) => event.stopPropagation(),
|
|
968
|
+
onKeyDown: (event_0) => event_0.stopPropagation(),
|
|
969
|
+
children: actions.row.map((action) => /* @__PURE__ */ jsx(ActionButton, {
|
|
970
|
+
action,
|
|
971
|
+
collection,
|
|
972
|
+
item: row_0.original,
|
|
973
|
+
helpers: actionHelpers,
|
|
974
|
+
size: "icon-sm",
|
|
975
|
+
iconOnly: true,
|
|
976
|
+
onOpenDialog: (dialogAction_0) => openDialog(dialogAction_0, row_0.original)
|
|
977
|
+
}, action.id))
|
|
978
|
+
}),
|
|
979
|
+
size: 72,
|
|
980
|
+
enableSorting: false,
|
|
981
|
+
enableHiding: false
|
|
982
|
+
});
|
|
403
983
|
return orderedColumns;
|
|
404
984
|
}, [
|
|
405
985
|
columns,
|
|
406
986
|
viewState.config.visibleColumns,
|
|
407
987
|
defaultColumns,
|
|
408
|
-
collectionMeta
|
|
988
|
+
collectionMeta,
|
|
989
|
+
isReorderMode,
|
|
990
|
+
actions.row,
|
|
991
|
+
collection,
|
|
992
|
+
actionHelpers,
|
|
993
|
+
openDialog,
|
|
994
|
+
t
|
|
409
995
|
]);
|
|
410
996
|
const [sorting, setSorting] = React.useState(() => {
|
|
411
|
-
const sortSource =
|
|
997
|
+
const sortSource = effectiveSort;
|
|
412
998
|
if (sortSource?.field) return [{
|
|
413
999
|
id: sortSource.field,
|
|
414
1000
|
desc: sortSource.direction === "desc"
|
|
@@ -439,7 +1025,78 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
439
1025
|
resource: collection,
|
|
440
1026
|
realtime: effectiveRealtime
|
|
441
1027
|
});
|
|
442
|
-
|
|
1028
|
+
React.useEffect(() => {
|
|
1029
|
+
if (!isReorderMode) {
|
|
1030
|
+
setOptimisticOrderIds(null);
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
setOptimisticOrderIds((current) => {
|
|
1034
|
+
const itemIds = items.map((item_0) => String(item_0.id));
|
|
1035
|
+
if (!current) return itemIds;
|
|
1036
|
+
const knownIds = new Set(itemIds);
|
|
1037
|
+
const next = current.filter((id) => knownIds.has(id));
|
|
1038
|
+
for (const id_0 of itemIds) if (!next.includes(id_0)) next.push(id_0);
|
|
1039
|
+
return next;
|
|
1040
|
+
});
|
|
1041
|
+
}, [isReorderMode, items]);
|
|
1042
|
+
const filteredItems = useMemo(() => {
|
|
1043
|
+
if (!isReorderMode || !optimisticOrderIds) return items;
|
|
1044
|
+
const itemsById = new Map(items.map((item_1) => [String(item_1.id), item_1]));
|
|
1045
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1046
|
+
const ordered = optimisticOrderIds.map((id_1) => {
|
|
1047
|
+
const item_2 = itemsById.get(id_1);
|
|
1048
|
+
if (item_2) seen.add(id_1);
|
|
1049
|
+
return item_2;
|
|
1050
|
+
}).filter(Boolean);
|
|
1051
|
+
for (const item_3 of items) {
|
|
1052
|
+
const id_2 = String(item_3.id);
|
|
1053
|
+
if (!seen.has(id_2)) ordered.push(item_3);
|
|
1054
|
+
}
|
|
1055
|
+
return ordered;
|
|
1056
|
+
}, [
|
|
1057
|
+
isReorderMode,
|
|
1058
|
+
items,
|
|
1059
|
+
optimisticOrderIds
|
|
1060
|
+
]);
|
|
1061
|
+
const hasActiveFilters = viewState.config.filters.length > 0;
|
|
1062
|
+
const isOrderSortActive = canUseOrderableSort && effectiveSort?.field === orderField && (effectiveSort.direction ?? "asc") === orderDirection;
|
|
1063
|
+
const hasMultiplePages = !isSearching && (listData?.totalPages ?? 1) > 1;
|
|
1064
|
+
const reorderHardBlocker = !isOrderableEnabled ? t("collection.reorderEnableOrderable") : !hasOrderField ? t("collection.reorderAddOrderField") : isSearching ? t("collection.reorderClearSearch") : viewState.config.groupBy ? t("collection.reorderRemoveGrouping") : hasActiveFilters ? t("collection.reorderClearFilters") : hasMultiplePages ? t("collection.reorderShowOnePage") : null;
|
|
1065
|
+
const reorderTooltip = reorderHardBlocker ?? (isOrderSortActive ? isReorderMode ? t("collection.reorderExitMode") : t("collection.reorderItems") : t("collection.reorderSwitchSort", { field: orderField }));
|
|
1066
|
+
const reorderAriaLabel = reorderHardBlocker ? t("collection.reorderUnavailable", { reason: reorderHardBlocker }) : isReorderMode ? t("collection.reorderExitMode") : t("collection.reorderEnterMode");
|
|
1067
|
+
const canReorder = isOrderableEnabled && !reorderHardBlocker;
|
|
1068
|
+
const handleReorderToggle = React.useCallback(() => {
|
|
1069
|
+
if (!canReorder) return;
|
|
1070
|
+
if (!isOrderSortActive) {
|
|
1071
|
+
const nextSort = {
|
|
1072
|
+
field: orderField,
|
|
1073
|
+
direction: orderDirection
|
|
1074
|
+
};
|
|
1075
|
+
setSorting([{
|
|
1076
|
+
id: nextSort.field,
|
|
1077
|
+
desc: nextSort.direction === "desc"
|
|
1078
|
+
}]);
|
|
1079
|
+
viewState.setSort(nextSort);
|
|
1080
|
+
setIsReorderMode(true);
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
setIsReorderMode((active) => !active);
|
|
1084
|
+
}, [
|
|
1085
|
+
canReorder,
|
|
1086
|
+
isOrderSortActive,
|
|
1087
|
+
orderDirection,
|
|
1088
|
+
viewState
|
|
1089
|
+
]);
|
|
1090
|
+
const hasViewOptionsState = hasActiveFilters || !!viewState.config.groupBy || viewState.config.visibleColumns.length !== defaultColumns.length || !!viewState.config.includeDeleted;
|
|
1091
|
+
const clearFilters = () => {
|
|
1092
|
+
viewState.setConfig({
|
|
1093
|
+
...viewState.config,
|
|
1094
|
+
filters: []
|
|
1095
|
+
});
|
|
1096
|
+
};
|
|
1097
|
+
React.useEffect(() => {
|
|
1098
|
+
if (isReorderMode && !canReorder) setIsReorderMode(false);
|
|
1099
|
+
}, [isReorderMode, canReorder]);
|
|
443
1100
|
const table = useReactTable({
|
|
444
1101
|
data: filteredItems,
|
|
445
1102
|
columns: visibleColumnDefs,
|
|
@@ -448,12 +1105,154 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
448
1105
|
onSortingChange: handleSortingChange,
|
|
449
1106
|
enableRowSelection: true,
|
|
450
1107
|
onRowSelectionChange: setRowSelection,
|
|
451
|
-
getRowId: (
|
|
1108
|
+
getRowId: (row_1) => row_1.id,
|
|
452
1109
|
state: {
|
|
453
1110
|
sorting,
|
|
454
1111
|
rowSelection
|
|
455
1112
|
}
|
|
456
1113
|
});
|
|
1114
|
+
const tableRows = table.getRowModel().rows;
|
|
1115
|
+
const visibleLeafColumns = table.getVisibleLeafColumns();
|
|
1116
|
+
const selectColumnWidth = getColumnSize(visibleLeafColumns[0], 40);
|
|
1117
|
+
const titleColumnWidth = getColumnSize(visibleLeafColumns[1], 360);
|
|
1118
|
+
const sortableRowIds = useMemo(() => tableRows.map((row_2) => String(row_2.id)), [tableRows]);
|
|
1119
|
+
const activeReorderRow = useMemo(() => activeReorderId ? tableRows.find((row_3) => String(row_3.id) === activeReorderId) : null, [activeReorderId, tableRows]);
|
|
1120
|
+
const reorderSensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
1121
|
+
const handleReorderDragStart = React.useCallback((event_1) => {
|
|
1122
|
+
const initialRect = event_1.active.rect.current.initial;
|
|
1123
|
+
clearReorderOverlay();
|
|
1124
|
+
reorderStartOrderIdsRef.current = sortableRowIds;
|
|
1125
|
+
setActiveReorderId(String(event_1.active.id));
|
|
1126
|
+
setActiveReorderRect(initialRect ? {
|
|
1127
|
+
width: initialRect.width,
|
|
1128
|
+
height: initialRect.height
|
|
1129
|
+
} : null);
|
|
1130
|
+
setOptimisticOrderIds((current_0) => current_0 ?? sortableRowIds);
|
|
1131
|
+
}, [clearReorderOverlay, sortableRowIds]);
|
|
1132
|
+
const handleReorderDragCancel = React.useCallback(() => {
|
|
1133
|
+
setOptimisticOrderIds(reorderStartOrderIdsRef.current);
|
|
1134
|
+
clearReorderOverlay();
|
|
1135
|
+
reorderStartOrderIdsRef.current = null;
|
|
1136
|
+
}, [clearReorderOverlay]);
|
|
1137
|
+
const handleReorderDragEnd = React.useCallback(async (event_2) => {
|
|
1138
|
+
if (updateBatchMutation.isPending) {
|
|
1139
|
+
clearReorderOverlay();
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
const { active: active_0, over } = event_2;
|
|
1143
|
+
const previousOrderIds = reorderStartOrderIdsRef.current ?? sortableRowIds;
|
|
1144
|
+
reorderStartOrderIdsRef.current = null;
|
|
1145
|
+
if (!over) {
|
|
1146
|
+
setOptimisticOrderIds(previousOrderIds);
|
|
1147
|
+
clearReorderOverlay();
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
let nextOrderIds = previousOrderIds;
|
|
1151
|
+
if (active_0.id !== over.id) {
|
|
1152
|
+
const oldIndex = previousOrderIds.indexOf(String(active_0.id));
|
|
1153
|
+
const newIndex = previousOrderIds.indexOf(String(over.id));
|
|
1154
|
+
if (oldIndex === -1 || newIndex === -1 || oldIndex === newIndex) {
|
|
1155
|
+
clearReorderOverlay(REORDER_DROP_DURATION);
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
nextOrderIds = arrayMove(previousOrderIds, oldIndex, newIndex);
|
|
1159
|
+
}
|
|
1160
|
+
if (nextOrderIds.join("\0") === previousOrderIds.join("\0")) {
|
|
1161
|
+
clearReorderOverlay(REORDER_DROP_DURATION);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
setOptimisticOrderIds(nextOrderIds);
|
|
1165
|
+
clearReorderOverlay(REORDER_DROP_DURATION);
|
|
1166
|
+
const rowsById = new Map(tableRows.map((row_4) => [String(row_4.id), row_4]));
|
|
1167
|
+
const reorderedRows = nextOrderIds.map((id_3) => rowsById.get(id_3)).filter((row_5) => !!row_5);
|
|
1168
|
+
try {
|
|
1169
|
+
await updateBatchMutation.mutateAsync({ updates: reorderedRows.map((row_6, index) => ({
|
|
1170
|
+
id: String(row_6.id),
|
|
1171
|
+
data: { [orderField]: (index + 1) * orderStep }
|
|
1172
|
+
})) });
|
|
1173
|
+
actionHelpers.toast.success(t("collection.orderSaved"));
|
|
1174
|
+
} catch (error) {
|
|
1175
|
+
clearReorderOverlay();
|
|
1176
|
+
setOptimisticOrderIds(previousOrderIds);
|
|
1177
|
+
actionHelpers.toast.error(error instanceof Error ? error.message : t("collection.orderSaveFailed"));
|
|
1178
|
+
}
|
|
1179
|
+
}, [
|
|
1180
|
+
sortableRowIds,
|
|
1181
|
+
tableRows,
|
|
1182
|
+
updateBatchMutation,
|
|
1183
|
+
orderField,
|
|
1184
|
+
orderStep,
|
|
1185
|
+
t,
|
|
1186
|
+
actionHelpers.toast,
|
|
1187
|
+
clearReorderOverlay
|
|
1188
|
+
]);
|
|
1189
|
+
const groupedRowModel = useMemo(() => {
|
|
1190
|
+
const rows = tableRows;
|
|
1191
|
+
const groupBy_0 = viewState.config.groupBy;
|
|
1192
|
+
if (!groupBy_0) return rows.map((row_7) => ({
|
|
1193
|
+
type: "row",
|
|
1194
|
+
row: row_7
|
|
1195
|
+
}));
|
|
1196
|
+
const groupField = groupableFields.find((field_2) => field_2.name === groupBy_0);
|
|
1197
|
+
const collapsedGroups = new Set(viewState.config.collapsedGroups ?? []);
|
|
1198
|
+
const serverGroups = !isSearching ? listData?.groups : void 0;
|
|
1199
|
+
if (serverGroups?.length) {
|
|
1200
|
+
const rowsById_0 = new Map(rows.map((row_8) => [row_8.id, row_8]));
|
|
1201
|
+
return serverGroups.flatMap((group) => {
|
|
1202
|
+
const label = stringifyGroupValue(group.value, groupField, resolveText, t("common.noValue"));
|
|
1203
|
+
const groupKey = `${groupBy_0}:${label}`;
|
|
1204
|
+
const collapsed = collapsedGroups.has(groupKey);
|
|
1205
|
+
const groupRows = (group.docs ?? []).map((doc) => rowsById_0.get(String(doc.id))).filter(Boolean);
|
|
1206
|
+
return [{
|
|
1207
|
+
type: "group",
|
|
1208
|
+
key: groupKey,
|
|
1209
|
+
label,
|
|
1210
|
+
count: group.count,
|
|
1211
|
+
collapsed
|
|
1212
|
+
}, ...collapsed ? [] : groupRows.map((row_9) => ({
|
|
1213
|
+
type: "row",
|
|
1214
|
+
row: row_9
|
|
1215
|
+
}))];
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1219
|
+
for (const row_10 of rows) {
|
|
1220
|
+
const valueLabel = stringifyGroupValue(row_10.original?.[groupBy_0], groupField, resolveText, t("common.noValue"));
|
|
1221
|
+
const groupKey_0 = `${groupBy_0}:${valueLabel}`;
|
|
1222
|
+
const group_0 = groups.get(groupKey_0);
|
|
1223
|
+
if (group_0) {
|
|
1224
|
+
group_0.rows.push(row_10);
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
groups.set(groupKey_0, {
|
|
1228
|
+
label: valueLabel,
|
|
1229
|
+
rows: [row_10],
|
|
1230
|
+
sortIndex: getGroupSortIndex(row_10.original?.[groupBy_0], groupField)
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
return Array.from(groups.entries()).sort(([, a], [, b]) => a.sortIndex - b.sortIndex).flatMap(([key_0, group_1]) => {
|
|
1234
|
+
const collapsed_0 = collapsedGroups.has(key_0);
|
|
1235
|
+
return [{
|
|
1236
|
+
type: "group",
|
|
1237
|
+
key: key_0,
|
|
1238
|
+
label: group_1.label,
|
|
1239
|
+
count: group_1.rows.length,
|
|
1240
|
+
collapsed: collapsed_0
|
|
1241
|
+
}, ...collapsed_0 ? [] : group_1.rows.map((row_11) => ({
|
|
1242
|
+
type: "row",
|
|
1243
|
+
row: row_11
|
|
1244
|
+
}))];
|
|
1245
|
+
});
|
|
1246
|
+
}, [
|
|
1247
|
+
tableRows,
|
|
1248
|
+
viewState.config.groupBy,
|
|
1249
|
+
viewState.config.collapsedGroups,
|
|
1250
|
+
groupableFields,
|
|
1251
|
+
isSearching,
|
|
1252
|
+
listData?.groups,
|
|
1253
|
+
resolveText,
|
|
1254
|
+
t
|
|
1255
|
+
]);
|
|
457
1256
|
const handleSaveView = (name, config_0) => {
|
|
458
1257
|
saveViewMutation.mutate({
|
|
459
1258
|
name,
|
|
@@ -463,11 +1262,11 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
463
1262
|
const handleDeleteView = (viewId) => {
|
|
464
1263
|
deleteViewMutation.mutate(viewId);
|
|
465
1264
|
};
|
|
466
|
-
const handleRowClick = (
|
|
467
|
-
navigate(`${basePath}/collections/${collection}/${
|
|
1265
|
+
const handleRowClick = (item_4) => {
|
|
1266
|
+
navigate(`${basePath}/collections/${collection}/${item_4.id}`);
|
|
468
1267
|
};
|
|
469
1268
|
const handleBulkDelete = React.useCallback(async (ids_0) => {
|
|
470
|
-
const results = await Promise.allSettled(ids_0.map((
|
|
1269
|
+
const results = await Promise.allSettled(ids_0.map((id_4) => deleteMutation.mutateAsync({ id: id_4 })));
|
|
471
1270
|
const successCount = results.filter((r) => r.status === "fulfilled").length;
|
|
472
1271
|
const failCount = results.filter((r_0) => r_0.status === "rejected").length;
|
|
473
1272
|
if (failCount === 0) actionHelpers.toast.success(t("collection.bulkDeleteSuccess", { count: successCount }));
|
|
@@ -482,7 +1281,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
482
1281
|
t
|
|
483
1282
|
]);
|
|
484
1283
|
const handleBulkRestore = React.useCallback(async (ids_1) => {
|
|
485
|
-
const results_0 = await Promise.allSettled(ids_1.map((
|
|
1284
|
+
const results_0 = await Promise.allSettled(ids_1.map((id_5) => restoreMutation.mutateAsync({ id: id_5 })));
|
|
486
1285
|
const successCount_0 = results_0.filter((r_1) => r_1.status === "fulfilled").length;
|
|
487
1286
|
const failCount_0 = results_0.filter((r_2) => r_2.status === "rejected").length;
|
|
488
1287
|
if (failCount_0 === 0) actionHelpers.toast.success(t("collection.bulkRestoreSuccess", { count: successCount_0 }));
|
|
@@ -496,100 +1295,157 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
496
1295
|
actionHelpers,
|
|
497
1296
|
t
|
|
498
1297
|
]);
|
|
499
|
-
if (listError && !isSearching)
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
className: "
|
|
503
|
-
children:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
children: listError instanceof Error ? listError.message : t("errors.failedToLoad")
|
|
511
|
-
}),
|
|
512
|
-
/* @__PURE__ */ jsx(Button, {
|
|
1298
|
+
if (listError && !isSearching) {
|
|
1299
|
+
const errorMessage = listError instanceof Error ? listError.message : void 0;
|
|
1300
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1301
|
+
className: "container",
|
|
1302
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
1303
|
+
variant: "error",
|
|
1304
|
+
iconName: "ph:warning-circle",
|
|
1305
|
+
title: t("error.failedToLoad"),
|
|
1306
|
+
description: errorMessage,
|
|
1307
|
+
height: "h-64",
|
|
1308
|
+
action: /* @__PURE__ */ jsxs(Button, {
|
|
513
1309
|
variant: "outline",
|
|
514
1310
|
size: "sm",
|
|
1311
|
+
className: "gap-2",
|
|
515
1312
|
onClick: () => window.location.reload(),
|
|
516
|
-
children:
|
|
1313
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1314
|
+
icon: "ph:arrow-clockwise",
|
|
1315
|
+
className: "size-3.5"
|
|
1316
|
+
}), t("common.retry")]
|
|
517
1317
|
})
|
|
518
|
-
|
|
519
|
-
})
|
|
520
|
-
}
|
|
521
|
-
if (isLoading) return /* @__PURE__ */ jsx(
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
1318
|
+
})
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
if (isLoading) return /* @__PURE__ */ jsx(TableViewSkeleton, {});
|
|
1322
|
+
const emptyStateTitle = isSearching || hasActiveFilters ? t("collectionSearch.noResults") : t("table.noItemsInCollection");
|
|
1323
|
+
const emptyStateDescription = isSearching ? t("collectionSearch.noResultsDescription") : hasActiveFilters ? t("viewOptions.noResultsDescription") : t("table.emptyDescription");
|
|
1324
|
+
const emptyStateAction = isSearching || hasActiveFilters ? /* @__PURE__ */ jsxs(Fragment, { children: [isSearching && /* @__PURE__ */ jsxs(Button, {
|
|
1325
|
+
variant: "outline",
|
|
1326
|
+
size: "sm",
|
|
1327
|
+
className: "gap-2",
|
|
1328
|
+
onClick: () => setSearchTerm(""),
|
|
1329
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1330
|
+
icon: "ph:x",
|
|
1331
|
+
className: "size-3.5"
|
|
1332
|
+
}), t("common.clear")]
|
|
1333
|
+
}), hasActiveFilters && /* @__PURE__ */ jsxs(Button, {
|
|
1334
|
+
variant: "outline",
|
|
1335
|
+
size: "sm",
|
|
1336
|
+
className: "gap-2",
|
|
1337
|
+
onClick: clearFilters,
|
|
1338
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1339
|
+
icon: "ph:funnel-x",
|
|
1340
|
+
className: "size-3.5"
|
|
1341
|
+
}), t("viewOptions.clearFilters")]
|
|
1342
|
+
})] }) : void 0;
|
|
1343
|
+
return /* @__PURE__ */ jsx(AdminViewLayout, {
|
|
1344
|
+
header: /* @__PURE__ */ jsx(AdminViewHeader, {
|
|
1345
|
+
title: resolveText(config?.label ?? schema?.admin?.config?.label, collection),
|
|
1346
|
+
titleAccessory: localeOptions.length > 0 ? /* @__PURE__ */ jsx(LocaleSwitcher, {
|
|
1347
|
+
locales: localeOptions,
|
|
1348
|
+
value: contentLocale,
|
|
1349
|
+
onChange: setContentLocale
|
|
1350
|
+
}) : void 0,
|
|
1351
|
+
description: resolveText(config?.description ?? schema?.admin?.config?.description),
|
|
1352
|
+
actions: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1353
|
+
isOrderableEnabled && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Button, {
|
|
1354
|
+
variant: "outline",
|
|
1355
|
+
size: "icon-sm",
|
|
1356
|
+
className: cn("relative aria-disabled:opacity-50", isReorderMode && "border-foreground bg-foreground text-background hover:bg-foreground/90 hover:text-background"),
|
|
1357
|
+
onClick: handleReorderToggle,
|
|
1358
|
+
"aria-label": reorderAriaLabel,
|
|
1359
|
+
"aria-disabled": !canReorder || void 0,
|
|
1360
|
+
"aria-pressed": isReorderMode,
|
|
1361
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "ph:arrows-down-up" })
|
|
1362
|
+
}) }), /* @__PURE__ */ jsx(TooltipContent, {
|
|
1363
|
+
side: "bottom",
|
|
1364
|
+
align: "end",
|
|
1365
|
+
children: reorderTooltip
|
|
1366
|
+
})] }),
|
|
1367
|
+
showSearch && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsxs(Button, {
|
|
1368
|
+
variant: "outline",
|
|
1369
|
+
size: "icon-sm",
|
|
1370
|
+
className: "relative",
|
|
1371
|
+
onClick: () => setIsSearchPanelOpen((open) => !open),
|
|
1372
|
+
"aria-label": t("common.search"),
|
|
1373
|
+
children: [/* @__PURE__ */ jsx(Icon, { icon: "ph:magnifying-glass" }), searchTerm && /* @__PURE__ */ jsx("span", { className: "bg-foreground absolute top-1 right-1 size-1.5 rounded-full" })]
|
|
1374
|
+
}) }), /* @__PURE__ */ jsx(TooltipContent, {
|
|
1375
|
+
side: "bottom",
|
|
1376
|
+
align: "end",
|
|
1377
|
+
children: t("common.search")
|
|
1378
|
+
})] }),
|
|
1379
|
+
showFilters && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsxs(Button, {
|
|
1380
|
+
variant: "outline",
|
|
1381
|
+
size: "icon-sm",
|
|
1382
|
+
className: "relative",
|
|
1383
|
+
onClick: () => setIsSheetOpen(true),
|
|
1384
|
+
"aria-label": t("viewOptions.title"),
|
|
1385
|
+
children: [/* @__PURE__ */ jsx(Icon, { icon: "ph:sliders-horizontal" }), hasViewOptionsState && /* @__PURE__ */ jsx("span", { className: "bg-foreground absolute top-1 right-1 size-1.5 rounded-full" })]
|
|
1386
|
+
}) }), /* @__PURE__ */ jsx(TooltipContent, {
|
|
1387
|
+
side: "bottom",
|
|
1388
|
+
align: "end",
|
|
1389
|
+
children: t("viewOptions.title")
|
|
1390
|
+
})] }),
|
|
1391
|
+
canUploadToCollection && /* @__PURE__ */ jsx(UploadCollectionButton, {
|
|
1392
|
+
collection,
|
|
1393
|
+
onUploaded: () => actionHelpers.invalidateCollection(collection)
|
|
1394
|
+
}),
|
|
1395
|
+
headerActions,
|
|
1396
|
+
((actions.header.primary?.length ?? 0) > 0 || (actions.header.secondary?.length ?? 0) > 0) && /* @__PURE__ */ jsx(HeaderActions, {
|
|
1397
|
+
actions: actions.header,
|
|
1398
|
+
collection,
|
|
1399
|
+
helpers: actionHelpers,
|
|
1400
|
+
onOpenDialog: (action_0) => openDialog(action_0)
|
|
1401
|
+
})
|
|
1402
|
+
] })
|
|
1403
|
+
}),
|
|
1404
|
+
contentClassName: "overflow-y-auto pb-3",
|
|
539
1405
|
children: /* @__PURE__ */ jsxs("div", {
|
|
540
|
-
className: "qa-table-
|
|
1406
|
+
className: "qa-table-view min-w-0 space-y-4",
|
|
541
1407
|
children: [
|
|
542
|
-
/* @__PURE__ */
|
|
543
|
-
className: "
|
|
1408
|
+
showToolbar && showSearch && (isSearchPanelOpen || searchTerm) && /* @__PURE__ */ jsx("div", {
|
|
1409
|
+
className: "max-w-xl",
|
|
1410
|
+
children: /* @__PURE__ */ jsx(SearchInput, {
|
|
1411
|
+
value: searchTerm,
|
|
1412
|
+
onChange: (e_3) => setSearchTerm(e_3.target.value),
|
|
1413
|
+
onClear: () => setSearchTerm(""),
|
|
1414
|
+
placeholder: t("common.search"),
|
|
1415
|
+
containerClassName: "h-10"
|
|
1416
|
+
})
|
|
1417
|
+
}),
|
|
1418
|
+
isReorderMode && canUseOrderableSort && /* @__PURE__ */ jsxs("div", {
|
|
1419
|
+
className: "border-border/70 bg-muted/30 text-muted-foreground flex min-h-10 items-center justify-between gap-3 border-y px-3 py-2 font-mono text-xs",
|
|
544
1420
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
545
|
-
className: "min-w-0
|
|
546
|
-
children: [
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
1421
|
+
className: "flex min-w-0 items-center gap-2",
|
|
1422
|
+
children: [
|
|
1423
|
+
/* @__PURE__ */ jsx("span", {
|
|
1424
|
+
className: "bg-foreground text-background inline-flex size-5 items-center justify-center rounded-full",
|
|
1425
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
1426
|
+
icon: "ph:arrows-down-up",
|
|
1427
|
+
className: "size-3"
|
|
1428
|
+
})
|
|
1429
|
+
}),
|
|
1430
|
+
/* @__PURE__ */ jsx("span", {
|
|
1431
|
+
className: "text-foreground font-medium",
|
|
1432
|
+
children: t("collection.reorderMode")
|
|
1433
|
+
}),
|
|
1434
|
+
/* @__PURE__ */ jsx("span", {
|
|
1435
|
+
className: "hidden sm:inline",
|
|
1436
|
+
children: t("collection.sortedByField", {
|
|
1437
|
+
field: orderField,
|
|
1438
|
+
direction: orderDirection
|
|
1439
|
+
})
|
|
1440
|
+
})
|
|
1441
|
+
]
|
|
1442
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
1443
|
+
variant: "ghost",
|
|
1444
|
+
size: "xs",
|
|
1445
|
+
onClick: () => setIsReorderMode(false),
|
|
1446
|
+
children: t("common.done")
|
|
568
1447
|
})]
|
|
569
1448
|
}),
|
|
570
|
-
showToolbar && /* @__PURE__ */ jsx("div", {
|
|
571
|
-
className: "space-y-2",
|
|
572
|
-
children: /* @__PURE__ */ jsxs(Toolbar, { children: [showSearch && /* @__PURE__ */ jsx(ToolbarSection, {
|
|
573
|
-
className: "flex-1",
|
|
574
|
-
children: /* @__PURE__ */ jsx(SearchInput, {
|
|
575
|
-
value: searchTerm,
|
|
576
|
-
onChange: (e_3) => setSearchTerm(e_3.target.value),
|
|
577
|
-
onClear: () => setSearchTerm(""),
|
|
578
|
-
placeholder: t("common.search"),
|
|
579
|
-
containerClassName: "border-none bg-transparent dark:bg-transparent"
|
|
580
|
-
})
|
|
581
|
-
}), showFilters && /* @__PURE__ */ jsxs(Fragment, { children: [showSearch && /* @__PURE__ */ jsx(ToolbarSeparator, {}), /* @__PURE__ */ jsx(ToolbarSection, { children: /* @__PURE__ */ jsxs(Button, {
|
|
582
|
-
variant: "outline",
|
|
583
|
-
size: "sm",
|
|
584
|
-
onClick: () => setIsSheetOpen(true),
|
|
585
|
-
className: "gap-2",
|
|
586
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
587
|
-
icon: "ph:sliders-horizontal",
|
|
588
|
-
width: 16,
|
|
589
|
-
height: 16
|
|
590
|
-
}), t("viewOptions.title")]
|
|
591
|
-
}) })] })] })
|
|
592
|
-
}),
|
|
593
1449
|
/* @__PURE__ */ jsx(BulkActionToolbar, {
|
|
594
1450
|
table,
|
|
595
1451
|
actions: actions.bulk,
|
|
@@ -597,104 +1453,178 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
597
1453
|
helpers: actionHelpers,
|
|
598
1454
|
totalCount: isSearching ? searchData?.total : listData?.totalDocs,
|
|
599
1455
|
pageCount: filteredItems.length,
|
|
600
|
-
onOpenDialog: (
|
|
1456
|
+
onOpenDialog: (action_1, items_0) => openDialog(action_1, items_0),
|
|
601
1457
|
onBulkDelete: handleBulkDelete,
|
|
602
1458
|
onBulkRestore: handleBulkRestore,
|
|
603
1459
|
filterCount: viewState.config.filters.length,
|
|
604
1460
|
onOpenFilters: () => setIsSheetOpen(true),
|
|
605
|
-
onClearFilters:
|
|
606
|
-
...viewState.config,
|
|
607
|
-
filters: []
|
|
608
|
-
})
|
|
1461
|
+
onClearFilters: clearFilters
|
|
609
1462
|
}),
|
|
610
1463
|
/* @__PURE__ */ jsxs("div", {
|
|
611
|
-
className: "qa-table-view__table-wrapper
|
|
612
|
-
children: [/* @__PURE__ */
|
|
613
|
-
|
|
614
|
-
children:
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
"
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
return /* @__PURE__ */ jsx(TableRow, {
|
|
642
|
-
"data-state": row_1.getIsSelected() && "selected",
|
|
643
|
-
className: cn("group", isHighlighted(row_1.id) && "animate-realtime-pulse", isRowDeleted && "opacity-50"),
|
|
644
|
-
children: row_1.getVisibleCells().map((cell, cellIndex) => {
|
|
645
|
-
return /* @__PURE__ */ jsx(TableCell, {
|
|
646
|
-
stickyLeft: cellIndex === 0 ? 0 : cellIndex === 1 ? 36 : void 0,
|
|
647
|
-
showStickyBorder: cellIndex === 1,
|
|
648
|
-
className: cellIndex === 0 ? "w-9 min-w-9 px-1.5" : void 0,
|
|
649
|
-
children: cellIndex === 1 ? /* @__PURE__ */ jsxs("div", {
|
|
650
|
-
className: "flex items-center gap-2",
|
|
651
|
-
children: [
|
|
652
|
-
/* @__PURE__ */ jsx("button", {
|
|
1464
|
+
className: "qa-table-view__table-wrapper min-w-0",
|
|
1465
|
+
children: [/* @__PURE__ */ jsx(ScrollFade, {
|
|
1466
|
+
leftInset: selectColumnWidth + titleColumnWidth,
|
|
1467
|
+
children: /* @__PURE__ */ jsxs(DndContext, {
|
|
1468
|
+
sensors: reorderSensors,
|
|
1469
|
+
collisionDetection: closestCenter,
|
|
1470
|
+
onDragStart: handleReorderDragStart,
|
|
1471
|
+
onDragCancel: handleReorderDragCancel,
|
|
1472
|
+
onDragEnd: handleReorderDragEnd,
|
|
1473
|
+
children: [/* @__PURE__ */ jsxs(Table, {
|
|
1474
|
+
className: "table-fixed",
|
|
1475
|
+
style: { width: table.getTotalSize() },
|
|
1476
|
+
"aria-label": resolveText(config?.label ?? schema?.admin?.config?.label, collection),
|
|
1477
|
+
children: [
|
|
1478
|
+
/* @__PURE__ */ jsx("colgroup", { children: visibleLeafColumns.map((column) => /* @__PURE__ */ jsx("col", { style: { width: column.getSize() } }, column.id)) }),
|
|
1479
|
+
/* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, {
|
|
1480
|
+
className: "hover:bg-transparent",
|
|
1481
|
+
children: headerGroup.headers.map((header, headerIndex) => {
|
|
1482
|
+
const isCheckboxCol = headerIndex === 0;
|
|
1483
|
+
const columnWidth = getColumnSize(header.column, isCheckboxCol ? 40 : 120);
|
|
1484
|
+
const stickyLeft = headerIndex < STICKY_TABLE_COLUMN_COUNT ? getStickyLeftOffset(visibleLeafColumns, headerIndex) : void 0;
|
|
1485
|
+
const sortDirection = header.column.getIsSorted();
|
|
1486
|
+
const ariaSort = header.column.getCanSort() ? sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none" : void 0;
|
|
1487
|
+
return /* @__PURE__ */ jsx(TableHead, {
|
|
1488
|
+
stickyLeft,
|
|
1489
|
+
showStickyBorder: headerIndex === STICKY_TABLE_COLUMN_COUNT - 1,
|
|
1490
|
+
className: isCheckboxCol ? "w-9 min-w-9 px-1.5" : void 0,
|
|
1491
|
+
style: getColumnSizeStyle(columnWidth),
|
|
1492
|
+
"aria-sort": ariaSort,
|
|
1493
|
+
children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs("button", {
|
|
653
1494
|
type: "button",
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
1495
|
+
className: header.column.getCanSort() ? "hover:text-foreground focus-visible:ring-ring/40 -mx-1.5 flex min-h-7 cursor-pointer items-center gap-2 rounded-md px-1.5 transition-colors select-none focus-visible:ring-2 focus-visible:outline-none" : "",
|
|
1496
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
1497
|
+
"aria-label": header.column.getCanSort() ? `Sort by ${typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : header.column.id}` : void 0,
|
|
1498
|
+
children: [flexRender(header.column.columnDef.header, header.getContext()), header.column.getIsSorted() && /* @__PURE__ */ jsx("span", {
|
|
1499
|
+
"aria-hidden": "true",
|
|
1500
|
+
children: header.column.getIsSorted() === "asc" ? "↑" : "↓"
|
|
1501
|
+
})]
|
|
1502
|
+
})
|
|
1503
|
+
}, header.id);
|
|
1504
|
+
})
|
|
1505
|
+
}, headerGroup.id)) }),
|
|
1506
|
+
/* @__PURE__ */ jsx(SortableContext, {
|
|
1507
|
+
items: sortableRowIds,
|
|
1508
|
+
strategy: verticalListSortingStrategy,
|
|
1509
|
+
children: /* @__PURE__ */ jsx(TableBody, { children: groupedRowModel.map((entry) => {
|
|
1510
|
+
if (entry.type === "group") return /* @__PURE__ */ jsxs(TableRow, {
|
|
1511
|
+
className: "hover:bg-transparent",
|
|
1512
|
+
children: [
|
|
1513
|
+
/* @__PURE__ */ jsx(TableCell, {
|
|
1514
|
+
stickyLeft: 0,
|
|
1515
|
+
className: "w-9 min-w-9 border-b-0 px-1.5 group-hover/row:bg-transparent",
|
|
1516
|
+
style: getColumnSizeStyle(selectColumnWidth)
|
|
1517
|
+
}),
|
|
1518
|
+
/* @__PURE__ */ jsx(TableCell, {
|
|
1519
|
+
stickyLeft: selectColumnWidth,
|
|
1520
|
+
showStickyBorder: true,
|
|
1521
|
+
className: "bg-background top-8 z-20 border-b-0 group-hover/row:bg-transparent",
|
|
1522
|
+
style: getColumnSizeStyle(titleColumnWidth),
|
|
1523
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
1524
|
+
type: "button",
|
|
1525
|
+
"aria-expanded": !entry.collapsed,
|
|
1526
|
+
className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring/40 -ml-1 inline-flex min-h-8 items-center gap-2 rounded-md px-1 font-mono text-[11px] font-semibold tracking-[0.12em] uppercase transition-colors focus-visible:ring-2 focus-visible:outline-none",
|
|
1527
|
+
onClick: () => viewState.toggleCollapsedGroup(entry.key),
|
|
1528
|
+
children: [
|
|
1529
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
1530
|
+
icon: entry.collapsed ? "ph:caret-right" : "ph:caret-down",
|
|
1531
|
+
className: "size-3.5 shrink-0"
|
|
1532
|
+
}),
|
|
1533
|
+
/* @__PURE__ */ jsx("span", { children: entry.label }),
|
|
1534
|
+
groupingConfig?.showCounts !== false && /* @__PURE__ */ jsx("span", {
|
|
1535
|
+
className: "bg-muted text-muted-foreground inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[10px] tracking-normal tabular-nums",
|
|
1536
|
+
children: entry.count
|
|
1537
|
+
})
|
|
1538
|
+
]
|
|
1539
|
+
})
|
|
1540
|
+
}),
|
|
1541
|
+
visibleLeafColumns.length > STICKY_TABLE_COLUMN_COUNT && /* @__PURE__ */ jsx(TableCell, {
|
|
1542
|
+
colSpan: visibleLeafColumns.length - STICKY_TABLE_COLUMN_COUNT,
|
|
1543
|
+
className: "border-b-0"
|
|
1544
|
+
})
|
|
1545
|
+
]
|
|
1546
|
+
}, entry.key);
|
|
1547
|
+
const row_12 = entry.row;
|
|
1548
|
+
const isRowDeleted = !!row_12.original?.deletedAt;
|
|
1549
|
+
return /* @__PURE__ */ jsx(isReorderMode ? SortableTableRow : TableRow, {
|
|
1550
|
+
id: String(row_12.id),
|
|
1551
|
+
"data-state": row_12.getIsSelected() && "selected",
|
|
1552
|
+
className: cn("group", isReorderMode && "bg-muted/[0.18]", isHighlighted(row_12.id) && "animate-realtime-pulse", isRowDeleted && "opacity-50"),
|
|
1553
|
+
children: row_12.getVisibleCells().map((cell, cellIndex) => {
|
|
1554
|
+
const isCheckboxCol_0 = cellIndex === 0;
|
|
1555
|
+
const columnWidth_0 = getColumnSize(cell.column, isCheckboxCol_0 ? 40 : 120);
|
|
1556
|
+
const stickyLeft_0 = cellIndex < STICKY_TABLE_COLUMN_COUNT ? getStickyLeftOffset(visibleLeafColumns, cellIndex) : void 0;
|
|
1557
|
+
const isTitleCol = cellIndex === 1;
|
|
1558
|
+
return /* @__PURE__ */ jsx(TableCell, {
|
|
1559
|
+
stickyLeft: stickyLeft_0,
|
|
1560
|
+
showStickyBorder: cellIndex === STICKY_TABLE_COLUMN_COUNT - 1,
|
|
1561
|
+
className: isCheckboxCol_0 ? "w-9 min-w-9 px-1.5" : void 0,
|
|
1562
|
+
style: getColumnSizeStyle(columnWidth_0),
|
|
1563
|
+
children: isTitleCol ? /* @__PURE__ */ jsxs("div", {
|
|
1564
|
+
className: "flex min-w-0 items-center gap-2",
|
|
1565
|
+
children: [
|
|
1566
|
+
/* @__PURE__ */ jsx("button", {
|
|
1567
|
+
type: "button",
|
|
1568
|
+
onClick: () => handleRowClick(row_12.original),
|
|
1569
|
+
disabled: isReorderMode,
|
|
1570
|
+
className: cn("decoration-muted-foreground/50 hover:decoration-foreground max-w-full min-w-0 text-left underline underline-offset-2 transition-colors disabled:cursor-default disabled:no-underline", !isReorderMode && "cursor-pointer"),
|
|
1571
|
+
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
1572
|
+
}),
|
|
1573
|
+
isRowDeleted && /* @__PURE__ */ jsxs("span", {
|
|
1574
|
+
className: "text-destructive bg-destructive/10 inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-xs",
|
|
1575
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
1576
|
+
icon: "ph:trash",
|
|
1577
|
+
className: "size-3"
|
|
1578
|
+
}), t("common.deleted")]
|
|
1579
|
+
}),
|
|
1580
|
+
isDocLocked(row_12.id) && (() => {
|
|
1581
|
+
const lock = getLock(row_12.id);
|
|
1582
|
+
const user_0 = lock ? getLockUser(lock) : null;
|
|
1583
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
1584
|
+
className: "text-muted-foreground bg-muted inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-xs",
|
|
1585
|
+
title: user_0?.name ?? user_0?.email ?? "Someone is editing",
|
|
1586
|
+
children: [user_0?.image ? /* @__PURE__ */ jsx("img", {
|
|
1587
|
+
src: user_0.image,
|
|
1588
|
+
alt: "",
|
|
1589
|
+
className: "image-outline size-4 rounded-full"
|
|
1590
|
+
}) : /* @__PURE__ */ jsx(Icon, {
|
|
1591
|
+
icon: "ph:pencil-simple",
|
|
1592
|
+
className: "size-3"
|
|
1593
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1594
|
+
className: "max-w-20 truncate",
|
|
1595
|
+
children: user_0?.name?.split(" ")[0] ?? t("table.editing")
|
|
1596
|
+
})]
|
|
1597
|
+
});
|
|
1598
|
+
})()
|
|
1599
|
+
]
|
|
1600
|
+
}) : flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
1601
|
+
}, cell.id);
|
|
1602
|
+
})
|
|
1603
|
+
}, row_12.id);
|
|
1604
|
+
}) })
|
|
1605
|
+
})
|
|
1606
|
+
]
|
|
1607
|
+
}), /* @__PURE__ */ jsx(DragOverlay, {
|
|
1608
|
+
adjustScale: false,
|
|
1609
|
+
dropAnimation: REORDER_DROP_ANIMATION,
|
|
1610
|
+
children: /* @__PURE__ */ jsx(ReorderDragOverlay, {
|
|
1611
|
+
row: activeReorderRow,
|
|
1612
|
+
columns: visibleLeafColumns,
|
|
1613
|
+
rect: activeReorderRect
|
|
687
1614
|
})
|
|
688
|
-
}
|
|
689
|
-
})
|
|
1615
|
+
})]
|
|
1616
|
+
})
|
|
690
1617
|
}), !table.getRowModel().rows.length && (emptyState || /* @__PURE__ */ jsx(EmptyState, {
|
|
691
|
-
|
|
692
|
-
|
|
1618
|
+
variant: isSearching || hasActiveFilters ? "search" : "empty",
|
|
1619
|
+
iconName: isSearching ? "ph:magnifying-glass" : hasActiveFilters ? "ph:funnel-x" : "ph:tray",
|
|
1620
|
+
title: emptyStateTitle,
|
|
1621
|
+
description: emptyStateDescription,
|
|
1622
|
+
action: emptyStateAction,
|
|
693
1623
|
height: "h-48"
|
|
694
1624
|
}))]
|
|
695
1625
|
}),
|
|
696
1626
|
!isSearching && /* @__PURE__ */ jsxs("div", {
|
|
697
|
-
className: "qa-table-view__pagination flex items-center justify-between gap-4 py-2",
|
|
1627
|
+
className: "qa-table-view__pagination flex items-center justify-between gap-4 py-2 tabular-nums",
|
|
698
1628
|
role: "navigation",
|
|
699
1629
|
"aria-label": t("table.pagination"),
|
|
700
1630
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
@@ -704,13 +1634,14 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
704
1634
|
children: [/* @__PURE__ */ jsxs("span", { children: [
|
|
705
1635
|
filteredItems.length > 0 ? `${((viewState.config.pagination?.page ?? 1) - 1) * (viewState.config.pagination?.pageSize ?? 25) + 1}-${Math.min(((viewState.config.pagination?.page ?? 1) - 1) * (viewState.config.pagination?.pageSize ?? 25) + (viewState.config.pagination?.pageSize ?? 25), listData?.totalDocs ?? filteredItems.length)}` : "0",
|
|
706
1636
|
" ",
|
|
707
|
-
"of
|
|
1637
|
+
t("table.of"),
|
|
1638
|
+
" ",
|
|
708
1639
|
listData?.totalDocs ?? 0
|
|
709
1640
|
] }), /* @__PURE__ */ jsxs("div", {
|
|
710
1641
|
className: "flex items-center gap-2",
|
|
711
1642
|
children: [/* @__PURE__ */ jsx("span", {
|
|
712
1643
|
className: "text-muted-foreground",
|
|
713
|
-
children: "
|
|
1644
|
+
children: t("table.show")
|
|
714
1645
|
}), /* @__PURE__ */ jsxs(Select, {
|
|
715
1646
|
value: String(viewState.config.pagination?.pageSize ?? 25),
|
|
716
1647
|
onValueChange: (value_0) => viewState.setPageSize(Number(value_0)),
|
|
@@ -740,7 +1671,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
740
1671
|
className: "size-8 p-0",
|
|
741
1672
|
disabled: (viewState.config.pagination?.page ?? 1) <= 1,
|
|
742
1673
|
onClick: () => viewState.setPage((viewState.config.pagination?.page ?? 1) - 1),
|
|
743
|
-
"aria-label": "
|
|
1674
|
+
"aria-label": t("table.previousPage"),
|
|
744
1675
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
745
1676
|
icon: "ph:caret-left",
|
|
746
1677
|
className: "size-4"
|
|
@@ -757,9 +1688,9 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
757
1688
|
return /* @__PURE__ */ jsx(Button, {
|
|
758
1689
|
variant: currentPage === pageNum ? "secondary" : "ghost",
|
|
759
1690
|
size: "sm",
|
|
760
|
-
className: "size-8 min-w-[32px] p-0",
|
|
1691
|
+
className: "size-8 min-w-[32px] p-0 tabular-nums",
|
|
761
1692
|
onClick: () => viewState.setPage(pageNum),
|
|
762
|
-
"aria-label":
|
|
1693
|
+
"aria-label": t("table.page", { page: pageNum }),
|
|
763
1694
|
"aria-current": currentPage === pageNum ? "page" : void 0,
|
|
764
1695
|
children: pageNum
|
|
765
1696
|
}, pageNum);
|
|
@@ -770,7 +1701,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
770
1701
|
className: "size-8 p-0",
|
|
771
1702
|
disabled: (viewState.config.pagination?.page ?? 1) >= (listData?.totalPages ?? 1),
|
|
772
1703
|
onClick: () => viewState.setPage((viewState.config.pagination?.page ?? 1) + 1),
|
|
773
|
-
"aria-label": "
|
|
1704
|
+
"aria-label": t("table.nextPage"),
|
|
774
1705
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
775
1706
|
icon: "ph:caret-right",
|
|
776
1707
|
className: "size-4"
|
|
@@ -780,7 +1711,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
780
1711
|
})]
|
|
781
1712
|
}),
|
|
782
1713
|
isSearching && /* @__PURE__ */ jsxs("div", {
|
|
783
|
-
className: "text-muted-foreground flex items-center gap-2 py-2 text-sm",
|
|
1714
|
+
className: "text-muted-foreground flex items-center gap-2 py-2 text-sm tabular-nums",
|
|
784
1715
|
"aria-live": "polite",
|
|
785
1716
|
"aria-atomic": "true",
|
|
786
1717
|
children: [
|
|
@@ -809,6 +1740,8 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
809
1740
|
onConfigChange: viewState.setConfig,
|
|
810
1741
|
isOpen: isSheetOpen,
|
|
811
1742
|
onOpenChange: setIsSheetOpen,
|
|
1743
|
+
groupableFields,
|
|
1744
|
+
defaultGroupBy,
|
|
812
1745
|
savedViews: savedViewsData?.docs ?? [],
|
|
813
1746
|
savedViewsLoading,
|
|
814
1747
|
onSaveView: handleSaveView,
|
|
@@ -817,7 +1750,7 @@ function TableViewInner({ collection, config, viewConfig, navigate, basePath = "
|
|
|
817
1750
|
}),
|
|
818
1751
|
dialogAction && /* @__PURE__ */ jsx(ActionDialog, {
|
|
819
1752
|
open: !!dialogAction,
|
|
820
|
-
onOpenChange: (
|
|
1753
|
+
onOpenChange: (open_0) => !open_0 && closeDialog(),
|
|
821
1754
|
action: dialogAction,
|
|
822
1755
|
collection,
|
|
823
1756
|
item: dialogItem,
|