apostrophe 4.22.0 → 4.23.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 +29 -0
- package/defaults.js +2 -0
- package/index.js +16 -6
- package/lib/image.js +48 -0
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBreakpointPreviewMode.vue +7 -3
- package/modules/@apostrophecms/area/index.js +98 -22
- package/modules/@apostrophecms/area/ui/apos/apps/AposAreas.js +16 -4
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +2 -697
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +587 -278
- package/modules/@apostrophecms/area/ui/apos/components/AposBreadcrumbOperations.vue +416 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposBreadcrumbSwitch.vue +212 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +97 -110
- package/modules/@apostrophecms/area/ui/apos/lib/operations.js +22 -0
- package/modules/@apostrophecms/area/ui/apos/lib/package.json +4 -0
- package/modules/@apostrophecms/area/ui/apos/lib/walk-widgets.js +57 -0
- package/modules/@apostrophecms/area/ui/apos/logic/AposAreaEditor.js +642 -0
- package/modules/@apostrophecms/area/views/area.html +39 -9
- package/modules/@apostrophecms/asset/lib/build/internals.js +1 -1
- package/modules/@apostrophecms/asset/lib/globalIcons.js +11 -0
- package/modules/@apostrophecms/color-field/index.js +1 -5
- package/modules/@apostrophecms/color-field/ui/apos/components/AposColor.vue +2 -26
- package/modules/@apostrophecms/color-field/ui/apos/components/AposInputColor.vue +86 -18
- package/modules/@apostrophecms/color-field/ui/apos/logic/AposInputColor.js +14 -1
- package/modules/@apostrophecms/color-field/ui/apos/logic/finalOptions.js +28 -0
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocLocalePicker.vue +5 -0
- package/modules/@apostrophecms/express/index.js +1 -0
- package/modules/@apostrophecms/i18n/i18n/de.json +2 -0
- package/modules/@apostrophecms/i18n/i18n/en.json +22 -0
- package/modules/@apostrophecms/i18n/i18n/es.json +2 -0
- package/modules/@apostrophecms/i18n/i18n/fr.json +2 -0
- package/modules/@apostrophecms/i18n/i18n/it.json +2 -0
- package/modules/@apostrophecms/i18n/i18n/pt-BR.json +2 -0
- package/modules/@apostrophecms/i18n/i18n/sk.json +2 -0
- package/modules/@apostrophecms/image/index.js +18 -2
- package/modules/@apostrophecms/image/ui/apos/apps/AposImageRelationshipQueryFilter.js +1 -1
- package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +9 -30
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +40 -29
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaUploaderUi.vue +25 -4
- package/modules/@apostrophecms/image-widget/ui/apos/components/AposImageWidget.vue +12 -6
- package/modules/@apostrophecms/layout-column-widget/index.js +188 -0
- package/modules/@apostrophecms/layout-column-widget/views/widget.html +1 -0
- package/modules/@apostrophecms/layout-widget/index.js +371 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposAreaLayoutEditor.vue +439 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposGridLayout.vue +408 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposGridManager.vue +1292 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/components/AposLayoutColControlDialog.vue +171 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/layout.css +72 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/lib/grid-manager.js +665 -0
- package/modules/@apostrophecms/layout-widget/ui/apos/lib/grid-state.mjs +1727 -0
- package/modules/@apostrophecms/layout-widget/ui/src/layout.css +97 -0
- package/modules/@apostrophecms/layout-widget/views/column.html +19 -0
- package/modules/@apostrophecms/layout-widget/views/widget.html +15 -0
- package/modules/@apostrophecms/login/index.js +116 -26
- package/modules/@apostrophecms/migration/index.js +2 -4
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +5 -0
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +1 -1
- package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +12 -0
- package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +18 -2
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +29 -3
- package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +0 -1
- package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +11 -42
- package/modules/@apostrophecms/schema/ui/apos/logic/AposSubform.js +3 -2
- package/modules/@apostrophecms/template/index.js +8 -5
- package/modules/@apostrophecms/ui/ui/apos/apps/AposBreakpointPreview.js +5 -0
- package/modules/@apostrophecms/ui/ui/apos/apps/AposWidgetStore.js +9 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +56 -15
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +115 -10
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +1 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposLocalePicker.vue +9 -1
- package/modules/@apostrophecms/ui/ui/apos/scss/global/_inputs.scss +29 -4
- package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_theme_mixins.scss +1 -0
- package/modules/@apostrophecms/ui/ui/apos/stores/breakpointPreview.js +15 -0
- package/modules/@apostrophecms/ui/ui/apos/stores/widget.js +116 -0
- package/modules/@apostrophecms/user/index.js +14 -0
- package/modules/@apostrophecms/widget-type/index.js +198 -24
- package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +4 -1
- package/modules/@apostrophecms/widget-type/ui/apos/mixins/AposWidgetMixin.js +4 -2
- package/package.json +3 -2
- package/test/areas.js +96 -89
- package/test/images.js +102 -0
- package/test/layout-widget-ui.js +1411 -0
- package/test/login.js +497 -3
- package/test/walk-widgets.js +549 -0
- package/test/widgets.js +12 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.23.0 (2025-10-30)
|
|
4
|
+
|
|
5
|
+
### Adds
|
|
6
|
+
|
|
7
|
+
* Add locale picker in the page and piece manager modals.
|
|
8
|
+
* Support for the `render-areas` query parameter in the REST API when using Astro as an external frontend, provided the Astro project has the corresponding route. This allows section template library previews to work in Astro projects. For ease of migration, if Astro cannot satisfy the request, ApostropheCMS will also attempt to render the widget natively.
|
|
9
|
+
* Made `self.apos.externalFrontKey` available, simplifying API calls back to Astro.
|
|
10
|
+
* Layout widget for dynamic grid layouts.
|
|
11
|
+
* `widgetOperations` support for `placement: 'breadcrumb'` to add operations to the breadcrumb menu of widgets. Extend the widget operations configuration to support various features when in the breadcrumb menu.
|
|
12
|
+
* Area template (Nunjucks) support for `aposStyle`, `aposClassName`, `aposParentOptions` and `aposAttrs` contextual named variables (`with {}` syntax).
|
|
13
|
+
* New login option `caseInsensitive` to force login usernames and emails to be case insensitive. New task `login-case-insensitive` updating all login names / email to lowercase, used by a new migration when switching to `caseInsensitive`.
|
|
14
|
+
* Adds `disableIfProps` and `disableTooltip` to widget operations and breadcrumb operations.
|
|
15
|
+
|
|
16
|
+
### Changes
|
|
17
|
+
|
|
18
|
+
* Enable `/api/v1/@apostrophecms/login/logout` and `/api/v1/@apostrophecms/login/whoami` routes when `localLogin` is `false`.
|
|
19
|
+
* Refactored complex logic regarding data updates in `AposSchema`.
|
|
20
|
+
* Cleaned up `annotateAreaForExternalFront` logic and added context so developers understand the reason if it fails due to a widget type with no matching module in the project.
|
|
21
|
+
* Color fields now display their preset color swatches in the field UI rather than just the color picker popup
|
|
22
|
+
* Moves widget operations to backend with new `action` and `nativeAction` properties.
|
|
23
|
+
* Moves `mode` from breakpoint preview to it's own store (to be used by layout).
|
|
24
|
+
|
|
25
|
+
### Fixes
|
|
26
|
+
|
|
27
|
+
* The `render-areas` query parameter now works correctly with areas nested in array items.
|
|
28
|
+
* Fix min size calculation for image widgets configured with an aspect ratio.
|
|
29
|
+
* Added missing `await` in helper library function for the asset module, ensuring JS assets build reliably.
|
|
30
|
+
* Autodetection of bundles, and automatic activation of "improvements" shipped in those bundles, now works correctly when the bundle is delivered in ES module format rather than commonjs format.
|
|
31
|
+
|
|
3
32
|
## 4.22.0 (2025-10-01)
|
|
4
33
|
|
|
5
34
|
### Adds
|
package/defaults.js
CHANGED
|
@@ -41,6 +41,8 @@ module.exports = {
|
|
|
41
41
|
'@apostrophecms/search': {},
|
|
42
42
|
'@apostrophecms/any-page-type': {},
|
|
43
43
|
'@apostrophecms/area': {},
|
|
44
|
+
'@apostrophecms/layout-widget': {},
|
|
45
|
+
'@apostrophecms/layout-column-widget': {},
|
|
44
46
|
'@apostrophecms/rich-text-widget': {},
|
|
45
47
|
'@apostrophecms/html-widget': {},
|
|
46
48
|
'@apostrophecms/color-field': {},
|
package/index.js
CHANGED
|
@@ -14,6 +14,8 @@ const glob = require('./lib/glob.js');
|
|
|
14
14
|
const moogRequire = require('./lib/moog-require');
|
|
15
15
|
let defaults = require('./defaults.js');
|
|
16
16
|
|
|
17
|
+
const importFresh = moduleName => import(`${moduleName}?${Date.now()}`);
|
|
18
|
+
|
|
17
19
|
// ## Top-level options
|
|
18
20
|
//
|
|
19
21
|
// `cluster`
|
|
@@ -435,16 +437,24 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
435
437
|
continue;
|
|
436
438
|
}
|
|
437
439
|
|
|
438
|
-
const apostropheModule = await
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
440
|
+
const { default: apostropheModule } = await importFresh(npmPath);
|
|
441
|
+
const bundle = apostropheModule.bundle;
|
|
442
|
+
if (bundle) {
|
|
443
|
+
self.options.bundles = [
|
|
444
|
+
...new Set(
|
|
445
|
+
[
|
|
446
|
+
...(self.options.bundles || []),
|
|
447
|
+
apostropheModuleName
|
|
448
|
+
]
|
|
449
|
+
)
|
|
450
|
+
];
|
|
451
|
+
const bundleModules = bundle.modules;
|
|
442
452
|
for (const bundleModuleName of bundleModules) {
|
|
443
453
|
if (!apostropheModules.includes(bundleModuleName)) {
|
|
444
|
-
const bundledModule = await
|
|
454
|
+
const { default: bundledModule } = await importFresh(
|
|
445
455
|
path.resolve(
|
|
446
456
|
path.dirname(npmPath),
|
|
447
|
-
|
|
457
|
+
bundle.directory,
|
|
448
458
|
bundleModuleName,
|
|
449
459
|
'index.js'
|
|
450
460
|
)
|
package/lib/image.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function computeMinSizes([ minWidth, minHeight ], aspectRatio) {
|
|
2
|
+
const aspectRatioFloat = Array.isArray(aspectRatio)
|
|
3
|
+
? aspectRatio[0] / aspectRatio[1]
|
|
4
|
+
: aspectRatio;
|
|
5
|
+
|
|
6
|
+
if (!aspectRatioFloat) {
|
|
7
|
+
return {
|
|
8
|
+
minWidth,
|
|
9
|
+
minHeight
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// If ratio wants a square,
|
|
14
|
+
// we simply take the higher min size
|
|
15
|
+
if (aspectRatioFloat === 1) {
|
|
16
|
+
const higherValue = Math.max(minWidth, minHeight);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
minWidth: higherValue,
|
|
20
|
+
minHeight: higherValue
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const diff = minWidth / minHeight - aspectRatioFloat;
|
|
25
|
+
|
|
26
|
+
if (diff > 0) {
|
|
27
|
+
return {
|
|
28
|
+
minWidth,
|
|
29
|
+
minHeight: minWidth / aspectRatioFloat
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (diff < 0) {
|
|
34
|
+
return {
|
|
35
|
+
minWidth: minHeight * aspectRatioFloat,
|
|
36
|
+
minHeight
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
minWidth,
|
|
42
|
+
minHeight
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
computeMinSizes
|
|
48
|
+
};
|
package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBreakpointPreviewMode.vue
CHANGED
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
</div>
|
|
57
57
|
</template>
|
|
58
58
|
<script>
|
|
59
|
+
import { mapState, mapActions } from 'pinia';
|
|
60
|
+
import { useBreakpointPreviewStore } from 'Modules/@apostrophecms/ui/stores/breakpointPreview.js';
|
|
61
|
+
|
|
59
62
|
export default {
|
|
60
63
|
name: 'TheAposContextBreakpointPreviewMode',
|
|
61
64
|
props: {
|
|
@@ -83,7 +86,6 @@ export default {
|
|
|
83
86
|
emits: [ 'switch-breakpoint-preview-mode', 'reset-breakpoint-preview-mode' ],
|
|
84
87
|
data() {
|
|
85
88
|
return {
|
|
86
|
-
mode: null,
|
|
87
89
|
originalBodyBackground: null,
|
|
88
90
|
shortcuts: this.getShortcuts(),
|
|
89
91
|
breakpoints: this.getBreakpointItems(),
|
|
@@ -94,6 +96,7 @@ export default {
|
|
|
94
96
|
};
|
|
95
97
|
},
|
|
96
98
|
computed: {
|
|
99
|
+
...mapState(useBreakpointPreviewStore, [ 'mode' ]),
|
|
97
100
|
activeScreen() {
|
|
98
101
|
return this.mode && this.screens[this.mode];
|
|
99
102
|
},
|
|
@@ -154,6 +157,7 @@ export default {
|
|
|
154
157
|
);
|
|
155
158
|
},
|
|
156
159
|
methods: {
|
|
160
|
+
...mapActions(useBreakpointPreviewStore, [ 'setMode' ]),
|
|
157
161
|
observerCallback(mutationList, observer) {
|
|
158
162
|
for (const mutation of mutationList) {
|
|
159
163
|
if (
|
|
@@ -205,7 +209,7 @@ export default {
|
|
|
205
209
|
refreshableEl.style.width = width;
|
|
206
210
|
refreshableEl.style.height = height;
|
|
207
211
|
|
|
208
|
-
this.mode
|
|
212
|
+
this.setMode(mode);
|
|
209
213
|
this.$emit('switch-breakpoint-preview-mode', {
|
|
210
214
|
mode,
|
|
211
215
|
label,
|
|
@@ -249,7 +253,7 @@ export default {
|
|
|
249
253
|
refreshableEl.style.removeProperty('width');
|
|
250
254
|
refreshableEl.style.removeProperty('height');
|
|
251
255
|
|
|
252
|
-
this.
|
|
256
|
+
this.setMode(null);
|
|
253
257
|
this.$emit('reset-breakpoint-preview-mode');
|
|
254
258
|
this.saveState({ mode: this.mode });
|
|
255
259
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const { stripIndent } = require('common-tags');
|
|
3
|
+
const cheerio = require('cheerio');
|
|
3
4
|
|
|
4
5
|
// An area is a series of zero or more widgets, in which users can add
|
|
5
6
|
// and remove widgets and drag them to reorder them. This module implements
|
|
@@ -270,7 +271,9 @@ module.exports = {
|
|
|
270
271
|
self.missingWidgetTypes = {};
|
|
271
272
|
}
|
|
272
273
|
if (!self.missingWidgetTypes[name]) {
|
|
273
|
-
self.apos.util.error(
|
|
274
|
+
self.apos.util.error(`WARNING: widget type ${name} exists in your database but is not configured.\n` +
|
|
275
|
+
`You probably do not have a ${name}-widget module in your project.`
|
|
276
|
+
);
|
|
274
277
|
self.missingWidgetTypes[name] = true;
|
|
275
278
|
}
|
|
276
279
|
},
|
|
@@ -292,6 +295,10 @@ module.exports = {
|
|
|
292
295
|
// If `inline` is true then the rendering of each widget is attached
|
|
293
296
|
// to the widget as a `_rendered` property, bypassing normal full-area
|
|
294
297
|
// HTML responses, and the return value of this method is `null`.
|
|
298
|
+
//
|
|
299
|
+
// If an external front key is configured, ApostropheCMS will attempt
|
|
300
|
+
// to render the widget via Astro before attempting to render it
|
|
301
|
+
// natively.
|
|
295
302
|
async renderArea(req, area, _with, { inline = false } = {}) {
|
|
296
303
|
if (!area._id) {
|
|
297
304
|
throw new Error('All areas must have an _id property in A3.x. Area details:\n\n' + JSON.stringify(area));
|
|
@@ -337,27 +344,86 @@ module.exports = {
|
|
|
337
344
|
// just use the helpers
|
|
338
345
|
self.apos.attachment.all(area, { annotate: true });
|
|
339
346
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
347
|
+
|
|
348
|
+
let externalError = null;
|
|
349
|
+
if (!self.apos.externalFrontKey) {
|
|
350
|
+
return renderNatively();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
try {
|
|
354
|
+
return await renderViaExternalFront();
|
|
355
|
+
} catch (e) {
|
|
356
|
+
externalError = e;
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
return await renderNatively();
|
|
360
|
+
} catch (e) {
|
|
361
|
+
throw new Error('Could not render area for API, neither via the external frontend nor natively.\n\n' +
|
|
362
|
+
'Check your Astro server logs as well.\n\n' +
|
|
363
|
+
niceError(externalError) + '\n\n' +
|
|
364
|
+
niceError(e)
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async function renderViaExternalFront() {
|
|
369
|
+
if (!self.apos.baseUrl && self.apos.externalFrontKey) {
|
|
370
|
+
throw new Error('APOS_BASE_URL and APOS_EXTERNAL_FRONT_KEY must both be set in order to render\nvia the external frontend');
|
|
371
|
+
}
|
|
372
|
+
// Astro can render components or return JSON but not both, at least not without
|
|
373
|
+
// using its experimental container API which would potentially not have
|
|
374
|
+
// the same configuration as the main Astro project. So we let Astro be Astro,
|
|
375
|
+
// then we pull out the individual renderings with Cheerio. -Tom
|
|
376
|
+
const response = await fetch(`${self.apos.baseUrl}/api/apos-external-front/render-area`, {
|
|
377
|
+
method: 'POST',
|
|
378
|
+
headers: {
|
|
379
|
+
'apos-external-front-key': self.apos.externalFrontKey
|
|
380
|
+
},
|
|
381
|
+
body: JSON.stringify({
|
|
382
|
+
area
|
|
383
|
+
})
|
|
384
|
+
});
|
|
385
|
+
if (response.status >= 400) {
|
|
386
|
+
throw response;
|
|
387
|
+
}
|
|
388
|
+
const html = await response.text();
|
|
389
|
+
const $ = cheerio.load(`<div id="root">${html}</div>`);
|
|
390
|
+
if (inline) {
|
|
391
|
+
for (let i = 0; (i < area.items.length); i++) {
|
|
392
|
+
area.items[i]._rendered = $(`#root [data-widget-id="${area.items[i]._id}"]`).html() || '';
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
} else {
|
|
396
|
+
const $children = $('#root [data-widget-id]');
|
|
397
|
+
return $children.map(function() {
|
|
398
|
+
return $(this).html();
|
|
399
|
+
}).join('\n');
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function renderNatively() {
|
|
404
|
+
if (inline) {
|
|
405
|
+
for (const item of area.items) {
|
|
406
|
+
item._rendered = await self.renderWidget(
|
|
407
|
+
req,
|
|
408
|
+
item.type,
|
|
409
|
+
item,
|
|
410
|
+
widgets[item.type]
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
} else {
|
|
415
|
+
return self.render(req, 'area', {
|
|
416
|
+
// TODO filter area to exclude big relationship objects, but
|
|
417
|
+
// not so sloppy this time please
|
|
418
|
+
area,
|
|
419
|
+
field,
|
|
420
|
+
options,
|
|
421
|
+
choices,
|
|
422
|
+
_with,
|
|
423
|
+
canEdit
|
|
424
|
+
});
|
|
348
425
|
}
|
|
349
|
-
return null;
|
|
350
426
|
}
|
|
351
|
-
return self.render(req, 'area', {
|
|
352
|
-
// TODO filter area to exclude big relationship objects, but
|
|
353
|
-
// not so sloppy this time please
|
|
354
|
-
area,
|
|
355
|
-
field,
|
|
356
|
-
options,
|
|
357
|
-
choices,
|
|
358
|
-
_with,
|
|
359
|
-
canEdit
|
|
360
|
-
});
|
|
361
427
|
},
|
|
362
428
|
// Replace documents' area objects with rendered HTML for each area.
|
|
363
429
|
// This is used by GET requests including the `render-areas` query
|
|
@@ -373,6 +439,10 @@ module.exports = {
|
|
|
373
439
|
let index = 0;
|
|
374
440
|
// Loop over the docs in the array passed in.
|
|
375
441
|
for (const doc of within) {
|
|
442
|
+
if (self.apos.externalFrontKey) {
|
|
443
|
+
self.apos.template.annotateDocForExternalFront(doc);
|
|
444
|
+
}
|
|
445
|
+
|
|
376
446
|
const rendered = [];
|
|
377
447
|
|
|
378
448
|
const areasToRender = {};
|
|
@@ -409,8 +479,8 @@ module.exports = {
|
|
|
409
479
|
index++;
|
|
410
480
|
}
|
|
411
481
|
|
|
412
|
-
async function render(area, path, context
|
|
413
|
-
const preppedArea = self.prepForRender(area, context, path);
|
|
482
|
+
async function render(area, path, context) {
|
|
483
|
+
const preppedArea = self.prepForRender(area, context, path.split('.').at(-1));
|
|
414
484
|
|
|
415
485
|
const areaRendered = await self.apos.area.renderArea(
|
|
416
486
|
req,
|
|
@@ -903,3 +973,9 @@ module.exports = {
|
|
|
903
973
|
};
|
|
904
974
|
}
|
|
905
975
|
};
|
|
976
|
+
|
|
977
|
+
function niceError(e) {
|
|
978
|
+
// Node.js includes the error message in the stack property, it's
|
|
979
|
+
// actually a complete rendering plus the stack 🤷
|
|
980
|
+
return e.stack;
|
|
981
|
+
}
|
|
@@ -3,8 +3,6 @@ import createApp from 'Modules/@apostrophecms/ui/lib/vue';
|
|
|
3
3
|
|
|
4
4
|
export default function() {
|
|
5
5
|
|
|
6
|
-
const component = apos.vueComponents.AposAreaEditor;
|
|
7
|
-
|
|
8
6
|
let widgetsRendering = 0;
|
|
9
7
|
|
|
10
8
|
apos.area.widgetOptions = [];
|
|
@@ -66,13 +64,25 @@ export default function() {
|
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
function createAreaApp(el) {
|
|
69
|
-
const options = JSON.parse(el.getAttribute('data-options'));
|
|
70
|
-
const data = JSON.parse(el.getAttribute('data'));
|
|
67
|
+
const options = JSON.parse(el.getAttribute('data-options')) || {};
|
|
68
|
+
const data = JSON.parse(el.getAttribute('data')) || {};
|
|
71
69
|
const fieldId = el.getAttribute('data-field-id');
|
|
70
|
+
const moduleName = el.getAttribute('data-module');
|
|
72
71
|
const choices = JSON.parse(el.getAttribute('data-choices'));
|
|
73
72
|
const renderings = {};
|
|
74
73
|
const _docId = data._docId;
|
|
75
74
|
|
|
75
|
+
const parentOptionsStr = el.getAttribute('data-parent-options');
|
|
76
|
+
const parentOptions = parentOptionsStr ? JSON.parse(parentOptionsStr) : null;
|
|
77
|
+
|
|
78
|
+
let componentName = options.editorComponent || 'AposAreaEditor';
|
|
79
|
+
if (!apos.vueComponents[componentName]) {
|
|
80
|
+
// eslint-disable-next-line no-console
|
|
81
|
+
console.error(`Area Editor component "${componentName}" not found. Switching to default.`);
|
|
82
|
+
componentName = 'AposAreaEditor';
|
|
83
|
+
}
|
|
84
|
+
const component = apos.vueComponents[componentName];
|
|
85
|
+
|
|
76
86
|
for (const widgetEl of el.querySelectorAll('[data-apos-widget]')) {
|
|
77
87
|
const _id = widgetEl.getAttribute('data-apos-widget');
|
|
78
88
|
const item = data.items.find(item => _id === item._id);
|
|
@@ -109,6 +119,8 @@ export default function() {
|
|
|
109
119
|
choices,
|
|
110
120
|
docId: _docId,
|
|
111
121
|
fieldId,
|
|
122
|
+
moduleName,
|
|
123
|
+
parentOptions,
|
|
112
124
|
renderings
|
|
113
125
|
});
|
|
114
126
|
|