@riducms/admin 0.2.2 → 0.3.0
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/THIRD_PARTY_NOTICES.md +60 -37
- package/package.json +27 -15
- package/src/app/admin-core-view-route.svelte +38 -53
- package/src/app/admin-extension-route.svelte +19 -0
- package/src/app/admin-layout.scss +175 -0
- package/src/app/admin-layout.svelte +144 -410
- package/src/app/admin-navigation-progress.svelte +11 -77
- package/src/app/admin-page-title.svelte +17 -85
- package/src/app/admin-page-title.ts +136 -0
- package/src/app/admin-route-error.svelte +24 -0
- package/src/app/admin-router-provider.svelte +34 -0
- package/src/app/admin-router-root.svelte +41 -0
- package/src/app/admin-routes.svelte +56 -19
- package/src/app/loading-boundary.svelte +3 -1
- package/src/app-meta.ts +13 -0
- package/src/app.css +138 -496
- package/src/app.svelte +60 -26
- package/src/components/brand/ridu-logo.svelte +19 -5
- package/src/components/data/list-table.scss +63 -0
- package/src/components/icons/LICENSE.md +24 -0
- package/src/components/icons/chevron.svelte +8 -0
- package/src/components/icons/plus.svelte +12 -0
- package/src/components/icons/search.svelte +12 -0
- package/src/components/icons/x.svelte +8 -0
- package/src/components/json-tree/json-tree-node.svelte +61 -67
- package/src/components/json-tree/json-viewer.scss +153 -0
- package/src/components/json-tree/json-viewer.svelte +57 -96
- package/src/components/ui/banner/banner.scss +28 -0
- package/src/components/ui/banner/banner.svelte +9 -8
- package/src/components/ui/banner/index.ts +1 -5
- package/src/components/ui/code-editor/code-editor.scss +20 -0
- package/src/components/ui/code-editor/code-editor.svelte +71 -0
- package/src/components/ui/code-editor/code-editor.ts +151 -0
- package/src/components/ui/code-editor/code-languages.ts +29 -0
- package/src/components/ui/collapsible-panel/collapsible-panel.scss +38 -0
- package/src/components/ui/collapsible-panel/collapsible-panel.svelte +13 -0
- package/src/components/ui/collapsible-panel/index.ts +1 -0
- package/src/components/ui/combobox/combobox.scss +163 -0
- package/src/components/ui/combobox/index.ts +22 -0
- package/src/components/ui/date-value-control/date-value-calendar.svelte +128 -16
- package/src/components/ui/date-value-control/date-value-control-loader.scss +26 -0
- package/src/components/ui/date-value-control/date-value-control-loader.svelte +35 -13
- package/src/components/ui/date-value-control/date-value-control.scss +223 -0
- package/src/components/ui/date-value-control/date-value-control.svelte +62 -44
- package/src/components/ui/drawer/drawer-depth.ts +8 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +2 -5
- package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +2 -5
- package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -2
- package/src/components/ui/dropdown-menu/dropdown-menu.scss +62 -0
- package/src/components/ui/kbd/kbd.scss +17 -0
- package/src/components/ui/kbd/kbd.svelte +3 -10
- package/src/components/ui/navigation-drawer/navigation-drawer.scss +40 -0
- package/src/components/ui/navigation-drawer/navigation-drawer.svelte +38 -0
- package/src/components/ui/popover/popover-content.svelte +3 -5
- package/src/components/ui/popover/popover.scss +18 -0
- package/src/components/ui/radio-group/index.ts +0 -1
- package/src/components/ui/radio-group/radio-card-item.svelte +7 -12
- package/src/components/ui/radio-group/radio-group.svelte +2 -2
- package/src/components/ui/radio-group/radio.scss +45 -0
- package/src/components/ui/select/select-content.svelte +5 -6
- package/src/components/ui/select/select-item.svelte +8 -8
- package/src/components/ui/select/select-scroll-down-button.svelte +3 -5
- package/src/components/ui/select/select-scroll-up-button.svelte +3 -5
- package/src/components/ui/select/select-trigger.svelte +6 -7
- package/src/components/ui/select/select.scss +126 -0
- package/src/components/ui/sheet/sheet-content.svelte +6 -34
- package/src/components/ui/sheet/sheet-description.svelte +2 -2
- package/src/components/ui/sheet/sheet-overlay.svelte +2 -21
- package/src/components/ui/sheet/sheet-title.svelte +2 -2
- package/src/components/ui/sheet/sheet.scss +221 -0
- package/src/components/ui/skeleton/skeleton.scss +20 -0
- package/src/components/ui/skeleton/skeleton.svelte +4 -16
- package/src/components/ui/sonner/sonner.scss +121 -0
- package/src/components/ui/sonner/sonner.svelte +11 -10
- package/src/components/ui/status-indicator/status-indicator.scss +48 -0
- package/src/components/ui/status-indicator/status-indicator.svelte +14 -14
- package/src/components/ui/tabs/tabs-content.svelte +2 -2
- package/src/components/ui/tabs/tabs-list.svelte +7 -7
- package/src/components/ui/tabs/tabs-trigger.svelte +2 -8
- package/src/components/ui/tabs/tabs.scss +86 -0
- package/src/components/ui/tabs/tabs.svelte +2 -2
- package/src/components/ui/timezone-picker/timezone-picker.svelte +152 -0
- package/src/core/api/admin-client.ts +2 -2
- package/src/core/bootstrap/admin-bootstrap.ts +396 -0
- package/src/core/bootstrap/admin-prepared-state.ts +213 -0
- package/src/core/bootstrap/admin-route-modules.ts +66 -0
- package/src/core/clipboard/copy-feedback.svelte.ts +43 -0
- package/src/core/forms/embedded-fields.ts +4 -8
- package/src/core/forms/field-editor-authoring.ts +8 -0
- package/src/core/forms/field-issue-focus.ts +4 -4
- package/src/core/forms/field-occurrence.ts +4 -7
- package/src/core/forms/form-controller.svelte.ts +14 -21
- package/src/core/forms/form-draft-recovery.ts +17 -4
- package/src/core/forms/form-issue-correlation.ts +13 -13
- package/src/core/forms/form-path.ts +17 -0
- package/src/core/forms/form-schema.ts +12 -43
- package/src/core/forms/form-validation.ts +7 -46
- package/src/core/forms/plugin-field-authoring.ts +6 -2
- package/src/core/forms/plugin-field-write.ts +2 -6
- package/src/core/i18n/admin-i18n.svelte.ts +18 -0
- package/src/core/i18n/format-admin-date-time.ts +19 -0
- package/src/core/i18n/humanize-identifier.ts +5 -0
- package/src/core/i18n/time-zone-label.ts +20 -0
- package/src/core/loaders/admin-view-host.svelte +72 -0
- package/src/core/loaders/admin-view-loader.svelte.ts +90 -0
- package/src/core/notifications/validation-toast.svelte +2 -2
- package/src/core/plugins/field-registry.ts +7 -8
- package/src/core/routing/admin-paths.ts +53 -2
- package/src/core/routing/admin-scroll.svelte.ts +74 -0
- package/src/core/routing/admin-view-selection.ts +78 -0
- package/src/core/runtime/admin-runtime.svelte.ts +121 -124
- package/src/core/schema/field-default.ts +33 -0
- package/src/core/schema/field-localization.ts +15 -0
- package/src/core/schema/read-document-path.ts +11 -0
- package/src/features/account/account-menu.scss +37 -0
- package/src/features/account/account-menu.svelte +115 -0
- package/src/features/{auth → account}/account-navigation.svelte +16 -19
- package/src/features/{auth → account}/account-route.svelte +206 -49
- package/src/features/account/account-security-controller.svelte.ts +157 -0
- package/src/features/{auth → account}/account-security-route.svelte +140 -42
- package/src/features/api-reference/api-reference-code.svelte +64 -0
- package/src/features/api-reference/api-reference-content.svelte +258 -0
- package/src/features/api-reference/api-reference-drawer.scss +74 -0
- package/src/features/api-reference/api-reference-examples.ts +381 -0
- package/src/features/api-reference/api-reference-schema.ts +332 -0
- package/src/features/api-reference/api-reference.scss +190 -0
- package/src/features/api-reference/api-reference.svelte +74 -0
- package/src/features/auth/auth-brand.svelte +5 -3
- package/src/features/auth/auth-field.svelte +92 -0
- package/src/features/auth/auth-frame.svelte +5 -8
- package/src/features/auth/auth.scss +122 -0
- package/src/features/auth/create-first-user-controller.svelte.ts +20 -51
- package/src/features/auth/create-first-user-route.svelte +83 -122
- package/src/features/auth/forgot-password-route.svelte +31 -23
- package/src/features/auth/login-route.svelte +68 -116
- package/src/features/auth/logout-button.scss +34 -0
- package/src/features/auth/logout-button.svelte +52 -0
- package/src/features/auth/request-verification-route.svelte +27 -22
- package/src/features/auth/reset-password-route.svelte +108 -41
- package/src/features/auth/verify-email-route.svelte +49 -15
- package/src/features/bulk-edit/bulk-edit-fields.ts +23 -0
- package/src/features/bulk-edit/bulk-edit.scss +152 -0
- package/src/features/bulk-edit/field-picker.svelte +176 -0
- package/src/features/collections/bulk/bulk-actions.svelte +148 -0
- package/src/features/collections/bulk/bulk-confirmation.svelte +153 -0
- package/src/features/collections/bulk/bulk-editor-loader.svelte +95 -0
- package/src/features/collections/bulk/bulk-editor.svelte +186 -0
- package/src/features/collections/collection-list-cell-values.ts +144 -0
- package/src/features/collections/collection-list-controller.svelte.ts +268 -379
- package/src/features/collections/collection-list-preferences-controller.svelte.ts +54 -40
- package/src/features/collections/collection-list-query.ts +223 -0
- package/src/features/collections/collection-list-results.svelte +205 -329
- package/src/features/collections/collection-list-route.svelte +143 -884
- package/src/features/collections/collection-list.scss +261 -0
- package/src/features/collections/collection-list.svelte.ts +362 -0
- package/src/features/collections/controls/column-picker.svelte +110 -0
- package/src/features/collections/controls/column-pill.svelte +62 -0
- package/src/features/collections/controls/filter-builder.svelte +193 -0
- package/src/features/collections/controls/filter-row.svelte +142 -0
- package/src/features/collections/controls/list-controls.scss +196 -0
- package/src/features/collections/controls/list-options.svelte +203 -0
- package/src/features/collections/controls/list-pagination.scss +78 -0
- package/src/features/collections/controls/list-pagination.svelte +115 -0
- package/src/features/collections/controls/list-toolbar.svelte +132 -0
- package/src/features/collections/controls/sort-heading.scss +52 -0
- package/src/features/collections/controls/sort-heading.svelte +78 -0
- package/src/features/collections/list-columns.ts +43 -0
- package/src/features/collections/list-workspace.ts +155 -54
- package/src/features/dashboard/dashboard-route.svelte +82 -86
- package/src/features/dashboard/dashboard.scss +131 -0
- package/src/features/development/development-tools.svelte +20 -36
- package/src/features/documents/document-action-bar.svelte +438 -0
- package/src/features/documents/document-api-view-loader.svelte +17 -6
- package/src/features/documents/document-api-view.scss +120 -0
- package/src/features/documents/document-api-view.svelte +169 -454
- package/src/features/documents/document-controller.svelte.ts +526 -613
- package/src/features/documents/document-credentials.scss +37 -0
- package/src/features/documents/document-credentials.svelte +72 -0
- package/src/features/documents/{document-route-dirty.ts → document-credentials.ts} +25 -0
- package/src/features/documents/document-field-sections.scss +39 -0
- package/src/features/documents/document-field-sections.svelte +4 -13
- package/src/features/documents/document-loading.scss +24 -0
- package/src/features/documents/document-lock-controller.svelte.ts +187 -0
- package/src/features/documents/document-operation-dialogs.svelte +110 -0
- package/src/features/documents/document-route-loader.svelte +17 -5
- package/src/features/documents/document-route.svelte +305 -811
- package/src/features/documents/document-schedule.scss +127 -0
- package/src/features/documents/document-schedule.svelte +323 -0
- package/src/features/documents/document-title.ts +25 -0
- package/src/features/documents/document.scss +274 -0
- package/src/features/documents/live-preview-panel.scss +117 -0
- package/src/features/documents/live-preview-panel.svelte +167 -168
- package/src/features/documents/live-preview.ts +2 -10
- package/src/features/documents/upload-document-preview-loader.svelte +26 -23
- package/src/features/localization/content-locale-switcher.scss +43 -0
- package/src/features/localization/content-locale-switcher.svelte +24 -17
- package/src/features/navigation/admin-breadcrumbs.scss +56 -0
- package/src/features/navigation/admin-breadcrumbs.svelte +102 -37
- package/src/features/navigation/admin-command-menu.svelte +38 -15
- package/src/features/navigation/admin-navigation.scss +133 -0
- package/src/features/navigation/admin-navigation.svelte +169 -0
- package/src/features/navigation/breadcrumb-context.svelte.ts +15 -0
- package/src/features/navigation/navigation-preference.svelte.ts +70 -0
- package/src/features/reference-browser/reference-browser-editor.svelte +180 -0
- package/src/features/reference-browser/reference-browser-list.scss +113 -0
- package/src/features/reference-browser/reference-browser-list.svelte +370 -0
- package/src/features/reference-browser/reference-browser-loader.svelte +26 -8
- package/src/features/reference-browser/reference-browser-workflow.svelte.ts +335 -236
- package/src/features/reference-browser/reference-browser.scss +217 -0
- package/src/features/reference-browser/reference-browser.svelte +154 -797
- package/src/features/reference-browser/reference-collection-picker.svelte +116 -0
- package/src/features/reference-browser/reference-list-query.ts +35 -0
- package/src/features/uploads/bulk-upload-controller.svelte.ts +604 -0
- package/src/features/uploads/bulk-upload-edit-all.svelte +92 -0
- package/src/features/uploads/bulk-upload-editor.svelte +191 -0
- package/src/features/uploads/bulk-upload-file-picker.svelte +70 -0
- package/src/features/uploads/bulk-upload-remote.svelte +100 -0
- package/src/features/uploads/bulk-upload-route-loader.svelte +54 -0
- package/src/features/uploads/bulk-upload-route.svelte +172 -592
- package/src/features/uploads/bulk-upload-sidebar.svelte +125 -0
- package/src/features/uploads/bulk-upload.scss +526 -0
- package/src/features/uploads/bulk-upload.ts +105 -14
- package/src/features/uploads/crop-surface.ts +150 -0
- package/src/features/uploads/image-editor.svelte +231 -0
- package/src/features/uploads/rendition-preview.svelte +64 -0
- package/src/features/uploads/upload-control.svelte +340 -0
- package/src/features/uploads/upload-document-contracts.ts +30 -0
- package/src/features/uploads/upload-draft.svelte.ts +294 -0
- package/src/features/uploads/upload-metadata-fields.scss +32 -0
- package/src/features/uploads/upload-metadata-fields.svelte +8 -7
- package/src/features/uploads/upload-thumbnail.svelte +47 -0
- package/src/features/uploads/upload.scss +361 -0
- package/src/features/versions/version-comparison.svelte +361 -0
- package/src/features/versions/version-diff-fields.svelte +136 -0
- package/src/features/versions/version-diff.ts +296 -41
- package/src/features/versions/version-history-controller.svelte.ts +311 -0
- package/src/features/versions/version-history-route-loader.svelte +32 -0
- package/src/features/versions/version-history-route.svelte +157 -522
- package/src/features/versions/version-history.scss +444 -0
- package/src/features/versions/version-history.ts +45 -0
- package/src/features/versions/version-table.svelte +91 -0
- package/src/fields/embedded-schema-draft-editor.scss +48 -0
- package/src/fields/embedded-schema-draft-editor.svelte +24 -16
- package/src/fields/field-collapsible.svelte +14 -8
- package/src/fields/field-layout.scss +171 -0
- package/src/fields/field-layout.svelte +3 -5
- package/src/fields/field-renderer.svelte +17 -29
- package/src/fields/field-shell.svelte +1 -1
- package/src/fields/field-tab-layout.svelte +25 -19
- package/src/fields/join/join-field-controller.svelte.ts +513 -0
- package/src/fields/join/join-field-values.ts +111 -0
- package/src/fields/join/join-field.scss +189 -0
- package/src/fields/join/join-field.svelte +164 -332
- package/src/fields/live-validation-feedback.svelte +4 -3
- package/src/fields/local-field-editor.svelte +2 -2
- package/src/fields/nested/block-name-input.svelte +11 -12
- package/src/fields/nested/block-picker.scss +128 -0
- package/src/fields/nested/block-picker.svelte +81 -0
- package/src/fields/nested/block-placeholder.svg +2 -0
- package/src/fields/nested/nested-field.scss +331 -0
- package/src/fields/nested/nested-field.svelte +265 -245
- package/src/fields/nested/sortable-row.svelte +9 -7
- package/src/fields/plugin-field.svelte +4 -6
- package/src/fields/point/point-field.svelte +51 -38
- package/src/fields/primitive-list/primitive-list-field.svelte +63 -19
- package/src/fields/primitive-list/primitive-list.scss +109 -0
- package/src/fields/radio/radio-field.svelte +2 -1
- package/src/fields/relationship/relationship-field-controller.svelte.ts +81 -41
- package/src/fields/relationship/relationship-field.svelte +144 -175
- package/src/fields/relationship/relationship-lookup-controller.svelte.ts +58 -30
- package/src/fields/relationship/relationship-query.ts +2 -10
- package/src/fields/relationship/relationship-quick-picker-controller.svelte.ts +36 -62
- package/src/fields/relationship/relationship-quick-picker.svelte +178 -227
- package/src/fields/relationship/relationship-selection.svelte +120 -0
- package/src/fields/relationship/relationship-value.ts +46 -7
- package/src/fields/relationship/relationship.scss +182 -0
- package/src/fields/scalar/code-field.svelte +101 -0
- package/src/fields/scalar/date-control-value.ts +13 -0
- package/src/fields/scalar/scalar-field.svelte +25 -67
- package/src/fields/select/select-field.svelte +132 -94
- package/src/fields/text/slug-field.scss +28 -0
- package/src/fields/text/slug-field.svelte +19 -15
- package/src/fields/text/text-field.svelte +1 -2
- package/src/fields/ui/ui-field.svelte +7 -4
- package/src/fields/virtual/virtual-field.svelte +2 -5
- package/src/index.ts +1 -2
- package/src/routing.ts +2 -0
- package/src/app/deferred-redirect.svelte +0 -23
- package/src/components/code-block/code-block.svelte +0 -107
- package/src/components/ui/bulk-action-bar/bulk-action-bar.svelte +0 -50
- package/src/components/ui/bulk-action-bar/index.ts +0 -1
- package/src/components/ui/button/index.ts +0 -8
- package/src/components/ui/calendar/calendar-caption.svelte +0 -72
- package/src/components/ui/calendar/calendar-cell.svelte +0 -20
- package/src/components/ui/calendar/calendar-day.svelte +0 -27
- package/src/components/ui/calendar/calendar-grid-row.svelte +0 -13
- package/src/components/ui/calendar/calendar-grid.svelte +0 -17
- package/src/components/ui/calendar/calendar-head-cell.svelte +0 -20
- package/src/components/ui/calendar/calendar-header.svelte +0 -20
- package/src/components/ui/calendar/calendar-heading.svelte +0 -17
- package/src/components/ui/calendar/calendar-month-select.svelte +0 -45
- package/src/components/ui/calendar/calendar-month.svelte +0 -16
- package/src/components/ui/calendar/calendar-months.svelte +0 -20
- package/src/components/ui/calendar/calendar-nav.svelte +0 -20
- package/src/components/ui/calendar/calendar-next-button.svelte +0 -30
- package/src/components/ui/calendar/calendar-prev-button.svelte +0 -30
- package/src/components/ui/calendar/calendar-year-select.svelte +0 -44
- package/src/components/ui/calendar/calendar.svelte +0 -118
- package/src/components/ui/calendar/index.ts +0 -1
- package/src/components/ui/checkbox/checkbox.svelte +0 -35
- package/src/components/ui/checkbox/index.ts +0 -1
- package/src/components/ui/dialog/dialog-close.svelte +0 -11
- package/src/components/ui/dialog/dialog-content.svelte +0 -52
- package/src/components/ui/dialog/dialog-description.svelte +0 -20
- package/src/components/ui/dialog/dialog-footer.svelte +0 -20
- package/src/components/ui/dialog/dialog-header.svelte +0 -20
- package/src/components/ui/dialog/dialog-overlay.svelte +0 -20
- package/src/components/ui/dialog/dialog-title.svelte +0 -17
- package/src/components/ui/dialog/dialog-trigger.svelte +0 -11
- package/src/components/ui/dialog/dialog.svelte +0 -7
- package/src/components/ui/dialog/index.ts +0 -8
- package/src/components/ui/empty-state/empty-state.svelte +0 -34
- package/src/components/ui/empty-state/index.ts +0 -1
- package/src/components/ui/input/index.ts +0 -1
- package/src/components/ui/pagination/index.ts +0 -1
- package/src/components/ui/pagination/pagination.svelte +0 -88
- package/src/components/ui/radio-group/radio-group-item.svelte +0 -17
- package/src/components/ui/slider/index.ts +0 -3
- package/src/components/ui/slider/slider-content.svelte +0 -59
- package/src/components/ui/slider/slider.svelte +0 -35
- package/src/components/ui/table/index.ts +0 -6
- package/src/components/ui/table/table-body.svelte +0 -20
- package/src/components/ui/table/table-cell.svelte +0 -23
- package/src/components/ui/table/table-head.svelte +0 -23
- package/src/components/ui/table/table-header.svelte +0 -20
- package/src/components/ui/table/table-row.svelte +0 -23
- package/src/components/ui/table/table.svelte +0 -22
- package/src/components/ui/textarea/index.ts +0 -1
- package/src/components/ui/tooltip/index.ts +0 -4
- package/src/components/ui/tooltip/tooltip-content.svelte +0 -50
- package/src/components/ui/tooltip/tooltip-provider.svelte +0 -7
- package/src/components/ui/tooltip/tooltip-trigger.svelte +0 -7
- package/src/components/ui/tooltip/tooltip.svelte +0 -7
- package/src/features/auth/account-menu.svelte +0 -159
- package/src/features/auth/account-security-controller.svelte.ts +0 -119
- package/src/features/collections/collection-list-bulk-actions.svelte +0 -143
- package/src/features/collections/collection-list-bulk-editor.svelte +0 -157
- package/src/features/collections/collection-list-filter-popover.svelte +0 -238
- package/src/features/collections/collection-list-workspace-toolbar.svelte +0 -409
- package/src/features/collections/collection-table-skeleton.svelte +0 -44
- package/src/features/documents/document-heading.ts +0 -20
- package/src/features/documents/upload-document-preview.svelte +0 -525
|
@@ -1,633 +1,115 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import APIReference from "@admin/features/api-reference/api-reference.svelte";
|
|
3
|
+
import "@admin/features/collections/collection-list.scss";
|
|
4
|
+
import "@admin/components/data/list-table.scss";
|
|
5
|
+
import {
|
|
6
|
+
Link,
|
|
7
|
+
useHref,
|
|
8
|
+
useLocation,
|
|
9
|
+
useNavigation,
|
|
10
|
+
useParams,
|
|
11
|
+
useSearchParams,
|
|
12
|
+
} from "@hvniel/svelte-router";
|
|
13
|
+
import { Button } from "@riducms/ui";
|
|
9
14
|
import { Banner } from "@admin/components/ui/banner";
|
|
10
|
-
import { Button, buttonVariants } from "@admin/components/ui/button";
|
|
11
|
-
import { ConfirmationDialog } from "@admin/components/ui/confirmation-dialog";
|
|
12
15
|
import {
|
|
13
16
|
collectionPath,
|
|
14
17
|
collectionTrashPath,
|
|
15
|
-
|
|
16
|
-
createDocumentPath,
|
|
17
|
-
documentPath,
|
|
18
|
+
withContentLocale,
|
|
18
19
|
} from "@admin/core/routing/admin-paths";
|
|
20
|
+
import { registerAdminScrollPage } from "@admin/core/routing/admin-scroll.svelte";
|
|
19
21
|
import { getAdminRuntime } from "@admin/core/runtime/admin-runtime.svelte";
|
|
22
|
+
import { getAdminBootstrapCoordinator } from "@admin/core/bootstrap/admin-bootstrap";
|
|
20
23
|
import { getNotificationCenter } from "@admin/core/notifications/notification-center.svelte";
|
|
21
|
-
import type { AdminDocument } from "@admin/core/api/admin-client";
|
|
22
|
-
import { preferenceOwnerID } from "@admin/core/preferences/preference-write-queue";
|
|
23
|
-
|
|
24
|
-
import { CollectionListController } from "@admin/features/collections/collection-list-controller.svelte";
|
|
25
|
-
import CollectionListBulkActions from "@admin/features/collections/collection-list-bulk-actions.svelte";
|
|
26
|
-
import CollectionListBulkEditor from "@admin/features/collections/collection-list-bulk-editor.svelte";
|
|
27
24
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} from "@admin/features/collections/collection-list
|
|
25
|
+
CollectionList,
|
|
26
|
+
setCollectionList,
|
|
27
|
+
} from "@admin/features/collections/collection-list.svelte";
|
|
28
|
+
import { CollectionListQuery } from "@admin/features/collections/collection-list-query";
|
|
31
29
|
import CollectionListResults from "@admin/features/collections/collection-list-results.svelte";
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
listPageSizes,
|
|
39
|
-
parseListFilters,
|
|
40
|
-
parseListPageSize,
|
|
41
|
-
visibleColumnNames,
|
|
42
|
-
type ListFilter,
|
|
43
|
-
type ListPageSize,
|
|
44
|
-
} from "@admin/features/collections/list-workspace";
|
|
45
|
-
import { formatDateDisplay } from "@admin/fields/scalar/date-value";
|
|
30
|
+
import ListToolbar from "@admin/features/collections/controls/list-toolbar.svelte";
|
|
31
|
+
import CollectionListBulkActions from "@admin/features/collections/bulk/bulk-actions.svelte";
|
|
32
|
+
import CollectionListBulkEditorLoader from "@admin/features/collections/bulk/bulk-editor-loader.svelte";
|
|
33
|
+
import BulkConfirmation, {
|
|
34
|
+
type BulkConfirmationAction,
|
|
35
|
+
} from "@admin/features/collections/bulk/bulk-confirmation.svelte";
|
|
46
36
|
|
|
47
37
|
const runtime = getAdminRuntime();
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const params =
|
|
51
|
-
const location =
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
);
|
|
68
|
-
const statusOptions = $derived(statusField?.select?.options ?? []);
|
|
69
|
-
const searchParams = $derived(new URLSearchParams(location.search));
|
|
70
|
-
const localization = $derived(runtime.manifest?.application.localization);
|
|
71
|
-
const requestedLocale = $derived(searchParams.get("locale"));
|
|
72
|
-
const contentLocale = $derived(
|
|
73
|
-
localization?.locales.some((locale) => locale.code === requestedLocale)
|
|
74
|
-
? (requestedLocale ?? localization?.defaultLocale)
|
|
75
|
-
: (runtime.contentLocale ?? localization?.defaultLocale)
|
|
76
|
-
);
|
|
77
|
-
const query = $derived(searchParams.get("q") ?? "");
|
|
78
|
-
const requestedPage = $derived(parsePage(searchParams.get("page")));
|
|
79
|
-
const requestedStatus = $derived(searchParams.get("status") ?? "");
|
|
80
|
-
const requestedFolder = $derived(searchParams.get("folder") ?? "");
|
|
81
|
-
const hierarchy = $derived(searchParams.get("view") === "hierarchy");
|
|
82
|
-
const requestedSort = $derived(searchParams.get("sort") ?? "");
|
|
83
|
-
const folderField = $derived(
|
|
84
|
-
collection?.fields.find((field) => field.name === collection.admin.folderField)
|
|
85
|
-
);
|
|
86
|
-
const parentField = $derived(
|
|
87
|
-
collection?.fields.find((field) => field.name === collection.admin.parentField)
|
|
88
|
-
);
|
|
89
|
-
const folderCollection = $derived(
|
|
90
|
-
runtime.manifest?.collections.find(
|
|
91
|
-
(candidate) => candidate.slug === folderField?.relationship?.collectionSlug
|
|
92
|
-
)
|
|
93
|
-
);
|
|
94
|
-
let folders = $state.raw<AdminDocument[]>([]);
|
|
95
|
-
let referenceLabels = $state.raw<Record<string, string>>({});
|
|
96
|
-
let searchInput = $state<HTMLInputElement | null>(null);
|
|
97
|
-
const activeStatus = $derived(
|
|
98
|
-
statusOptions.some((option) => option.value === requestedStatus) ? requestedStatus : ""
|
|
99
|
-
);
|
|
100
|
-
const bulkEditableFields = $derived(
|
|
101
|
-
collection?.fields.filter(
|
|
102
|
-
(field) =>
|
|
103
|
-
field.category === "scalar" &&
|
|
104
|
-
field.localized !== true &&
|
|
105
|
-
field.admin.readOnly !== true &&
|
|
106
|
-
["text", "textarea", "email", "date", "number", "checkbox", "select", "radio"].includes(
|
|
107
|
-
field.type
|
|
108
|
-
)
|
|
109
|
-
) ?? []
|
|
110
|
-
);
|
|
111
|
-
const customListCells = $derived(
|
|
112
|
-
runtime.listCells.flatMap((cell) => {
|
|
113
|
-
if (cell.collection !== slug) return [];
|
|
114
|
-
const field = collection?.fields.find(
|
|
115
|
-
(candidate) => candidate.path === cell.field || candidate.name === cell.field
|
|
116
|
-
);
|
|
117
|
-
return field === undefined ? [] : [{ ...cell, field }];
|
|
118
|
-
})
|
|
119
|
-
);
|
|
120
|
-
const availableColumnFields = $derived(
|
|
121
|
-
listColumnFields(collection, titleField?.name).filter(
|
|
122
|
-
(field) =>
|
|
123
|
-
field.path !== statusField?.path &&
|
|
124
|
-
!customListCells.some((cell) => cell.field.path === field.path)
|
|
125
|
-
)
|
|
126
|
-
);
|
|
127
|
-
const availableFilterFields = $derived(filterableFields(collection?.fields ?? []));
|
|
128
|
-
const defaultColumns = $derived(defaultListColumns(collection, availableColumnFields));
|
|
129
|
-
const preferences = new CollectionListPreferencesController(
|
|
130
|
-
runtime.client,
|
|
131
|
-
notifications,
|
|
132
|
-
() => runtime.session?.id ?? "",
|
|
133
|
-
runtime.i18n
|
|
134
|
-
);
|
|
135
|
-
const { workspace, presets, presetsPending } = $derived(preferences);
|
|
136
|
-
const visibleColumns = $derived(
|
|
137
|
-
visibleColumnNames(searchParams.get("columns"), workspace.columns).flatMap((name) => {
|
|
138
|
-
const field = availableColumnFields.find((candidate) => candidate.path === name);
|
|
139
|
-
return field === undefined ? [] : [field];
|
|
140
|
-
})
|
|
141
|
-
);
|
|
142
|
-
const pageSize = $derived(parseListPageSize(searchParams.get("limit"), workspace.limit));
|
|
143
|
-
const showID = $derived(workspace.showID);
|
|
144
|
-
const showCreated = $derived(workspace.showCreated);
|
|
145
|
-
const listFilters = $derived(
|
|
146
|
-
parseListFilters(searchParams.get("filters"), availableFilterFields)
|
|
147
|
-
);
|
|
148
|
-
const filterWhere = $derived(buildListFilterWhere(listFilters, availableFilterFields));
|
|
149
|
-
const sortField = $derived(requestedSort.replace(/^-/, ""));
|
|
150
|
-
const sortDescending = $derived(requestedSort.startsWith("-"));
|
|
151
|
-
let bulkEditOpen = $state(false);
|
|
152
|
-
type ConfirmationAction =
|
|
153
|
-
| { kind: "delete-document"; id: string }
|
|
154
|
-
| { kind: "delete-selected" }
|
|
155
|
-
| { kind: "restore-selected" }
|
|
156
|
-
| { kind: "delete-selected-permanently" }
|
|
157
|
-
| { kind: "empty-trash" };
|
|
158
|
-
let confirmationOpen = $state(false);
|
|
159
|
-
let confirmationAction = $state.raw<ConfirmationAction>();
|
|
160
|
-
const confirmationCopy = $derived(confirmationText(confirmationAction));
|
|
161
|
-
const controller = new CollectionListController({
|
|
162
|
-
client: runtime.client,
|
|
163
|
-
notifications,
|
|
164
|
-
i18n: runtime.i18n,
|
|
38
|
+
const bootstrap = getAdminBootstrapCoordinator();
|
|
39
|
+
const navigation = useNavigation();
|
|
40
|
+
const params = useParams<"collection">();
|
|
41
|
+
const location = useLocation();
|
|
42
|
+
const currentPath = useHref(() => location.current.pathname);
|
|
43
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
44
|
+
|
|
45
|
+
const list = new CollectionList({
|
|
46
|
+
runtime,
|
|
47
|
+
notifications: getNotificationCenter(),
|
|
48
|
+
query: new CollectionListQuery(searchParams, setSearchParams, () => {
|
|
49
|
+
const destination = navigation.current.location;
|
|
50
|
+
if (
|
|
51
|
+
destination?.pathname === currentPath.current &&
|
|
52
|
+
new URLSearchParams(destination.search).get("locale") === searchParams.current.get("locale")
|
|
53
|
+
) {
|
|
54
|
+
return destination.search;
|
|
55
|
+
}
|
|
56
|
+
}),
|
|
165
57
|
get slug() {
|
|
166
|
-
return
|
|
167
|
-
},
|
|
168
|
-
get locale() {
|
|
169
|
-
return contentLocale;
|
|
170
|
-
},
|
|
171
|
-
get page() {
|
|
172
|
-
return requestedPage;
|
|
173
|
-
},
|
|
174
|
-
get search() {
|
|
175
|
-
return query;
|
|
176
|
-
},
|
|
177
|
-
get titleField() {
|
|
178
|
-
return titleField?.name;
|
|
179
|
-
},
|
|
180
|
-
get status() {
|
|
181
|
-
return activeStatus;
|
|
182
|
-
},
|
|
183
|
-
get statusField() {
|
|
184
|
-
return statusField?.name;
|
|
185
|
-
},
|
|
186
|
-
get statusOptions() {
|
|
187
|
-
return statusOptions;
|
|
188
|
-
},
|
|
189
|
-
get versioned() {
|
|
190
|
-
return collection?.capabilities.versions === true;
|
|
58
|
+
return params.current.collection ?? "";
|
|
191
59
|
},
|
|
192
60
|
get trashOnly() {
|
|
193
|
-
return
|
|
61
|
+
return location.current.pathname.endsWith("/trash");
|
|
194
62
|
},
|
|
195
|
-
get
|
|
196
|
-
return
|
|
63
|
+
get navigationIdle() {
|
|
64
|
+
return navigation.current.state === "idle";
|
|
197
65
|
},
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
get hierarchy() {
|
|
202
|
-
return hierarchy;
|
|
203
|
-
},
|
|
204
|
-
get limit() {
|
|
205
|
-
return pageSize;
|
|
206
|
-
},
|
|
207
|
-
get sort() {
|
|
208
|
-
return requestedSort === "" ? [] : [requestedSort];
|
|
209
|
-
},
|
|
210
|
-
get filterWhere() {
|
|
211
|
-
return filterWhere;
|
|
212
|
-
},
|
|
213
|
-
});
|
|
214
|
-
const {
|
|
215
|
-
allDocuments,
|
|
216
|
-
canCreate,
|
|
217
|
-
docs,
|
|
218
|
-
error,
|
|
219
|
-
pagination,
|
|
220
|
-
selectedIDs,
|
|
221
|
-
bulkPending,
|
|
222
|
-
showStatus,
|
|
223
|
-
showUpdated,
|
|
224
|
-
statusColumnAvailable,
|
|
225
|
-
} = $derived(controller);
|
|
226
|
-
const {
|
|
227
|
-
optionCount,
|
|
228
|
-
canReadField,
|
|
229
|
-
deletePermanent,
|
|
230
|
-
bulkDelete,
|
|
231
|
-
bulkDeletePermanent,
|
|
232
|
-
bulkRestore,
|
|
233
|
-
emptyTrash,
|
|
234
|
-
bulkUpdate,
|
|
235
|
-
retry,
|
|
236
|
-
setShowStatus,
|
|
237
|
-
setShowUpdated,
|
|
238
|
-
title,
|
|
239
|
-
} = controller;
|
|
66
|
+
prepared() {
|
|
67
|
+
// A retained route may only adopt a seed for its exact pathname and query.
|
|
68
|
+
const route = bootstrap.routeData(location.current.pathname, location.current.search);
|
|
240
69
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
updateSearch(next, true);
|
|
70
|
+
return route?.kind === "collection-list" || route?.kind === "collection-trash"
|
|
71
|
+
? route.data
|
|
72
|
+
: undefined;
|
|
73
|
+
},
|
|
246
74
|
});
|
|
247
75
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
() =>
|
|
251
|
-
controller.bulkPending || controller.selectionPending || controller.mutationPending.size > 0
|
|
252
|
-
)
|
|
253
|
-
);
|
|
76
|
+
setCollectionList(list);
|
|
77
|
+
registerAdminScrollPage({ ready: () => list.ready });
|
|
254
78
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
preferenceOwnerID: preferenceOwnerID(runtime.session),
|
|
260
|
-
columnFields: availableColumnFields,
|
|
261
|
-
filterFields: availableFilterFields,
|
|
262
|
-
defaultColumns,
|
|
263
|
-
});
|
|
264
|
-
});
|
|
79
|
+
const { controller } = list;
|
|
80
|
+
const { slug, collection, trashOnly, contentLocale, filtered } = $derived(list);
|
|
81
|
+
const { canCreate, error, pagination, bulkPending } = $derived(controller);
|
|
82
|
+
const { retry } = controller;
|
|
265
83
|
|
|
266
|
-
$
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
84
|
+
const collectionViews = $derived([
|
|
85
|
+
{ trash: false, label: runtime.i18n.t("collections:allDocuments", { label: list.label }) },
|
|
86
|
+
{ trash: true, label: runtime.i18n.t("collections:trash") },
|
|
87
|
+
]);
|
|
270
88
|
|
|
271
|
-
|
|
89
|
+
let bulkEditOpen = $state(false);
|
|
90
|
+
let confirmationOpen = $state(false);
|
|
91
|
+
let confirmationAction = $state<BulkConfirmationAction>("delete-selected");
|
|
272
92
|
|
|
273
|
-
$
|
|
274
|
-
|
|
275
|
-
const revision = runtime.documentRevision;
|
|
276
|
-
if (target === undefined || revision < 0) {
|
|
277
|
-
folders = [];
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
const request = new AbortController();
|
|
281
|
-
runtime.client
|
|
282
|
-
.list(target.slug, { limit: 100, locale: contentLocale, signal: request.signal })
|
|
283
|
-
.then((page) => {
|
|
284
|
-
if (!request.signal.aborted) folders = page.docs;
|
|
285
|
-
})
|
|
286
|
-
.catch(() => {
|
|
287
|
-
if (!request.signal.aborted) folders = [];
|
|
288
|
-
});
|
|
289
|
-
return () => request.abort();
|
|
290
|
-
});
|
|
93
|
+
let searchInput = $state<HTMLInputElement | null>(null);
|
|
94
|
+
let focusSearchAfterNavigation = $state(false);
|
|
291
95
|
|
|
292
96
|
$effect(() => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
if (documents.length === 0 || fields.length === 0) {
|
|
297
|
-
referenceLabels = {};
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
const lookups = new Map<string, { collection: SchemaCollection; id: string }>();
|
|
301
|
-
for (const document of documents) {
|
|
302
|
-
for (const field of fields) {
|
|
303
|
-
for (const reference of fieldReferences(field, documentPathValue(document, field.path))) {
|
|
304
|
-
const target = collections.find((candidate) => candidate.slug === reference.collection);
|
|
305
|
-
if (target !== undefined) {
|
|
306
|
-
lookups.set(referenceKey(reference.collection, reference.id), {
|
|
307
|
-
collection: target,
|
|
308
|
-
id: reference.id,
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
97
|
+
if (list.navigationIdle && focusSearchAfterNavigation) {
|
|
98
|
+
focusSearchAfterNavigation = false;
|
|
99
|
+
searchInput?.focus();
|
|
313
100
|
}
|
|
314
|
-
const request = new AbortController();
|
|
315
|
-
Promise.all(
|
|
316
|
-
[...lookups].map(async ([key, lookup]) => {
|
|
317
|
-
try {
|
|
318
|
-
const document = await runtime.client.find(lookup.collection.slug, lookup.id, {
|
|
319
|
-
signal: request.signal,
|
|
320
|
-
locale: contentLocale,
|
|
321
|
-
});
|
|
322
|
-
return [key, referenceTitle(lookup.collection, document)] as const;
|
|
323
|
-
} catch {
|
|
324
|
-
return [key, lookup.id] as const;
|
|
325
|
-
}
|
|
326
|
-
})
|
|
327
|
-
).then((entries) => {
|
|
328
|
-
if (!request.signal.aborted) referenceLabels = Object.fromEntries(entries);
|
|
329
|
-
});
|
|
330
|
-
return () => request.abort();
|
|
331
101
|
});
|
|
332
102
|
|
|
333
|
-
function parsePage(value: string | null) {
|
|
334
|
-
const page = Number(value);
|
|
335
|
-
return Number.isInteger(page) && page > 0 ? page : 1;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function contentPath(path: string) {
|
|
339
|
-
if (contentLocale === undefined) return path;
|
|
340
|
-
return `${path}?${new URLSearchParams({ locale: contentLocale }).toString()}`;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function updateSearch(next: URLSearchParams, replace: boolean) {
|
|
344
|
-
navigate(
|
|
345
|
-
{ pathname: location.pathname, search: next.size === 0 ? "" : `?${next}` },
|
|
346
|
-
{ replace }
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
function handleSearch(value: string) {
|
|
351
|
-
const next = new URLSearchParams(searchParams);
|
|
352
|
-
if (value.trim().length > 0) next.set("q", value);
|
|
353
|
-
else next.delete("q");
|
|
354
|
-
next.delete("page");
|
|
355
|
-
updateSearch(next, true);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function clearSearch() {
|
|
359
|
-
const next = new URLSearchParams(searchParams);
|
|
360
|
-
next.delete("q");
|
|
361
|
-
next.delete("page");
|
|
362
|
-
updateSearch(next, true);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function clearFilters() {
|
|
366
|
-
const next = new URLSearchParams(searchParams);
|
|
367
|
-
next.delete("q");
|
|
368
|
-
next.delete("status");
|
|
369
|
-
next.delete("page");
|
|
370
|
-
next.delete("folder");
|
|
371
|
-
next.delete("filters");
|
|
372
|
-
updateSearch(next, true);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
103
|
function clearFiltersAndFocusSearch() {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function updateListFilters(filters: readonly ListFilter[]) {
|
|
381
|
-
const next = new URLSearchParams(searchParams);
|
|
382
|
-
if (filters.length === 0) next.delete("filters");
|
|
383
|
-
else next.set("filters", JSON.stringify(filters));
|
|
384
|
-
next.delete("page");
|
|
385
|
-
updateSearch(next, false);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function toggleSort(name: string) {
|
|
389
|
-
const next = new URLSearchParams(searchParams);
|
|
390
|
-
if (sortField !== name) next.set("sort", name);
|
|
391
|
-
else if (!sortDescending) next.set("sort", `-${name}`);
|
|
392
|
-
else next.delete("sort");
|
|
393
|
-
next.delete("page");
|
|
394
|
-
updateSearch(next, false);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function selectPageSize(limit: ListPageSize) {
|
|
398
|
-
const next = new URLSearchParams(searchParams);
|
|
399
|
-
next.set("limit", String(limit));
|
|
400
|
-
next.delete("page");
|
|
401
|
-
updateSearch(next, false);
|
|
402
|
-
void preferences.persistWorkspace({ ...workspace, limit });
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function toggleColumn(name: string, show: boolean) {
|
|
406
|
-
// Workspace state is updated synchronously by persistWorkspace. Using it as
|
|
407
|
-
// the source prevents two quick checkbox changes from racing a router update.
|
|
408
|
-
const nextNames = new Set(workspace.columns);
|
|
409
|
-
if (show) nextNames.add(name);
|
|
410
|
-
else nextNames.delete(name);
|
|
411
|
-
const columns = availableColumnFields
|
|
412
|
-
.map((field) => field.path)
|
|
413
|
-
.filter((candidate) => nextNames.has(candidate));
|
|
414
|
-
const next = new URLSearchParams(searchParams);
|
|
415
|
-
if (columns.length === 0) next.set("columns", "");
|
|
416
|
-
else next.set("columns", columns.join(","));
|
|
417
|
-
updateSearch(next, true);
|
|
418
|
-
void preferences.persistWorkspace({ ...workspace, columns });
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
function toggleStatusColumn(show: boolean) {
|
|
422
|
-
void preferences.persistWorkspace({ ...workspace, showStatus: show });
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
function toggleUpdatedColumn(show: boolean) {
|
|
426
|
-
void preferences.persistWorkspace({ ...workspace, showUpdated: show });
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
function toggleIDColumn(show: boolean) {
|
|
430
|
-
void preferences.persistWorkspace({ ...workspace, showID: show });
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function toggleCreatedColumn(show: boolean) {
|
|
434
|
-
void preferences.persistWorkspace({ ...workspace, showCreated: show });
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
function selectFolder(folder: string) {
|
|
438
|
-
const next = new URLSearchParams(searchParams);
|
|
439
|
-
if (folder === "") next.delete("folder");
|
|
440
|
-
else next.set("folder", folder);
|
|
441
|
-
next.delete("page");
|
|
442
|
-
updateSearch(next, false);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
function selectView(view: "list" | "hierarchy") {
|
|
446
|
-
const next = new URLSearchParams(searchParams);
|
|
447
|
-
if (view === "list") next.delete("view");
|
|
448
|
-
else next.set("view", view);
|
|
449
|
-
next.delete("page");
|
|
450
|
-
updateSearch(next, false);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
function savePreset(name: string) {
|
|
454
|
-
return preferences.savePreset(name, {
|
|
455
|
-
q: query,
|
|
456
|
-
status: activeStatus,
|
|
457
|
-
folder: requestedFolder,
|
|
458
|
-
view: hierarchy ? "hierarchy" : "list",
|
|
459
|
-
filters: listFilters,
|
|
460
|
-
sort: requestedSort,
|
|
461
|
-
columns: visibleColumns.map((field) => field.path),
|
|
462
|
-
limit: pageSize,
|
|
463
|
-
showStatus,
|
|
464
|
-
showID,
|
|
465
|
-
showCreated,
|
|
466
|
-
showUpdated,
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function applyPreset(preset: CollectionListPreset) {
|
|
471
|
-
const next = new URLSearchParams();
|
|
472
|
-
if (contentLocale !== undefined) next.set("locale", contentLocale);
|
|
473
|
-
if (preset.q !== "") next.set("q", preset.q);
|
|
474
|
-
if (preset.status !== "") next.set("status", preset.status);
|
|
475
|
-
if (preset.folder !== "") next.set("folder", preset.folder);
|
|
476
|
-
if (preset.view === "hierarchy") next.set("view", "hierarchy");
|
|
477
|
-
if (preset.filters.length > 0) next.set("filters", JSON.stringify(preset.filters));
|
|
478
|
-
if (preset.sort !== "") next.set("sort", preset.sort);
|
|
479
|
-
if (preset.columns.length > 0) next.set("columns", preset.columns.join(","));
|
|
480
|
-
next.set("limit", String(preset.limit));
|
|
481
|
-
void preferences.persistWorkspace({
|
|
482
|
-
columns: preset.columns,
|
|
483
|
-
limit: preset.limit,
|
|
484
|
-
showStatus: preset.showStatus,
|
|
485
|
-
showID: preset.showID,
|
|
486
|
-
showCreated: preset.showCreated,
|
|
487
|
-
showUpdated: preset.showUpdated,
|
|
488
|
-
});
|
|
489
|
-
updateSearch(next, false);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
function selectStatus(status: string) {
|
|
493
|
-
const next = new URLSearchParams(searchParams);
|
|
494
|
-
if (status === "") next.delete("status");
|
|
495
|
-
else next.set("status", status);
|
|
496
|
-
next.delete("page");
|
|
497
|
-
updateSearch(next, false);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
function selectPage(page: number) {
|
|
501
|
-
const next = new URLSearchParams(searchParams);
|
|
502
|
-
if (page <= 1) next.delete("page");
|
|
503
|
-
else next.set("page", String(page));
|
|
504
|
-
updateSearch(next, false);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
function columnValue(document: AdminDocument, field: SchemaField) {
|
|
508
|
-
if (!canReadField(field.path, document.id)) return "—";
|
|
509
|
-
const value = documentPathValue(document, field.path);
|
|
510
|
-
if (value === undefined || value === null || value === "") return "—";
|
|
511
|
-
if (field.type === "checkbox") {
|
|
512
|
-
return value === true ? runtime.i18n.t("general:yes") : runtime.i18n.t("general:no");
|
|
513
|
-
}
|
|
514
|
-
if (field.type === "select" || field.type === "radio") {
|
|
515
|
-
return field.select?.options.find((option) => option.value === value)?.label ?? String(value);
|
|
516
|
-
}
|
|
517
|
-
if (field.type === "array") return summarizeRows(value, "row");
|
|
518
|
-
if (field.type === "blocks") return summarizeRows(value, "block");
|
|
519
|
-
if (field.type === "json" || field.plugin !== undefined) return summarizeStructured(value);
|
|
520
|
-
if (field.type === "date") return formatDateDisplay(value, field.date?.format, runtime.i18n);
|
|
521
|
-
if (referenceField(field)) {
|
|
522
|
-
return runtime.i18n.formatList(
|
|
523
|
-
fieldReferences(field, value).map(
|
|
524
|
-
(reference) =>
|
|
525
|
-
referenceLabels[referenceKey(reference.collection, reference.id)] ?? reference.id
|
|
526
|
-
)
|
|
527
|
-
);
|
|
528
|
-
}
|
|
529
|
-
if (Array.isArray(value)) return runtime.i18n.formatList(value.map(displayReference));
|
|
530
|
-
if (typeof value === "object") return displayReference(value);
|
|
531
|
-
return String(value);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
function referenceField(field: SchemaField) {
|
|
535
|
-
return (
|
|
536
|
-
field.relationship !== undefined || field.upload !== undefined || field.join !== undefined
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
function fieldReferences(field: SchemaField, value: unknown) {
|
|
541
|
-
const values = Array.isArray(value) ? value : [value];
|
|
542
|
-
return values.flatMap((candidate): { collection: string; id: string }[] => {
|
|
543
|
-
if (typeof candidate === "string") {
|
|
544
|
-
const target =
|
|
545
|
-
field.relationship?.collectionSlug ??
|
|
546
|
-
field.upload?.collectionSlug ??
|
|
547
|
-
field.join?.collectionSlug;
|
|
548
|
-
return target === undefined ? [] : [{ collection: target, id: candidate }];
|
|
549
|
-
}
|
|
550
|
-
if (typeof candidate !== "object" || candidate === null) return [];
|
|
551
|
-
const record = candidate as Record<string, unknown>;
|
|
552
|
-
const id = typeof record.id === "string" ? record.id : undefined;
|
|
553
|
-
const target =
|
|
554
|
-
typeof record.relationTo === "string"
|
|
555
|
-
? record.relationTo
|
|
556
|
-
: (field.relationship?.collectionSlug ??
|
|
557
|
-
field.upload?.collectionSlug ??
|
|
558
|
-
field.join?.collectionSlug);
|
|
559
|
-
return id === undefined || target === undefined ? [] : [{ collection: target, id }];
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
function referenceKey(collection: string, id: string) {
|
|
564
|
-
return `${collection}:${id}`;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
function referenceTitle(collection: SchemaCollection, document: AdminDocument) {
|
|
568
|
-
const titleField =
|
|
569
|
-
collection.fields.find((field) => field.name === collection.admin.useAsTitle) ??
|
|
570
|
-
collection.fields.find((field) => ["text", "email", "select", "radio"].includes(field.type));
|
|
571
|
-
const value =
|
|
572
|
-
titleField === undefined ? undefined : documentPathValue(document, titleField.path);
|
|
573
|
-
return value === undefined || value === null || value === "" ? document.id : String(value);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
function displayReference(value: unknown) {
|
|
577
|
-
if (typeof value === "string") return value;
|
|
578
|
-
if (typeof value !== "object" || value === null) return String(value ?? "—");
|
|
579
|
-
const record = value as Record<string, unknown>;
|
|
580
|
-
return String(
|
|
581
|
-
record.title ??
|
|
582
|
-
record.name ??
|
|
583
|
-
record.email ??
|
|
584
|
-
record.id ??
|
|
585
|
-
runtime.i18n.t("collections:relatedDocument")
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
function documentPathValue(document: AdminDocument, path: string) {
|
|
590
|
-
let value: unknown = document;
|
|
591
|
-
for (const segment of path.split(".")) {
|
|
592
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return undefined;
|
|
593
|
-
value = Reflect.get(value, segment);
|
|
594
|
-
}
|
|
595
|
-
return value;
|
|
104
|
+
focusSearchAfterNavigation = true;
|
|
105
|
+
return list.query.clearFilters();
|
|
596
106
|
}
|
|
597
107
|
|
|
598
|
-
function
|
|
599
|
-
|
|
600
|
-
const previews = value.slice(0, 2).map((row) => {
|
|
601
|
-
if (typeof row !== "object" || row === null) return String(row);
|
|
602
|
-
const record = row as Record<string, unknown>;
|
|
603
|
-
return String(
|
|
604
|
-
record.label ??
|
|
605
|
-
record.title ??
|
|
606
|
-
record.heading ??
|
|
607
|
-
record.name ??
|
|
608
|
-
record.blockType ??
|
|
609
|
-
runtime.i18n.t(singular === "row" ? "collections:rowNumber" : "collections:blockNumber", {
|
|
610
|
-
number: runtime.i18n.formatNumber(value.indexOf(row) + 1),
|
|
611
|
-
})
|
|
612
|
-
);
|
|
613
|
-
});
|
|
614
|
-
const summary = runtime.i18n.formatList(previews);
|
|
615
|
-
return value.length > previews.length
|
|
616
|
-
? runtime.i18n.t("collections:moreItems", {
|
|
617
|
-
summary,
|
|
618
|
-
count: runtime.i18n.formatNumber(value.length - previews.length),
|
|
619
|
-
})
|
|
620
|
-
: summary;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
function summarizeStructured(value: unknown) {
|
|
624
|
-
if (value === undefined || value === null) return "—";
|
|
625
|
-
if (typeof value !== "object") return String(value);
|
|
626
|
-
const text = JSON.stringify(value);
|
|
627
|
-
return text.length > 72 ? `${text.slice(0, 69)}…` : text;
|
|
108
|
+
function contentPath(path: string) {
|
|
109
|
+
return withContentLocale(path, contentLocale);
|
|
628
110
|
}
|
|
629
111
|
|
|
630
|
-
function requestConfirmation(action:
|
|
112
|
+
function requestConfirmation(action: BulkConfirmationAction) {
|
|
631
113
|
confirmationAction = action;
|
|
632
114
|
confirmationOpen = true;
|
|
633
115
|
}
|
|
@@ -635,316 +117,93 @@
|
|
|
635
117
|
function openBulkEdit() {
|
|
636
118
|
bulkEditOpen = true;
|
|
637
119
|
}
|
|
638
|
-
|
|
639
|
-
function applyBulkEdit(field: SchemaField, value: unknown) {
|
|
640
|
-
return bulkUpdate({ [field.name]: value });
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
async function performConfirmation() {
|
|
644
|
-
const action = confirmationAction;
|
|
645
|
-
if (action === undefined) return;
|
|
646
|
-
if (action.kind === "delete-document") await deletePermanent(action.id);
|
|
647
|
-
else if (action.kind === "delete-selected") await bulkDelete();
|
|
648
|
-
else if (action.kind === "restore-selected") await bulkRestore();
|
|
649
|
-
else if (action.kind === "delete-selected-permanently") await bulkDeletePermanent();
|
|
650
|
-
else await emptyTrash();
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
function confirmationText(action: ConfirmationAction | undefined) {
|
|
654
|
-
const count = selectedIDs.size;
|
|
655
|
-
if (action?.kind === "delete-document") {
|
|
656
|
-
return {
|
|
657
|
-
title: runtime.i18n.t("collections:confirmDeleteDocumentPermanently"),
|
|
658
|
-
description: runtime.i18n.t("collections:cannotUndo"),
|
|
659
|
-
confirmLabel: runtime.i18n.t("collections:deletePermanently"),
|
|
660
|
-
destructive: true,
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
if (action?.kind === "restore-selected") {
|
|
664
|
-
return {
|
|
665
|
-
title: runtime.i18n.t("collections:confirmRestoreSelected", {
|
|
666
|
-
count,
|
|
667
|
-
formattedCount: runtime.i18n.formatNumber(count),
|
|
668
|
-
}),
|
|
669
|
-
description: runtime.i18n.t("collections:restoreSelectedDescription"),
|
|
670
|
-
confirmLabel: runtime.i18n.t("documents:restore"),
|
|
671
|
-
destructive: false,
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
if (action?.kind === "delete-selected-permanently") {
|
|
675
|
-
return {
|
|
676
|
-
title: runtime.i18n.t("collections:confirmDeleteSelectedPermanently", {
|
|
677
|
-
count,
|
|
678
|
-
formattedCount: runtime.i18n.formatNumber(count),
|
|
679
|
-
}),
|
|
680
|
-
description: runtime.i18n.t("collections:cannotUndo"),
|
|
681
|
-
confirmLabel: runtime.i18n.t("collections:deletePermanently"),
|
|
682
|
-
destructive: true,
|
|
683
|
-
};
|
|
684
|
-
}
|
|
685
|
-
if (action?.kind === "empty-trash") {
|
|
686
|
-
const trashCount = pagination.totalDocs;
|
|
687
|
-
return {
|
|
688
|
-
title: runtime.i18n.t("collections:confirmEmptyTrash", {
|
|
689
|
-
label:
|
|
690
|
-
collection?.labels.plural.toLocaleLowerCase(runtime.i18n.language) ??
|
|
691
|
-
runtime.i18n.t("collections:documents"),
|
|
692
|
-
}),
|
|
693
|
-
description: runtime.i18n.t("collections:emptyTrashDescription", {
|
|
694
|
-
count: trashCount,
|
|
695
|
-
formattedCount: runtime.i18n.formatNumber(trashCount),
|
|
696
|
-
}),
|
|
697
|
-
confirmLabel: runtime.i18n.t("collections:emptyTrash"),
|
|
698
|
-
destructive: true,
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
return {
|
|
702
|
-
title: runtime.i18n.t("collections:confirmDeleteSelected", {
|
|
703
|
-
count,
|
|
704
|
-
formattedCount: runtime.i18n.formatNumber(count),
|
|
705
|
-
}),
|
|
706
|
-
description: runtime.i18n.t("collections:deleteSelectedDescription"),
|
|
707
|
-
confirmLabel: runtime.i18n.t("general:delete"),
|
|
708
|
-
destructive: true,
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
120
|
</script>
|
|
712
121
|
|
|
713
|
-
<section class="
|
|
714
|
-
<header class="
|
|
715
|
-
<div>
|
|
716
|
-
<
|
|
717
|
-
|
|
718
|
-
class="text-[28px] font-semibold leading-tight tracking-[-0.02em] text-foreground-strong"
|
|
719
|
-
>
|
|
720
|
-
{collection?.labels.plural ?? slug}
|
|
721
|
-
</h1>
|
|
722
|
-
{#if !trashOnly && canCreate}
|
|
723
|
-
<Link class={buttonVariants()} to={contentPath(createDocumentPath(slug))}>
|
|
724
|
-
{runtime.i18n.t("general:create")}
|
|
725
|
-
</Link>
|
|
726
|
-
{/if}
|
|
727
|
-
</div>
|
|
728
|
-
<p class="mt-1.5 text-[12.5px] text-foreground-muted">
|
|
729
|
-
{runtime.i18n.t("collections:documentCount", {
|
|
730
|
-
count: allDocuments,
|
|
731
|
-
formattedCount: runtime.i18n.formatNumber(allDocuments),
|
|
732
|
-
})}
|
|
733
|
-
{#if collection?.capabilities.versions === true}
|
|
734
|
-
<span aria-hidden="true">·</span>
|
|
735
|
-
{runtime.i18n.t("collections:draftsAndVersions")}
|
|
736
|
-
{/if}
|
|
737
|
-
</p>
|
|
738
|
-
</div>
|
|
739
|
-
<div class="flex items-center gap-2">
|
|
740
|
-
{#if !trashOnly && canCreate && collection?.capabilities.upload === true}
|
|
122
|
+
<section class="ridu-list">
|
|
123
|
+
<header class="ridu-list__header" inert={!list.navigationIdle}>
|
|
124
|
+
<div class="ridu-list__title">
|
|
125
|
+
<h1>{collection?.labels.plural ?? slug}</h1>
|
|
126
|
+
{#if !trashOnly && canCreate}
|
|
741
127
|
<Link
|
|
742
|
-
class=
|
|
743
|
-
|
|
128
|
+
class="ridu-list__pill"
|
|
129
|
+
aria-label={runtime.i18n.t("collections:createNew", {
|
|
130
|
+
label: collection?.labels.singular ?? slug,
|
|
131
|
+
})}
|
|
132
|
+
to={list.createHref}
|
|
744
133
|
>
|
|
745
|
-
|
|
746
|
-
{runtime.i18n.t("collections:bulkUpload")}
|
|
134
|
+
{runtime.i18n.t("collections:createNewButton")}
|
|
747
135
|
</Link>
|
|
748
136
|
{/if}
|
|
749
|
-
{#if
|
|
750
|
-
{
|
|
751
|
-
|
|
752
|
-
variant="destructive"
|
|
753
|
-
disabled={pagination.totalDocs === 0 || bulkPending}
|
|
754
|
-
onclick={() => requestConfirmation({ kind: "empty-trash" })}
|
|
755
|
-
>
|
|
756
|
-
{runtime.i18n.t("collections:emptyTrash")}
|
|
757
|
-
</Button>
|
|
758
|
-
{/if}
|
|
759
|
-
<Link
|
|
760
|
-
class={buttonVariants({ variant: "outline" })}
|
|
761
|
-
to={contentPath(trashOnly ? collectionPath(slug) : collectionTrashPath(slug))}
|
|
762
|
-
>
|
|
763
|
-
{#if trashOnly}<RotateCcwIcon class="size-3.5" />
|
|
764
|
-
{runtime.i18n.t("collections:backToCollection")}{:else}<Trash2Icon class="size-3.5" />
|
|
765
|
-
{runtime.i18n.t("collections:trash")}{/if}
|
|
137
|
+
{#if list.uploadHref !== undefined}
|
|
138
|
+
<Link class="ridu-list__pill" to={list.uploadHref}>
|
|
139
|
+
{runtime.i18n.t("collections:bulkUpload")}
|
|
766
140
|
</Link>
|
|
767
141
|
{/if}
|
|
768
|
-
|
|
769
|
-
</header>
|
|
770
|
-
|
|
771
|
-
{#if statusOptions.length > 0 && !trashOnly}
|
|
772
|
-
<div
|
|
773
|
-
class="mt-6 flex h-9 w-full items-center justify-start gap-5 border-b border-control-border"
|
|
774
|
-
role="group"
|
|
775
|
-
aria-label={runtime.i18n.t("collections:statusFilters")}
|
|
776
|
-
>
|
|
777
|
-
<button
|
|
778
|
-
type="button"
|
|
779
|
-
class="relative h-9 flex-none cursor-pointer px-px pb-2.5 text-[13px] text-foreground-muted outline-none after:absolute after:inset-x-0 after:bottom-[-1px] after:h-0.5 after:bg-primary after:opacity-0 after:transition-opacity hover:text-foreground-strong focus-visible:outline-2 focus-visible:outline-primary/60 focus-visible:outline-offset-2 aria-pressed:text-foreground-strong aria-pressed:after:opacity-100"
|
|
780
|
-
aria-pressed={activeStatus === ""}
|
|
781
|
-
onclick={() => selectStatus("")}
|
|
782
|
-
>
|
|
783
|
-
{runtime.i18n.t("collections:all")}
|
|
784
|
-
<span class="font-mono ms-1 text-[9.5px] text-foreground-faint">
|
|
785
|
-
{runtime.i18n.formatNumber(allDocuments)}
|
|
786
|
-
</span>
|
|
787
|
-
</button>
|
|
788
|
-
{#each statusOptions as option (option.value)}
|
|
789
|
-
{const statusCount = $derived(optionCount(option))}
|
|
142
|
+
{#if trashOnly}
|
|
790
143
|
<button
|
|
791
144
|
type="button"
|
|
792
|
-
class="
|
|
793
|
-
|
|
794
|
-
onclick={() =>
|
|
145
|
+
class="ridu-list__pill"
|
|
146
|
+
disabled={bulkPending || (pagination.totalDocs === 0 && !filtered)}
|
|
147
|
+
onclick={() => requestConfirmation("empty-trash")}
|
|
795
148
|
>
|
|
796
|
-
{
|
|
797
|
-
{#if statusCount !== undefined}
|
|
798
|
-
<span class="font-mono ms-1 text-[9.5px] text-foreground-faint">
|
|
799
|
-
{runtime.i18n.formatNumber(statusCount)}
|
|
800
|
-
</span>
|
|
801
|
-
{/if}
|
|
149
|
+
{runtime.i18n.t("collections:emptyTrash")}
|
|
802
150
|
</button>
|
|
803
|
-
{/
|
|
151
|
+
{/if}
|
|
804
152
|
</div>
|
|
805
|
-
|
|
153
|
+
|
|
154
|
+
<div class="ridu-list__header-actions">
|
|
155
|
+
{#if collection}
|
|
156
|
+
{#key collection.slug}
|
|
157
|
+
<APIReference {collection} />
|
|
158
|
+
{/key}
|
|
159
|
+
{/if}
|
|
160
|
+
<CollectionListBulkActions
|
|
161
|
+
onEdit={openBulkEdit}
|
|
162
|
+
onRequestPublish={() => requestConfirmation("publish-selected")}
|
|
163
|
+
onRequestUnpublish={() => requestConfirmation("unpublish-selected")}
|
|
164
|
+
onRequestDelete={() => requestConfirmation("delete-selected")}
|
|
165
|
+
onRequestRestore={() => requestConfirmation("restore-selected")}
|
|
166
|
+
onRequestDeletePermanent={() => requestConfirmation("delete-selected-permanently")}
|
|
167
|
+
/>
|
|
168
|
+
|
|
169
|
+
{#if collection?.capabilities.trash}
|
|
170
|
+
<nav class="ridu-list__views" aria-label={runtime.i18n.t("collections:collectionViews")}>
|
|
171
|
+
{#each collectionViews as view}
|
|
172
|
+
{#if trashOnly === view.trash}
|
|
173
|
+
<button type="button" class="ridu-list__view" aria-current="page" disabled>
|
|
174
|
+
{view.label}
|
|
175
|
+
</button>
|
|
176
|
+
{:else}
|
|
177
|
+
<Link
|
|
178
|
+
class="ridu-list__view"
|
|
179
|
+
to={contentPath(view.trash ? collectionTrashPath(slug) : collectionPath(slug))}
|
|
180
|
+
>
|
|
181
|
+
{view.label}
|
|
182
|
+
</Link>
|
|
183
|
+
{/if}
|
|
184
|
+
{/each}
|
|
185
|
+
</nav>
|
|
186
|
+
{/if}
|
|
187
|
+
</div>
|
|
188
|
+
</header>
|
|
806
189
|
|
|
807
190
|
{#if error !== undefined}
|
|
808
|
-
<Banner class="
|
|
809
|
-
<span class="
|
|
810
|
-
<span class="
|
|
191
|
+
<Banner class="ridu-list__error" tone="destructive">
|
|
192
|
+
<span class="ridu-list__error-marker" aria-hidden="true"></span>
|
|
193
|
+
<span class="ridu-list__error-message">{error}</span>
|
|
811
194
|
<Button variant="outline" size="sm" onclick={retry}>
|
|
812
195
|
{runtime.i18n.t("general:retry")}
|
|
813
196
|
</Button>
|
|
814
197
|
</Banner>
|
|
815
198
|
{/if}
|
|
816
199
|
|
|
817
|
-
{#
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
class={buttonVariants({ variant: "outline", class: "h-[31px] gap-1.75 px-3" })}
|
|
821
|
-
to={contentPath(collectionPath(folderCollection.slug))}
|
|
822
|
-
>
|
|
823
|
-
<FolderIcon class="size-3" />
|
|
824
|
-
{runtime.i18n.t("collections:manageFolders")}
|
|
825
|
-
</Link>
|
|
826
|
-
{/if}
|
|
827
|
-
{/snippet}
|
|
828
|
-
|
|
829
|
-
<CollectionListWorkspaceToolbar
|
|
830
|
-
{slug}
|
|
831
|
-
{query}
|
|
832
|
-
{searchLabel}
|
|
833
|
-
bind:searchInput
|
|
834
|
-
filterFields={availableFilterFields}
|
|
835
|
-
filters={listFilters}
|
|
836
|
-
{canReadField}
|
|
837
|
-
{folders}
|
|
838
|
-
{requestedFolder}
|
|
839
|
-
manageFoldersLink={folderCollection === undefined ? undefined : manageFoldersLink}
|
|
840
|
-
showFolder={folderField !== undefined && !trashOnly}
|
|
841
|
-
showHierarchy={parentField !== undefined && !trashOnly}
|
|
842
|
-
{hierarchy}
|
|
843
|
-
sessionActive={runtime.session !== undefined && !trashOnly}
|
|
844
|
-
{presets}
|
|
845
|
-
{presetsPending}
|
|
846
|
-
{statusColumnAvailable}
|
|
847
|
-
{availableColumnFields}
|
|
848
|
-
{visibleColumns}
|
|
849
|
-
{showStatus}
|
|
850
|
-
{showID}
|
|
851
|
-
{showCreated}
|
|
852
|
-
{showUpdated}
|
|
853
|
-
{pageSize}
|
|
854
|
-
onSearch={handleSearch}
|
|
855
|
-
onClearSearch={clearSearch}
|
|
856
|
-
onFiltersChange={updateListFilters}
|
|
857
|
-
onSelectFolder={selectFolder}
|
|
858
|
-
onSelectView={selectView}
|
|
859
|
-
onSavePreset={savePreset}
|
|
860
|
-
onApplyPreset={applyPreset}
|
|
861
|
-
onDeletePreset={preferences.deletePreset}
|
|
862
|
-
onToggleColumn={toggleColumn}
|
|
863
|
-
onToggleStatus={toggleStatusColumn}
|
|
864
|
-
onToggleID={toggleIDColumn}
|
|
865
|
-
onToggleCreated={toggleCreatedColumn}
|
|
866
|
-
onToggleUpdated={toggleUpdatedColumn}
|
|
867
|
-
onSelectPageSize={selectPageSize}
|
|
868
|
-
/>
|
|
200
|
+
{#key slug}
|
|
201
|
+
<ListToolbar bind:searchInput />
|
|
202
|
+
{/key}
|
|
869
203
|
|
|
870
|
-
<CollectionListResults
|
|
871
|
-
i18n={runtime.i18n}
|
|
872
|
-
{controller}
|
|
873
|
-
resourceKey={slug}
|
|
874
|
-
{collection}
|
|
875
|
-
{titleField}
|
|
876
|
-
{customListCells}
|
|
877
|
-
{visibleColumns}
|
|
878
|
-
{showID}
|
|
879
|
-
{showCreated}
|
|
880
|
-
{showUpdated}
|
|
881
|
-
parentFieldName={parentField?.name}
|
|
882
|
-
{hierarchy}
|
|
883
|
-
{trashOnly}
|
|
884
|
-
filtered={query !== "" ||
|
|
885
|
-
activeStatus !== "" ||
|
|
886
|
-
requestedFolder !== "" ||
|
|
887
|
-
listFilters.length > 0}
|
|
888
|
-
{sortField}
|
|
889
|
-
{sortDescending}
|
|
890
|
-
{columnValue}
|
|
891
|
-
onClearFilters={clearFiltersAndFocusSearch}
|
|
892
|
-
onToggleSort={toggleSort}
|
|
893
|
-
onSelectPage={selectPage}
|
|
894
|
-
onRequestDeletePermanent={(id) => requestConfirmation({ kind: "delete-document", id })}
|
|
895
|
-
>
|
|
896
|
-
{#snippet documentLink(document)}
|
|
897
|
-
<Link class="block max-w-[600px]" to={contentPath(documentPath(slug, document.id))}>
|
|
898
|
-
<span
|
|
899
|
-
class="block truncate text-[14px] font-medium text-foreground-strong transition-colors group-hover:text-primary"
|
|
900
|
-
>
|
|
901
|
-
{title(document)}
|
|
902
|
-
</span>
|
|
903
|
-
</Link>
|
|
904
|
-
{/snippet}
|
|
905
|
-
{#snippet createAction()}
|
|
906
|
-
<Link
|
|
907
|
-
class={buttonVariants({ variant: "outline" })}
|
|
908
|
-
to={contentPath(createDocumentPath(slug))}
|
|
909
|
-
>
|
|
910
|
-
{runtime.i18n.t("collections:createNew", {
|
|
911
|
-
label:
|
|
912
|
-
collection?.labels.singular.toLocaleLowerCase(runtime.i18n.language) ??
|
|
913
|
-
runtime.i18n.t("collections:document"),
|
|
914
|
-
})}
|
|
915
|
-
</Link>
|
|
916
|
-
{/snippet}
|
|
917
|
-
</CollectionListResults>
|
|
204
|
+
<CollectionListResults onClearFilters={clearFiltersAndFocusSearch} />
|
|
918
205
|
</section>
|
|
919
206
|
|
|
920
|
-
<
|
|
921
|
-
i18n={runtime.i18n}
|
|
922
|
-
{controller}
|
|
923
|
-
{trashOnly}
|
|
924
|
-
versioned={collection?.capabilities.versions === true}
|
|
925
|
-
hasBulkEditableFields={bulkEditableFields.length > 0}
|
|
926
|
-
onEdit={openBulkEdit}
|
|
927
|
-
onRequestDelete={() => requestConfirmation({ kind: "delete-selected" })}
|
|
928
|
-
onRequestRestore={() => requestConfirmation({ kind: "restore-selected" })}
|
|
929
|
-
onRequestDeletePermanent={() => requestConfirmation({ kind: "delete-selected-permanently" })}
|
|
930
|
-
onOpenDocument={(id) => navigate(contentPath(documentPath(slug, id)))}
|
|
931
|
-
/>
|
|
932
|
-
|
|
933
|
-
<ConfirmationDialog
|
|
934
|
-
bind:open={confirmationOpen}
|
|
935
|
-
title={confirmationCopy.title}
|
|
936
|
-
description={confirmationCopy.description}
|
|
937
|
-
confirmLabel={confirmationCopy.confirmLabel}
|
|
938
|
-
cancelLabel={runtime.i18n.t("general:cancel")}
|
|
939
|
-
destructive={confirmationCopy.destructive}
|
|
940
|
-
disabled={bulkPending}
|
|
941
|
-
onconfirm={performConfirmation}
|
|
942
|
-
/>
|
|
207
|
+
<BulkConfirmation bind:open={confirmationOpen} action={confirmationAction} />
|
|
943
208
|
|
|
944
|
-
<
|
|
945
|
-
bind:open={bulkEditOpen}
|
|
946
|
-
selectedCount={selectedIDs.size}
|
|
947
|
-
fields={bulkEditableFields}
|
|
948
|
-
pending={bulkPending}
|
|
949
|
-
onApply={applyBulkEdit}
|
|
950
|
-
/>
|
|
209
|
+
<CollectionListBulkEditorLoader bind:open={bulkEditOpen} />
|