@xleddyl/nuxt-cms 0.9.3 → 0.10.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/README.md +1 -1
- package/dist/module.d.mts +20 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1037 -148
- package/dist/runtime/app/blocks/CmsBlocks.d.vue.ts +1 -1
- package/dist/runtime/app/blocks/CmsBlocks.vue +57 -9
- package/dist/runtime/app/blocks/CmsBlocks.vue.d.ts +1 -1
- package/dist/runtime/app/blocks/CmsField.d.ts +24 -0
- package/dist/runtime/app/blocks/CmsField.js +16 -0
- package/dist/runtime/app/blocks/node.d.ts +37 -0
- package/dist/runtime/app/blocks/node.js +17 -0
- package/dist/runtime/app/blocks/resolve.d.ts +18 -0
- package/dist/runtime/app/blocks/resolve.js +34 -0
- package/dist/runtime/app/components/cms/BlockPicker.d.vue.ts +22 -0
- package/dist/runtime/app/components/cms/BlockPicker.vue +87 -0
- package/dist/runtime/app/components/cms/BlockPicker.vue.d.ts +22 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.d.vue.ts +38 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.vue +44 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.vue.d.ts +38 -0
- package/dist/runtime/app/components/cms/BlockTree.d.vue.ts +29 -0
- package/dist/runtime/app/components/cms/BlockTree.vue +322 -0
- package/dist/runtime/app/components/cms/BlockTree.vue.d.ts +29 -0
- package/dist/runtime/app/components/cms/BlocksField.vue +569 -218
- package/dist/runtime/app/components/cms/BrandMark.vue +7 -13
- package/dist/runtime/app/components/cms/ConfirmGroups.vue +15 -13
- package/dist/runtime/app/components/cms/{BlockPalette.vue.d.ts → EditorHistory.d.vue.ts} +6 -5
- package/dist/runtime/app/components/cms/EditorHistory.vue +34 -0
- package/dist/runtime/app/components/cms/{BlockPalette.d.vue.ts → EditorHistory.vue.d.ts} +6 -5
- package/dist/runtime/app/components/cms/EntryDrawer.d.vue.ts +11 -5
- package/dist/runtime/app/components/cms/EntryDrawer.vue +183 -152
- package/dist/runtime/app/components/cms/EntryDrawer.vue.d.ts +11 -5
- package/dist/runtime/app/components/cms/EntryForm.d.vue.ts +16 -4
- package/dist/runtime/app/components/cms/EntryForm.vue +106 -146
- package/dist/runtime/app/components/cms/EntryForm.vue.d.ts +16 -4
- package/dist/runtime/app/components/cms/FieldInput.vue +10 -2
- package/dist/runtime/app/components/cms/FormSections.d.vue.ts +22 -0
- package/dist/runtime/app/components/cms/FormSections.vue +71 -0
- package/dist/runtime/app/components/cms/FormSections.vue.d.ts +22 -0
- package/dist/runtime/app/components/cms/ImportModal.vue +46 -58
- package/dist/runtime/app/components/cms/LinkField.d.vue.ts +16 -0
- package/dist/runtime/app/components/cms/LinkField.vue +250 -0
- package/dist/runtime/app/components/cms/LinkField.vue.d.ts +16 -0
- package/dist/runtime/app/components/cms/ListFilters.vue +10 -12
- package/dist/runtime/app/components/cms/LocaleSwitch.d.vue.ts +2 -1
- package/dist/runtime/app/components/cms/LocaleSwitch.vue +29 -5
- package/dist/runtime/app/components/cms/LocaleSwitch.vue.d.ts +2 -1
- package/dist/runtime/app/components/cms/MediaDetail.d.vue.ts +2 -0
- package/dist/runtime/app/components/cms/MediaDetail.vue +112 -83
- package/dist/runtime/app/components/cms/MediaDetail.vue.d.ts +2 -0
- package/dist/runtime/app/components/cms/MediaField.vue +35 -25
- package/dist/runtime/app/components/cms/MediaFolderPicker.vue +26 -71
- package/dist/runtime/app/components/cms/MediaGallery.d.vue.ts +1 -0
- package/dist/runtime/app/components/cms/MediaGallery.vue +442 -419
- package/dist/runtime/app/components/cms/MediaGallery.vue.d.ts +1 -0
- package/dist/runtime/app/components/cms/MediaThumb.vue +9 -25
- package/dist/runtime/app/components/cms/MediaUpload.vue +1 -1
- package/dist/runtime/app/components/cms/{BlockOutline.d.vue.ts → NestedBlockList.d.vue.ts} +5 -5
- package/dist/runtime/app/components/cms/NestedBlockList.vue +87 -0
- package/dist/runtime/app/components/cms/{BlockOutline.vue.d.ts → NestedBlockList.vue.d.ts} +5 -5
- package/dist/runtime/app/components/cms/PoweredBy.vue +12 -5
- package/dist/runtime/app/components/cms/PresetModal.d.vue.ts +18 -0
- package/dist/runtime/app/components/cms/PresetModal.vue +70 -0
- package/dist/runtime/app/components/cms/PresetModal.vue.d.ts +18 -0
- package/dist/runtime/app/components/cms/RelationField.vue +2 -8
- package/dist/runtime/app/components/cms/SettingsAccount.vue +60 -71
- package/dist/runtime/app/components/cms/SettingsColumns.vue +47 -69
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue +21 -0
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntries.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntries.vue +50 -0
- package/dist/runtime/app/components/cms/SettingsEntries.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntry.d.vue.ts +1 -10
- package/dist/runtime/app/components/cms/SettingsEntry.vue +11 -95
- package/dist/runtime/app/components/cms/SettingsEntry.vue.d.ts +1 -10
- package/dist/runtime/app/components/cms/SettingsEntryActions.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryActions.vue +42 -0
- package/dist/runtime/app/components/cms/SettingsEntryActions.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.vue +21 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.vue +17 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsLayout.vue +18 -14
- package/dist/runtime/app/components/cms/SettingsPresetForm.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsPresetForm.vue +60 -0
- package/dist/runtime/app/components/cms/SettingsPresetForm.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsPresets.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsPresets.vue +65 -0
- package/dist/runtime/app/components/cms/SettingsPresets.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.d.vue.ts +32 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.vue +45 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.vue.d.ts +32 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.vue +59 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.vue +77 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.vue +117 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.d.vue.ts +17 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.vue +43 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.vue.d.ts +17 -0
- package/dist/runtime/app/components/cms/SettingsSite.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsSite.vue +140 -0
- package/dist/runtime/app/components/cms/SettingsSite.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.d.vue.ts +8 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.vue +82 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.vue.d.ts +8 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.vue +179 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsUsers.d.vue.ts +9 -6
- package/dist/runtime/app/components/cms/SettingsUsers.vue +88 -234
- package/dist/runtime/app/components/cms/SettingsUsers.vue.d.ts +9 -6
- package/dist/runtime/app/components/cms/SharePreview.d.vue.ts +18 -0
- package/dist/runtime/app/components/cms/SharePreview.vue +219 -0
- package/dist/runtime/app/components/cms/SharePreview.vue.d.ts +18 -0
- package/dist/runtime/app/components/cms/SlugField.vue +5 -3
- package/dist/runtime/app/components/cms/StatusBadge.vue +9 -8
- package/dist/runtime/app/components/cms/TranslationBadges.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/TranslationBadges.vue +45 -0
- package/dist/runtime/app/components/cms/TranslationBadges.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/TranslationMenu.d.vue.ts +17 -0
- package/dist/runtime/app/components/cms/TranslationMenu.vue +28 -0
- package/dist/runtime/app/components/cms/TranslationMenu.vue.d.ts +17 -0
- package/dist/runtime/app/components/cms/VisualEditor.d.vue.ts +22 -4
- package/dist/runtime/app/components/cms/VisualEditor.vue +1152 -335
- package/dist/runtime/app/components/cms/VisualEditor.vue.d.ts +22 -4
- package/dist/runtime/app/components/cms/WelcomeModal.vue +32 -50
- package/dist/runtime/app/composables/cms-clipboard.d.ts +8 -0
- package/dist/runtime/app/composables/cms-clipboard.js +38 -0
- package/dist/runtime/app/composables/cms-confirm.d.ts +6 -8
- package/dist/runtime/app/composables/cms-confirm.js +5 -7
- package/dist/runtime/app/composables/cms-entry-disabled.d.ts +5 -1
- package/dist/runtime/app/composables/cms-entry-disabled.js +7 -0
- package/dist/runtime/app/composables/cms-entry-form.d.ts +15 -0
- package/dist/runtime/app/composables/cms-entry-form.js +40 -0
- package/dist/runtime/app/composables/cms-entry-settings.d.ts +30 -0
- package/dist/runtime/app/composables/cms-entry-settings.js +122 -0
- package/dist/runtime/app/composables/cms-entry.d.ts +5 -1
- package/dist/runtime/app/composables/cms-entry.js +36 -11
- package/dist/runtime/app/composables/cms-history.d.ts +10 -0
- package/dist/runtime/app/composables/cms-history.js +24 -0
- package/dist/runtime/app/composables/cms-link-targets.d.ts +10 -0
- package/dist/runtime/app/composables/cms-link-targets.js +40 -0
- package/dist/runtime/app/composables/cms-link-usage.d.ts +1 -0
- package/dist/runtime/app/composables/cms-link-usage.js +45 -0
- package/dist/runtime/app/composables/cms-media-library.d.ts +19 -9
- package/dist/runtime/app/composables/cms-media-library.js +31 -13
- package/dist/runtime/app/composables/cms-media-uploader.js +6 -20
- package/dist/runtime/app/composables/cms-permissions.d.ts +18 -0
- package/dist/runtime/app/composables/cms-permissions.js +54 -0
- package/dist/runtime/app/composables/cms-presets.d.ts +11 -0
- package/dist/runtime/app/composables/cms-presets.js +40 -0
- package/dist/runtime/app/composables/cms-preview-mode.d.ts +4 -0
- package/dist/runtime/app/composables/cms-preview-mode.js +8 -0
- package/dist/runtime/app/composables/cms-query.d.ts +3 -0
- package/dist/runtime/app/composables/cms-query.js +45 -20
- package/dist/runtime/app/composables/cms-record-list.d.ts +31 -0
- package/dist/runtime/app/composables/cms-record-list.js +75 -0
- package/dist/runtime/app/composables/cms-route.d.ts +6 -0
- package/dist/runtime/app/composables/cms-route.js +36 -0
- package/dist/runtime/app/composables/cms-runtime.d.ts +1 -0
- package/dist/runtime/app/composables/cms-save-handoff.d.ts +4 -0
- package/dist/runtime/app/composables/cms-save-handoff.js +19 -0
- package/dist/runtime/app/composables/cms-seo.d.ts +12 -0
- package/dist/runtime/app/composables/cms-seo.js +69 -0
- package/dist/runtime/app/composables/cms-settings-form.d.ts +13 -0
- package/dist/runtime/app/composables/cms-settings-form.js +29 -0
- package/dist/runtime/app/composables/cms-settings-sections.d.ts +26 -0
- package/dist/runtime/app/composables/cms-settings-sections.js +181 -0
- package/dist/runtime/app/composables/cms-settings-stores.d.ts +52 -0
- package/dist/runtime/app/composables/cms-settings-stores.js +156 -0
- package/dist/runtime/app/composables/cms-settings.d.ts +3 -3
- package/dist/runtime/app/composables/cms-settings.js +14 -8
- package/dist/runtime/app/composables/cms-site-disabled.d.ts +7 -0
- package/dist/runtime/app/composables/cms-site-disabled.js +8 -0
- package/dist/runtime/app/composables/cms-site.d.ts +7 -0
- package/dist/runtime/app/composables/cms-site.js +22 -0
- package/dist/runtime/app/composables/cms-toast.d.ts +2 -8
- package/dist/runtime/app/composables/cms-toast.js +3 -9
- package/dist/runtime/app/composables/cms-translation-actions.d.ts +15 -0
- package/dist/runtime/app/composables/cms-translation-actions.js +108 -0
- package/dist/runtime/app/css-url.d.ts +4 -0
- package/dist/runtime/app/image/CmsImage.d.vue.ts +89 -0
- package/dist/runtime/app/image/CmsImage.vue +91 -0
- package/dist/runtime/app/image/CmsImage.vue.d.ts +89 -0
- package/dist/runtime/app/layouts/cms-admin.d.vue.ts +2 -2
- package/dist/runtime/app/layouts/cms-admin.vue +98 -76
- package/dist/runtime/app/layouts/cms-admin.vue.d.ts +2 -2
- package/dist/runtime/app/layouts/cms-editor.vue +7 -2
- package/dist/runtime/app/links/CmsLink.d.vue.ts +18 -0
- package/dist/runtime/app/links/CmsLink.vue +18 -0
- package/dist/runtime/app/links/CmsLink.vue.d.ts +18 -0
- package/dist/runtime/app/middleware/cms-auth.js +13 -1
- package/dist/runtime/app/pages/admin-collection.vue +473 -297
- package/dist/runtime/app/pages/admin-content.vue +190 -53
- package/dist/runtime/app/pages/admin-entry.vue +79 -75
- package/dist/runtime/app/pages/admin-index.vue +18 -5
- package/dist/runtime/app/pages/admin-login.vue +1 -1
- package/dist/runtime/app/pages/admin-logout.vue +1 -1
- package/dist/runtime/app/pages/admin-media.vue +3 -3
- package/dist/runtime/app/pages/admin-preview.vue +112 -24
- package/dist/runtime/app/plugins/cms-field.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-field.js +8 -0
- package/dist/runtime/app/plugins/cms-preview-banner.client.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-preview-banner.client.js +19 -0
- package/dist/runtime/app/plugins/cms-preview.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-preview.js +27 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.d.vue.ts +7 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.vue +63 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.vue.d.ts +7 -0
- package/dist/runtime/app/preview/PreviewOverlay.d.vue.ts +17 -3
- package/dist/runtime/app/preview/PreviewOverlay.vue +629 -166
- package/dist/runtime/app/preview/PreviewOverlay.vue.d.ts +17 -3
- package/dist/runtime/app/preview/field-marker.d.ts +12 -0
- package/dist/runtime/app/preview/field-marker.js +20 -0
- package/dist/runtime/app/preview/inline-text.d.ts +15 -0
- package/dist/runtime/app/preview/inline-text.js +158 -0
- package/dist/runtime/app/utils/block-editor.d.ts +22 -0
- package/dist/runtime/app/utils/block-editor.js +12 -0
- package/dist/runtime/app/utils/keyboard.d.ts +6 -0
- package/dist/runtime/app/utils/keyboard.js +52 -0
- package/dist/runtime/app/utils/redirects.d.ts +6 -0
- package/dist/runtime/app/utils/redirects.js +7 -0
- package/dist/runtime/app/utils/ui.d.ts +8 -0
- package/dist/runtime/app/utils/ui.js +15 -1
- package/dist/runtime/app/utils/users.d.ts +15 -0
- package/dist/runtime/app/utils/users.js +14 -0
- package/dist/runtime/assets/cms.css +1 -1
- package/dist/runtime/generate.js +16 -2
- package/dist/runtime/server/api/collection-export.get.js +3 -2
- package/dist/runtime/server/api/collection-import.post.js +39 -11
- package/dist/runtime/server/api/collection.get.js +29 -10
- package/dist/runtime/server/api/collection.post.js +28 -11
- package/dist/runtime/server/api/collection.put.js +35 -13
- package/dist/runtime/server/api/item.delete.js +19 -7
- package/dist/runtime/server/api/item.get.js +3 -2
- package/dist/runtime/server/api/item.put.js +52 -18
- package/dist/runtime/server/api/link-usage.post.d.ts +5 -0
- package/dist/runtime/server/api/link-usage.post.js +21 -0
- package/dist/runtime/server/api/media-delete.post.js +4 -2
- package/dist/runtime/server/api/media-download.get.js +2 -2
- package/dist/runtime/server/api/media-folder.delete.js +8 -2
- package/dist/runtime/server/api/media-folder.patch.js +10 -2
- package/dist/runtime/server/api/media-folder.post.js +4 -2
- package/dist/runtime/server/api/media-move.post.js +7 -4
- package/dist/runtime/server/api/media-presign.post.js +2 -2
- package/dist/runtime/server/api/media-upload.put.js +2 -2
- package/dist/runtime/server/api/media-usage.post.d.ts +2 -4
- package/dist/runtime/server/api/media-usage.post.js +13 -9
- package/dist/runtime/server/api/media.delete.js +4 -2
- package/dist/runtime/server/api/media.get.js +22 -7
- package/dist/runtime/server/api/media.post.js +4 -2
- package/dist/runtime/server/api/media.put.js +33 -16
- package/dist/runtime/server/api/preset.delete.d.ts +4 -0
- package/dist/runtime/server/api/preset.delete.js +9 -0
- package/dist/runtime/server/api/preset.put.d.ts +3 -0
- package/dist/runtime/server/api/preset.put.js +23 -0
- package/dist/runtime/server/api/presets-field.get.d.ts +3 -0
- package/dist/runtime/server/api/presets-field.get.js +13 -0
- package/dist/runtime/server/api/presets-field.post.d.ts +3 -0
- package/dist/runtime/server/api/presets-field.post.js +36 -0
- package/dist/runtime/server/api/presets.get.d.ts +3 -0
- package/dist/runtime/server/api/presets.get.js +7 -0
- package/dist/runtime/server/api/preview-link.delete.d.ts +4 -0
- package/dist/runtime/server/api/preview-link.delete.js +15 -0
- package/dist/runtime/server/api/preview-links.get.d.ts +3 -0
- package/dist/runtime/server/api/preview-links.get.js +10 -0
- package/dist/runtime/server/api/preview-links.post.d.ts +3 -0
- package/dist/runtime/server/api/preview-links.post.js +17 -0
- package/dist/runtime/server/api/preview.get.d.ts +3 -0
- package/dist/runtime/server/api/preview.get.js +7 -0
- package/dist/runtime/server/api/redirect.delete.d.ts +4 -0
- package/dist/runtime/server/api/redirect.delete.js +10 -0
- package/dist/runtime/server/api/redirect.put.d.ts +3 -0
- package/dist/runtime/server/api/redirect.put.js +8 -0
- package/dist/runtime/server/api/redirects-import.post.d.ts +3 -0
- package/dist/runtime/server/api/redirects-import.post.js +13 -0
- package/dist/runtime/server/api/redirects.get.d.ts +3 -0
- package/dist/runtime/server/api/redirects.get.js +7 -0
- package/dist/runtime/server/api/redirects.post.d.ts +3 -0
- package/dist/runtime/server/api/redirects.post.js +7 -0
- package/dist/runtime/server/api/search.get.js +8 -3
- package/dist/runtime/server/api/settings.delete.js +2 -2
- package/dist/runtime/server/api/settings.get.js +4 -2
- package/dist/runtime/server/api/settings.put.js +2 -2
- package/dist/runtime/server/api/site.get.d.ts +3 -0
- package/dist/runtime/server/api/site.get.js +7 -0
- package/dist/runtime/server/api/site.put.d.ts +3 -0
- package/dist/runtime/server/api/site.put.js +16 -0
- package/dist/runtime/server/api/tags.get.js +3 -2
- package/dist/runtime/server/api/user.delete.js +8 -2
- package/dist/runtime/server/api/user.put.js +14 -4
- package/dist/runtime/server/api/users.get.js +2 -2
- package/dist/runtime/server/api/users.post.js +8 -4
- package/dist/runtime/server/middleware/hidden-site.d.ts +2 -0
- package/dist/runtime/server/middleware/hidden-site.js +8 -0
- package/dist/runtime/server/middleware/preview-links.d.ts +2 -0
- package/dist/runtime/server/middleware/preview-links.js +6 -0
- package/dist/runtime/server/middleware/redirects.d.ts +2 -0
- package/dist/runtime/server/middleware/redirects.js +18 -0
- package/dist/runtime/server/plugins/session-validate.js +4 -1
- package/dist/runtime/server/plugins/webhooks.d.ts +3 -0
- package/dist/runtime/server/plugins/webhooks.js +27 -0
- package/dist/runtime/server/routes/graphql.js +5 -3
- package/dist/runtime/server/routes/robots.d.ts +2 -0
- package/dist/runtime/server/routes/robots.js +16 -0
- package/dist/runtime/server/routes/sitemap.d.ts +2 -0
- package/dist/runtime/server/routes/sitemap.js +67 -0
- package/dist/runtime/server/utils/cached-value.d.ts +5 -0
- package/dist/runtime/server/utils/cached-value.js +24 -0
- package/dist/runtime/server/utils/content-routes.d.ts +5 -0
- package/dist/runtime/server/utils/content-routes.js +29 -0
- package/dist/runtime/server/utils/field-rules.d.ts +19 -0
- package/dist/runtime/server/utils/field-rules.js +72 -0
- package/dist/runtime/server/utils/graphql.d.ts +3 -1
- package/dist/runtime/server/utils/graphql.js +145 -29
- package/dist/runtime/server/utils/hooks.d.ts +14 -0
- package/dist/runtime/server/utils/hooks.js +71 -0
- package/dist/runtime/server/utils/import.d.ts +7 -2
- package/dist/runtime/server/utils/import.js +108 -14
- package/dist/runtime/server/utils/link-usage.d.ts +4 -0
- package/dist/runtime/server/utils/link-usage.js +28 -0
- package/dist/runtime/server/utils/media-references.d.ts +6 -1
- package/dist/runtime/server/utils/media-references.js +49 -20
- package/dist/runtime/server/utils/media-usage.d.ts +2 -0
- package/dist/runtime/server/utils/media-usage.js +5 -3
- package/dist/runtime/server/utils/page-rows.d.ts +2 -0
- package/dist/runtime/server/utils/page-rows.js +42 -29
- package/dist/runtime/server/utils/permissions.d.ts +14 -0
- package/dist/runtime/server/utils/permissions.js +43 -0
- package/dist/runtime/server/utils/presets.d.ts +18 -0
- package/dist/runtime/server/utils/presets.js +68 -0
- package/dist/runtime/server/utils/preview-links.d.ts +207 -0
- package/dist/runtime/server/utils/preview-links.js +161 -0
- package/dist/runtime/server/utils/redirects.d.ts +31 -0
- package/dist/runtime/server/utils/redirects.js +240 -0
- package/dist/runtime/server/utils/registry.js +4 -1
- package/dist/runtime/server/utils/relations.d.ts +8 -0
- package/dist/runtime/server/utils/relations.js +25 -6
- package/dist/runtime/server/utils/require-admin.d.ts +0 -1
- package/dist/runtime/server/utils/require-admin.js +4 -8
- package/dist/runtime/server/utils/search.d.ts +1 -0
- package/dist/runtime/server/utils/search.js +44 -19
- package/dist/runtime/server/utils/single-row.d.ts +3 -0
- package/dist/runtime/server/utils/single-row.js +4 -0
- package/dist/runtime/server/utils/site.d.ts +23 -0
- package/dist/runtime/server/utils/site.js +79 -0
- package/dist/runtime/server/utils/sitemap.d.ts +12 -0
- package/dist/runtime/server/utils/sitemap.js +109 -0
- package/dist/runtime/server/utils/user-management.d.ts +4 -0
- package/dist/runtime/server/utils/user-management.js +20 -0
- package/dist/runtime/server/utils/users.d.ts +1 -1
- package/dist/runtime/server/utils/users.js +1 -1
- package/dist/runtime/server/utils/visibility.d.ts +1 -0
- package/dist/runtime/server/utils/visibility.js +6 -1
- package/dist/runtime/server/utils/webhooks.d.ts +24 -0
- package/dist/runtime/server/utils/webhooks.js +90 -0
- package/dist/runtime/shared/block-paths.d.ts +66 -0
- package/dist/runtime/shared/block-paths.js +310 -0
- package/dist/runtime/shared/block-picker.d.ts +18 -0
- package/dist/runtime/shared/block-picker.js +31 -0
- package/dist/runtime/shared/block-signature.d.ts +4 -0
- package/dist/runtime/shared/block-signature.js +46 -0
- package/dist/runtime/shared/clipboard.d.ts +31 -0
- package/dist/runtime/shared/clipboard.js +206 -0
- package/dist/runtime/shared/conditions.d.ts +36 -0
- package/dist/runtime/shared/conditions.js +100 -0
- package/dist/runtime/shared/content-routes.d.ts +42 -0
- package/dist/runtime/shared/content-routes.js +237 -0
- package/dist/runtime/shared/duplicate.js +2 -1
- package/dist/runtime/shared/editor-layout.d.ts +18 -0
- package/dist/runtime/shared/editor-layout.js +9 -0
- package/dist/runtime/shared/field-options.d.ts +21 -0
- package/dist/runtime/shared/field-options.js +90 -0
- package/dist/runtime/shared/graphql-sdl.d.ts +1 -0
- package/dist/runtime/shared/graphql-sdl.js +50 -26
- package/dist/runtime/shared/history.d.ts +27 -0
- package/dist/runtime/shared/history.js +123 -0
- package/dist/runtime/shared/hooks.d.ts +45 -0
- package/dist/runtime/shared/hooks.js +28 -0
- package/dist/runtime/shared/index.d.ts +90 -21
- package/dist/runtime/shared/index.js +121 -37
- package/dist/runtime/shared/inline-text.d.ts +38 -0
- package/dist/runtime/shared/inline-text.js +85 -0
- package/dist/runtime/shared/layout.d.ts +2 -1
- package/dist/runtime/shared/layout.js +3 -0
- package/dist/runtime/shared/links.d.ts +48 -0
- package/dist/runtime/shared/links.js +155 -0
- package/dist/runtime/shared/list-filters.d.ts +2 -0
- package/dist/runtime/shared/list-filters.js +2 -0
- package/dist/runtime/shared/media-focal.d.ts +30 -0
- package/dist/runtime/shared/media-focal.js +52 -0
- package/dist/runtime/shared/migrations-dir.d.ts +14 -0
- package/dist/runtime/shared/migrations-dir.js +48 -2
- package/dist/runtime/shared/presets.d.ts +67 -0
- package/dist/runtime/shared/presets.js +127 -0
- package/dist/runtime/shared/preview-links.d.ts +64 -0
- package/dist/runtime/shared/preview-links.js +54 -0
- package/dist/runtime/shared/preview.d.ts +124 -21
- package/dist/runtime/shared/preview.js +419 -81
- package/dist/runtime/shared/redirects.d.ts +75 -0
- package/dist/runtime/shared/redirects.js +230 -0
- package/dist/runtime/shared/roles.d.ts +57 -0
- package/dist/runtime/shared/roles.js +293 -0
- package/dist/runtime/shared/save-state.d.ts +8 -0
- package/dist/runtime/shared/save-state.js +15 -0
- package/dist/runtime/shared/search.d.ts +16 -1
- package/dist/runtime/shared/search.js +41 -7
- package/dist/runtime/shared/seo.d.ts +167 -0
- package/dist/runtime/shared/seo.js +335 -0
- package/dist/runtime/shared/transfer.js +2 -1
- package/dist/runtime/shared/translations.d.ts +29 -0
- package/dist/runtime/shared/translations.js +123 -0
- package/dist/runtime/shared/users.d.ts +1 -1
- package/dist/runtime/shared/validation.d.ts +23 -1
- package/dist/runtime/shared/validation.js +214 -64
- package/dist/runtime/webhooks.d.ts +33 -0
- package/dist/runtime/webhooks.js +57 -0
- package/dist/types.d.mts +5 -1
- package/package.json +6 -2
- package/dist/runtime/app/components/cms/BlockOutline.vue +0 -88
- package/dist/runtime/app/components/cms/BlockPalette.vue +0 -31
- package/dist/runtime/app/components/cms/SettingsModal.d.vue.ts +0 -12
- package/dist/runtime/app/components/cms/SettingsModal.vue +0 -126
- package/dist/runtime/app/components/cms/SettingsModal.vue.d.ts +0 -12
- package/dist/runtime/app/composables/cms-field-focus.d.ts +0 -4
- package/dist/runtime/app/composables/cms-field-focus.js +0 -20
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getCurrentScope, onScopeDispose, readonly, ref, watch } from "#imports";
|
|
2
|
+
import { createCmsHistory } from "../../shared/history.js";
|
|
3
|
+
export function useCmsHistory(options) {
|
|
4
|
+
const canUndo = ref(false);
|
|
5
|
+
const canRedo = ref(false);
|
|
6
|
+
const history = createCmsHistory({
|
|
7
|
+
...options,
|
|
8
|
+
onUpdate: (status) => {
|
|
9
|
+
canUndo.value = status.canUndo;
|
|
10
|
+
canRedo.value = status.canRedo;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
watch(options.state, history.observe);
|
|
14
|
+
if (getCurrentScope()) onScopeDispose(history.dispose);
|
|
15
|
+
return {
|
|
16
|
+
canUndo: readonly(canUndo),
|
|
17
|
+
canRedo: readonly(canRedo),
|
|
18
|
+
change: history.change,
|
|
19
|
+
release: history.release,
|
|
20
|
+
undo: history.undo,
|
|
21
|
+
redo: history.redo,
|
|
22
|
+
reset: history.reset
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CmsConfig, CmsLinkValue } from '#nuxt-cms';
|
|
2
|
+
type Row = Record<string, unknown>;
|
|
3
|
+
export type CmsLinkTargetState = 'loading' | 'live' | 'draft' | 'scheduled' | 'missing';
|
|
4
|
+
export declare function useCmsLinkTargets(config: CmsConfig): {
|
|
5
|
+
load: (entry: string, id: string) => void;
|
|
6
|
+
remember: (entry: string, row: Row) => void;
|
|
7
|
+
target: (entry: string, id: string) => Row | null | undefined;
|
|
8
|
+
state: (link: CmsLinkValue | null | undefined) => CmsLinkTargetState | null;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isScheduledContent, linkTargetKey, pageLinkPath } from "#nuxt-cms";
|
|
2
|
+
import { reactive } from "#imports";
|
|
3
|
+
import { useCmsPermissions } from "./cms-permissions.js";
|
|
4
|
+
const rows = reactive(/* @__PURE__ */ new Map());
|
|
5
|
+
const pending = /* @__PURE__ */ new Set();
|
|
6
|
+
function statusOf(error) {
|
|
7
|
+
return error?.statusCode ?? error?.status;
|
|
8
|
+
}
|
|
9
|
+
export function useCmsLinkTargets(config) {
|
|
10
|
+
const { can } = useCmsPermissions();
|
|
11
|
+
function load(entry, id) {
|
|
12
|
+
const key = linkTargetKey(entry, id);
|
|
13
|
+
if (!import.meta.client || rows.has(key) || pending.has(key)) return;
|
|
14
|
+
if (config[entry]?.kind !== "content" || !can(`${entry}.read`)) return;
|
|
15
|
+
pending.add(key);
|
|
16
|
+
$fetch(`/api/cms/admin/${entry}/${encodeURIComponent(id)}`).then((row) => rows.set(key, row)).catch((error) => {
|
|
17
|
+
if (statusOf(error) === 404) rows.set(key, null);
|
|
18
|
+
}).finally(() => pending.delete(key));
|
|
19
|
+
}
|
|
20
|
+
function remember(entry, row) {
|
|
21
|
+
if (row.id == null) return;
|
|
22
|
+
const key = linkTargetKey(entry, String(row.id));
|
|
23
|
+
rows.set(key, { ...rows.get(key), ...row });
|
|
24
|
+
}
|
|
25
|
+
function target(entry, id) {
|
|
26
|
+
return rows.get(linkTargetKey(entry, id));
|
|
27
|
+
}
|
|
28
|
+
function state(link) {
|
|
29
|
+
if (!link?.entry || !link.id || link.url) return null;
|
|
30
|
+
const entry = config[link.entry];
|
|
31
|
+
if (!entry) return "missing";
|
|
32
|
+
if (entry.kind === "page") return pageLinkPath(entry, link.id) ? "live" : "missing";
|
|
33
|
+
const row = target(link.entry, link.id);
|
|
34
|
+
if (row === void 0) return "loading";
|
|
35
|
+
if (row === null) return "missing";
|
|
36
|
+
if (row.status !== "published") return "draft";
|
|
37
|
+
return isScheduledContent(row) ? "scheduled" : "live";
|
|
38
|
+
}
|
|
39
|
+
return { load, remember, target, state };
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useCmsLinkedDelete(): (entry: string, ids: string[], question: string, titles?: Record<string, string>) => Promise<boolean>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { groupMediaUsage, isLinkTargetEntry, linkTargetKey } from "#nuxt-cms";
|
|
2
|
+
import cmsConfig from "#cms-config";
|
|
3
|
+
import { cmsApi } from "../utils/api.js";
|
|
4
|
+
import { useCmsConfirm } from "./cms-confirm.js";
|
|
5
|
+
import { usageItem } from "./cms-media-library.js";
|
|
6
|
+
function linksLabel(count) {
|
|
7
|
+
return `${count} ${count === 1 ? "entry" : "entries"}`;
|
|
8
|
+
}
|
|
9
|
+
async function loadUsage(entry, ids) {
|
|
10
|
+
try {
|
|
11
|
+
const { usage } = await cmsApi(
|
|
12
|
+
"/api/cms/link-usage",
|
|
13
|
+
{ method: "POST", body: { targets: ids.map((id) => ({ entry, id })) } }
|
|
14
|
+
);
|
|
15
|
+
return usage;
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function useCmsLinkedDelete() {
|
|
21
|
+
const confirmAction = useCmsConfirm();
|
|
22
|
+
return async (entry, ids, question, titles = {}) => {
|
|
23
|
+
if (!ids.length || !isLinkTargetEntry(cmsConfig[entry]))
|
|
24
|
+
return confirmAction({ title: question });
|
|
25
|
+
const usage = await loadUsage(entry, ids);
|
|
26
|
+
if (!usage)
|
|
27
|
+
return confirmAction({
|
|
28
|
+
title: question,
|
|
29
|
+
description: "Could not check where it is linked."
|
|
30
|
+
});
|
|
31
|
+
const groups = ids.map((id) => ({ id, entries: groupMediaUsage(usage[linkTargetKey(entry, id)] ?? []) })).filter((group) => group.entries.length > 0);
|
|
32
|
+
if (!groups.length) return confirmAction({ title: question });
|
|
33
|
+
const single = ids.length === 1;
|
|
34
|
+
const linked = single ? `It is linked from ${linksLabel(groups[0].entries.length)}.` : `${groups.length} of ${ids.length} are linked from your content.`;
|
|
35
|
+
return confirmAction({
|
|
36
|
+
title: single ? "Item is linked" : "Items are linked",
|
|
37
|
+
description: `${question} ${linked} Those links disappear from the site until they point somewhere else.`,
|
|
38
|
+
confirmLabel: "Delete anyway",
|
|
39
|
+
groups: groups.map((group) => ({
|
|
40
|
+
title: titles[group.id] ?? `#${group.id}`,
|
|
41
|
+
items: group.entries.map(usageItem)
|
|
42
|
+
}))
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RecordListItem } from '@xleddyl/443-components-vue';
|
|
2
|
+
import type { MediaItem, MediaSourceInfo, MediaUsage, MediaUsageEntry, MediaUsageReport } from '../../shared/index.js';
|
|
2
3
|
export interface MediaFolderStats {
|
|
3
4
|
files: number;
|
|
4
5
|
folders: number;
|
|
@@ -13,8 +14,10 @@ export declare function useCmsMediaLibrary(): {
|
|
|
13
14
|
size: number | null;
|
|
14
15
|
width: number | null;
|
|
15
16
|
height: number | null;
|
|
17
|
+
focalX: number | null;
|
|
18
|
+
focalY: number | null;
|
|
16
19
|
createdAt: string | null;
|
|
17
|
-
type: import("
|
|
20
|
+
type: import("#nuxt-cms").MediaType;
|
|
18
21
|
url: string | null;
|
|
19
22
|
}[], MediaItem[] | {
|
|
20
23
|
id?: number | undefined;
|
|
@@ -25,16 +28,18 @@ export declare function useCmsMediaLibrary(): {
|
|
|
25
28
|
size: number | null;
|
|
26
29
|
width: number | null;
|
|
27
30
|
height: number | null;
|
|
31
|
+
focalX: number | null;
|
|
32
|
+
focalY: number | null;
|
|
28
33
|
createdAt: string | null;
|
|
29
|
-
type: import("
|
|
34
|
+
type: import("#nuxt-cms").MediaType;
|
|
30
35
|
url: string | null;
|
|
31
36
|
}[]>;
|
|
32
37
|
source: import("vue").Ref<{
|
|
33
|
-
kind: import("
|
|
38
|
+
kind: import("#nuxt-cms").MediaSourceKind;
|
|
34
39
|
root: string;
|
|
35
40
|
builtAt: string | null;
|
|
36
41
|
} | null, MediaSourceInfo | {
|
|
37
|
-
kind: import("
|
|
42
|
+
kind: import("#nuxt-cms").MediaSourceKind;
|
|
38
43
|
root: string;
|
|
39
44
|
builtAt: string | null;
|
|
40
45
|
} | null>;
|
|
@@ -55,8 +60,10 @@ export declare function useCmsMediaLibrary(): {
|
|
|
55
60
|
size: number | null;
|
|
56
61
|
width: number | null;
|
|
57
62
|
height: number | null;
|
|
63
|
+
focalX: number | null;
|
|
64
|
+
focalY: number | null;
|
|
58
65
|
createdAt: string | null;
|
|
59
|
-
type: import("
|
|
66
|
+
type: import("#nuxt-cms").MediaType;
|
|
60
67
|
url: string | null;
|
|
61
68
|
}[];
|
|
62
69
|
createFolder: (name: string) => Promise<boolean>;
|
|
@@ -67,8 +74,11 @@ export declare function useCmsMediaLibrary(): {
|
|
|
67
74
|
updateItem: (key: string, changes: {
|
|
68
75
|
alt?: string | null;
|
|
69
76
|
folder?: string | null;
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
focalX?: number | null;
|
|
78
|
+
focalY?: number | null;
|
|
79
|
+
}) => Promise<void>;
|
|
80
|
+
usage: (keys: string[]) => Promise<MediaUsageReport | null>;
|
|
72
81
|
};
|
|
73
82
|
export type CmsMediaLibrary = ReturnType<typeof useCmsMediaLibrary>;
|
|
74
|
-
export declare function usageLink(usage: Pick<MediaUsage, 'collection' | 'id'>): string;
|
|
83
|
+
export declare function usageLink(usage: Pick<MediaUsage, 'collection' | 'id' | 'kind'>): string;
|
|
84
|
+
export declare function usageItem(entry: MediaUsageEntry, index: number): RecordListItem;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toast } from "@xleddyl/443-components-vue";
|
|
1
2
|
import {
|
|
2
3
|
expandMediaFolders,
|
|
3
4
|
isWithinMediaFolder,
|
|
@@ -5,13 +6,13 @@ import {
|
|
|
5
6
|
mediaFolderParent
|
|
6
7
|
} from "../../shared/index.js";
|
|
7
8
|
import { computed, ref } from "#imports";
|
|
8
|
-
import
|
|
9
|
+
import cmsConfig from "#cms-config";
|
|
10
|
+
import { cmsIcon, cmsSettingsLink, errorMessage } from "../utils/ui.js";
|
|
11
|
+
import { CMS_ENTRY_KIND_ICONS } from "./cms-entry-settings.js";
|
|
9
12
|
import { invalidateCmsMediaKeys } from "./cms-media-keys.js";
|
|
10
|
-
import { useCmsToast } from "./cms-toast.js";
|
|
11
13
|
const endpoint = "/api/cms/admin/media";
|
|
12
14
|
const USAGE_CHUNK = 1e3;
|
|
13
15
|
export function useCmsMediaLibrary() {
|
|
14
|
-
const toast = useCmsToast();
|
|
15
16
|
const items = ref([]);
|
|
16
17
|
const serverFolders = ref([]);
|
|
17
18
|
const source = ref(null);
|
|
@@ -61,7 +62,7 @@ export function useCmsMediaLibrary() {
|
|
|
61
62
|
await action();
|
|
62
63
|
return true;
|
|
63
64
|
} catch (err) {
|
|
64
|
-
toast.
|
|
65
|
+
toast.error(title, { description: errorMessage(err) });
|
|
65
66
|
return false;
|
|
66
67
|
}
|
|
67
68
|
}
|
|
@@ -101,22 +102,23 @@ export function useCmsMediaLibrary() {
|
|
|
101
102
|
});
|
|
102
103
|
}
|
|
103
104
|
function updateItem(key, changes) {
|
|
104
|
-
return
|
|
105
|
+
return (async () => {
|
|
105
106
|
await $fetch(endpoint, { method: "PUT", body: { key, ...changes } });
|
|
106
107
|
await reload({ quiet: true });
|
|
107
|
-
});
|
|
108
|
+
})();
|
|
108
109
|
}
|
|
109
110
|
async function usage(keys) {
|
|
110
111
|
const unique = [...new Set(keys)];
|
|
111
|
-
|
|
112
|
+
const merged = { usage: {}, hidden: {} };
|
|
113
|
+
if (!unique.length) return merged;
|
|
112
114
|
try {
|
|
113
|
-
const merged = {};
|
|
114
115
|
for (let index = 0; index < unique.length; index += USAGE_CHUNK) {
|
|
115
|
-
const result = await $fetch(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
);
|
|
119
|
-
Object.assign(merged, result.usage);
|
|
116
|
+
const result = await $fetch(`${endpoint}/usage`, {
|
|
117
|
+
method: "POST",
|
|
118
|
+
body: { keys: unique.slice(index, index + USAGE_CHUNK) }
|
|
119
|
+
});
|
|
120
|
+
Object.assign(merged.usage, result.usage);
|
|
121
|
+
Object.assign(merged.hidden, result.hidden);
|
|
120
122
|
}
|
|
121
123
|
return merged;
|
|
122
124
|
} catch {
|
|
@@ -143,5 +145,21 @@ export function useCmsMediaLibrary() {
|
|
|
143
145
|
};
|
|
144
146
|
}
|
|
145
147
|
export function usageLink(usage) {
|
|
148
|
+
if (usage.kind === "site") return cmsSettingsLink("site", "/cms/media");
|
|
146
149
|
return usage.id === null ? `/cms/${usage.collection}` : `/cms/${usage.collection}/${usage.id}`;
|
|
147
150
|
}
|
|
151
|
+
function usageIcon(usage) {
|
|
152
|
+
if (usage.kind === "site") return cmsIcon("globe-alt");
|
|
153
|
+
const entry = cmsConfig[usage.collection];
|
|
154
|
+
return cmsIcon(entry?.icon ?? CMS_ENTRY_KIND_ICONS[usage.kind]);
|
|
155
|
+
}
|
|
156
|
+
export function usageItem(entry, index) {
|
|
157
|
+
return {
|
|
158
|
+
id: index,
|
|
159
|
+
title: entry.title ?? entry.label,
|
|
160
|
+
description: entry.fields.join(", "),
|
|
161
|
+
meta: entry.title ? entry.label : void 0,
|
|
162
|
+
icon: usageIcon(entry),
|
|
163
|
+
to: usageLink(entry)
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -5,9 +5,8 @@ import {
|
|
|
5
5
|
normalizeMediaFolder
|
|
6
6
|
} from "../../shared/index.js";
|
|
7
7
|
import { ref } from "#imports";
|
|
8
|
-
import { readDroppedFiles } from "@xleddyl/443-components-vue";
|
|
8
|
+
import { readDroppedFiles, toast } from "@xleddyl/443-components-vue";
|
|
9
9
|
import { useCmsRuntime } from "./cms-runtime.js";
|
|
10
|
-
import { useCmsToast } from "./cms-toast.js";
|
|
11
10
|
async function imageDimensions(file) {
|
|
12
11
|
try {
|
|
13
12
|
const bitmap = await createImageBitmap(file);
|
|
@@ -105,7 +104,6 @@ function isWithinOrAbove(folder, other) {
|
|
|
105
104
|
return other === folder || other.startsWith(`${folder}/`);
|
|
106
105
|
}
|
|
107
106
|
export function useCmsMediaUploader() {
|
|
108
|
-
const toast = useCmsToast();
|
|
109
107
|
const { mediaMaxFileSize } = useCmsRuntime();
|
|
110
108
|
const uploading = ref(false);
|
|
111
109
|
const done = ref(0);
|
|
@@ -149,11 +147,7 @@ export function useCmsMediaUploader() {
|
|
|
149
147
|
})
|
|
150
148
|
);
|
|
151
149
|
const failed = results.filter((r) => r.status === "rejected").length;
|
|
152
|
-
if (failed)
|
|
153
|
-
toast.add({
|
|
154
|
-
title: `${failed} folder${failed > 1 ? "s" : ""} could not be created`,
|
|
155
|
-
color: "error"
|
|
156
|
-
});
|
|
150
|
+
if (failed) toast.error(`${failed} folder${failed > 1 ? "s" : ""} could not be created`);
|
|
157
151
|
}
|
|
158
152
|
async function upload(source, options) {
|
|
159
153
|
const tree = Array.isArray(source) || source instanceof FileList ? uploadTreeFromFiles(source) : source;
|
|
@@ -161,16 +155,10 @@ export function useCmsMediaUploader() {
|
|
|
161
155
|
let files = all.filter((entry) => matchesAccept(entry.file, options.accept));
|
|
162
156
|
const rejected = all.length - files.length;
|
|
163
157
|
if (rejected) {
|
|
164
|
-
toast.
|
|
165
|
-
title: `${rejected} file${rejected > 1 ? "s" : ""} of an unsupported type skipped`,
|
|
166
|
-
color: "error"
|
|
167
|
-
});
|
|
158
|
+
toast.error(`${rejected} file${rejected > 1 ? "s" : ""} of an unsupported type skipped`);
|
|
168
159
|
}
|
|
169
160
|
for (const { file } of files.filter((entry) => entry.file.size > mediaMaxFileSize)) {
|
|
170
|
-
toast.
|
|
171
|
-
title: `File too large (max ${formatFileSize(mediaMaxFileSize)}): ${file.name}`,
|
|
172
|
-
color: "error"
|
|
173
|
-
});
|
|
161
|
+
toast.error(`File too large (max ${formatFileSize(mediaMaxFileSize)}): ${file.name}`);
|
|
174
162
|
}
|
|
175
163
|
files = files.filter((entry) => entry.file.size <= mediaMaxFileSize);
|
|
176
164
|
const nested = options.multiple !== false;
|
|
@@ -188,8 +176,7 @@ export function useCmsMediaUploader() {
|
|
|
188
176
|
)
|
|
189
177
|
].filter((folder) => !fileFolders.some((other) => isWithinOrAbove(folder, other)));
|
|
190
178
|
if (planned.some((entry) => entry.flattened)) {
|
|
191
|
-
toast
|
|
192
|
-
title: `Folders nest up to ${MEDIA_FOLDER_MAX_DEPTH} levels`,
|
|
179
|
+
toast(`Folders nest up to ${MEDIA_FOLDER_MAX_DEPTH} levels`, {
|
|
193
180
|
description: "Files in deeper folders were uploaded to the deepest allowed folder."
|
|
194
181
|
});
|
|
195
182
|
}
|
|
@@ -205,8 +192,7 @@ export function useCmsMediaUploader() {
|
|
|
205
192
|
);
|
|
206
193
|
const ok = results.filter((r) => r.status === "fulfilled").map((r) => r.value);
|
|
207
194
|
const failed = results.length - ok.length;
|
|
208
|
-
if (failed)
|
|
209
|
-
toast.add({ title: `${failed} upload${failed > 1 ? "s" : ""} failed`, color: "error" });
|
|
195
|
+
if (failed) toast.error(`${failed} upload${failed > 1 ? "s" : ""} failed`);
|
|
210
196
|
return ok;
|
|
211
197
|
} finally {
|
|
212
198
|
uploading.value = false;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CmsEntry } from '#nuxt-cms';
|
|
2
|
+
import type { CmsRoles } from '../../shared/roles.js';
|
|
3
|
+
export interface CmsEntryLockOptions {
|
|
4
|
+
isNew: boolean;
|
|
5
|
+
status?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function useCmsPermissions(): {
|
|
8
|
+
role: import("vue").ComputedRef<import("#nuxt-cms").CmsUserRole | null | undefined>;
|
|
9
|
+
access: import("vue").ComputedRef<import("#nuxt-cms").CmsAccess | null>;
|
|
10
|
+
roles: CmsRoles;
|
|
11
|
+
can: (permission: string) => boolean;
|
|
12
|
+
entryLock: (name: string, entry: CmsEntry, options: CmsEntryLockOptions) => "Your role cannot create entries here." | "Your role can view this entry but not edit it." | "This entry is published. Your role can only edit drafts." | null;
|
|
13
|
+
firstPath: () => string | null;
|
|
14
|
+
roleLabel: (key: string | null | undefined) => string;
|
|
15
|
+
roleOptions: import("#nuxt-cms").CmsRoleOption[];
|
|
16
|
+
canGrant: (key: string) => boolean;
|
|
17
|
+
canManage: (key: string) => boolean;
|
|
18
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { computed } from "#imports";
|
|
2
|
+
import cmsConfig from "#cms-config";
|
|
3
|
+
import cmsRoles from "#cms-roles";
|
|
4
|
+
import {
|
|
5
|
+
can as canAccess,
|
|
6
|
+
canGrantRole,
|
|
7
|
+
canManageAccount,
|
|
8
|
+
cmsRoleLabel,
|
|
9
|
+
cmsRoleOptions,
|
|
10
|
+
CMS_SUPERADMIN_ROLE,
|
|
11
|
+
resolveCmsAccess
|
|
12
|
+
} from "../../shared/roles.js";
|
|
13
|
+
import { useCmsAccount } from "./cms-account.js";
|
|
14
|
+
export function useCmsPermissions() {
|
|
15
|
+
const { user, isSuperAdmin } = useCmsAccount();
|
|
16
|
+
const roles = cmsRoles;
|
|
17
|
+
const config = cmsConfig;
|
|
18
|
+
const role = computed(
|
|
19
|
+
() => user.value ? isSuperAdmin.value ? CMS_SUPERADMIN_ROLE : user.value.role : null
|
|
20
|
+
);
|
|
21
|
+
const access = computed(
|
|
22
|
+
() => role.value === null ? null : resolveCmsAccess(role.value, roles, config)
|
|
23
|
+
);
|
|
24
|
+
function can(permission) {
|
|
25
|
+
return canAccess(access.value, permission);
|
|
26
|
+
}
|
|
27
|
+
function entryLock(name, entry, options) {
|
|
28
|
+
if (options.isNew) {
|
|
29
|
+
return can(`${name}.create`) ? null : "Your role cannot create entries here.";
|
|
30
|
+
}
|
|
31
|
+
if (!can(`${name}.update`)) return "Your role can view this entry but not edit it.";
|
|
32
|
+
if (entry.drafts && options.status === "published" && !can(`${name}.publish`)) {
|
|
33
|
+
return "This entry is published. Your role can only edit drafts.";
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function firstPath() {
|
|
38
|
+
const first = Object.keys(config).find((name) => can(`${name}.read`));
|
|
39
|
+
if (first) return `/cms/${first}`;
|
|
40
|
+
return can("media.read") ? "/cms/media" : null;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
role,
|
|
44
|
+
access,
|
|
45
|
+
roles,
|
|
46
|
+
can,
|
|
47
|
+
entryLock,
|
|
48
|
+
firstPath,
|
|
49
|
+
roleLabel: (key) => cmsRoleLabel(key, roles),
|
|
50
|
+
roleOptions: cmsRoleOptions(roles),
|
|
51
|
+
canGrant: (key) => canGrantRole(access.value, key, roles, config),
|
|
52
|
+
canManage: (key) => canManageAccount(access.value, key, roles, config)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CmsBlockPreset } from '../../shared/presets.js';
|
|
2
|
+
import type { CmsBlockValue } from '../../shared/preview.js';
|
|
3
|
+
export declare function useCmsPresets(entryName: () => string | undefined, fieldKey: () => string | undefined): {
|
|
4
|
+
presets: import("vue").ComputedRef<CmsBlockPreset[]>;
|
|
5
|
+
load: () => Promise<void>;
|
|
6
|
+
create: (input: {
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
items: CmsBlockValue[];
|
|
10
|
+
}) => Promise<CmsBlockPreset>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { computed, useState } from "#imports";
|
|
2
|
+
import { cmsApi } from "../utils/api.js";
|
|
3
|
+
const PRESETS_ENDPOINT = "/api/cms/presets";
|
|
4
|
+
function usePresetCache() {
|
|
5
|
+
return useState("cms-presets", () => ({}));
|
|
6
|
+
}
|
|
7
|
+
function fieldEndpoint(entryName, fieldKey) {
|
|
8
|
+
return `${PRESETS_ENDPOINT}/${encodeURIComponent(entryName)}/${encodeURIComponent(fieldKey)}`;
|
|
9
|
+
}
|
|
10
|
+
export function useCmsPresets(entryName, fieldKey) {
|
|
11
|
+
const cache = usePresetCache();
|
|
12
|
+
const scope = computed(() => {
|
|
13
|
+
const entry = entryName();
|
|
14
|
+
const field = fieldKey();
|
|
15
|
+
return entry && field ? { entry, field, key: `${entry}.${field}` } : null;
|
|
16
|
+
});
|
|
17
|
+
const presets = computed(() => scope.value ? cache.value[scope.value.key] ?? [] : []);
|
|
18
|
+
async function load() {
|
|
19
|
+
const current = scope.value;
|
|
20
|
+
if (!current) return;
|
|
21
|
+
try {
|
|
22
|
+
const list = await cmsApi(fieldEndpoint(current.entry, current.field));
|
|
23
|
+
cache.value = { ...cache.value, [current.key]: list };
|
|
24
|
+
} catch {
|
|
25
|
+
cache.value = { ...cache.value, [current.key]: cache.value[current.key] ?? [] };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function create(input) {
|
|
29
|
+
const current = scope.value;
|
|
30
|
+
if (!current) throw new Error("This field cannot hold presets");
|
|
31
|
+
const preset = await cmsApi(fieldEndpoint(current.entry, current.field), {
|
|
32
|
+
method: "POST",
|
|
33
|
+
body: input
|
|
34
|
+
});
|
|
35
|
+
cache.value = {};
|
|
36
|
+
await load();
|
|
37
|
+
return preset;
|
|
38
|
+
}
|
|
39
|
+
return { presets, load, create };
|
|
40
|
+
}
|
|
@@ -4,6 +4,9 @@ export interface CmsAsyncDataOptions<ResT, DefaultT> extends Pick<AsyncDataOptio
|
|
|
4
4
|
key?: string;
|
|
5
5
|
default?: () => DefaultT;
|
|
6
6
|
}
|
|
7
|
+
export declare function cmsPreviewToken(): string | null;
|
|
8
|
+
export declare function cmsPreviewKey(key: string, preview: string | null): string;
|
|
7
9
|
export declare function cmsQueryKey(query: string, variables?: unknown): string;
|
|
10
|
+
export declare function cmsQueryWithPreview<const Q extends string>(query: Q, variables: CmsVariables<Q> | undefined, preview: string | null): Promise<CmsResult<Q>>;
|
|
8
11
|
export declare function $cmsQuery<const Q extends string>(query: Q, variables?: CmsVariables<Q>): Promise<CmsResult<Q>>;
|
|
9
12
|
export declare function useCms<const Q extends string, DefaultT = undefined>(query: Q, variables?: CmsVariables<Q>, options?: CmsAsyncDataOptions<CmsResult<Q>, DefaultT>): AsyncData<CmsResult<Q> | DefaultT | undefined, Error | undefined>;
|
|
@@ -1,28 +1,35 @@
|
|
|
1
|
-
import { useAsyncData } from "#imports";
|
|
2
|
-
import {
|
|
1
|
+
import { tryUseNuxtApp, useAsyncData } from "#imports";
|
|
2
|
+
import {
|
|
3
|
+
CMS_GRAPHQL_BATCH_LIMIT,
|
|
4
|
+
PREVIEW_HEADER,
|
|
5
|
+
PREVIEW_QUERY_PARAM,
|
|
6
|
+
previewTokenFrom
|
|
7
|
+
} from "../../shared/index.js";
|
|
3
8
|
const ENDPOINT = "/api/cms/graphql";
|
|
4
9
|
const inFlight = /* @__PURE__ */ new Map();
|
|
5
|
-
let
|
|
10
|
+
let queues = /* @__PURE__ */ new Map();
|
|
6
11
|
let scheduled = false;
|
|
7
12
|
function responseError(response) {
|
|
8
13
|
return new Error(
|
|
9
14
|
response?.errors?.map((e) => e.message).join("; ") || "Invalid batched GraphQL response"
|
|
10
15
|
);
|
|
11
16
|
}
|
|
12
|
-
async function sendBatch(batch) {
|
|
17
|
+
async function sendBatch(batch, preview) {
|
|
18
|
+
const headers = preview ? { headers: { [PREVIEW_HEADER]: preview } } : {};
|
|
13
19
|
try {
|
|
14
20
|
if (batch.length === 1) {
|
|
15
21
|
batch[0].resolve(
|
|
16
22
|
await $fetch(ENDPOINT, {
|
|
17
23
|
method: "POST",
|
|
18
|
-
body: batch[0].body
|
|
24
|
+
body: batch[0].body,
|
|
25
|
+
...headers
|
|
19
26
|
})
|
|
20
27
|
);
|
|
21
28
|
return;
|
|
22
29
|
}
|
|
23
30
|
const responses = await $fetch(
|
|
24
31
|
ENDPOINT,
|
|
25
|
-
{ method: "POST", body: batch.map((pending) => pending.body) }
|
|
32
|
+
{ method: "POST", body: batch.map((pending) => pending.body), ...headers }
|
|
26
33
|
);
|
|
27
34
|
if (!Array.isArray(responses)) throw responseError(responses);
|
|
28
35
|
batch.forEach((pending, index) => {
|
|
@@ -35,42 +42,60 @@ async function sendBatch(batch) {
|
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
44
|
function flushQueue() {
|
|
38
|
-
const pending =
|
|
39
|
-
|
|
45
|
+
const pending = queues;
|
|
46
|
+
queues = /* @__PURE__ */ new Map();
|
|
40
47
|
scheduled = false;
|
|
41
|
-
for (
|
|
42
|
-
|
|
48
|
+
for (const [preview, list] of pending) {
|
|
49
|
+
for (let index = 0; index < list.length; index += CMS_GRAPHQL_BATCH_LIMIT) {
|
|
50
|
+
void sendBatch(list.slice(index, index + CMS_GRAPHQL_BATCH_LIMIT), preview);
|
|
51
|
+
}
|
|
43
52
|
}
|
|
44
53
|
}
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (existing) return existing;
|
|
49
|
-
const request = new Promise((resolve, reject) => {
|
|
54
|
+
function enqueue(body, preview) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const queue = queues.get(preview) ?? [];
|
|
50
57
|
queue.push({ body, resolve, reject });
|
|
58
|
+
queues.set(preview, queue);
|
|
51
59
|
if (!scheduled) {
|
|
52
60
|
scheduled = true;
|
|
53
61
|
setTimeout(flushQueue, 0);
|
|
54
62
|
}
|
|
55
|
-
})
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function requestGraphql(body, preview) {
|
|
66
|
+
if (preview) return enqueue(body, preview);
|
|
67
|
+
const key = JSON.stringify(body);
|
|
68
|
+
const existing = inFlight.get(key);
|
|
69
|
+
if (existing) return existing;
|
|
70
|
+
const request = enqueue(body, "").finally(() => inFlight.delete(key));
|
|
56
71
|
inFlight.set(key, request);
|
|
57
72
|
return request;
|
|
58
73
|
}
|
|
74
|
+
export function cmsPreviewToken() {
|
|
75
|
+
return previewTokenFrom(tryUseNuxtApp()?._route?.query?.[PREVIEW_QUERY_PARAM]);
|
|
76
|
+
}
|
|
77
|
+
export function cmsPreviewKey(key, preview) {
|
|
78
|
+
return preview ? `${key}:cms-preview` : key;
|
|
79
|
+
}
|
|
59
80
|
export function cmsQueryKey(query, variables) {
|
|
60
81
|
return `cms-gql:${query}:${JSON.stringify(variables ?? {})}`;
|
|
61
82
|
}
|
|
62
|
-
export async function
|
|
63
|
-
const res = await requestGraphql({ query, variables });
|
|
83
|
+
export async function cmsQueryWithPreview(query, variables, preview) {
|
|
84
|
+
const res = await requestGraphql({ query, variables }, preview);
|
|
64
85
|
if (res.errors?.length) {
|
|
65
86
|
throw new Error(res.errors.map((e) => e.message).join("; "));
|
|
66
87
|
}
|
|
67
88
|
return res.data;
|
|
68
89
|
}
|
|
90
|
+
export function $cmsQuery(query, variables) {
|
|
91
|
+
return cmsQueryWithPreview(query, variables, cmsPreviewToken());
|
|
92
|
+
}
|
|
69
93
|
export function useCms(query, variables, options = {}) {
|
|
70
94
|
const { key, ...asyncDataOptions } = options;
|
|
95
|
+
const preview = cmsPreviewToken();
|
|
71
96
|
return useAsyncData(
|
|
72
|
-
key ?? cmsQueryKey(query, variables),
|
|
73
|
-
() =>
|
|
97
|
+
key ?? cmsPreviewKey(cmsQueryKey(query, variables), preview),
|
|
98
|
+
() => cmsQueryWithPreview(query, variables, preview),
|
|
74
99
|
asyncDataOptions
|
|
75
100
|
);
|
|
76
101
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface CmsListRecord {
|
|
2
|
+
id: string;
|
|
3
|
+
}
|
|
4
|
+
export interface CmsRecordListOptions<T> {
|
|
5
|
+
key: string;
|
|
6
|
+
url: string;
|
|
7
|
+
label: (item: T) => string;
|
|
8
|
+
compare?: (a: T, b: T) => number;
|
|
9
|
+
loadError: string;
|
|
10
|
+
confirmDelete?: (item: T) => {
|
|
11
|
+
title: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
};
|
|
14
|
+
deleted?: string;
|
|
15
|
+
deleteError?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function useCmsRecordList<T extends CmsListRecord>(options: CmsRecordListOptions<T>): {
|
|
18
|
+
items: import("vue").Ref<T[], T[]>;
|
|
19
|
+
sorted: import("vue").ComputedRef<T[]>;
|
|
20
|
+
loaded: import("vue").Ref<boolean, boolean>;
|
|
21
|
+
loading: import("vue").Ref<boolean, boolean>;
|
|
22
|
+
load: () => Promise<void>;
|
|
23
|
+
ensureLoaded: () => Promise<void>;
|
|
24
|
+
find: (id: string | null | undefined) => T | undefined;
|
|
25
|
+
upsert: (record: T) => void;
|
|
26
|
+
removeLocal: (id: string) => void;
|
|
27
|
+
resolveLabel: (id: string) => Promise<string | undefined>;
|
|
28
|
+
remove: (record: T) => Promise<boolean>;
|
|
29
|
+
label: (item: T) => string;
|
|
30
|
+
};
|
|
31
|
+
export type CmsRecordList<T extends CmsListRecord> = ReturnType<typeof useCmsRecordList<T>>;
|