apostrophe 4.15.2 → 4.16.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/CHANGELOG.md +28 -0
- package/defaults.js +3 -3
- package/index.js +39 -22
- package/lib/check-if-conditions.js +27 -9
- package/lib/moog-require.js +23 -16
- package/lib/moog.js +23 -18
- package/lib/opentelemetry.js +4 -3
- package/modules/@apostrophecms/admin-bar/index.js +23 -16
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarMenu.vue +21 -20
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarUser.vue +2 -2
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBar.vue +22 -19
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBreakpointPreviewMode.vue +4 -3
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +20 -10
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +8 -6
- package/modules/@apostrophecms/any-page-type/index.js +53 -40
- package/modules/@apostrophecms/archive-page/index.js +2 -1
- package/modules/@apostrophecms/area/index.js +142 -71
- package/modules/@apostrophecms/area/ui/apos/apps/AposAreas.js +6 -22
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaContextualMenu.vue +28 -6
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +19 -14
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +4 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +32 -14
- package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +179 -109
- package/modules/@apostrophecms/asset/index.js +173 -140
- package/modules/@apostrophecms/asset/lib/build/external-module-api.js +110 -120
- package/modules/@apostrophecms/asset/lib/build/internals.js +57 -56
- package/modules/@apostrophecms/asset/lib/build/manager-apos.js +2 -1
- package/modules/@apostrophecms/asset/lib/build/manager-index.js +5 -4
- package/modules/@apostrophecms/asset/lib/build/task.js +16 -13
- package/modules/@apostrophecms/asset/lib/globalIcons.js +3 -0
- package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.config.js +8 -6
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.config.js +8 -6
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.scss.js +2 -1
- package/modules/@apostrophecms/asset/lib/webpack/utils.js +16 -14
- package/modules/@apostrophecms/attachment/index.js +57 -36
- package/modules/@apostrophecms/attachment/lib/legacy-migrations.js +2 -2
- package/modules/@apostrophecms/cache/index.js +8 -7
- package/modules/@apostrophecms/color-field/index.js +3 -1
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorHue.vue +20 -2
- package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorSaturation.vue +3 -1
- package/modules/@apostrophecms/command-menu/index.js +35 -10
- package/modules/@apostrophecms/db/index.js +6 -6
- package/modules/@apostrophecms/doc/index.js +132 -109
- package/modules/@apostrophecms/doc/lib/legacy-migrations.js +2 -2
- package/modules/@apostrophecms/doc/lib/migrations.js +11 -7
- package/modules/@apostrophecms/doc/ui/apos/apps/AposDoc.js +4 -4
- package/modules/@apostrophecms/doc-type/index.js +242 -172
- package/modules/@apostrophecms/doc-type/lib/autocomplete.js +2 -1
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +14 -6
- package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +4 -4
- package/modules/@apostrophecms/email/index.js +6 -2
- package/modules/@apostrophecms/error/index.js +7 -6
- package/modules/@apostrophecms/express/index.js +17 -17
- package/modules/@apostrophecms/file/index.js +6 -5
- package/modules/@apostrophecms/global/index.js +25 -23
- package/modules/@apostrophecms/html-widget/index.js +4 -3
- package/modules/@apostrophecms/http/index.js +80 -66
- package/modules/@apostrophecms/i18n/i18n/de.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/en.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/es.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/fr.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/it.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/pt-BR.json +0 -1
- package/modules/@apostrophecms/i18n/i18n/sk.json +0 -1
- package/modules/@apostrophecms/i18n/index.js +55 -59
- package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +10 -9
- package/modules/@apostrophecms/image/index.js +48 -37
- package/modules/@apostrophecms/image/ui/apos/components/AposImageCropper.vue +33 -14
- package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +58 -28
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +7 -6
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerEditor.vue +37 -17
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaUploader.vue +3 -2
- package/modules/@apostrophecms/image-widget/index.js +37 -10
- package/modules/@apostrophecms/image-widget/views/widget.html +1 -0
- package/modules/@apostrophecms/job/index.js +17 -16
- package/modules/@apostrophecms/launder/index.js +2 -2
- package/modules/@apostrophecms/lock/index.js +17 -16
- package/modules/@apostrophecms/log/index.js +66 -79
- package/modules/@apostrophecms/login/index.js +29 -25
- package/modules/@apostrophecms/login/ui/apos/logic/AposForgotPasswordForm.js +2 -2
- package/modules/@apostrophecms/login/ui/apos/logic/AposLoginForm.js +24 -18
- package/modules/@apostrophecms/login/ui/apos/logic/AposResetPasswordForm.js +2 -2
- package/modules/@apostrophecms/login/ui/apos/logic/TheAposLogin.js +5 -4
- package/modules/@apostrophecms/migration/index.js +45 -39
- package/modules/@apostrophecms/migration/lib/addMissingSchemaFields.js +13 -5
- package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +3 -3
- package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +10 -4
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalLip.vue +89 -16
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalReport.vue +13 -7
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalTabs.vue +5 -2
- package/modules/@apostrophecms/modal/ui/apos/components/AposWidgetModalTabs.vue +6 -3
- package/modules/@apostrophecms/modal/ui/apos/components/TheAposModals.vue +5 -4
- package/modules/@apostrophecms/modal/ui/apos/composables/AposFocus.js +17 -10
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +6 -5
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +9 -5
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposModalTabsMixin.js +4 -2
- package/modules/@apostrophecms/module/index.js +73 -50
- package/modules/@apostrophecms/module/lib/events.js +18 -7
- package/modules/@apostrophecms/notification/index.js +20 -15
- package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +3 -2
- package/modules/@apostrophecms/oembed/index.js +19 -13
- package/modules/@apostrophecms/oembed-field/index.js +7 -6
- package/modules/@apostrophecms/page/index.js +287 -180
- package/modules/@apostrophecms/page/lib/legacy-migrations.js +2 -2
- package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +9 -8
- package/modules/@apostrophecms/page-type/index.js +34 -25
- package/modules/@apostrophecms/permission/index.js +30 -10
- package/modules/@apostrophecms/permission/lib/legacy-migrations.js +2 -2
- package/modules/@apostrophecms/piece-page-type/index.js +46 -35
- package/modules/@apostrophecms/piece-type/index.js +103 -71
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerDisplay.vue +3 -1
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposUtilityOperations.vue +5 -5
- package/modules/@apostrophecms/rich-text-widget/index.js +25 -12
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +3 -3
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapColor.vue +3 -3
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapStyles.vue +2 -1
- package/modules/@apostrophecms/rich-text-widget/ui/apos/tiptap-extensions/Document.js +2 -1
- package/modules/@apostrophecms/schema/index.js +164 -141
- package/modules/@apostrophecms/schema/lib/addFieldTypes.js +78 -48
- package/modules/@apostrophecms/schema/lib/joinr.js +39 -23
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +0 -2
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +2 -1
- package/modules/@apostrophecms/schema/ui/apos/components/AposLogo.vue +1 -0
- package/modules/@apostrophecms/schema/ui/apos/components/AposLogoIcon.vue +1 -0
- package/modules/@apostrophecms/schema/ui/apos/components/AposLogoPadless.vue +1 -0
- package/modules/@apostrophecms/schema/ui/apos/lib/conditionalFields.js +2 -1
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArray.js +19 -9
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputCheckboxes.js +3 -1
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +3 -10
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSlug.js +2 -2
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +12 -3
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +4 -5
- package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +7 -2
- package/modules/@apostrophecms/schema/ui/apos/logic/AposSubform.js +3 -4
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputFollowingMixin.js +3 -1
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +2 -1
- package/modules/@apostrophecms/search/index.js +29 -19
- package/modules/@apostrophecms/settings/index.js +37 -29
- package/modules/@apostrophecms/soft-redirect/index.js +10 -6
- package/modules/@apostrophecms/submitted-draft/index.js +6 -4
- package/modules/@apostrophecms/task/index.js +16 -5
- package/modules/@apostrophecms/template/index.js +70 -68
- package/modules/@apostrophecms/template/lib/bundlesLoader.js +4 -4
- package/modules/@apostrophecms/template/lib/custom-tags/fragment.js +4 -3
- package/modules/@apostrophecms/template/lib/custom-tags/render.js +2 -1
- package/modules/@apostrophecms/template/lib/nunjucksLoader.js +6 -4
- package/modules/@apostrophecms/translation/index.js +21 -19
- package/modules/@apostrophecms/translation/ui/apos/components/AposTranslationIndicator.vue +1 -0
- package/modules/@apostrophecms/ui/ui/apos/apps/AposBusEvent.js +2 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposButtonSplit.vue +3 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposCloudUploadIcon.vue +1 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposCombo.vue +2 -2
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +18 -9
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +11 -11
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +53 -15
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuTip.vue +1 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposFilterMenu.vue +9 -4
- package/modules/@apostrophecms/ui/ui/apos/components/AposLoading.vue +1 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposSlatList.vue +4 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposSpinner.vue +100 -18
- package/modules/@apostrophecms/ui/ui/apos/components/AposTable.vue +9 -7
- package/modules/@apostrophecms/ui/ui/apos/components/AposTreeHeader.vue +2 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposTreeRows.vue +3 -2
- package/modules/@apostrophecms/ui/ui/apos/composables/AposFocusTrap.js +9 -5
- package/modules/@apostrophecms/ui/ui/apos/lib/click-outside-element.js +5 -1
- package/modules/@apostrophecms/ui/ui/apos/lib/i18next.js +7 -1
- package/modules/@apostrophecms/ui/ui/apos/lib/tooltip.js +2 -1
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposAdvisoryLockMixin.js +31 -29
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposArchiveMixin.js +10 -7
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposCellMixin.js +2 -2
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposModifiedMixin.js +2 -2
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposPublishMixin.js +18 -14
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposThemeMixin.js +2 -1
- package/modules/@apostrophecms/ui/ui/apos/scss/global/_theme.scss +2 -0
- package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_theme_mixins.scss +1 -0
- package/modules/@apostrophecms/ui/ui/apos/stores/modal.js +2 -1
- package/modules/@apostrophecms/ui/ui/apos/utils/index.js +27 -22
- package/modules/@apostrophecms/uploadfs/index.js +6 -4
- package/modules/@apostrophecms/url/index.js +2 -2
- package/modules/@apostrophecms/user/index.js +34 -28
- package/modules/@apostrophecms/user/lib/legacy-migrations.js +2 -2
- package/modules/@apostrophecms/user/lib/password-hash.js +5 -1
- package/modules/@apostrophecms/util/index.js +87 -52
- package/modules/@apostrophecms/util/ui/src/http.js +29 -26
- package/modules/@apostrophecms/util/ui/src/util.js +24 -17
- package/modules/@apostrophecms/video-widget/index.js +3 -2
- package/modules/@apostrophecms/widget-type/index.js +117 -56
- package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +68 -23
- package/modules/@apostrophecms/widget-type/ui/apos/mixins/AposWidgetMixin.js +4 -4
- package/package.json +2 -2
- package/test/add-missing-schema-fields.js +4 -3
- package/test/areas.js +14 -17
- package/test/asset-external.js +2 -2
- package/test/assets.js +3 -1
- package/test/attachments.js +2 -1
- package/test/autocomplete.js +155 -0
- package/test/big-upload.js +2 -2
- package/test/change-doc-ids.js +6 -2
- package/test/concurrent-array-relationships.js +2 -2
- package/test/db.js +2 -1
- package/test/docs.js +4 -2
- package/test/draft-published.js +2 -2
- package/test/external-front.js +2 -1
- package/test/i18n-batch.js +4 -6
- package/test/i18n.js +6 -3
- package/test/images.js +8 -4
- package/test/oembed.js +3 -7
- package/test/pages-public-api.js +3 -1
- package/test/pages-rest.js +2 -552
- package/test/pages.js +4 -2
- package/test/parked-pages.js +2 -1
- package/test/pieces-public-api.js +3 -1
- package/test/pieces.js +32 -11
- package/test/relationships.js +2 -1
- package/test/restApiRoutes.js +2 -2
- package/test/reverse-relationship.js +5 -5
- package/test/schemas.js +52 -8
- package/test/settings.js +2 -2
- package/test/templates.js +2 -2
- package/test/users.js +16 -4
- package/test/widgets.js +105 -2
- package/test-lib/test.js +2 -2
- package/test-lib/util.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.16.0 (2025-05-14)
|
|
4
|
+
|
|
5
|
+
### Adds
|
|
6
|
+
|
|
7
|
+
* Uses new `widgetOperations` to add the `adjustImage` operation to the image widget.
|
|
8
|
+
* Adds a server validation before adding a widget to an area. Introduces a new POST route `@apostrophecms/area/validate-widget`.
|
|
9
|
+
* The new `widgetOperations` cascade config property can be used to display custom operations for widgets. An `if` condition can be used to test properties of the widget before displaying an operation.
|
|
10
|
+
|
|
11
|
+
### Changes
|
|
12
|
+
|
|
13
|
+
* Enable widget live preview by default.
|
|
14
|
+
|
|
15
|
+
### Fixes
|
|
16
|
+
|
|
17
|
+
* Fixes `range` field type default value not being set properly.
|
|
18
|
+
* Fixes autocomplete and search sorting and as a consequence, fixes potential duplicates during pagination.
|
|
19
|
+
* Fixes all eslint warnings.
|
|
20
|
+
* When pasting a widget from the clipboard, the correct widget type is always offered on the "Add Content" menu.
|
|
21
|
+
* Widget live preview is now attempting to auto-position the Widget Editor modal only if no explicit widget configuration (`options.origin`) is provided.
|
|
22
|
+
* `required` is now implemented on the server side as well for `relationship` fields. It behaves like `min: 1`. It was always implemented on the front end. However, note that a relationship can still become empty if the related document is archived or deleted.
|
|
23
|
+
* Image widgets, and others with a placeholder when empty, now restore their placeholder view when canceling the widget editor in live preview mode.
|
|
24
|
+
* Fixes `z-index` of widget controls, going above the controls add button.
|
|
25
|
+
|
|
26
|
+
### Changes
|
|
27
|
+
|
|
28
|
+
* Updates the default fields for the `getMangageApiProjection()` to include a more sensible base configuration and adds a `true` option to return the minimal default values.
|
|
29
|
+
|
|
3
30
|
## 4.15.2 (2025-04-28)
|
|
4
31
|
|
|
5
32
|
### Security
|
|
@@ -33,6 +60,7 @@
|
|
|
33
60
|
|
|
34
61
|
### Fixes
|
|
35
62
|
|
|
63
|
+
* Adds missing notifications and error handling in media manager and save notification for auto-published pieces.
|
|
36
64
|
* Update `uploadfs` to `1.24.3`.
|
|
37
65
|
* Fixes an edge case where reordering a page in the Page Manager might affect another locale.
|
|
38
66
|
* Fixes chrome bug when pages manager checkboxes need a double click when coming from the rich text editor (because some text is selected).
|
package/defaults.js
CHANGED
|
@@ -31,8 +31,8 @@ module.exports = {
|
|
|
31
31
|
'@apostrophecms/oembed': {},
|
|
32
32
|
'@apostrophecms/pager': {},
|
|
33
33
|
'@apostrophecms/any-doc-type': {},
|
|
34
|
-
// global comes first so it can register a doc type manager and clean
|
|
35
|
-
// pages claims any orphan page types
|
|
34
|
+
// global comes first so it can register a doc type manager and clean
|
|
35
|
+
// things up before pages claims any orphan page types
|
|
36
36
|
'@apostrophecms/global': {},
|
|
37
37
|
'@apostrophecms/polymorphic-type': {},
|
|
38
38
|
'@apostrophecms/page': {},
|
|
@@ -43,7 +43,6 @@ module.exports = {
|
|
|
43
43
|
'@apostrophecms/area': {},
|
|
44
44
|
'@apostrophecms/rich-text-widget': {},
|
|
45
45
|
'@apostrophecms/html-widget': {},
|
|
46
|
-
'@apostrophecms/image-widget': {},
|
|
47
46
|
'@apostrophecms/color-field': {},
|
|
48
47
|
'@apostrophecms/oembed-field': {},
|
|
49
48
|
'@apostrophecms/video-widget': {},
|
|
@@ -52,6 +51,7 @@ module.exports = {
|
|
|
52
51
|
'@apostrophecms/settings': {},
|
|
53
52
|
'@apostrophecms/image': {},
|
|
54
53
|
'@apostrophecms/image-tag': {},
|
|
54
|
+
'@apostrophecms/image-widget': {},
|
|
55
55
|
'@apostrophecms/file': {},
|
|
56
56
|
'@apostrophecms/file-tag': {},
|
|
57
57
|
'@apostrophecms/soft-redirect': {},
|
package/index.js
CHANGED
|
@@ -44,24 +44,25 @@ let defaults = require('./defaults.js');
|
|
|
44
44
|
//
|
|
45
45
|
// `openTelemetryProvider`
|
|
46
46
|
//
|
|
47
|
-
// If set, Apostrophe will register it as a global OpenTelemetry tracer
|
|
48
|
-
// The expected value is an object, an instance of TracerProvider.
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
47
|
+
// If set, Apostrophe will register it as a global OpenTelemetry tracer
|
|
48
|
+
// provider. The expected value is an object, an instance of TracerProvider. If
|
|
49
|
+
// the Node SDK is used in the application instead of manual configuration, the
|
|
50
|
+
// provider instance is only available as a private property:
|
|
51
|
+
// `sdkInstance._tracerProvider`. An issue can be opened to discuss the exposure
|
|
52
|
+
// of a public getter with the OpenTelemetry developers.
|
|
53
53
|
//
|
|
54
54
|
// `beforeExit`
|
|
55
55
|
//
|
|
56
56
|
// If set, Apostrophe will invoke it (await) before invoking process.exit.
|
|
57
|
-
// `beforeExit` may be an async function, will be awaited, and takes no
|
|
57
|
+
// `beforeExit` may be an async function, will be awaited, and takes no
|
|
58
|
+
// arguments.
|
|
58
59
|
//
|
|
59
60
|
// `pnpm`
|
|
60
61
|
// A boolean to force on or off the pnpm related build routines. If not set,
|
|
61
62
|
// an automated check will be performed to determine if pnpm is in use. We offer
|
|
62
63
|
// an option, because automated check is not 100% reliable. Monorepo tools are
|
|
63
|
-
// often hiding package management specifics (lock files, node_module
|
|
64
|
-
// in a centralized store.
|
|
64
|
+
// often hiding package management specifics (lock files, node_module
|
|
65
|
+
// structure, etc.) in a centralized store.
|
|
65
66
|
//
|
|
66
67
|
// ## Awaiting the Apostrophe function
|
|
67
68
|
//
|
|
@@ -147,7 +148,8 @@ module.exports = async function(options) {
|
|
|
147
148
|
return null;
|
|
148
149
|
});
|
|
149
150
|
} else {
|
|
150
|
-
// continue as a worker operation, the pid should be recorded
|
|
151
|
+
// continue as a worker operation, the pid should be recorded
|
|
152
|
+
// by the auto instrumentation
|
|
151
153
|
spanName += ':worker';
|
|
152
154
|
console.log(`Cluster worker ${process.pid} started`);
|
|
153
155
|
}
|
|
@@ -248,8 +250,9 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
248
250
|
}
|
|
249
251
|
};
|
|
250
252
|
|
|
251
|
-
// Signals to various (build related) places that we are running a pnpm
|
|
252
|
-
// The relevant option, if set, has a higher precedence over
|
|
253
|
+
// Signals to various (build related) places that we are running a pnpm
|
|
254
|
+
// installation. The relevant option, if set, has a higher precedence over
|
|
255
|
+
// the automated check.
|
|
253
256
|
self.isPnpm = options.pnpm ??
|
|
254
257
|
fs.existsSync(path.join(self.npmRootDir, 'pnpm-lock.yaml'));
|
|
255
258
|
|
|
@@ -320,8 +323,8 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
320
323
|
self.apos.schema.registerAllSchemas();
|
|
321
324
|
await self.apos.lock.withLock('@apostrophecms/migration:migrate', async () => {
|
|
322
325
|
await self.apos.migration.migrate(self.argv);
|
|
323
|
-
// Inserts the global doc in the default locale if it does not exist;
|
|
324
|
-
// singleton piece types registered by other modules
|
|
326
|
+
// Inserts the global doc in the default locale if it does not exist;
|
|
327
|
+
// same for other singleton piece types registered by other modules
|
|
325
328
|
for (const apostropheModule of Object.values(self.modules)) {
|
|
326
329
|
if (self.instanceOf(apostropheModule, '@apostrophecms/piece-type') && apostropheModule.options.singletonAuto) {
|
|
327
330
|
await apostropheModule.insertIfMissing();
|
|
@@ -329,8 +332,8 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
329
332
|
}
|
|
330
333
|
await self.apos.page.implementParkAllInDefaultLocale();
|
|
331
334
|
await self.apos.doc.replicate(); // emits beforeReplicate and afterReplicate events
|
|
332
|
-
// Replicate will have created the parked pages across locales if needed,
|
|
333
|
-
// still need to reset parked properties
|
|
335
|
+
// Replicate will have created the parked pages across locales if needed,
|
|
336
|
+
// but we may still need to reset parked properties
|
|
334
337
|
await self.apos.page.implementParkAllInOtherLocales();
|
|
335
338
|
});
|
|
336
339
|
await self.emit('ready'); // formerly afterInit
|
|
@@ -625,8 +628,9 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
625
628
|
if (!target) {
|
|
626
629
|
continue;
|
|
627
630
|
}
|
|
628
|
-
// Add all the modules that want to be before this one to the target's
|
|
629
|
-
// Do this recursively for every module from the beforeSelf
|
|
631
|
+
// Add all the modules that want to be before this one to the target's
|
|
632
|
+
// beforeSelf. Do this recursively for every module from the beforeSelf
|
|
633
|
+
// array that has own `beforeSelf` members.
|
|
630
634
|
addBeforeSelfRecursive(name, m.beforeSelf, target.beforeSelf);
|
|
631
635
|
}
|
|
632
636
|
|
|
@@ -670,7 +674,8 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
670
674
|
function modulesToBeInstantiated() {
|
|
671
675
|
return Object.keys(self.options.modules).filter(name => {
|
|
672
676
|
const improvement = self.synth.isImprovement(name);
|
|
673
|
-
return !(self.options.modules[name] &&
|
|
677
|
+
return !(self.options.modules[name] &&
|
|
678
|
+
(improvement || self.options.modules[name].instantiate === false));
|
|
674
679
|
});
|
|
675
680
|
}
|
|
676
681
|
|
|
@@ -712,7 +717,11 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
712
717
|
return;
|
|
713
718
|
}
|
|
714
719
|
const submodule = await self.root.import(path.resolve(self.localModules, name, 'index.js'));
|
|
715
|
-
if (
|
|
720
|
+
if (
|
|
721
|
+
submodule &&
|
|
722
|
+
submodule.options &&
|
|
723
|
+
submodule.options.ignoreUnusedFolderWarning
|
|
724
|
+
) {
|
|
716
725
|
return;
|
|
717
726
|
}
|
|
718
727
|
} catch (e) {
|
|
@@ -777,14 +786,22 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
777
786
|
if (apostropheModule.options.extends && ((typeof apostropheModule.options.extends) === 'string')) {
|
|
778
787
|
lint(`The module ${name} contains an "extends" option. This is probably a\nmistake. In Apostrophe "extend" is used to extend other modules.`);
|
|
779
788
|
}
|
|
780
|
-
if (
|
|
789
|
+
if (
|
|
790
|
+
apostropheModule.options.singletonWarningIfNot &&
|
|
791
|
+
(name !== apostropheModule.options.singletonWarningIfNot)
|
|
792
|
+
) {
|
|
781
793
|
lint(`The module ${name} extends ${apostropheModule.options.singletonWarningIfNot}, which is normally\na singleton (Apostrophe creates only one instance of it). Two competing\ninstances will lead to problems. If you are adding project-level code to it,\njust use modules/${apostropheModule.options.singletonWarningIfNot}/index.js and do not use "extend".\nIf you are improving it via an npm module, use "improve" rather than "extend".\nIf neither situation applies you should probably just make a new module that does\nnot extend anything.\n\nIf you are sure you know what you are doing, you can set the\nsingletonWarningIfNot: false option for this module.`);
|
|
782
794
|
}
|
|
783
795
|
if (name.match(/-widget$/) && (!extending(apostropheModule)) && (!apostropheModule.options.ignoreNoExtendWarning)) {
|
|
784
796
|
lint(`The module ${name} does not extend anything.\n\nA -widget module usually extends @apostrophecms/widget-type or another widget type.\nOr possibly you forgot to npm install something.\n\nIf you are sure you are doing the right thing, set the\nignoreNoExtendWarning option to true for this module.`);
|
|
785
797
|
} else if (name.match(/-page$/) && (name !== '@apostrophecms/page') && (!extending(apostropheModule)) && (!apostropheModule.options.ignoreNoExtendWarning)) {
|
|
786
798
|
lint(`The module ${name} does not extend anything.\n\nA -page module usually extends @apostrophecms/page-type or\n@apostrophecms/piece-page-type or another page type.\nOr possibly you forgot to npm install something.\n\nIf you are sure you are doing the right thing, set the\nignoreNoExtendWarning option to true for this module.`);
|
|
787
|
-
} else if (
|
|
799
|
+
} else if (
|
|
800
|
+
!extending(apostropheModule) &&
|
|
801
|
+
!hasCode(name) &&
|
|
802
|
+
!isBundle(name) &&
|
|
803
|
+
!apostropheModule.options.ignoreNoCodeWarning
|
|
804
|
+
) {
|
|
788
805
|
lint(`The module ${name} does not extend anything and does not have any code.\n\nThis usually means that you:\n\n1. Forgot to "extend" another module\n2. Configured a module that comes from npm without npm installing it\n3. Simply haven't written your "index.js" yet\n\nIf you really want a module with no code, set the ignoreNoCodeWarning option\nto true for this module.`);
|
|
789
806
|
}
|
|
790
807
|
}
|
|
@@ -9,15 +9,25 @@ export default function checkIfConditions(doc, conditions) {
|
|
|
9
9
|
return checkAndConditions(doc, value);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
if (
|
|
13
|
+
typeof value === 'object' &&
|
|
14
|
+
!Array.isArray(value) &&
|
|
15
|
+
value !== null
|
|
16
|
+
) {
|
|
17
|
+
if (Object.hasOwn(value, '$ne')) {
|
|
18
|
+
return getNestedPropValue(doc, key) !== value.$ne;
|
|
19
|
+
} else if (Object.hasOwn(value, '$exists')) {
|
|
20
|
+
// Per MongoDB documentation, $exists should treat null and undefined the same.
|
|
21
|
+
// == null and != null are documented to match or reject null, undefined
|
|
22
|
+
// and nothing else.
|
|
23
|
+
const actual = getNestedPropValue(doc, key);
|
|
24
|
+
if (value.$exists) {
|
|
25
|
+
return actual != null;
|
|
26
|
+
} else {
|
|
27
|
+
return actual == null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
19
30
|
}
|
|
20
|
-
|
|
21
31
|
return getNestedPropValue(doc, key) === value;
|
|
22
32
|
});
|
|
23
33
|
}
|
|
@@ -37,7 +47,15 @@ function checkAndConditions(doc, conditions) {
|
|
|
37
47
|
function getNestedPropValue(doc, key) {
|
|
38
48
|
if (key.includes('.')) {
|
|
39
49
|
const keys = key.split('.');
|
|
40
|
-
|
|
50
|
+
// Do not crash if a key is not found — mongodb doesn't, which is useful because
|
|
51
|
+
// you can test for things like _image.0 where both might not exist yet
|
|
52
|
+
return keys.reduce((acc, cur) => {
|
|
53
|
+
if ((typeof acc !== 'object') || (acc == null)) {
|
|
54
|
+
return undefined;
|
|
55
|
+
} else {
|
|
56
|
+
return acc[cur];
|
|
57
|
+
}
|
|
58
|
+
}, doc);
|
|
41
59
|
}
|
|
42
60
|
|
|
43
61
|
return doc[key];
|
package/lib/moog-require.js
CHANGED
|
@@ -59,16 +59,18 @@ module.exports = async function(options) {
|
|
|
59
59
|
|
|
60
60
|
if (options.nestedModuleSubdirs) {
|
|
61
61
|
if (!self._indexes) {
|
|
62
|
-
// Fetching a list of index.js files on the first call and then
|
|
63
|
-
// one that refers to the right type name
|
|
64
|
-
//
|
|
62
|
+
// Fetching a list of index.js files on the first call and then
|
|
63
|
+
// searching it each time for one that refers to the right type name
|
|
64
|
+
// shaves as much as 60 seconds off the startup time in a large project,
|
|
65
|
+
// compared to using the glob cache feature
|
|
65
66
|
self._indexes = glob(self.options.localModules + '/**/index.js', { follow: true });
|
|
66
67
|
}
|
|
67
68
|
const matches = self._indexes.filter(function(index) {
|
|
68
|
-
// Double-check that we're not confusing "@apostrophecms/asset" with
|
|
69
|
-
// making sure "type" is not preceded by an npm namespace
|
|
70
|
-
// this never comes up (because npm
|
|
71
|
-
//
|
|
69
|
+
// Double-check that we're not confusing "@apostrophecms/asset" with
|
|
70
|
+
// "asset" by making sure "type" is not preceded by an npm namespace
|
|
71
|
+
// folder. If type is itself namespaced this never comes up (because npm
|
|
72
|
+
// namespaces don't nest). The risk is that a legitimate project level
|
|
73
|
+
// module that happens to end with the same name as a namespaced module
|
|
72
74
|
// will be rejected as a duplicate when nestedModuleSubdirs is present
|
|
73
75
|
return index.endsWith('/' + type + '/index.js') && !index.match(new RegExp(`/@[^/]+/${regExpQuote(type)}/index\\.js$`));
|
|
74
76
|
});
|
|
@@ -78,7 +80,11 @@ module.exports = async function(options) {
|
|
|
78
80
|
projectLevelPath = matches[0] ? path.normalize(matches[0]) : projectLevelPath;
|
|
79
81
|
}
|
|
80
82
|
if (fs.existsSync(projectLevelPath)) {
|
|
81
|
-
const {
|
|
83
|
+
const {
|
|
84
|
+
default: defaultProjectLevelDefinition
|
|
85
|
+
} = await importFresh(
|
|
86
|
+
resolveFrom(path.dirname(self.root.filename), projectLevelPath)
|
|
87
|
+
);
|
|
82
88
|
projectLevelDefinition = defaultProjectLevelDefinition;
|
|
83
89
|
if (Object.keys(projectLevelDefinition).length === 0) {
|
|
84
90
|
/* eslint-disable-next-line no-console */
|
|
@@ -159,15 +165,15 @@ module.exports = async function(options) {
|
|
|
159
165
|
if (npmDefinition) {
|
|
160
166
|
result = await superDefine(type, npmDefinition);
|
|
161
167
|
if (npmDefinition.improve) {
|
|
162
|
-
// Restore the name of the improving module as otherwise our asset
|
|
163
|
-
// multiple references to my-foo which is ambiguous
|
|
168
|
+
// Restore the name of the improving module as otherwise our asset
|
|
169
|
+
// chains have multiple references to my-foo which is ambiguous
|
|
164
170
|
result.__meta.name = originalType;
|
|
165
171
|
}
|
|
166
172
|
}
|
|
167
173
|
result = await superDefine(type, definition);
|
|
168
174
|
if (npmDefinition && npmDefinition.improve) {
|
|
169
|
-
// Restore the name of the improving module as otherwise our asset chains
|
|
170
|
-
// multiple references to my-foo which is ambiguous
|
|
175
|
+
// Restore the name of the improving module as otherwise our asset chains
|
|
176
|
+
// have multiple references to my-foo which is ambiguous
|
|
171
177
|
result.__meta.name = self.originalToMy(originalType);
|
|
172
178
|
}
|
|
173
179
|
// Mark "my" modules as such
|
|
@@ -256,7 +262,8 @@ module.exports = async function(options) {
|
|
|
256
262
|
return [];
|
|
257
263
|
}
|
|
258
264
|
|
|
259
|
-
// Ternary is required because glob expects at least 2 entries
|
|
265
|
+
// Ternary is required because glob expects at least 2 entries
|
|
266
|
+
// when using curly braces
|
|
260
267
|
const pattern = workspaces.length === 1 ? workspaces[0] : `{${workspaces.join(',')}}`;
|
|
261
268
|
const packagePath = path.resolve(folder, pattern, 'package.json');
|
|
262
269
|
const workspacePackages = glob(packagePath, { follow: true });
|
|
@@ -275,9 +282,9 @@ module.exports = async function(options) {
|
|
|
275
282
|
|
|
276
283
|
self.applyImprovementsBeforeProjectLevel = () => {
|
|
277
284
|
for (const [ name, definition ] of Object.entries(self.definitions)) {
|
|
278
|
-
// At this stage the complete definition of a type is a linked list of
|
|
279
|
-
// properties starting from what should be project level, unless
|
|
280
|
-
// are improvements. Shuffle project level to be the first in the
|
|
285
|
+
// At this stage the complete definition of a type is a linked list of
|
|
286
|
+
// `extend` properties starting from what should be project level, unless
|
|
287
|
+
// there are improvements. Shuffle project level to be the first in the
|
|
281
288
|
// linked list
|
|
282
289
|
if (definition.__meta.name !== self.originalToMy(name)) {
|
|
283
290
|
let candidate = definition;
|
package/lib/moog.js
CHANGED
|
@@ -131,7 +131,8 @@ module.exports = function(options) {
|
|
|
131
131
|
// Now we want to start from the base class and go down
|
|
132
132
|
steps.reverse();
|
|
133
133
|
|
|
134
|
-
// Actually just the apos object merging in, app.js merging was handled
|
|
134
|
+
// Actually just the apos object merging in, app.js merging was handled
|
|
135
|
+
// elsewhere
|
|
135
136
|
Object.assign(options, _options || {});
|
|
136
137
|
|
|
137
138
|
self.options.sections = self.options.sections || [];
|
|
@@ -186,7 +187,8 @@ module.exports = function(options) {
|
|
|
186
187
|
if (!that[`${cascade}Groups`]) {
|
|
187
188
|
that[`${cascade}Groups`] = {};
|
|
188
189
|
}
|
|
189
|
-
// You can have access to options within a function, if you choose to
|
|
190
|
+
// You can have access to options within a function, if you choose to
|
|
191
|
+
// provide one
|
|
190
192
|
const properties = ((typeof step[cascade]) === 'function') ? step[cascade](that, options) : step[cascade];
|
|
191
193
|
if (properties) {
|
|
192
194
|
const valid = [ 'add', 'remove', 'order', 'group' ];
|
|
@@ -235,7 +237,8 @@ module.exports = function(options) {
|
|
|
235
237
|
if (properties.group) {
|
|
236
238
|
const groups = klona(that[`${cascade}Groups`]);
|
|
237
239
|
for (const value of Object.values(properties.group)) {
|
|
238
|
-
// Handle `operations` alias of `fields`. Only one of them should
|
|
240
|
+
// Handle `operations` alias of `fields`. Only one of them should
|
|
241
|
+
// be used.
|
|
239
242
|
if (Array.isArray(value.operations)) {
|
|
240
243
|
value.fields = value.operations;
|
|
241
244
|
}
|
|
@@ -279,9 +282,9 @@ module.exports = function(options) {
|
|
|
279
282
|
}
|
|
280
283
|
}
|
|
281
284
|
|
|
282
|
-
// This needs to be after the options and cascades are compiled so it can
|
|
283
|
-
// the result, yet we've already reordered the steps with the
|
|
284
|
-
// so walk them backwards to implement beforeSuperClass
|
|
285
|
+
// This needs to be after the options and cascades are compiled so it can
|
|
286
|
+
// manipulate the result, yet we've already reordered the steps with the
|
|
287
|
+
// superclass first, so walk them backwards to implement beforeSuperClass
|
|
285
288
|
for (let i = (steps.length - 1); (i >= 0); i--) {
|
|
286
289
|
const step = steps[i];
|
|
287
290
|
if (step.beforeSuperClass) {
|
|
@@ -293,14 +296,15 @@ module.exports = function(options) {
|
|
|
293
296
|
// in other sections
|
|
294
297
|
build(null, 'methods');
|
|
295
298
|
|
|
296
|
-
// Unparsed sections, like `queries` and `extendQueries`. These are just
|
|
297
|
-
// in an object with the props from each level so the module can do
|
|
298
|
-
// them at runtime. Do it before init so that init can carry
|
|
299
|
+
// Unparsed sections, like `queries` and `extendQueries`. These are just
|
|
300
|
+
// captured in an object with the props from each level so the module can do
|
|
301
|
+
// something with them at runtime. Do it before init so that init can carry
|
|
302
|
+
// out queries
|
|
299
303
|
(self.options.unparsedSections || []).forEach(section => capture(section));
|
|
300
304
|
|
|
301
|
-
// init is called BEFORE routes etc. are called so that the section
|
|
302
|
-
// for those things can benefit from methods, properties, etc. set
|
|
303
|
-
// when deciding what to return
|
|
305
|
+
// init is called BEFORE routes etc. are called so that the section
|
|
306
|
+
// functions for those things can benefit from methods, properties, etc. set
|
|
307
|
+
// by init when deciding what to return
|
|
304
308
|
for (const step of steps) {
|
|
305
309
|
if (step.init) {
|
|
306
310
|
await step.init(that, options);
|
|
@@ -312,9 +316,9 @@ module.exports = function(options) {
|
|
|
312
316
|
|
|
313
317
|
// afterAllSections is called last and has access to self.routes, etc.
|
|
314
318
|
// For project-level developers this is usually not important, but
|
|
315
|
-
// the core does call certain methods in the @apostrophecms/modules base
|
|
316
|
-
// implementation of afterAllSections to actually add the routes and
|
|
317
|
-
// to the system
|
|
319
|
+
// the core does call certain methods in the @apostrophecms/modules base
|
|
320
|
+
// class implementation of afterAllSections to actually add the routes and
|
|
321
|
+
// handlers to the system
|
|
318
322
|
for (const step of steps) {
|
|
319
323
|
if (step.afterAllSections) {
|
|
320
324
|
await step.afterAllSections(that, options);
|
|
@@ -419,9 +423,10 @@ module.exports = function(options) {
|
|
|
419
423
|
|
|
420
424
|
self.options.unparsedSections = self.options.unparsedSections || [];
|
|
421
425
|
|
|
422
|
-
// Unparsed sections, like `queries` and `extendQueries`. These are just
|
|
423
|
-
// in an object with the props from each level so the module can do
|
|
424
|
-
// them at runtime. Do it before init so that init can carry
|
|
426
|
+
// Unparsed sections, like `queries` and `extendQueries`. These are just
|
|
427
|
+
// captured in an object with the props from each level so the module can do
|
|
428
|
+
// something with them at runtime. Do it before init so that init can carry
|
|
429
|
+
// out queries
|
|
425
430
|
(self.options.unparsedSections || []).forEach(section => capture(section));
|
|
426
431
|
|
|
427
432
|
return that;
|
package/lib/opentelemetry.js
CHANGED
|
@@ -32,8 +32,8 @@ module.exports = function (options = {}) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* Start and return a new span. Optionally provide a parent span or allow the
|
|
36
|
-
* span to be auto-detected.
|
|
35
|
+
* Start and return a new span. Optionally provide a parent span or allow the
|
|
36
|
+
* parent span to be auto-detected.
|
|
37
37
|
* Use this when the current code block does the tracing and it doesn't expect
|
|
38
38
|
* more tracing to happen down the line.
|
|
39
39
|
*
|
|
@@ -82,7 +82,8 @@ module.exports = function (options = {}) {
|
|
|
82
82
|
* @returns {api.Span|any} the return value of the handler or the newly created span
|
|
83
83
|
* @example
|
|
84
84
|
* // Activate span, return some value
|
|
85
|
-
* const value = await self.apos.telemetry.startActiveSpan(spanName, async
|
|
85
|
+
* const value = await self.apos.telemetry.startActiveSpan(spanName, async
|
|
86
|
+
* (span) => {
|
|
86
87
|
* // Use the span, do work, end span, return any value
|
|
87
88
|
* span.end();
|
|
88
89
|
* return value;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
// The admin bar module implements Apostrophe's admin bar at the top of the
|
|
2
|
-
// can register a button (or more than one) for this bar by
|
|
3
|
-
// module. Buttons can also be grouped into
|
|
4
|
-
// particular permissions.
|
|
5
|
-
//
|
|
1
|
+
// The admin bar module implements Apostrophe's admin bar at the top of the
|
|
2
|
+
// screen. Any module can register a button (or more than one) for this bar by
|
|
3
|
+
// calling the `add` method of this module. Buttons can also be grouped into
|
|
4
|
+
// dropdown menus and restricted to those with particular permissions.
|
|
5
|
+
// [@apostrophecms/piece-type](../@apostrophecms/piece-type/index.html)
|
|
6
|
+
// automatically takes advantage of this module.
|
|
6
7
|
|
|
7
8
|
const _ = require('lodash');
|
|
8
9
|
const { createId } = require('@paralleldrive/cuid2');
|
|
@@ -190,14 +191,15 @@ module.exports = {
|
|
|
190
191
|
// wish to implement a custom admin bar item not powered by
|
|
191
192
|
// the `AposModals` app.
|
|
192
193
|
//
|
|
193
|
-
// If `options.contextUtility` is true, the item will be displayed in a
|
|
194
|
-
// icons just to the right of the login and/or locales menu. If
|
|
195
|
-
// then the button will have the `active`
|
|
196
|
-
// off again. `options.tooltip.deactivate` and
|
|
197
|
-
// provided to offer a different tooltip
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
//
|
|
194
|
+
// If `options.contextUtility` is true, the item will be displayed in a
|
|
195
|
+
// tray of icons just to the right of the login and/or locales menu. If
|
|
196
|
+
// `options.toggle` is also true, then the button will have the `active`
|
|
197
|
+
// state until toggled off again. `options.tooltip.deactivate` and
|
|
198
|
+
// `options.tooltip.activate` may be provided to offer a different tooltip
|
|
199
|
+
// during the active versus inactive states, respectively. Otherwise,
|
|
200
|
+
// `options.tooltip` is used. The regular label is also present for
|
|
201
|
+
// screenreaders only. The contextUtility functionality is typically used
|
|
202
|
+
// for experiences that temporarily change the current editing context.
|
|
201
203
|
//
|
|
202
204
|
// If `options.user` is true, the menu bar item will appear
|
|
203
205
|
// on the user's personal dropdown, where "Log Out" appears. Such items
|
|
@@ -256,7 +258,10 @@ module.exports = {
|
|
|
256
258
|
}
|
|
257
259
|
// Only build a menu if there are at least two items after filtering
|
|
258
260
|
// for permissions
|
|
259
|
-
if (
|
|
261
|
+
if (
|
|
262
|
+
item.menuLeader === item.name &&
|
|
263
|
+
items[i + 1]?.menuLeader === item.name
|
|
264
|
+
) {
|
|
260
265
|
menu = {
|
|
261
266
|
menu: true,
|
|
262
267
|
items: [ item ],
|
|
@@ -313,7 +318,8 @@ module.exports = {
|
|
|
313
318
|
groupItems() {
|
|
314
319
|
// Implement the groups and addGroups options. Mark the grouped items
|
|
315
320
|
// with a `menuLeader` property.
|
|
316
|
-
const groups = self.options.groups ||
|
|
321
|
+
const groups = self.options.groups ||
|
|
322
|
+
self.groups.concat(self.options.addGroups || []);
|
|
317
323
|
|
|
318
324
|
groups.forEach(function (group) {
|
|
319
325
|
if (!group.label) {
|
|
@@ -418,7 +424,8 @@ module.exports = {
|
|
|
418
424
|
screens: {}
|
|
419
425
|
},
|
|
420
426
|
// Base API URL appropriate to the context document
|
|
421
|
-
contextBar: context && self.apos.doc
|
|
427
|
+
contextBar: context && self.apos.doc
|
|
428
|
+
.getManager(context.type).options.contextBar,
|
|
422
429
|
showAdminBar: self.getShowAdminBar(req),
|
|
423
430
|
// Simplifies frontend logic
|
|
424
431
|
contextId: context && context._id,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
class="apos-admin-bar__btn"
|
|
14
14
|
:modifiers="['no-motion']"
|
|
15
15
|
role="menuitem"
|
|
16
|
-
@click="emitEvent('@apostrophecms/page:manager')"
|
|
16
|
+
@click="emitEvent({ action: '@apostrophecms/page:manager' })"
|
|
17
17
|
/>
|
|
18
18
|
</li>
|
|
19
19
|
<li
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
:modifiers="['no-motion']"
|
|
43
43
|
class="apos-admin-bar__btn"
|
|
44
44
|
role="menuitem"
|
|
45
|
-
@click="emitEvent(item
|
|
45
|
+
@click="emitEvent(item)"
|
|
46
46
|
/>
|
|
47
47
|
</li>
|
|
48
48
|
<li
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
:label="item.label"
|
|
86
86
|
:action="item.action"
|
|
87
87
|
:state="trayItemState[item.name] ? [ 'active' ] : []"
|
|
88
|
-
@click="emitEvent(item
|
|
88
|
+
@click="emitEvent(item)"
|
|
89
89
|
/>
|
|
90
90
|
</template>
|
|
91
91
|
</li>
|
|
@@ -122,10 +122,9 @@ export default {
|
|
|
122
122
|
}
|
|
123
123
|
},
|
|
124
124
|
async mounted() {
|
|
125
|
-
apos.bus.$on('admin-menu-click', this.onAdminMenuClick);
|
|
126
|
-
|
|
127
125
|
const itemsSet = klona(this.items);
|
|
128
|
-
this.menuItems = itemsSet
|
|
126
|
+
this.menuItems = itemsSet
|
|
127
|
+
.filter(item => !(item.options && item.options.contextUtility))
|
|
129
128
|
.map(item => {
|
|
130
129
|
if (item.items) {
|
|
131
130
|
item.items.forEach(subitem => {
|
|
@@ -148,12 +147,25 @@ export default {
|
|
|
148
147
|
});
|
|
149
148
|
},
|
|
150
149
|
methods: {
|
|
151
|
-
emitEvent(
|
|
152
|
-
apos.bus.$emit('admin-menu-click',
|
|
150
|
+
emitEvent(item) {
|
|
151
|
+
apos.bus.$emit('admin-menu-click', item.action);
|
|
152
|
+
|
|
153
|
+
// Maintain a knowledge of which tray item toggles are active
|
|
154
|
+
const trayItem = this.trayItems.find(trayItem => trayItem.name === item.action);
|
|
155
|
+
|
|
156
|
+
if (trayItem && trayItem.options.toggle) {
|
|
157
|
+
this.trayItemState = {
|
|
158
|
+
...this.trayItemState,
|
|
159
|
+
[item.action]: !this.trayItemState[item.action]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
153
162
|
},
|
|
154
163
|
trayItemTooltip(item) {
|
|
155
164
|
if (item.options.toggle) {
|
|
156
|
-
if (
|
|
165
|
+
if (
|
|
166
|
+
this.trayItemState[item.name] &&
|
|
167
|
+
item.options.tooltip?.deactivate
|
|
168
|
+
) {
|
|
157
169
|
return {
|
|
158
170
|
content: item.options.tooltip.deactivate,
|
|
159
171
|
placement: 'bottom'
|
|
@@ -169,17 +181,6 @@ export default {
|
|
|
169
181
|
} else {
|
|
170
182
|
return item.options.tooltip;
|
|
171
183
|
}
|
|
172
|
-
},
|
|
173
|
-
// Maintain a knowledge of which tray item toggles are active
|
|
174
|
-
onAdminMenuClick(e) {
|
|
175
|
-
const name = e.itemName || e;
|
|
176
|
-
const trayItem = this.trayItems.find(item => item.name === name);
|
|
177
|
-
if (trayItem && trayItem.options.toggle) {
|
|
178
|
-
this.trayItemState = {
|
|
179
|
-
...this.trayItemState,
|
|
180
|
-
[name]: !this.trayItemState[name]
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
};
|