includio-cms 0.25.0 → 0.26.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/API.md +57 -4
- package/CHANGELOG.md +53 -0
- package/DOCS.md +1 -1
- package/README.md +2 -0
- package/ROADMAP.md +6 -0
- package/dist/admin/client/account/lang.d.ts +1 -0
- package/dist/admin/client/account/lang.js +4 -2
- package/dist/admin/client/account/profile-section.svelte +2 -2
- package/dist/admin/client/account/security-section.svelte +27 -4
- package/dist/admin/client/account/sessions-section.svelte +1 -1
- package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
- package/dist/admin/client/admin/dashboard-page.svelte +34 -10
- package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
- package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
- package/dist/admin/client/collection/collection-entries.svelte +52 -36
- package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
- package/dist/admin/client/collection/collection.svelte +28 -14
- package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
- package/dist/admin/client/collection/data-table.svelte +279 -130
- package/dist/admin/client/collection/data-table.svelte.d.ts +11 -0
- package/dist/admin/client/collection/date-cell.svelte +4 -4
- package/dist/admin/client/collection/row-actions.svelte +2 -1
- package/dist/admin/client/collection/sortable-header.svelte +33 -9
- package/dist/admin/client/collection/state-display.svelte +102 -0
- package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
- package/dist/admin/client/collection/status-badge.svelte +99 -11
- package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
- package/dist/admin/client/collection/table-pagination.svelte +21 -6
- package/dist/admin/client/collection/table-toolbar.svelte +105 -80
- package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
- package/dist/admin/client/entry/entry-form.svelte +36 -11
- package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
- package/dist/admin/client/entry/entry-header.svelte +22 -15
- package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
- package/dist/admin/client/entry/entry.svelte +269 -165
- package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
- package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
- package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
- package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
- package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
- package/dist/admin/client/entry/header/status-badge.svelte +60 -15
- package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
- package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
- package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
- package/dist/admin/client/entry/utils.d.ts +14 -0
- package/dist/admin/client/entry/utils.js +28 -0
- package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
- package/dist/admin/client/form/form-submissions.svelte +143 -194
- package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
- package/dist/admin/client/login/lang.d.ts +3 -0
- package/dist/admin/client/login/lang.js +10 -4
- package/dist/admin/client/login/login-form.svelte +8 -1
- package/dist/admin/client/login/reset-password-page.svelte +24 -3
- package/dist/admin/client/login/schema.d.ts +14 -2
- package/dist/admin/client/login/schema.js +19 -8
- package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
- package/dist/admin/client/media/media-page.svelte +1 -1
- package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
- package/dist/admin/client/shop/coupon-form.svelte +282 -138
- package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
- package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
- package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
- package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
- package/dist/admin/client/shop/coupon-schema.js +53 -0
- package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
- package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
- package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
- package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
- package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
- package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
- package/dist/admin/client/shop/shop-order-detail-page.svelte +113 -84
- package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
- package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
- package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
- package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
- package/dist/admin/client/users/accept-invite-page.svelte +24 -3
- package/dist/admin/client/users/create-user-dialog.svelte +3 -8
- package/dist/admin/client/users/lang.d.ts +2 -0
- package/dist/admin/client/users/lang.js +4 -0
- package/dist/admin/client/users/pending-invitations.svelte +2 -9
- package/dist/admin/client/users/user-name-cell.svelte +20 -0
- package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
- package/dist/admin/client/users/user-role-badge.svelte +16 -0
- package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
- package/dist/admin/client/users/user-row-actions.svelte +72 -0
- package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
- package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
- package/dist/admin/client/users/users-page.svelte +283 -497
- package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
- package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
- package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
- package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
- package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
- package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
- package/dist/admin/components/fields/blocks-field.svelte +46 -1
- package/dist/admin/components/fields/boolean-field.svelte +1 -1
- package/dist/admin/components/fields/field-renderer.svelte +23 -21
- package/dist/admin/components/fields/file-field.svelte +344 -30
- package/dist/admin/components/fields/media-field.svelte +16 -2
- package/dist/admin/components/fields/radio-field.svelte +22 -0
- package/dist/admin/components/fields/relation-field.svelte +123 -97
- package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
- package/dist/admin/components/fields/seo-field.svelte +60 -30
- package/dist/admin/components/fields/shop-field.svelte +9 -4
- package/dist/admin/components/fields/simple-array-field.svelte +321 -151
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
- package/dist/admin/components/fields/slug-field.svelte +146 -21
- package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
- package/dist/admin/components/fields/text-field.svelte +7 -2
- package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
- package/dist/admin/components/fields/url-field.svelte +36 -23
- package/dist/admin/components/forms/form-error-summary.svelte +143 -0
- package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
- package/dist/admin/components/layout/app-sidebar.svelte +7 -2
- package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
- package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
- package/dist/admin/components/layout/lang.d.ts +5 -0
- package/dist/admin/components/layout/lang.js +10 -0
- package/dist/admin/components/layout/layout-renderer.svelte +71 -2
- package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
- package/dist/admin/components/layout/layout-tabs.svelte +172 -0
- package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
- package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
- package/dist/admin/components/layout/nav-collections.svelte +23 -36
- package/dist/admin/components/layout/nav-forms.svelte +19 -35
- package/dist/admin/components/layout/nav-main.svelte +3 -28
- package/dist/admin/components/layout/nav-search.svelte +70 -2
- package/dist/admin/components/layout/nav-section.svelte +77 -0
- package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
- package/dist/admin/components/layout/nav-shop.svelte +3 -27
- package/dist/admin/components/layout/nav-singletons.svelte +16 -28
- package/dist/admin/components/layout/page-header.stories.svelte +93 -0
- package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
- package/dist/admin/components/layout/page-header.svelte +68 -0
- package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
- package/dist/admin/components/layout/site-header.svelte +9 -0
- package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
- package/dist/admin/components/media/file/file-name-input.svelte +6 -2
- package/dist/admin/components/media/file/file-preview.svelte +130 -17
- package/dist/admin/components/media/file-upload.svelte +16 -7
- package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
- package/dist/admin/components/media/files-list.svelte +153 -53
- package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
- package/dist/admin/components/media/media-library.svelte +577 -198
- package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
- package/dist/admin/components/media/media-selector.svelte +4 -2
- package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
- package/dist/admin/components/media/tag-sidebar.svelte +4 -4
- package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
- package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
- package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
- package/dist/admin/components/tiptap/content-editor.svelte +28 -24
- package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
- package/dist/admin/components/tiptap/extensions.js +5 -1
- package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
- package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
- package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
- package/dist/admin/i18n/errors.d.ts +140 -0
- package/dist/admin/i18n/errors.js +151 -0
- package/dist/admin/remote/entry.remote.d.ts +59 -4
- package/dist/admin/remote/entry.remote.js +239 -62
- package/dist/admin/remote/shop.remote.d.ts +37 -32
- package/dist/admin/remote/shop.remote.js +9 -2
- package/dist/admin/shared/password-generate.d.ts +6 -0
- package/dist/admin/shared/password-generate.js +40 -0
- package/dist/admin/shared/password-schema.d.ts +6 -0
- package/dist/admin/shared/password-schema.js +10 -3
- package/dist/admin/styles/admin.css +23 -6
- package/dist/admin/styles/tokens.md +244 -0
- package/dist/admin/utils/accordionActivation.d.ts +13 -0
- package/dist/admin/utils/accordionActivation.js +35 -0
- package/dist/admin/utils/entryLabel.d.ts +23 -0
- package/dist/admin/utils/entryLabel.js +51 -12
- package/dist/admin/utils/field-a11y.d.ts +29 -0
- package/dist/admin/utils/field-a11y.js +23 -0
- package/dist/admin/utils/fieldPathElement.d.ts +9 -0
- package/dist/admin/utils/fieldPathElement.js +18 -0
- package/dist/admin/utils/fileDisplay.d.ts +10 -0
- package/dist/admin/utils/fileDisplay.js +26 -0
- package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
- package/dist/admin/utils/flattenFormErrors.js +102 -0
- package/dist/admin/utils/formatters.d.ts +12 -0
- package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
- package/dist/admin/utils/scrollWithin.d.ts +9 -0
- package/dist/admin/utils/scrollWithin.js +32 -0
- package/dist/admin/utils/tabActivation.d.ts +12 -0
- package/dist/admin/utils/tabActivation.js +24 -0
- package/dist/cms/runtime/schema.d.ts +1 -0
- package/dist/cms/runtime/schema.js +1 -0
- package/dist/cms/runtime/types.d.ts +80 -7
- package/dist/components/ui/accordion/accordion-content.svelte +17 -3
- package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
- package/dist/components/ui/alert/alert.stories.svelte +14 -0
- package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
- package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
- package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
- package/dist/components/ui/badge/badge.stories.svelte +15 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
- package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
- package/dist/components/ui/button/button.stories.svelte +53 -6
- package/dist/components/ui/button/button.svelte +39 -5
- package/dist/components/ui/button/button.svelte.d.ts +4 -0
- package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
- package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
- package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/card/card.stories.svelte +7 -0
- package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
- package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
- package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
- package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
- package/dist/components/ui/checkbox/checkbox.svelte +3 -3
- package/dist/components/ui/command/command.stories.svelte +18 -0
- package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
- package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
- package/dist/components/ui/dialog/dialog-content.svelte +5 -0
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
- package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
- package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
- package/dist/components/ui/field/field-context.svelte.js +9 -0
- package/dist/components/ui/field/field-control.svelte +18 -0
- package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
- package/dist/components/ui/field/field-description.svelte +12 -0
- package/dist/components/ui/field/field-error.svelte +14 -6
- package/dist/components/ui/field/field-label.svelte +10 -0
- package/dist/components/ui/field/field.stories.svelte +95 -9
- package/dist/components/ui/field/field.svelte +57 -0
- package/dist/components/ui/field/field.svelte.d.ts +2 -0
- package/dist/components/ui/field/index.d.ts +3 -1
- package/dist/components/ui/field/index.js +4 -2
- package/dist/components/ui/form/form-field-errors.svelte +1 -1
- package/dist/components/ui/form/form.stories.svelte +25 -0
- package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
- package/dist/components/ui/input/input.stories.svelte +26 -0
- package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
- package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
- package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/item/item.stories.svelte +61 -0
- package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
- package/dist/components/ui/label/label.stories.svelte +7 -0
- package/dist/components/ui/live-region/index.d.ts +1 -0
- package/dist/components/ui/live-region/index.js +1 -0
- package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
- package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
- package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
- package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
- package/dist/components/ui/live-region/live-region.svelte +12 -0
- package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
- package/dist/components/ui/popover/popover.stories.svelte +34 -0
- package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
- package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
- package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
- package/dist/components/ui/select/select.stories.svelte +49 -0
- package/dist/components/ui/separator/separator.stories.svelte +18 -0
- package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
- package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
- package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
- package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
- package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
- package/dist/components/ui/skeleton/skeleton.svelte +6 -0
- package/dist/components/ui/sonner/index.d.ts +1 -1
- package/dist/components/ui/sonner/index.js +1 -1
- package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
- package/dist/components/ui/sonner/sonner.svelte +17 -1
- package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
- package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
- package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
- package/dist/components/ui/switch/switch.stories.svelte +56 -0
- package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
- package/dist/components/ui/table/table-cell.svelte +1 -1
- package/dist/components/ui/table/table-head.svelte +1 -1
- package/dist/components/ui/table/table.stories.svelte +68 -0
- package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
- package/dist/components/ui/table/table.svelte +1 -1
- package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
- package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
- package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
- package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
- package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
- package/dist/core/fields/fieldSchemaToTs.js +234 -90
- package/dist/core/fields/layoutUtils.d.ts +4 -1
- package/dist/core/fields/layoutUtils.js +41 -4
- package/dist/core/fields/resolveSeo.d.ts +70 -0
- package/dist/core/fields/resolveSeo.js +88 -0
- package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
- package/dist/core/fields/seoFieldDescriptor.js +74 -0
- package/dist/core/fields/slugPath.d.ts +13 -0
- package/dist/core/fields/slugPath.js +32 -0
- package/dist/core/fields/urlUtils.d.ts +8 -0
- package/dist/core/fields/urlUtils.js +27 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/server/entries/operations/create.js +13 -0
- package/dist/core/server/entries/operations/get.d.ts +7 -0
- package/dist/core/server/entries/operations/get.js +10 -6
- package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
- package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
- package/dist/core/server/entries/operations/update.d.ts +6 -1
- package/dist/core/server/entries/operations/update.js +24 -1
- package/dist/core/server/fields/slugResolver.d.ts +3 -13
- package/dist/core/server/fields/slugResolver.js +8 -37
- package/dist/core/server/generator/fields.js +10 -17
- package/dist/core/server/generator/formFields.js +2 -1
- package/dist/core/server/generator/generator.js +4 -4
- package/dist/core/server/generator/utils.d.ts +1 -0
- package/dist/core/server/generator/utils.js +4 -0
- package/dist/paraglide/messages/_index.d.ts +3 -36
- package/dist/paraglide/messages/_index.js +3 -71
- package/dist/paraglide/messages/hello_world.d.ts +5 -0
- package/dist/paraglide/messages/hello_world.js +33 -0
- package/dist/paraglide/messages/login_hello.d.ts +16 -0
- package/dist/paraglide/messages/login_hello.js +34 -0
- package/dist/paraglide/messages/login_please_login.d.ts +16 -0
- package/dist/paraglide/messages/login_please_login.js +34 -0
- package/dist/shop/server/orders.d.ts +1 -0
- package/dist/shop/server/orders.js +14 -0
- package/dist/shop/server/shop-data.d.ts +2 -0
- package/dist/shop/server/shop-data.js +20 -5
- package/dist/sveltekit/server/handle.js +17 -0
- package/dist/types/cms.schema.js +4 -2
- package/dist/types/fields.d.ts +35 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/layout.d.ts +35 -2
- package/dist/updates/0.26.0/index.d.ts +2 -0
- package/dist/updates/0.26.0/index.js +51 -0
- package/dist/updates/index.js +3 -1
- package/package.json +29 -7
- package/dist/admin/client/collection/empty-state.svelte +0 -28
- package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
- package/dist/admin/client/form/submission-status-badge.svelte +0 -41
- package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
- package/dist/admin/components/media/file-preview.svelte +0 -51
- package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
- package/dist/admin/utils/formatDate.d.ts +0 -5
- package/dist/paraglide/messages/en.d.ts +0 -5
- package/dist/paraglide/messages/en.js +0 -14
- package/dist/paraglide/messages/pl.d.ts +0 -5
- package/dist/paraglide/messages/pl.js +0 -14
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AriaCMS — Error message catalog (COGA-friendly, PL/EN).
|
|
3
|
+
*
|
|
4
|
+
* Tone-of-voice (zob. `src/stories/docs/tone-of-voice.mdx`):
|
|
5
|
+
* - Mów do użytkownika, nie o nim
|
|
6
|
+
* - Konkretnie + akcja co zrobić, nie sucha diagnoza
|
|
7
|
+
* - Bez żargonu, kodów HTTP, "UWAGA!", "Validation failed"
|
|
8
|
+
* - Bez strachu — prowadź, nie strasz
|
|
9
|
+
*
|
|
10
|
+
* Wzorzec: "Brak/Problem X — zrób Y, żeby Z."
|
|
11
|
+
*
|
|
12
|
+
* `@public` od v0.26.0. Migracja do paraglide w S10.
|
|
13
|
+
*/
|
|
14
|
+
export const errorMessages = {
|
|
15
|
+
validation: {
|
|
16
|
+
required: {
|
|
17
|
+
pl: "Wpisz to pole, żeby zapisać.",
|
|
18
|
+
en: "Fill in this field to save.",
|
|
19
|
+
},
|
|
20
|
+
invalidEmail: {
|
|
21
|
+
pl: "Sprawdź email — wygląda jakby brakowało @ i domeny.",
|
|
22
|
+
en: "Check the email — looks like @ or domain is missing.",
|
|
23
|
+
},
|
|
24
|
+
minLength: (n) => ({
|
|
25
|
+
pl: `Wpisz przynajmniej ${n} ${pluralPL(n, "znak", "znaki", "znaków")}.`,
|
|
26
|
+
en: `Use at least ${n} character${n === 1 ? "" : "s"}.`,
|
|
27
|
+
}),
|
|
28
|
+
passwordWeak: {
|
|
29
|
+
pl: "Hasło musi mieć wielką literę, cyfrę i znak specjalny — to chroni twoje konto.",
|
|
30
|
+
en: "Password needs an uppercase letter, a digit and a special character — for your account safety.",
|
|
31
|
+
},
|
|
32
|
+
passwordsDoNotMatch: {
|
|
33
|
+
pl: "Hasła się różnią — wpisz to samo w obu polach.",
|
|
34
|
+
en: "Passwords don't match — type the same one in both fields.",
|
|
35
|
+
},
|
|
36
|
+
invalidFormat: {
|
|
37
|
+
pl: "Sprawdź wpisaną wartość — format wygląda na inny niż oczekiwany.",
|
|
38
|
+
en: "Check the value — the format looks unexpected.",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
network: {
|
|
42
|
+
offline: {
|
|
43
|
+
pl: "Brak połączenia z internetem — sprawdź sieć i spróbuj ponownie.",
|
|
44
|
+
en: "No internet connection — check your network and try again.",
|
|
45
|
+
},
|
|
46
|
+
timeout: {
|
|
47
|
+
pl: "Serwer odpowiada wolno — spróbuj jeszcze raz za chwilę.",
|
|
48
|
+
en: "The server is slow to respond — try again in a moment.",
|
|
49
|
+
},
|
|
50
|
+
generic: {
|
|
51
|
+
pl: "Nie udało się połączyć — spróbuj jeszcze raz.",
|
|
52
|
+
en: "Couldn't connect — try again.",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
permission: {
|
|
56
|
+
denied: {
|
|
57
|
+
pl: "Nie masz dostępu do tego działania — poproś administratora o uprawnienia.",
|
|
58
|
+
en: "You don't have access to this action — ask an admin for permissions.",
|
|
59
|
+
},
|
|
60
|
+
sessionExpired: {
|
|
61
|
+
pl: "Sesja wygasła — zaloguj się ponownie, żeby kontynuować.",
|
|
62
|
+
en: "Your session expired — sign in again to continue.",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
conflict: {
|
|
66
|
+
nameTaken: {
|
|
67
|
+
pl: "Ta nazwa jest już zajęta — wybierz inną.",
|
|
68
|
+
en: "That name is already taken — pick a different one.",
|
|
69
|
+
},
|
|
70
|
+
alreadyExists: {
|
|
71
|
+
pl: "Taki wpis już istnieje — sprawdź czy nie tworzysz duplikatu.",
|
|
72
|
+
en: "An item like this already exists — check that you're not duplicating it.",
|
|
73
|
+
},
|
|
74
|
+
staleData: {
|
|
75
|
+
pl: "Ktoś zaktualizował te dane — odśwież stronę i wprowadź zmiany ponownie.",
|
|
76
|
+
en: "Someone updated this data — refresh the page and try again.",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
server: {
|
|
80
|
+
saveFailed: {
|
|
81
|
+
pl: "Nie udało się zapisać — spróbuj jeszcze raz.",
|
|
82
|
+
en: "Couldn't save — try again.",
|
|
83
|
+
},
|
|
84
|
+
loadFailed: {
|
|
85
|
+
pl: "Nie udało się wczytać danych — odśwież stronę.",
|
|
86
|
+
en: "Couldn't load the data — refresh the page.",
|
|
87
|
+
},
|
|
88
|
+
uploadFailed: {
|
|
89
|
+
pl: "Nie udało się przesłać pliku — spróbuj jeszcze raz.",
|
|
90
|
+
en: "Couldn't upload the file — try again.",
|
|
91
|
+
},
|
|
92
|
+
generic: {
|
|
93
|
+
pl: "Coś poszło nie tak — spróbuj jeszcze raz.",
|
|
94
|
+
en: "Something went wrong — try again.",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
upload: {
|
|
98
|
+
fileTooLarge: (maxMB) => ({
|
|
99
|
+
pl: `Plik za duży — maksymalnie ${maxMB} MB. Spróbuj go skompresować.`,
|
|
100
|
+
en: `File too large — max ${maxMB} MB. Try compressing it.`,
|
|
101
|
+
}),
|
|
102
|
+
unsupportedType: {
|
|
103
|
+
pl: "Ten format nie jest obsługiwany — wybierz inny plik.",
|
|
104
|
+
en: "This format isn't supported — pick a different file.",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
notFound: {
|
|
108
|
+
entry: {
|
|
109
|
+
pl: "Nie znaleziono wpisu — mógł zostać usunięty lub przeniesiony.",
|
|
110
|
+
en: "Entry not found — it may have been deleted or moved.",
|
|
111
|
+
},
|
|
112
|
+
page: {
|
|
113
|
+
pl: "Nie znaleziono strony — sprawdź adres lub wróć do panelu.",
|
|
114
|
+
en: "Page not found — check the address or return to the dashboard.",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
export const successMessages = {
|
|
119
|
+
saved: {
|
|
120
|
+
pl: "Zapisano.",
|
|
121
|
+
en: "Saved.",
|
|
122
|
+
},
|
|
123
|
+
published: {
|
|
124
|
+
pl: "Opublikowano — zmiany są już widoczne na stronie.",
|
|
125
|
+
en: "Published — changes are now live.",
|
|
126
|
+
},
|
|
127
|
+
uploaded: {
|
|
128
|
+
pl: "Plik przesłany.",
|
|
129
|
+
en: "File uploaded.",
|
|
130
|
+
},
|
|
131
|
+
deleted: {
|
|
132
|
+
pl: "Usunięto.",
|
|
133
|
+
en: "Deleted.",
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Pobierz zlokalizowany komunikat dla interfejsu.
|
|
138
|
+
* @example pickError(errorMessages.server.saveFailed, lang.current)
|
|
139
|
+
*/
|
|
140
|
+
export function pickError(msg, lang) {
|
|
141
|
+
return msg[lang];
|
|
142
|
+
}
|
|
143
|
+
function pluralPL(n, singular, few, many) {
|
|
144
|
+
const mod10 = n % 10;
|
|
145
|
+
const mod100 = n % 100;
|
|
146
|
+
if (n === 1)
|
|
147
|
+
return singular;
|
|
148
|
+
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20))
|
|
149
|
+
return few;
|
|
150
|
+
return many;
|
|
151
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Localized } from '../../types/languages.js';
|
|
1
2
|
import { type RawEntry } from '../../types/entries.js';
|
|
2
3
|
export declare const getRawEntries: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
3
4
|
ids?: string[] | undefined;
|
|
@@ -25,12 +26,30 @@ export declare const getEntries: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
|
25
26
|
direction: "asc" | "desc";
|
|
26
27
|
} | undefined;
|
|
27
28
|
}, import("../../types/entries.js").Entry[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Cross-collection search for the URL field's internal-link picker. Matches
|
|
31
|
+
* the term (case-insensitive, OR) against each collection's admin-title field
|
|
32
|
+
* (`entryAdminTitle`), its `slug`-type field, and `seo.slug` / `seo.title`.
|
|
33
|
+
* The previous `getEntries({ dataLike })` call was a no-op because it never
|
|
34
|
+
* passed a collection slug (`if (!input.slug) return []`).
|
|
35
|
+
*/
|
|
36
|
+
export declare const searchLinkableEntries: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
37
|
+
term: string;
|
|
38
|
+
language?: string | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
_id: string;
|
|
41
|
+
_slug: string;
|
|
42
|
+
_url?: string;
|
|
43
|
+
title: string;
|
|
44
|
+
slug: string;
|
|
45
|
+
}[]>;
|
|
28
46
|
export declare const getEntryLabels: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
29
47
|
slug: string;
|
|
30
48
|
ids?: string[] | undefined;
|
|
31
49
|
search?: string | undefined;
|
|
32
50
|
limit?: number | undefined;
|
|
33
51
|
status?: "draft" | "published" | "all" | undefined;
|
|
52
|
+
language?: string | undefined;
|
|
34
53
|
}, {
|
|
35
54
|
id: string;
|
|
36
55
|
label: string;
|
|
@@ -58,7 +77,7 @@ export declare const updateEntryVersionCommand: import("@sveltejs/kit").RemoteCo
|
|
|
58
77
|
entryId: string;
|
|
59
78
|
lang: string;
|
|
60
79
|
data: Record<string, unknown>;
|
|
61
|
-
type: "draft" | "published-now" | "published-scheduled" | "cancel-published";
|
|
80
|
+
type: "draft" | "published-now" | "published-scheduled" | "cancel-published" | "cancel-scheduled";
|
|
62
81
|
scheduledAt?: Date | undefined;
|
|
63
82
|
}, Promise<import("../../types/entries.js").DbEntryVersion | undefined>>;
|
|
64
83
|
export declare const updateEntryCommand: import("@sveltejs/kit").RemoteCommand<{
|
|
@@ -79,18 +98,54 @@ export declare const getEntryVersion: import("@sveltejs/kit").RemoteQueryFunctio
|
|
|
79
98
|
id: string;
|
|
80
99
|
language: string;
|
|
81
100
|
}, import("../../types/entries.js").Entry | null>;
|
|
82
|
-
|
|
101
|
+
/**
|
|
102
|
+
* `containerLabel` carries the collection's plural label for collection entries
|
|
103
|
+
* and the single's name for singles; clients localise it. For collection entries
|
|
104
|
+
* `label` is the entry's own title (or `null` to fall back to the slug); for
|
|
105
|
+
* singles `label` is always `null` — the title shown is `containerLabel`.
|
|
106
|
+
*/
|
|
107
|
+
export declare const getRecentEntries: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
108
|
+
language: string;
|
|
109
|
+
limit?: number | undefined;
|
|
110
|
+
}, {
|
|
83
111
|
entryId: string;
|
|
84
112
|
slug: string;
|
|
85
|
-
|
|
113
|
+
kind: "collection" | "single";
|
|
114
|
+
containerLabel: Localized;
|
|
86
115
|
label: string | null;
|
|
116
|
+
labelLanguage: string | null;
|
|
87
117
|
status: "draft" | "published" | "scheduled";
|
|
88
118
|
updatedAt: Date;
|
|
89
119
|
}[]>;
|
|
90
|
-
export declare const getRecentActivity: import("@sveltejs/kit").RemoteQueryFunction<
|
|
120
|
+
export declare const getRecentActivity: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
121
|
+
language: string;
|
|
122
|
+
limit?: number | undefined;
|
|
123
|
+
}, {
|
|
91
124
|
type: "entry_edit";
|
|
92
125
|
entryId: string;
|
|
93
126
|
slug: string;
|
|
127
|
+
kind: "collection" | "single";
|
|
94
128
|
label: string | null;
|
|
129
|
+
labelLanguage: string | null;
|
|
130
|
+
containerLabel: Localized;
|
|
131
|
+
editorId: string | null;
|
|
132
|
+
editorName: string | null;
|
|
95
133
|
updatedAt: Date;
|
|
96
134
|
}[]>;
|
|
135
|
+
/**
|
|
136
|
+
* Global quick-search over entry titles plus single names. Titles are matched
|
|
137
|
+
* and returned in the requested `language`, falling back to any available
|
|
138
|
+
* translation (`titleLanguage` reports which one was used). Used by the sidebar
|
|
139
|
+
* command palette. A full multi-language FTS search is tracked separately.
|
|
140
|
+
*/
|
|
141
|
+
export declare const searchEntries: import("@sveltejs/kit").RemoteQueryFunction<{
|
|
142
|
+
query: string;
|
|
143
|
+
language: string;
|
|
144
|
+
}, {
|
|
145
|
+
entryId: string;
|
|
146
|
+
title: string;
|
|
147
|
+
titleLanguage: string | null;
|
|
148
|
+
kind: "collection" | "single";
|
|
149
|
+
containerSlug: string;
|
|
150
|
+
containerLabel: Localized;
|
|
151
|
+
}[]>;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { command, query } from '$app/server';
|
|
2
|
-
import {
|
|
2
|
+
import { error } from '@sveltejs/kit';
|
|
3
|
+
import { CmsError } from '../../core/errors.js';
|
|
4
|
+
import { getRawCollectionEntryLabelWithLanguage } from '../utils/entryLabel.js';
|
|
5
|
+
import { db } from '../../server/db/index.js';
|
|
6
|
+
import { user } from '../../server/db/schema/auth-schema.js';
|
|
7
|
+
import { inArray } from 'drizzle-orm';
|
|
3
8
|
import { createEntry as createEntryOperation, createEntrySchema, createEntryVersion } from '../../core/server/entries/operations/create.js';
|
|
4
9
|
import { _getRawEntries as getRawEntriesOperation, _countRawEntries as countRawEntriesOperation, _getRawEntry as getRawEntryOperation, _getRawEntryOrThrow as getRawEntryOrThrow, _getDbEntry as getDbEntry, getEntryVersion as getEntryVersionOperation, getEntryLabels as getEntryLabelsOperation } from '../../core/server/entries/operations/get.js';
|
|
5
10
|
import { resolveEntries, resolveEntry } from '../../core/server/entries/operations/resolveEntry.js';
|
|
6
11
|
import { getCMS } from '../../core/cms.js';
|
|
7
|
-
import {
|
|
12
|
+
import { getFieldsFromConfig } from '../../core/fields/layoutUtils.js';
|
|
13
|
+
import { pruneOldDraftVersions, unpublishEntryLang, cancelScheduledEntryLang, upsertDraftVersion, updateEntry, updateEntrySchema, updateEntryVersionCommandTypes } from '../../core/server/entries/operations/update.js';
|
|
8
14
|
import z from 'zod';
|
|
9
15
|
import { requireAuth } from './middleware/auth.js';
|
|
10
16
|
import { stableSlotReorder } from './reorder.js';
|
|
@@ -55,12 +61,84 @@ export const getEntries = query(z.object({
|
|
|
55
61
|
orderBy: input.orderBy
|
|
56
62
|
});
|
|
57
63
|
});
|
|
64
|
+
/**
|
|
65
|
+
* Cross-collection search for the URL field's internal-link picker. Matches
|
|
66
|
+
* the term (case-insensitive, OR) against each collection's admin-title field
|
|
67
|
+
* (`entryAdminTitle`), its `slug`-type field, and `seo.slug` / `seo.title`.
|
|
68
|
+
* The previous `getEntries({ dataLike })` call was a no-op because it never
|
|
69
|
+
* passed a collection slug (`if (!input.slug) return []`).
|
|
70
|
+
*/
|
|
71
|
+
export const searchLinkableEntries = query(z.object({ term: z.string(), language: z.string().optional() }), async ({ term, language }) => {
|
|
72
|
+
requireAuth();
|
|
73
|
+
const q = term.trim();
|
|
74
|
+
if (q.length < 2)
|
|
75
|
+
return [];
|
|
76
|
+
const cms = getCMS();
|
|
77
|
+
// Internal links are language-agnostic (resolved by id at render), but
|
|
78
|
+
// resolveEntries is strict per locale — so an entry that only has a
|
|
79
|
+
// `pl` version is invisible when searching the default `en`. Scan all
|
|
80
|
+
// languages (preferred one first) and dedupe by entry id.
|
|
81
|
+
const langs = [
|
|
82
|
+
...(language ? [language] : []),
|
|
83
|
+
...cms.languages.filter((l) => l !== language)
|
|
84
|
+
];
|
|
85
|
+
const results = [];
|
|
86
|
+
for (const config of Object.values(cms.collections)) {
|
|
87
|
+
if (config.type !== 'collection')
|
|
88
|
+
continue;
|
|
89
|
+
const fields = getFieldsFromConfig(config);
|
|
90
|
+
const titleField = config.entryAdminTitle;
|
|
91
|
+
const slugField = fields.find((f) => f.type === 'slug')?.slug;
|
|
92
|
+
const ilike = { seo: { slug: q, title: q } };
|
|
93
|
+
if (titleField)
|
|
94
|
+
ilike[titleField] = q;
|
|
95
|
+
if (slugField)
|
|
96
|
+
ilike[slugField] = q;
|
|
97
|
+
for (const locale of langs) {
|
|
98
|
+
let entries;
|
|
99
|
+
try {
|
|
100
|
+
entries = await resolveEntries({
|
|
101
|
+
collection: config.slug,
|
|
102
|
+
locale,
|
|
103
|
+
status: 'published',
|
|
104
|
+
filter: { dataILikeOr: ilike }
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
for (const e of entries) {
|
|
111
|
+
const seo = e.seo;
|
|
112
|
+
const rawTitle = titleField ? e[titleField] : undefined;
|
|
113
|
+
const title = (typeof rawTitle === 'string' && rawTitle) ||
|
|
114
|
+
(typeof seo?.title === 'string' && seo.title) ||
|
|
115
|
+
'';
|
|
116
|
+
const rawSlug = slugField ? e[slugField] : undefined;
|
|
117
|
+
const slug = (typeof rawSlug === 'string' && rawSlug) ||
|
|
118
|
+
(typeof seo?.slug === 'string' && seo.slug) ||
|
|
119
|
+
'';
|
|
120
|
+
results.push({
|
|
121
|
+
_id: e._id,
|
|
122
|
+
_slug: config.slug,
|
|
123
|
+
_url: typeof e._url === 'string' ? e._url : undefined,
|
|
124
|
+
title,
|
|
125
|
+
slug
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const seen = new Set();
|
|
131
|
+
return results
|
|
132
|
+
.filter((r) => (seen.has(r._id) ? false : (seen.add(r._id), true)))
|
|
133
|
+
.slice(0, 8);
|
|
134
|
+
});
|
|
58
135
|
export const getEntryLabels = query(z.object({
|
|
59
136
|
slug: z.string(),
|
|
60
137
|
ids: z.array(z.string().uuid()).optional(),
|
|
61
138
|
search: z.string().optional(),
|
|
62
139
|
limit: z.number().int().positive().optional(),
|
|
63
|
-
status: z.enum(['published', 'draft', 'all']).optional()
|
|
140
|
+
status: z.enum(['published', 'draft', 'all']).optional(),
|
|
141
|
+
language: z.string().optional()
|
|
64
142
|
}), async (input) => {
|
|
65
143
|
return getEntryLabelsOperation(input);
|
|
66
144
|
});
|
|
@@ -128,37 +206,51 @@ const updateEntryVersionCommandSchema = z.object({
|
|
|
128
206
|
export const updateEntryVersionCommand = command(updateEntryVersionCommandSchema, async (input) => {
|
|
129
207
|
const { user } = requireAuth();
|
|
130
208
|
let result;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
result = await createEntryVersion({
|
|
209
|
+
// Publish failures should reach the client with a structured body so the
|
|
210
|
+
// editor can pin the message to the offending field. SvelteKit hides any
|
|
211
|
+
// thrown error that isn't created via `error()`, so wrap publish writes.
|
|
212
|
+
const runPublish = async (publishedAt) => {
|
|
213
|
+
try {
|
|
214
|
+
return await createEntryVersion({
|
|
138
215
|
entryId: input.entryId,
|
|
139
216
|
lang: input.lang,
|
|
140
217
|
data: input.data,
|
|
141
|
-
publishedAt
|
|
218
|
+
publishedAt,
|
|
142
219
|
publishedBy: user.id
|
|
143
220
|
});
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
if (e instanceof CmsError && e.code === 'SLUG_DUPLICATE') {
|
|
224
|
+
error(409, {
|
|
225
|
+
message: e.message,
|
|
226
|
+
code: e.code,
|
|
227
|
+
path: typeof e.context.path === 'string' ? e.context.path : undefined
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
throw e;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
switch (input.type) {
|
|
234
|
+
case 'draft':
|
|
235
|
+
result = await upsertDraftVersion(input.entryId, input.data, input.lang, { skipValidation: true });
|
|
236
|
+
break;
|
|
237
|
+
case 'published-now': {
|
|
238
|
+
result = await runPublish(new Date());
|
|
144
239
|
break;
|
|
145
240
|
}
|
|
146
241
|
case 'published-scheduled': {
|
|
147
242
|
if (!input.scheduledAt) {
|
|
148
243
|
throw new Error('scheduledAt is required for scheduled publishing');
|
|
149
244
|
}
|
|
150
|
-
result = await
|
|
151
|
-
entryId: input.entryId,
|
|
152
|
-
lang: input.lang,
|
|
153
|
-
data: input.data,
|
|
154
|
-
publishedAt: input.scheduledAt,
|
|
155
|
-
publishedBy: user.id
|
|
156
|
-
});
|
|
245
|
+
result = await runPublish(input.scheduledAt);
|
|
157
246
|
break;
|
|
158
247
|
}
|
|
159
248
|
case 'cancel-published':
|
|
160
249
|
await unpublishEntryLang(input.entryId, input.lang);
|
|
161
250
|
break;
|
|
251
|
+
case 'cancel-scheduled':
|
|
252
|
+
await cancelScheduledEntryLang(input.entryId, input.lang);
|
|
253
|
+
break;
|
|
162
254
|
}
|
|
163
255
|
// Prune old draft versions only after publish/schedule (drafts upsert in-place)
|
|
164
256
|
if (input.type !== 'draft') {
|
|
@@ -210,7 +302,13 @@ export const getEntryVersion = query(z.object({
|
|
|
210
302
|
}), async (input) => {
|
|
211
303
|
return getEntryVersionOperation(input);
|
|
212
304
|
});
|
|
213
|
-
|
|
305
|
+
/**
|
|
306
|
+
* `containerLabel` carries the collection's plural label for collection entries
|
|
307
|
+
* and the single's name for singles; clients localise it. For collection entries
|
|
308
|
+
* `label` is the entry's own title (or `null` to fall back to the slug); for
|
|
309
|
+
* singles `label` is always `null` — the title shown is `containerLabel`.
|
|
310
|
+
*/
|
|
311
|
+
export const getRecentEntries = query(z.object({ limit: z.number().default(6), language: z.string() }), async ({ limit, language }) => {
|
|
214
312
|
const entries = await getRawEntriesOperation({
|
|
215
313
|
orderBy: { column: 'updatedAt', direction: 'desc' },
|
|
216
314
|
limit
|
|
@@ -223,30 +321,22 @@ export const getRecentEntries = query(z.number().default(6), async (limit) => {
|
|
|
223
321
|
catch {
|
|
224
322
|
// orphaned entry
|
|
225
323
|
}
|
|
226
|
-
const
|
|
324
|
+
const kind = config?.type === 'single' ? 'single' : 'collection';
|
|
227
325
|
let label = null;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
326
|
+
let labelLanguage = null;
|
|
327
|
+
if (config && config.type === 'collection') {
|
|
328
|
+
const resolved = getRawCollectionEntryLabelWithLanguage(entry, config, language);
|
|
329
|
+
if (resolved.label !== entry.id) {
|
|
330
|
+
label = resolved.label;
|
|
331
|
+
labelLanguage = resolved.language;
|
|
232
332
|
}
|
|
233
333
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
label = config.label;
|
|
240
|
-
}
|
|
334
|
+
let containerLabel = { pl: entry.slug, en: entry.slug };
|
|
335
|
+
if (config?.type === 'collection' && config.labels) {
|
|
336
|
+
containerLabel = config.labels.plural ?? config.labels.singular ?? containerLabel;
|
|
241
337
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (config.type === 'collection' && config.labels) {
|
|
245
|
-
collectionLabel = config.labels.plural ?? config.labels.singular ?? collectionLabel;
|
|
246
|
-
}
|
|
247
|
-
else if (config.type === 'single' && config.label) {
|
|
248
|
-
collectionLabel = config.label;
|
|
249
|
-
}
|
|
338
|
+
else if (config?.type === 'single' && config.label) {
|
|
339
|
+
containerLabel = config.label;
|
|
250
340
|
}
|
|
251
341
|
const hasPublished = Object.values(entry.publishedVersions).some((v) => v != null);
|
|
252
342
|
const hasScheduled = Object.values(entry.scheduledVersions).some((v) => v != null);
|
|
@@ -258,43 +348,130 @@ export const getRecentEntries = query(z.number().default(6), async (limit) => {
|
|
|
258
348
|
return {
|
|
259
349
|
entryId: entry.id,
|
|
260
350
|
slug: entry.slug,
|
|
261
|
-
|
|
351
|
+
kind,
|
|
352
|
+
containerLabel,
|
|
262
353
|
label,
|
|
354
|
+
labelLanguage,
|
|
263
355
|
status,
|
|
264
356
|
updatedAt: entry.updatedAt
|
|
265
357
|
};
|
|
266
358
|
});
|
|
267
359
|
});
|
|
268
|
-
export const getRecentActivity = query(z.number().default(10), async (limit) => {
|
|
360
|
+
export const getRecentActivity = query(z.object({ limit: z.number().default(10), language: z.string() }), async ({ limit, language }) => {
|
|
269
361
|
const entries = await getRawEntriesOperation({});
|
|
270
362
|
const activity = [];
|
|
271
363
|
for (const entry of entries) {
|
|
272
364
|
const latestVersion = entry.versions[0];
|
|
273
|
-
if (latestVersion)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
365
|
+
if (!latestVersion)
|
|
366
|
+
continue;
|
|
367
|
+
let config = null;
|
|
368
|
+
try {
|
|
369
|
+
config = getCMS().getBySlug(entry.slug);
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
// orphaned entry — still surface the edit, just without a friendly label
|
|
373
|
+
}
|
|
374
|
+
const kind = config?.type === 'single' ? 'single' : 'collection';
|
|
375
|
+
let label = null;
|
|
376
|
+
let labelLanguage = null;
|
|
377
|
+
let containerLabel = { pl: entry.slug, en: entry.slug };
|
|
378
|
+
if (config && config.type === 'collection') {
|
|
379
|
+
const resolved = getRawCollectionEntryLabelWithLanguage(entry, config, language);
|
|
380
|
+
if (resolved.label !== entry.id) {
|
|
381
|
+
label = resolved.label;
|
|
382
|
+
labelLanguage = resolved.language;
|
|
281
383
|
}
|
|
282
|
-
if (config
|
|
283
|
-
|
|
284
|
-
label = String(Object.values(config.label)[0] || '');
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
label = config.label;
|
|
288
|
-
}
|
|
384
|
+
if (config.labels) {
|
|
385
|
+
containerLabel = config.labels.singular ?? config.labels.plural ?? containerLabel;
|
|
289
386
|
}
|
|
290
|
-
|
|
291
|
-
|
|
387
|
+
}
|
|
388
|
+
else if (config?.type === 'single' && config.label) {
|
|
389
|
+
containerLabel = config.label;
|
|
390
|
+
}
|
|
391
|
+
activity.push({
|
|
392
|
+
type: 'entry_edit',
|
|
393
|
+
entryId: entry.id,
|
|
394
|
+
slug: entry.slug,
|
|
395
|
+
kind,
|
|
396
|
+
label,
|
|
397
|
+
labelLanguage,
|
|
398
|
+
containerLabel,
|
|
399
|
+
editorId: latestVersion.createdBy ?? null,
|
|
400
|
+
editorName: null,
|
|
401
|
+
updatedAt: latestVersion.createdAt
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
const recent = activity
|
|
405
|
+
.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())
|
|
406
|
+
.slice(0, limit);
|
|
407
|
+
// resolve editor names for the items we're returning
|
|
408
|
+
const editorIds = [...new Set(recent.map((a) => a.editorId).filter((id) => !!id))];
|
|
409
|
+
if (editorIds.length > 0) {
|
|
410
|
+
const rows = await db
|
|
411
|
+
.select({ id: user.id, name: user.name })
|
|
412
|
+
.from(user)
|
|
413
|
+
.where(inArray(user.id, editorIds));
|
|
414
|
+
const nameById = new Map(rows.map((r) => [r.id, r.name]));
|
|
415
|
+
for (const item of recent) {
|
|
416
|
+
if (item.editorId)
|
|
417
|
+
item.editorName = nameById.get(item.editorId) ?? null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return recent;
|
|
421
|
+
});
|
|
422
|
+
/**
|
|
423
|
+
* Global quick-search over entry titles plus single names. Titles are matched
|
|
424
|
+
* and returned in the requested `language`, falling back to any available
|
|
425
|
+
* translation (`titleLanguage` reports which one was used). Used by the sidebar
|
|
426
|
+
* command palette. A full multi-language FTS search is tracked separately.
|
|
427
|
+
*/
|
|
428
|
+
export const searchEntries = query(z.object({ query: z.string(), language: z.string() }), async ({ query: rawQuery, language }) => {
|
|
429
|
+
requireAuth();
|
|
430
|
+
const q = rawQuery.trim();
|
|
431
|
+
if (q.length < 2)
|
|
432
|
+
return [];
|
|
433
|
+
const cms = getCMS();
|
|
434
|
+
const needle = q.toLocaleLowerCase();
|
|
435
|
+
const results = [];
|
|
436
|
+
for (const config of Object.values(cms.collections)) {
|
|
437
|
+
const containerLabel = config.labels?.plural ?? config.labels?.singular ?? { pl: config.slug, en: config.slug };
|
|
438
|
+
const entries = await getRawEntriesOperation({ slug: config.slug });
|
|
439
|
+
for (const entry of entries) {
|
|
440
|
+
const resolved = getRawCollectionEntryLabelWithLanguage(entry, config, language);
|
|
441
|
+
if (resolved.label === entry.id)
|
|
442
|
+
continue; // no usable title
|
|
443
|
+
if (!resolved.label.toLocaleLowerCase().includes(needle))
|
|
444
|
+
continue;
|
|
445
|
+
results.push({
|
|
292
446
|
entryId: entry.id,
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
447
|
+
title: resolved.label,
|
|
448
|
+
titleLanguage: resolved.language,
|
|
449
|
+
kind: 'collection',
|
|
450
|
+
containerSlug: config.slug,
|
|
451
|
+
containerLabel
|
|
296
452
|
});
|
|
297
453
|
}
|
|
298
454
|
}
|
|
299
|
-
|
|
455
|
+
for (const config of Object.values(cms.singles)) {
|
|
456
|
+
const labelObj = config.label;
|
|
457
|
+
const names = labelObj && typeof labelObj === 'object' ? Object.values(labelObj) : labelObj ? [labelObj] : [];
|
|
458
|
+
const matches = config.slug.toLocaleLowerCase().includes(needle) ||
|
|
459
|
+
names.some((n) => typeof n === 'string' && n.toLocaleLowerCase().includes(needle));
|
|
460
|
+
if (!matches)
|
|
461
|
+
continue;
|
|
462
|
+
const localizedTitle = labelObj && typeof labelObj === 'object' ? labelObj[language] : undefined;
|
|
463
|
+
const title = localizedTitle ??
|
|
464
|
+
(labelObj && typeof labelObj === 'object'
|
|
465
|
+
? (Object.values(labelObj)[0] ?? config.slug)
|
|
466
|
+
: labelObj || config.slug);
|
|
467
|
+
results.push({
|
|
468
|
+
entryId: config.slug,
|
|
469
|
+
title,
|
|
470
|
+
titleLanguage: localizedTitle ? language : null,
|
|
471
|
+
kind: 'single',
|
|
472
|
+
containerSlug: config.slug,
|
|
473
|
+
containerLabel: labelObj && typeof labelObj === 'object' ? labelObj : { pl: title, en: title }
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
return results.slice(0, 20);
|
|
300
477
|
});
|