apostrophe 3.35.0 → 3.37.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 +25 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +1 -1
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +2 -5
- package/modules/@apostrophecms/asset/index.js +36 -5
- package/modules/@apostrophecms/doc/index.js +2 -1
- package/modules/@apostrophecms/doc-type/index.js +1 -1
- package/modules/@apostrophecms/file-tag/index.js +2 -1
- package/modules/@apostrophecms/image-tag/index.js +2 -1
- package/modules/@apostrophecms/image-widget/index.js +4 -1
- package/modules/@apostrophecms/image-widget/views/widget.html +1 -1
- package/modules/@apostrophecms/module/index.js +41 -0
- package/modules/@apostrophecms/polymorphic-type/index.js +10 -1
- package/modules/@apostrophecms/polymorphic-type/lib/migrations.js +18 -0
- package/modules/@apostrophecms/schema/index.js +4 -3
- package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +5 -0
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +3 -1
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +8 -0
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputChoicesMixin.js +2 -1
- package/modules/@apostrophecms/widget-type/index.js +4 -1
- package/package.json +1 -1
- package/test/widgets.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.37.0 (2023-01-06)
|
|
4
|
+
|
|
5
|
+
### Adds
|
|
6
|
+
|
|
7
|
+
* Dynamic choice functions in schemas now also receive a data object with their original doc id for further inspection by your function.
|
|
8
|
+
* Use `mergeWithCustomize` when merging extended source Webpack configuration. Introduce overideable asset module methods `srcCustomizeArray` and `srcCustomizeObject`, with reasonable default behavior, for fine tuning Webpack config arrays and objects merging. More info - [the Webpack mergeWithCustomize docs](https://github.com/survivejs/webpack-merge#mergewithcustomize-customizearray-customizeobject-configuration--configuration)
|
|
9
|
+
* The image widget now accepts a `placeholderImage` option that works like `previewImage` (just specify a file extension, like `placeholderImage: 'jpg'`, and provide the file `public/placeholder.jpg` in the module). The `placeholderUrl` option is still available for backwards compatibility.
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
* `docId` is now properly passed through array and object fields and into their child schemas.
|
|
14
|
+
* Remove module `@apostrophecms/polymorphic-type` name alias `@apostrophecms/polymorphic`. It was causing warnings
|
|
15
|
+
e.g. `A permission.can() call was made with a type that has no manager: @apostrophecms/polymorphic-type`.
|
|
16
|
+
* The module `webpack.extensions` configuration is not applied to the core Admin UI build anymore. This is the correct and intended behavior as explained in the [relevant documentation](https://v3.docs.apostrophecms.org/guide/webpack.html#extending-webpack-configuration).
|
|
17
|
+
* The `previewImage` option now works properly for widget modules loaded from npm and those that subclass them. Specifically, the preview image may be provided in the `public/` subdirectory of the original module, the project-level configuration of it, or a subclass.
|
|
18
|
+
|
|
19
|
+
## 3.36.0 (2022-12-22)
|
|
20
|
+
|
|
21
|
+
### Adds
|
|
22
|
+
|
|
23
|
+
* `shortcut` option for piece modules, allowing easy re-mapping of the manager command shortcut per module.
|
|
24
|
+
|
|
25
|
+
### Fixes
|
|
26
|
+
|
|
27
|
+
* Ensure there are no conflicting command shortcuts for the core modules.
|
|
3
28
|
|
|
4
29
|
## 3.35.0 (2022-12-21)
|
|
5
30
|
|
|
@@ -363,7 +363,7 @@ export default {
|
|
|
363
363
|
apos.area.activeEditor = this;
|
|
364
364
|
const result = await apos.modal.execute(componentName, {
|
|
365
365
|
value: widget,
|
|
366
|
-
options: this.
|
|
366
|
+
options: this.widgetOptionsByType(widget.type),
|
|
367
367
|
type: widget.type,
|
|
368
368
|
docId: this.docId
|
|
369
369
|
});
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
class="apos-icon--add"
|
|
37
37
|
/>
|
|
38
38
|
<img
|
|
39
|
-
v-if="item.
|
|
40
|
-
:src="previewUrl
|
|
39
|
+
v-if="item.previewUrl"
|
|
40
|
+
:src="item.previewUrl"
|
|
41
41
|
:alt="`${item.name} preview`"
|
|
42
42
|
class="apos-widget__preview-image"
|
|
43
43
|
>
|
|
@@ -176,9 +176,6 @@ export default {
|
|
|
176
176
|
hasIcon(widget) {
|
|
177
177
|
return widget.previewIcon || widget.icon;
|
|
178
178
|
},
|
|
179
|
-
previewUrl(widget) {
|
|
180
|
-
return widget.previewImage ? apos.util.assetUrl(`/modules/${widget.name}-widget/preview.${widget.previewImage}`) : '';
|
|
181
|
-
},
|
|
182
179
|
close() {
|
|
183
180
|
this.modal.showModal = false;
|
|
184
181
|
},
|
|
@@ -7,7 +7,7 @@ const path = require('path');
|
|
|
7
7
|
const util = require('util');
|
|
8
8
|
const express = require('express');
|
|
9
9
|
const { stripIndent } = require('common-tags');
|
|
10
|
-
const {
|
|
10
|
+
const { mergeWithCustomize: webpackMerge } = require('webpack-merge');
|
|
11
11
|
const cuid = require('cuid');
|
|
12
12
|
const chokidar = require('chokidar');
|
|
13
13
|
const _ = require('lodash');
|
|
@@ -73,7 +73,6 @@ module.exports = {
|
|
|
73
73
|
self.buildWatcherEnable = process.env.APOS_ASSET_WATCH !== '0' && self.options.watch !== false;
|
|
74
74
|
self.buildWatcherDebounceMs = parseInt(self.options.watchDebounceMs || 1000, 10);
|
|
75
75
|
self.buildWatcher = null;
|
|
76
|
-
|
|
77
76
|
},
|
|
78
77
|
handlers (self) {
|
|
79
78
|
return {
|
|
@@ -389,8 +388,11 @@ module.exports = {
|
|
|
389
388
|
es5TaskFn: self.es5TaskFn
|
|
390
389
|
}, self.apos);
|
|
391
390
|
|
|
392
|
-
const webpackInstanceConfigMerged = self.webpackExtensions
|
|
393
|
-
? webpackMerge(
|
|
391
|
+
const webpackInstanceConfigMerged = !options.apos && self.webpackExtensions
|
|
392
|
+
? webpackMerge({
|
|
393
|
+
customizeArray: self.srcCustomizeArray,
|
|
394
|
+
customizeObject: self.srcCustomizeObject
|
|
395
|
+
})(webpackInstanceConfig, ...Object.values(self.webpackExtensions))
|
|
394
396
|
: webpackInstanceConfig;
|
|
395
397
|
|
|
396
398
|
// Inject the cache location at the end - we need the merged config
|
|
@@ -941,6 +943,28 @@ module.exports = {
|
|
|
941
943
|
// Open the implementation for more dev comments.
|
|
942
944
|
transformRebundledFor,
|
|
943
945
|
|
|
946
|
+
// Optional functions passed to webpack's mergeWithCustomize, allowing
|
|
947
|
+
// fine control over merging of the webpack configuration for the
|
|
948
|
+
// src build. Extend or override to alter the default behavior.
|
|
949
|
+
// See https://github.com/survivejs/webpack-merge#mergewithcustomize-customizearray-customizeobject-configuration--configuration
|
|
950
|
+
srcCustomizeArray(a, b, key) {
|
|
951
|
+
// Keep arrays unique when merging
|
|
952
|
+
if (
|
|
953
|
+
[
|
|
954
|
+
'resolveLoader.extensions',
|
|
955
|
+
'resolveLoader.modules',
|
|
956
|
+
'resolve.extensions',
|
|
957
|
+
'resolve.modules'
|
|
958
|
+
].includes(key)
|
|
959
|
+
) {
|
|
960
|
+
return _.uniq([ ...a, ...b ]);
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
|
|
964
|
+
srcCustomizeObject(a, b, key) {
|
|
965
|
+
// override to alter the default webpack merge behavior
|
|
966
|
+
},
|
|
967
|
+
|
|
944
968
|
async initUploadfs() {
|
|
945
969
|
if (self.options.uploadfs) {
|
|
946
970
|
self.uploadfs = await self.apos.modules['@apostrophecms/uploadfs'].getInstance(self.options.uploadfs);
|
|
@@ -1319,6 +1343,11 @@ module.exports = {
|
|
|
1319
1343
|
return 'url(\'' + filter(url) + '\')';
|
|
1320
1344
|
});
|
|
1321
1345
|
return css;
|
|
1346
|
+
},
|
|
1347
|
+
// Return the URL of the asset with the given path, taking into account
|
|
1348
|
+
// the release id, uploadfs, etc.
|
|
1349
|
+
url(path) {
|
|
1350
|
+
return `${self.getAssetBaseUrl()}${path}`;
|
|
1322
1351
|
}
|
|
1323
1352
|
};
|
|
1324
1353
|
},
|
|
@@ -1336,8 +1365,10 @@ module.exports = {
|
|
|
1336
1365
|
}
|
|
1337
1366
|
return self.apos.template.safe(`<script data-apos-refresh-on-restart="${self.action}/restart-id" src="${self.action}/refresh-on-restart"></script>`);
|
|
1338
1367
|
},
|
|
1368
|
+
// Return the URL of the release asset with the given path, taking into account
|
|
1369
|
+
// the release id, uploadfs, etc.
|
|
1339
1370
|
url(path) {
|
|
1340
|
-
return
|
|
1371
|
+
return self.url(path);
|
|
1341
1372
|
}
|
|
1342
1373
|
};
|
|
1343
1374
|
},
|
|
@@ -1096,8 +1096,9 @@ module.exports = {
|
|
|
1096
1096
|
normalizeType(type) {
|
|
1097
1097
|
if (type === '@apostrophecms/page') {
|
|
1098
1098
|
// Backwards compatible
|
|
1099
|
-
|
|
1099
|
+
return '@apostrophecms/any-page-type';
|
|
1100
1100
|
}
|
|
1101
|
+
|
|
1101
1102
|
return type;
|
|
1102
1103
|
},
|
|
1103
1104
|
// Given a doc, an _id, or an aposDocId, this method
|
|
@@ -98,7 +98,7 @@ module.exports = {
|
|
|
98
98
|
action: 'edit',
|
|
99
99
|
type: self.__meta.name
|
|
100
100
|
},
|
|
101
|
-
shortcut: `G,${self.apos.task.getReq().t(self.options.label).slice(0, 1)}`
|
|
101
|
+
shortcut: self.options.shortcut ?? `G,${self.apos.task.getReq().t(self.options.label).slice(0, 1)}`
|
|
102
102
|
},
|
|
103
103
|
[`${self.__meta.name}:create-new`]: {
|
|
104
104
|
type: 'item',
|
|
@@ -7,7 +7,7 @@ module.exports = {
|
|
|
7
7
|
dimensionAttrs: false,
|
|
8
8
|
placeholder: true,
|
|
9
9
|
placeholderClass: false,
|
|
10
|
-
|
|
10
|
+
placeholderImage: 'jpg'
|
|
11
11
|
},
|
|
12
12
|
fields: {
|
|
13
13
|
add: {
|
|
@@ -19,5 +19,8 @@ module.exports = {
|
|
|
19
19
|
withType: '@apostrophecms/image'
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
},
|
|
23
|
+
init(self) {
|
|
24
|
+
self.determineBestAssetUrl('placeholder');
|
|
22
25
|
}
|
|
23
26
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{% if data.widget.aposPlaceholder and data.manager.options.placeholderUrl %}
|
|
2
2
|
<img
|
|
3
|
-
src="{{
|
|
3
|
+
src="{{ data.manager.options.placeholderUrl }}"
|
|
4
4
|
alt="{{ __t('apostrophe:imagePlaceholder') }}"
|
|
5
5
|
class="image-widget-placeholder"
|
|
6
6
|
/>
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
const { SemanticAttributes } = require('@opentelemetry/semantic-conventions');
|
|
29
29
|
const _ = require('lodash');
|
|
30
|
+
const fs = require('fs');
|
|
30
31
|
|
|
31
32
|
module.exports = {
|
|
32
33
|
|
|
@@ -761,6 +762,46 @@ module.exports = {
|
|
|
761
762
|
);
|
|
762
763
|
},
|
|
763
764
|
|
|
765
|
+
// Given a name such as "placeholder", look at the
|
|
766
|
+
// relevant options (nameImage and, as a fallback, nameUrl)
|
|
767
|
+
// and determine the appropriate asset URL. If nameImage is used,
|
|
768
|
+
// search the inheritance chain of the module
|
|
769
|
+
// for the best match, e.g. a file in a project-level override
|
|
770
|
+
// wins, followed by the original module in core or npm,
|
|
771
|
+
// followed by something in a base class that extends, etc.
|
|
772
|
+
// If no file is found, the method returns `undefined`.
|
|
773
|
+
//
|
|
774
|
+
// Even if `nameUrl is used, the method still corrects paths
|
|
775
|
+
// beginning with `/module` to account for the actual asset
|
|
776
|
+
// release URL (`nameUrl` is really an asset path, but for bc
|
|
777
|
+
// this is the naming pattern).
|
|
778
|
+
//
|
|
779
|
+
// In the above examples "name" should be replaced with the
|
|
780
|
+
// actual value of the name argument.
|
|
781
|
+
|
|
782
|
+
determineBestAssetUrl(name) {
|
|
783
|
+
let urlOption = self.options[`${name}Url`];
|
|
784
|
+
const imageOption = self.options[`${name}Image`];
|
|
785
|
+
if (!urlOption) {
|
|
786
|
+
if (imageOption) {
|
|
787
|
+
const chain = [ ...self.__meta.chain ].reverse();
|
|
788
|
+
for (const entry of chain) {
|
|
789
|
+
const path = `${entry.dirname}/public/${name}.${imageOption}`;
|
|
790
|
+
if (fs.existsSync(path)) {
|
|
791
|
+
urlOption = `/modules/${entry.name}/${name}.${imageOption}`;
|
|
792
|
+
break;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
if (urlOption && urlOption.startsWith('/modules')) {
|
|
798
|
+
urlOption = self.apos.asset.url(urlOption);
|
|
799
|
+
}
|
|
800
|
+
if (urlOption) {
|
|
801
|
+
self.options[`${name}Url`] = urlOption;
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
|
|
764
805
|
// Merge in the event emitter / responder capabilities
|
|
765
806
|
...require('./lib/events.js')(self)
|
|
766
807
|
};
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
|
+
const migrations = require('./lib/migrations.js');
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
5
|
extend: '@apostrophecms/doc-type',
|
|
5
6
|
options: {
|
|
6
|
-
name: '@apostrophecms/polymorphic',
|
|
7
|
+
name: '@apostrophecms/polymorphic-type',
|
|
7
8
|
showPermissions: false
|
|
8
9
|
},
|
|
10
|
+
init(self) {
|
|
11
|
+
self.addMigrations();
|
|
12
|
+
},
|
|
13
|
+
methods(self) {
|
|
14
|
+
return {
|
|
15
|
+
...migrations(self)
|
|
16
|
+
};
|
|
17
|
+
},
|
|
9
18
|
routes(self) {
|
|
10
19
|
return {
|
|
11
20
|
post: {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = (self) => {
|
|
2
|
+
return {
|
|
3
|
+
addMigrations() {
|
|
4
|
+
self.removePolymorphicTypeAliasMigration();
|
|
5
|
+
},
|
|
6
|
+
removePolymorphicTypeAliasMigration() {
|
|
7
|
+
self.apos.migration.add('remove-polymorphic-type-alias', () => {
|
|
8
|
+
return self.apos.doc.db.updateMany({
|
|
9
|
+
type: '@apostrophecms/polymorphic'
|
|
10
|
+
}, {
|
|
11
|
+
$set: {
|
|
12
|
+
type: '@apostrophecms/polymorphic-type'
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -1474,8 +1474,9 @@ module.exports = {
|
|
|
1474
1474
|
return {
|
|
1475
1475
|
get: {
|
|
1476
1476
|
async choices(req) {
|
|
1477
|
-
const
|
|
1478
|
-
const
|
|
1477
|
+
const fieldId = self.apos.launder.string(req.query.fieldId);
|
|
1478
|
+
const docId = self.apos.launder.string(req.query.docId);
|
|
1479
|
+
const field = self.getFieldById(fieldId);
|
|
1479
1480
|
let choices = [];
|
|
1480
1481
|
if (
|
|
1481
1482
|
!field ||
|
|
@@ -1484,7 +1485,7 @@ module.exports = {
|
|
|
1484
1485
|
) {
|
|
1485
1486
|
throw self.apos.error('invalid');
|
|
1486
1487
|
}
|
|
1487
|
-
choices = await self.apos.modules[field.moduleName][field.choices](req);
|
|
1488
|
+
choices = await self.apos.modules[field.moduleName][field.choices](req, { docId });
|
|
1488
1489
|
if (Array.isArray(choices)) {
|
|
1489
1490
|
return {
|
|
1490
1491
|
choices
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
@validate="triggerValidate"
|
|
73
73
|
:server-errors="currentDocServerErrors"
|
|
74
74
|
ref="schema"
|
|
75
|
+
:doc-id="docId"
|
|
75
76
|
/>
|
|
76
77
|
</div>
|
|
77
78
|
</div>
|
|
@@ -109,6 +110,10 @@ export default {
|
|
|
109
110
|
serverError: {
|
|
110
111
|
type: Object,
|
|
111
112
|
default: null
|
|
113
|
+
},
|
|
114
|
+
docId: {
|
|
115
|
+
type: String,
|
|
116
|
+
default: null
|
|
112
117
|
}
|
|
113
118
|
},
|
|
114
119
|
emits: [ 'modal-result', 'safe-close' ],
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
:utility-rail="false"
|
|
65
65
|
:generation="generation"
|
|
66
66
|
:modifiers="['small', 'inverted']"
|
|
67
|
+
:doc-id="docId"
|
|
67
68
|
/>
|
|
68
69
|
</div>
|
|
69
70
|
</transition>
|
|
@@ -214,7 +215,8 @@ export default {
|
|
|
214
215
|
const result = await apos.modal.execute('AposArrayEditor', {
|
|
215
216
|
field: this.field,
|
|
216
217
|
items: this.next,
|
|
217
|
-
serverError: this.serverError
|
|
218
|
+
serverError: this.serverError,
|
|
219
|
+
docId: this.docId
|
|
218
220
|
});
|
|
219
221
|
if (result) {
|
|
220
222
|
this.next = result;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
:trigger-validation="triggerValidation"
|
|
16
16
|
:utility-rail="false"
|
|
17
17
|
:generation="generation"
|
|
18
|
+
:doc-id="docId"
|
|
18
19
|
v-model="schemaInput"
|
|
19
20
|
ref="schema"
|
|
20
21
|
/>
|
|
@@ -37,6 +38,13 @@ export default {
|
|
|
37
38
|
default() {
|
|
38
39
|
return null;
|
|
39
40
|
}
|
|
41
|
+
},
|
|
42
|
+
docId: {
|
|
43
|
+
type: String,
|
|
44
|
+
required: false,
|
|
45
|
+
default() {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
40
48
|
}
|
|
41
49
|
},
|
|
42
50
|
data () {
|
|
@@ -106,6 +106,8 @@ module.exports = {
|
|
|
106
106
|
|
|
107
107
|
self.enableBrowserData();
|
|
108
108
|
|
|
109
|
+
self.determineBestAssetUrl('preview');
|
|
110
|
+
|
|
109
111
|
self.template = self.options.template || 'widget';
|
|
110
112
|
|
|
111
113
|
self.name = self.__meta.name.replace(/-widget$/, '');
|
|
@@ -362,6 +364,7 @@ module.exports = {
|
|
|
362
364
|
version. The method in 3.x simply returns an empty array.`);
|
|
363
365
|
return [];
|
|
364
366
|
}
|
|
367
|
+
|
|
365
368
|
};
|
|
366
369
|
},
|
|
367
370
|
extendMethods(self) {
|
|
@@ -384,7 +387,7 @@ module.exports = {
|
|
|
384
387
|
description: self.options.description,
|
|
385
388
|
icon: self.options.icon,
|
|
386
389
|
previewIcon: self.options.previewIcon,
|
|
387
|
-
|
|
390
|
+
previewUrl: self.options.previewUrl,
|
|
388
391
|
action: self.action,
|
|
389
392
|
schema: schema,
|
|
390
393
|
contextual: self.options.contextual,
|
package/package.json
CHANGED
package/test/widgets.js
CHANGED
|
@@ -290,7 +290,6 @@ describe('Widgets', function() {
|
|
|
290
290
|
},
|
|
291
291
|
assertFalsyPlaceholderUrl(document) {
|
|
292
292
|
const imgNodes = document.querySelectorAll('img');
|
|
293
|
-
|
|
294
293
|
assert(imgNodes.length === 0);
|
|
295
294
|
},
|
|
296
295
|
assertPlaceholderUrlOverride(document) {
|
|
@@ -409,7 +408,8 @@ describe('Widgets', function() {
|
|
|
409
408
|
'placeholder-page': {},
|
|
410
409
|
[`@apostrophecms/${type}-widget`]: {
|
|
411
410
|
options: {
|
|
412
|
-
placeholderUrl: null
|
|
411
|
+
placeholderUrl: null,
|
|
412
|
+
placeholderImage: null
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
415
|
}
|