apostrophe 3.24.0 → 3.25.0-alpha.2022080101
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 +23 -0
- package/index.js +2 -1
- package/modules/@apostrophecms/asset/index.js +20 -26
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.config.js +3 -6
- package/modules/@apostrophecms/db/index.js +1 -1
- package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +1 -1
- package/modules/@apostrophecms/module/index.js +10 -1
- package/modules/@apostrophecms/permission/ui/apos/components/AposInputRole.vue +10 -21
- package/modules/@apostrophecms/schema/index.js +7 -1
- package/modules/@apostrophecms/schema/lib/addFieldTypes.js +6 -8
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputCheckboxes.vue +5 -4
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +5 -4
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputSelect.vue +5 -23
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputChoicesMixin.js +32 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposSelect.vue +20 -2
- package/package.json +10 -15
- package/test/assets.js +19 -102
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.es5.js +0 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## UNRELEASED
|
|
4
|
+
|
|
5
|
+
### Adds
|
|
6
|
+
|
|
7
|
+
* Tasks can now be registered with the `afterModuleReady` flag, which is more useful than `afterModuleInit` because it waits for the module to be more fully initialized, including all "improvements" loaded via npm. The original `afterModuleInit` flag is still supported in case someone was counting on its behavior.
|
|
8
|
+
|
|
9
|
+
### Changes
|
|
10
|
+
|
|
11
|
+
* Since Microsoft has ended support for IE11 and support for ES5 builds is responsible for 50% of Apostrophe's installation time, the `es5: true` option now requires that the optional [@apostrophecms/asset-es5](https://github.com/apostrophecms/asset-es5) module also be installed by those who really need it. However, for backwards compatibility, if the option is enabled without the additional module a warning will be printed and the asset build will succeed normally without IE11 support.
|
|
12
|
+
|
|
13
|
+
## 3.25.0 (2022-07-20)
|
|
14
|
+
|
|
15
|
+
### Adds
|
|
16
|
+
|
|
17
|
+
* `radio` and `checkboxes` input field types now support a server side `choices` function for supplying their `choices` array dynamically, just like `select` fields do. Future custom field types can opt into this functionality with the field type flag `dynamicChoices: true`.
|
|
18
|
+
|
|
19
|
+
### Fixes
|
|
20
|
+
|
|
21
|
+
* `AposSelect` now emits values on `change` event as they were originally given. Their values "just work" so you do not have to think about JSON anymore when you receive it.
|
|
22
|
+
* Unpinned tiptap as the tiptap team has made releases that resolve the packaging errors that caused us to pin it in 3.22.1.
|
|
23
|
+
* Pinned `vue-loader` to the `15.9.x` minor release series for now. The `15.10.0` release breaks support for using `npm link` to develop the `apostrophe` module itself.
|
|
24
|
+
* Minimum version of `sanitize-html` bumped to ensure a potential denial-of-service vector is closed.
|
|
25
|
+
|
|
3
26
|
## 3.24.0 (2022-07-06)
|
|
4
27
|
|
|
5
28
|
### Adds
|
package/index.js
CHANGED
|
@@ -562,7 +562,8 @@ async function apostrophe(options, telemetry, rootSpan) {
|
|
|
562
562
|
self.modules = {};
|
|
563
563
|
for (const item of modulesToBeInstantiated()) {
|
|
564
564
|
// module registers itself in self.modules
|
|
565
|
-
await self.synth.create(item, { apos: self });
|
|
565
|
+
const module = await self.synth.create(item, { apos: self });
|
|
566
|
+
await module.emit('moduleReady');
|
|
566
567
|
}
|
|
567
568
|
}
|
|
568
569
|
|
|
@@ -42,6 +42,7 @@ module.exports = {
|
|
|
42
42
|
},
|
|
43
43
|
|
|
44
44
|
async init(self) {
|
|
45
|
+
|
|
45
46
|
self.restartId = self.apos.util.generateId();
|
|
46
47
|
self.iconMap = {
|
|
47
48
|
...globalIcons
|
|
@@ -63,6 +64,7 @@ module.exports = {
|
|
|
63
64
|
self.buildWatcherEnable = process.env.APOS_ASSET_WATCH !== '0' && self.options.watch !== false;
|
|
64
65
|
self.buildWatcherDebounceMs = parseInt(self.options.watchDebounceMs || 1000, 10);
|
|
65
66
|
self.buildWatcher = null;
|
|
67
|
+
|
|
66
68
|
},
|
|
67
69
|
handlers (self) {
|
|
68
70
|
return {
|
|
@@ -121,6 +123,16 @@ module.exports = {
|
|
|
121
123
|
usage: 'Build Apostrophe frontend CSS and JS bundles',
|
|
122
124
|
afterModuleInit: true,
|
|
123
125
|
async task(argv = {}) {
|
|
126
|
+
if (self.options.es5 && !self.es5TaskFn) {
|
|
127
|
+
self.apos.util.warnDev(stripIndent`
|
|
128
|
+
es5: true is set. IE11 compatibility builds now require that you
|
|
129
|
+
install the optional @apostrophecms/asset-es5 module. Until then,
|
|
130
|
+
for backwards compatibility, your build will succeed but
|
|
131
|
+
will not be IE11 compatible.
|
|
132
|
+
`);
|
|
133
|
+
self.options.es5 = false;
|
|
134
|
+
delete self.builds['src-es5'];
|
|
135
|
+
}
|
|
124
136
|
// The lock could become huge, cache it, see computeCacheMeta()
|
|
125
137
|
let packageLockContentCached;
|
|
126
138
|
const req = self.apos.task.getReq();
|
|
@@ -350,7 +362,11 @@ module.exports = {
|
|
|
350
362
|
modulesDir,
|
|
351
363
|
outputPath: bundleDir,
|
|
352
364
|
outputFilename,
|
|
353
|
-
bundles: webpackExtraBundles
|
|
365
|
+
bundles: webpackExtraBundles,
|
|
366
|
+
// Added on the fly by the
|
|
367
|
+
// @apostrophecms/asset-es5 module,
|
|
368
|
+
// if it is present
|
|
369
|
+
es5TaskFn: self.es5TaskFn
|
|
354
370
|
}, self.apos);
|
|
355
371
|
|
|
356
372
|
const webpackInstanceConfigMerged = self.webpackExtensions
|
|
@@ -841,7 +857,7 @@ module.exports = {
|
|
|
841
857
|
|
|
842
858
|
'clear-cache': {
|
|
843
859
|
usage: 'Clear build cache',
|
|
844
|
-
|
|
860
|
+
afterModuleReady: true,
|
|
845
861
|
async task(argv) {
|
|
846
862
|
const cacheBaseDir = self.getCacheBasePath();
|
|
847
863
|
|
|
@@ -1161,7 +1177,7 @@ module.exports = {
|
|
|
1161
1177
|
// If you are trying to enable IE11 support for ui/src, use the
|
|
1162
1178
|
// `es5: true` option (es5 builds are disabled by default).
|
|
1163
1179
|
configureBuilds() {
|
|
1164
|
-
|
|
1180
|
+
self.srcPrologue = stripIndent`
|
|
1165
1181
|
(function() {
|
|
1166
1182
|
window.apos = window.apos || {};
|
|
1167
1183
|
var data = document.body && document.body.getAttribute('data-apos');
|
|
@@ -1188,26 +1204,7 @@ module.exports = {
|
|
|
1188
1204
|
index: true,
|
|
1189
1205
|
// Load only in browsers that support ES6 modules
|
|
1190
1206
|
condition: 'module',
|
|
1191
|
-
prologue: srcPrologue
|
|
1192
|
-
},
|
|
1193
|
-
'src-es5': {
|
|
1194
|
-
// An alternative build from the same sources for IE11
|
|
1195
|
-
source: 'src',
|
|
1196
|
-
webpack: true,
|
|
1197
|
-
scenes: [ 'public', 'apos' ],
|
|
1198
|
-
// The CSS from the src build is identical, do not duplicate it
|
|
1199
|
-
outputs: [ 'js' ],
|
|
1200
|
-
label: 'apostrophe:ie11Build',
|
|
1201
|
-
// Load index.js and index.scss from each module
|
|
1202
|
-
index: true,
|
|
1203
|
-
// The polyfills babel will be expecting
|
|
1204
|
-
prologue: stripIndent`
|
|
1205
|
-
import "core-js/stable";
|
|
1206
|
-
import "regenerator-runtime/runtime";
|
|
1207
|
-
${srcPrologue}
|
|
1208
|
-
`,
|
|
1209
|
-
// Load only in browsers that do not support ES6 modules
|
|
1210
|
-
condition: 'nomodule'
|
|
1207
|
+
prologue: self.srcPrologue
|
|
1211
1208
|
},
|
|
1212
1209
|
public: {
|
|
1213
1210
|
scenes: [ 'public', 'apos' ],
|
|
@@ -1236,9 +1233,6 @@ module.exports = {
|
|
|
1236
1233
|
// We could add an apos-ie11 bundle that just pushes a "sorry charlie" prologue,
|
|
1237
1234
|
// if we chose
|
|
1238
1235
|
};
|
|
1239
|
-
if (!self.options.es5) {
|
|
1240
|
-
delete self.builds['src-es5'];
|
|
1241
|
-
}
|
|
1242
1236
|
},
|
|
1243
1237
|
// Filter the given css performing any necessary transformations,
|
|
1244
1238
|
// such as support for the /modules path regardless of where
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const merge = require('webpack-merge').merge;
|
|
3
3
|
const scssTask = require('./webpack.scss');
|
|
4
|
-
const
|
|
4
|
+
const { stripIndent } = require('common-tags');
|
|
5
5
|
const srcBuildNames = [ 'src-build', 'src-es5-build' ];
|
|
6
6
|
|
|
7
7
|
let BundleAnalyzerPlugin;
|
|
@@ -11,14 +11,11 @@ if (process.env.APOS_BUNDLE_ANALYZER) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
module.exports = ({
|
|
14
|
-
importFile, modulesDir, outputPath, outputFilename, bundles = {}, es5
|
|
14
|
+
importFile, modulesDir, outputPath, outputFilename, bundles = {}, es5, es5TaskFn
|
|
15
15
|
}, apos) => {
|
|
16
16
|
const mainBundleName = outputFilename.replace('.js', '');
|
|
17
|
-
const taskFns = [ scssTask ];
|
|
17
|
+
const taskFns = [ scssTask, ...(es5 ? [ es5TaskFn ] : []) ];
|
|
18
18
|
|
|
19
|
-
if (es5) {
|
|
20
|
-
taskFns.push(es5Task);
|
|
21
|
-
}
|
|
22
19
|
const tasks = taskFns.map(task =>
|
|
23
20
|
task(
|
|
24
21
|
{
|
|
@@ -168,7 +168,7 @@ This database contains an Apostrophe 2.x website. Exiting to avoid content loss.
|
|
|
168
168
|
// and start up your app, which will recreate them.
|
|
169
169
|
reset: {
|
|
170
170
|
usage: 'Usage: node app @apostrophecms/db:reset\n\nThis destroys ALL of your content. EVERYTHING in your database.\n',
|
|
171
|
-
|
|
171
|
+
afterModuleReady: true,
|
|
172
172
|
exitAfter: false,
|
|
173
173
|
task: async () => {
|
|
174
174
|
const argv = self.apos.argv;
|
|
@@ -705,8 +705,12 @@ module.exports = {
|
|
|
705
705
|
},
|
|
706
706
|
|
|
707
707
|
async executeAfterModuleInitTask() {
|
|
708
|
+
return self.executeAfterModuleTask('afterModuleInit');
|
|
709
|
+
},
|
|
710
|
+
|
|
711
|
+
async executeAfterModuleTask(when) {
|
|
708
712
|
for (const [ name, info ] of Object.entries(self.tasks || {})) {
|
|
709
|
-
if (info
|
|
713
|
+
if (info[when]) {
|
|
710
714
|
// Execute a task like @apostrophecms/asset:build or
|
|
711
715
|
// @apostrophecms/db:reset which
|
|
712
716
|
// must run before most modules are awake
|
|
@@ -764,6 +768,11 @@ module.exports = {
|
|
|
764
768
|
|
|
765
769
|
handlers(self) {
|
|
766
770
|
return {
|
|
771
|
+
moduleReady: {
|
|
772
|
+
executeAfterModuleReadyTask() {
|
|
773
|
+
return self.executeAfterModuleTask('afterModuleReady');
|
|
774
|
+
}
|
|
775
|
+
},
|
|
767
776
|
'apostrophe:modulesRegistered': {
|
|
768
777
|
addHelpers() {
|
|
769
778
|
// We check this just to allow init in bootstrap tests that
|
|
@@ -7,26 +7,15 @@
|
|
|
7
7
|
:display-options="displayOptions"
|
|
8
8
|
>
|
|
9
9
|
<template #body>
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
:selected="choice.value === value.data"
|
|
20
|
-
>
|
|
21
|
-
{{ $t(choice.label) }}
|
|
22
|
-
</option>
|
|
23
|
-
</select>
|
|
24
|
-
<AposIndicator
|
|
25
|
-
icon="menu-down-icon"
|
|
26
|
-
class="apos-input-icon"
|
|
27
|
-
:icon-size="20"
|
|
28
|
-
/>
|
|
29
|
-
</div>
|
|
10
|
+
<AposSelect
|
|
11
|
+
:choices="choices"
|
|
12
|
+
:disabled="field.readOnly"
|
|
13
|
+
:selected="value.data"
|
|
14
|
+
:id="uid"
|
|
15
|
+
:classes="[ 'apos-input__role' ]"
|
|
16
|
+
:wrapper-classes="[ 'apos-input__role' ]"
|
|
17
|
+
@change="change"
|
|
18
|
+
/>
|
|
30
19
|
<div class="apos-input__role__permission-grid">
|
|
31
20
|
<div
|
|
32
21
|
v-for="permissionSet in permissionSets"
|
|
@@ -152,7 +141,7 @@ export default {
|
|
|
152
141
|
},
|
|
153
142
|
change(value) {
|
|
154
143
|
// Allows expression of non-string values
|
|
155
|
-
this.next = this.choices.find(choice => choice.value ===
|
|
144
|
+
this.next = this.choices.find(choice => choice.value === value).value;
|
|
156
145
|
},
|
|
157
146
|
async getPermissionSets(role) {
|
|
158
147
|
return (await apos.http.get(`${apos.permission.action}/grid`, {
|
|
@@ -1453,6 +1453,12 @@ module.exports = {
|
|
|
1453
1453
|
_.each(self.apos.area.widgetManagers, function (manager, type) {
|
|
1454
1454
|
self.register('widget', type, manager.schema);
|
|
1455
1455
|
});
|
|
1456
|
+
},
|
|
1457
|
+
|
|
1458
|
+
async getChoices(req, field) {
|
|
1459
|
+
return typeof field.choices === 'string'
|
|
1460
|
+
? self.apos.modules[field.moduleName][field.choices](req)
|
|
1461
|
+
: field.choices;
|
|
1456
1462
|
}
|
|
1457
1463
|
|
|
1458
1464
|
};
|
|
@@ -1466,7 +1472,7 @@ module.exports = {
|
|
|
1466
1472
|
let choices = [];
|
|
1467
1473
|
if (
|
|
1468
1474
|
!field ||
|
|
1469
|
-
field.type
|
|
1475
|
+
!self.fieldTypes[field.type].dynamicChoices ||
|
|
1470
1476
|
!(field.choices && typeof field.choices === 'string')
|
|
1471
1477
|
) {
|
|
1472
1478
|
throw self.apos.error('invalid');
|
|
@@ -231,7 +231,9 @@ module.exports = (self) => {
|
|
|
231
231
|
|
|
232
232
|
self.addFieldType({
|
|
233
233
|
name: 'checkboxes',
|
|
234
|
+
dynamicChoices: true,
|
|
234
235
|
async convert(req, field, data, destination) {
|
|
236
|
+
const choices = await self.getChoices(req, field);
|
|
235
237
|
if (typeof data[field.name] === 'string') {
|
|
236
238
|
data[field.name] = self.apos.launder.string(data[field.name]).split(',');
|
|
237
239
|
|
|
@@ -241,14 +243,14 @@ module.exports = (self) => {
|
|
|
241
243
|
}
|
|
242
244
|
|
|
243
245
|
destination[field.name] = _.filter(data[field.name], function (choice) {
|
|
244
|
-
return _.includes(_.map(
|
|
246
|
+
return _.includes(_.map(choices, 'value'), choice);
|
|
245
247
|
});
|
|
246
248
|
} else {
|
|
247
249
|
if (!Array.isArray(data[field.name])) {
|
|
248
250
|
destination[field.name] = [];
|
|
249
251
|
} else {
|
|
250
252
|
destination[field.name] = _.filter(data[field.name], function (choice) {
|
|
251
|
-
return _.includes(_.map(
|
|
253
|
+
return _.includes(_.map(choices, 'value'), choice);
|
|
252
254
|
});
|
|
253
255
|
}
|
|
254
256
|
}
|
|
@@ -303,13 +305,9 @@ module.exports = (self) => {
|
|
|
303
305
|
|
|
304
306
|
self.addFieldType({
|
|
305
307
|
name: 'select',
|
|
308
|
+
dynamicChoices: true,
|
|
306
309
|
async convert(req, field, data, destination) {
|
|
307
|
-
|
|
308
|
-
if ((typeof field.choices) === 'string') {
|
|
309
|
-
choices = await self.apos.modules[field.moduleName][field.choices](req);
|
|
310
|
-
} else {
|
|
311
|
-
choices = field.choices;
|
|
312
|
-
}
|
|
310
|
+
const choices = await self.getChoices(req, field);
|
|
313
311
|
destination[field.name] = self.apos.launder.select(data[field.name], choices, field.def);
|
|
314
312
|
},
|
|
315
313
|
index: function (value, field, texts) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<template #body>
|
|
9
9
|
<AposCheckbox
|
|
10
10
|
:for="getChoiceId(uid, choice.value)"
|
|
11
|
-
v-for="choice in
|
|
11
|
+
v-for="choice in choices"
|
|
12
12
|
:key="choice.value"
|
|
13
13
|
:id="getChoiceId(uid, choice.value)"
|
|
14
14
|
:choice="choice"
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
|
|
22
22
|
<script>
|
|
23
23
|
import AposInputMixin from 'Modules/@apostrophecms/schema/mixins/AposInputMixin';
|
|
24
|
+
import AposInputChoicesMixin from 'Modules/@apostrophecms/schema/mixins/AposInputChoicesMixin';
|
|
24
25
|
|
|
25
26
|
export default {
|
|
26
27
|
name: 'AposInputCheckboxes',
|
|
27
|
-
mixins: [ AposInputMixin ],
|
|
28
|
+
mixins: [ AposInputMixin, AposInputChoicesMixin ],
|
|
28
29
|
beforeMount: function () {
|
|
29
30
|
this.value.data = Array.isArray(this.value.data) ? this.value.data : [];
|
|
30
31
|
},
|
|
@@ -38,7 +39,7 @@ export default {
|
|
|
38
39
|
},
|
|
39
40
|
validate(values) {
|
|
40
41
|
// The choices and values should always be arrays.
|
|
41
|
-
if (!Array.isArray(this.
|
|
42
|
+
if (!Array.isArray(this.choices) || !Array.isArray(values)) {
|
|
42
43
|
return 'malformed';
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -48,7 +49,7 @@ export default {
|
|
|
48
49
|
|
|
49
50
|
if (Array.isArray(values)) {
|
|
50
51
|
values.forEach(chosen => {
|
|
51
|
-
if (!this.
|
|
52
|
+
if (!this.choices.map(choice => {
|
|
52
53
|
return choice.value;
|
|
53
54
|
}).includes(chosen)) {
|
|
54
55
|
return 'invalid';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<template #body>
|
|
9
9
|
<label
|
|
10
10
|
class="apos-choice-label" :for="getChoiceId(uid, choice.value)"
|
|
11
|
-
v-for="choice in
|
|
11
|
+
v-for="choice in choices" :key="choice.value"
|
|
12
12
|
:class="{'apos-choice-label--disabled': field.readOnly}"
|
|
13
13
|
>
|
|
14
14
|
<input
|
|
@@ -43,12 +43,13 @@
|
|
|
43
43
|
|
|
44
44
|
<script>
|
|
45
45
|
import AposInputMixin from 'Modules/@apostrophecms/schema/mixins/AposInputMixin';
|
|
46
|
+
import AposInputChoicesMixin from 'Modules/@apostrophecms/schema/mixins/AposInputChoicesMixin';
|
|
46
47
|
import InformationIcon from 'vue-material-design-icons/Information.vue';
|
|
47
48
|
|
|
48
49
|
export default {
|
|
49
50
|
name: 'AposInputRadio',
|
|
50
51
|
components: { InformationIcon },
|
|
51
|
-
mixins: [ AposInputMixin ],
|
|
52
|
+
mixins: [ AposInputMixin, AposInputChoicesMixin ],
|
|
52
53
|
methods: {
|
|
53
54
|
getChoiceId(uid, value) {
|
|
54
55
|
return (uid + JSON.stringify(value)).replace(/\s+/g, '');
|
|
@@ -58,7 +59,7 @@ export default {
|
|
|
58
59
|
return 'required';
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
if (value && !this.
|
|
62
|
+
if (value && !this.choices.find(choice => choice.value === value)) {
|
|
62
63
|
return 'invalid';
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -66,7 +67,7 @@ export default {
|
|
|
66
67
|
},
|
|
67
68
|
change(value) {
|
|
68
69
|
// Allows expression of non-string values
|
|
69
|
-
this.next = this.
|
|
70
|
+
this.next = this.choices.find(choice => choice.value === JSON.parse(value)).value;
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
};
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
|
|
21
21
|
<script>
|
|
22
22
|
import AposInputMixin from 'Modules/@apostrophecms/schema/mixins/AposInputMixin';
|
|
23
|
+
import AposInputChoicesMixin from 'Modules/@apostrophecms/schema/mixins/AposInputChoicesMixin';
|
|
23
24
|
|
|
24
25
|
export default {
|
|
25
26
|
name: 'AposInputSelect',
|
|
26
|
-
mixins: [ AposInputMixin ],
|
|
27
|
+
mixins: [ AposInputMixin, AposInputChoicesMixin ],
|
|
27
28
|
props: {
|
|
28
29
|
icon: {
|
|
29
30
|
type: String,
|
|
@@ -37,34 +38,15 @@ export default {
|
|
|
37
38
|
};
|
|
38
39
|
},
|
|
39
40
|
async mounted() {
|
|
40
|
-
let choices;
|
|
41
|
-
if (typeof this.field.choices === 'string') {
|
|
42
|
-
const action = this.options.action;
|
|
43
|
-
const response = await apos.http.get(
|
|
44
|
-
`${action}/choices`,
|
|
45
|
-
{
|
|
46
|
-
qs: {
|
|
47
|
-
fieldId: this.field._id
|
|
48
|
-
},
|
|
49
|
-
busy: true
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
if (response.choices) {
|
|
53
|
-
choices = response.choices;
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
choices = this.field.choices;
|
|
57
|
-
}
|
|
58
41
|
// Add an null option if there isn't one already
|
|
59
|
-
if (!this.field.required && !choices.find(choice => {
|
|
42
|
+
if (!this.field.required && !this.choices.find(choice => {
|
|
60
43
|
return choice.value === null;
|
|
61
44
|
})) {
|
|
62
|
-
this.choices.
|
|
45
|
+
this.choices.unshift({
|
|
63
46
|
label: '',
|
|
64
47
|
value: null
|
|
65
48
|
});
|
|
66
49
|
}
|
|
67
|
-
this.choices = this.choices.concat(choices);
|
|
68
50
|
this.$nextTick(() => {
|
|
69
51
|
// this has to happen on nextTick to avoid emitting before schemaReady is
|
|
70
52
|
// set in AposSchema
|
|
@@ -87,7 +69,7 @@ export default {
|
|
|
87
69
|
},
|
|
88
70
|
change(value) {
|
|
89
71
|
// Allows expression of non-string values
|
|
90
|
-
this.next = this.choices.find(choice => choice.value ===
|
|
72
|
+
this.next = this.choices.find(choice => choice.value === value).value;
|
|
91
73
|
}
|
|
92
74
|
}
|
|
93
75
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Provides prep work for fetching choices from the server
|
|
3
|
+
* or defaulting to the choices provided with the field.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
data() {
|
|
8
|
+
return {
|
|
9
|
+
choices: []
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
async mounted() {
|
|
14
|
+
if (typeof this.field.choices === 'string') {
|
|
15
|
+
const action = this.options.action;
|
|
16
|
+
const response = await apos.http.get(
|
|
17
|
+
`${action}/choices`,
|
|
18
|
+
{
|
|
19
|
+
qs: {
|
|
20
|
+
fieldId: this.field._id
|
|
21
|
+
},
|
|
22
|
+
busy: true
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
if (response.choices) {
|
|
26
|
+
this.choices = response.choices;
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
this.choices = this.field.choices;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="apos-input-wrapper">
|
|
2
|
+
<div class="apos-input-wrapper" :class="wrapperClasses">
|
|
3
3
|
<select
|
|
4
4
|
class="apos-input apos-input--select"
|
|
5
|
+
:class="classes"
|
|
6
|
+
:uid="uid"
|
|
5
7
|
:disabled="disabled"
|
|
6
8
|
@change="change($event.target.value)"
|
|
7
9
|
>
|
|
@@ -30,6 +32,22 @@ export default {
|
|
|
30
32
|
type: String,
|
|
31
33
|
default: 'menu-down-icon'
|
|
32
34
|
},
|
|
35
|
+
uid: {
|
|
36
|
+
type: Number,
|
|
37
|
+
default: null
|
|
38
|
+
},
|
|
39
|
+
classes: {
|
|
40
|
+
type: Array,
|
|
41
|
+
default() {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
wrapperClasses: {
|
|
46
|
+
type: Array,
|
|
47
|
+
default() {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
},
|
|
33
51
|
choices: {
|
|
34
52
|
type: Array,
|
|
35
53
|
default() {
|
|
@@ -48,7 +66,7 @@ export default {
|
|
|
48
66
|
emits: [ 'change' ],
|
|
49
67
|
methods: {
|
|
50
68
|
change(value) {
|
|
51
|
-
this.$emit('change', value);
|
|
69
|
+
this.$emit('change', JSON.parse(value));
|
|
52
70
|
}
|
|
53
71
|
}
|
|
54
72
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apostrophe",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0-alpha.2022080101",
|
|
4
4
|
"description": "The Apostrophe Content Management System.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,19 +31,16 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@apostrophecms/vue-color": "^2.8.2",
|
|
34
|
-
"@babel/core": "^7.16.7",
|
|
35
|
-
"@babel/preset-env": "^7.16.7",
|
|
36
34
|
"@opentelemetry/api": "^1.0.4",
|
|
37
35
|
"@opentelemetry/semantic-conventions": "^1.0.1",
|
|
38
|
-
"@tiptap/extension-highlight": "2.0.0-beta.33",
|
|
39
|
-
"@tiptap/extension-link": "2.0.0-beta.38",
|
|
40
|
-
"@tiptap/extension-text-align": "2.0.0-beta.29",
|
|
41
|
-
"@tiptap/extension-text-style": "2.0.0-beta.23",
|
|
42
|
-
"@tiptap/extension-underline": "2.0.0-beta.23",
|
|
43
|
-
"@tiptap/starter-kit": "2.0.0-beta.185",
|
|
44
|
-
"@tiptap/vue-2": "2.0.0-beta.79",
|
|
36
|
+
"@tiptap/extension-highlight": "^2.0.0-beta.33",
|
|
37
|
+
"@tiptap/extension-link": "^2.0.0-beta.38",
|
|
38
|
+
"@tiptap/extension-text-align": "^2.0.0-beta.29",
|
|
39
|
+
"@tiptap/extension-text-style": "^2.0.0-beta.23",
|
|
40
|
+
"@tiptap/extension-underline": "^2.0.0-beta.23",
|
|
41
|
+
"@tiptap/starter-kit": "^2.0.0-beta.185",
|
|
42
|
+
"@tiptap/vue-2": "^2.0.0-beta.79",
|
|
45
43
|
"autoprefixer": "^10.4.1",
|
|
46
|
-
"babel-loader": "^8.2.5",
|
|
47
44
|
"bluebird": "^3.7.2",
|
|
48
45
|
"body-parser": "^1.18.2",
|
|
49
46
|
"boring": "^1.1.1",
|
|
@@ -54,7 +51,6 @@
|
|
|
54
51
|
"connect-mongo": "^3.0.0",
|
|
55
52
|
"connect-multiparty": "^2.1.1",
|
|
56
53
|
"cookie-parser": "^1.4.5",
|
|
57
|
-
"core-js": "~3.14.0",
|
|
58
54
|
"cors": "^2.8.5",
|
|
59
55
|
"credential": "^2.0.0",
|
|
60
56
|
"css-loader": "^5.2.4",
|
|
@@ -98,11 +94,10 @@
|
|
|
98
94
|
"postcss-scss": "^4.0.3",
|
|
99
95
|
"prompts": "^2.4.1",
|
|
100
96
|
"qs": "^6.10.1",
|
|
101
|
-
"regenerator-runtime": "^0.13.7",
|
|
102
97
|
"regexp-quote": "0.0.0",
|
|
103
98
|
"resolve": "^1.19.0",
|
|
104
99
|
"resolve-from": "^5.0.0",
|
|
105
|
-
"sanitize-html": "^2.
|
|
100
|
+
"sanitize-html": "^2.7.1",
|
|
106
101
|
"sass": "^1.52.3",
|
|
107
102
|
"sass-loader": "^10.1.1",
|
|
108
103
|
"server-destroy": "^1.0.1",
|
|
@@ -119,7 +114,7 @@
|
|
|
119
114
|
"vue": "^2.6.14",
|
|
120
115
|
"vue-advanced-cropper": "^1.10.1",
|
|
121
116
|
"vue-click-outside-element": "^1.0.15",
|
|
122
|
-
"vue-loader": "
|
|
117
|
+
"vue-loader": "~15.9.8",
|
|
123
118
|
"vue-material-design-icons": "~4.12.1",
|
|
124
119
|
"vue-style-loader": "^4.1.2",
|
|
125
120
|
"vue-template-compiler": "^2.6.14",
|
package/test/assets.js
CHANGED
|
@@ -267,55 +267,13 @@ describe('Assets', function() {
|
|
|
267
267
|
await t.destroy(apos);
|
|
268
268
|
});
|
|
269
269
|
|
|
270
|
-
it('should inject modules and nomodules scripts for extra bundles when es5 enabled', async function () {
|
|
271
|
-
const jar = apos.http.jar();
|
|
272
|
-
|
|
273
|
-
const es5Modules = {
|
|
274
|
-
...modules,
|
|
275
|
-
'@apostrophecms/asset': {
|
|
276
|
-
options: {
|
|
277
|
-
es5: true
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
apos = await t.create({
|
|
283
|
-
root: module,
|
|
284
|
-
modules: es5Modules
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
const { _id: homeId } = await apos.page.find(apos.task.getAnonReq(), { level: 0 }).toObject();
|
|
288
|
-
|
|
289
|
-
await apos.doc.db.insertMany(pagesToInsert(homeId));
|
|
290
|
-
|
|
291
|
-
await apos.asset.tasks.build.task();
|
|
292
|
-
|
|
293
|
-
const bundlePage = await apos.http.get('/bundle', { jar });
|
|
294
|
-
|
|
295
|
-
assert(bundlePage.includes(getScriptMarkup('public-module-bundle', 'module')));
|
|
296
|
-
assert(bundlePage.includes(getScriptMarkup('public-nomodule-bundle', 'nomodule')));
|
|
297
|
-
|
|
298
|
-
assert(bundlePage.includes(getScriptMarkup('extra2-module-bundle', 'module')));
|
|
299
|
-
assert(bundlePage.includes(getScriptMarkup('extra2-nomodule-bundle', 'nomodule')));
|
|
300
|
-
});
|
|
301
|
-
|
|
302
270
|
it('should build with cache and gain performance', async function() {
|
|
303
|
-
await t.destroy(apos);
|
|
304
271
|
await removeCache();
|
|
305
272
|
await removeCache(cacheFolderPath.replace('/webpack-cache', '/changed'));
|
|
306
273
|
|
|
307
|
-
const es5Modules = {
|
|
308
|
-
...modules,
|
|
309
|
-
'@apostrophecms/asset': {
|
|
310
|
-
options: {
|
|
311
|
-
es5: true
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
|
|
316
274
|
apos = await t.create({
|
|
317
275
|
root: module,
|
|
318
|
-
modules
|
|
276
|
+
modules
|
|
319
277
|
});
|
|
320
278
|
assert.throws(() => fs.readdirSync(cacheFolderPath), {
|
|
321
279
|
code: 'ENOENT'
|
|
@@ -330,11 +288,10 @@ describe('Assets', function() {
|
|
|
330
288
|
});
|
|
331
289
|
const execTime = Date.now() - startTime;
|
|
332
290
|
const { meta, folders } = getCacheMeta();
|
|
333
|
-
assert.equal(folders.length,
|
|
334
|
-
assert.equal(Object.keys(meta).length,
|
|
291
|
+
assert.equal(folders.length, 2);
|
|
292
|
+
assert.equal(Object.keys(meta).length, 2);
|
|
335
293
|
assert(meta['default:apos']);
|
|
336
294
|
assert(meta['default:src']);
|
|
337
|
-
assert(meta['default:src-es5']);
|
|
338
295
|
|
|
339
296
|
// Cache
|
|
340
297
|
startTime = Date.now();
|
|
@@ -343,11 +300,10 @@ describe('Assets', function() {
|
|
|
343
300
|
});
|
|
344
301
|
const execTimeCached = Date.now() - startTime;
|
|
345
302
|
const { meta: meta2, folders: folders2 } = getCacheMeta();
|
|
346
|
-
assert.equal(folders2.length,
|
|
347
|
-
assert.equal(Object.keys(meta2).length,
|
|
303
|
+
assert.equal(folders2.length, 2);
|
|
304
|
+
assert.equal(Object.keys(meta2).length, 2);
|
|
348
305
|
assert(meta2['default:apos']);
|
|
349
306
|
assert(meta2['default:src']);
|
|
350
|
-
assert(meta2['default:src-es5']);
|
|
351
307
|
|
|
352
308
|
// Expect at least 40% gain, in reallity it should be 50+
|
|
353
309
|
const gain = (execTime - execTimeCached) / execTime * 100;
|
|
@@ -358,8 +314,6 @@ describe('Assets', function() {
|
|
|
358
314
|
assert(meta2['default:apos'].mdate);
|
|
359
315
|
assert(meta['default:src'].mdate);
|
|
360
316
|
assert(meta2['default:src'].mdate);
|
|
361
|
-
assert(meta['default:src-es5'].mdate);
|
|
362
|
-
assert(meta2['default:src-es5'].mdate);
|
|
363
317
|
assert(
|
|
364
318
|
new Date(meta['default:apos'].mdate) < new Date(meta2['default:apos'].mdate)
|
|
365
319
|
);
|
|
@@ -374,13 +328,6 @@ describe('Assets', function() {
|
|
|
374
328
|
new Date(meta2['default:src'].mdate).toISOString(),
|
|
375
329
|
fs.statSync(meta2['default:src'].location).mtime.toISOString()
|
|
376
330
|
);
|
|
377
|
-
assert(
|
|
378
|
-
new Date(meta['default:src-es5'].mdate) < new Date(meta2['default:src-es5'].mdate)
|
|
379
|
-
);
|
|
380
|
-
assert.equal(
|
|
381
|
-
new Date(meta2['default:src-es5'].mdate).toISOString(),
|
|
382
|
-
fs.statSync(meta2['default:src-es5'].location).mtime.toISOString()
|
|
383
|
-
);
|
|
384
331
|
});
|
|
385
332
|
|
|
386
333
|
it('should invalidate build cache when namespace changes', async function() {
|
|
@@ -389,14 +336,12 @@ describe('Assets', function() {
|
|
|
389
336
|
'check-apos-build': false
|
|
390
337
|
});
|
|
391
338
|
const { meta, folders } = getCacheMeta();
|
|
392
|
-
assert.equal(folders.length,
|
|
393
|
-
assert.equal(Object.keys(meta).length,
|
|
339
|
+
assert.equal(folders.length, 4);
|
|
340
|
+
assert.equal(Object.keys(meta).length, 4);
|
|
394
341
|
assert(meta['test:apos']);
|
|
395
342
|
assert(meta['test:src']);
|
|
396
|
-
assert(meta['test:src-es5']);
|
|
397
343
|
assert(meta['default:apos']);
|
|
398
344
|
assert(meta['default:src']);
|
|
399
|
-
assert(meta['default:src-es5']);
|
|
400
345
|
delete process.env.APOS_DEBUG_NAMESPACE;
|
|
401
346
|
});
|
|
402
347
|
|
|
@@ -410,34 +355,25 @@ describe('Assets', function() {
|
|
|
410
355
|
JSON.stringify(lock, null, ' '),
|
|
411
356
|
'utf8'
|
|
412
357
|
);
|
|
413
|
-
const es5Modules = {
|
|
414
|
-
...modules,
|
|
415
|
-
'@apostrophecms/asset': {
|
|
416
|
-
options: {
|
|
417
|
-
es5: true
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
358
|
|
|
422
359
|
apos = await t.create({
|
|
423
360
|
root: module,
|
|
424
|
-
modules
|
|
361
|
+
modules
|
|
425
362
|
});
|
|
426
363
|
await apos.asset.tasks.build.task({
|
|
427
364
|
'check-apos-build': false
|
|
428
365
|
});
|
|
429
366
|
|
|
430
367
|
const { meta, folders } = getCacheMeta();
|
|
431
|
-
assert.equal(folders.length,
|
|
432
|
-
assert.equal(Object.keys(meta).length,
|
|
368
|
+
assert.equal(folders.length, 6);
|
|
369
|
+
assert.equal(Object.keys(meta).length, 6);
|
|
433
370
|
assert(meta['default:apos_2']);
|
|
434
371
|
assert(meta['default:src_2']);
|
|
435
|
-
assert(meta['default:src-es5_2']);
|
|
436
372
|
});
|
|
437
373
|
|
|
438
374
|
it('should invalidate build cache when configuration changes', async function() {
|
|
439
375
|
await t.destroy(apos);
|
|
440
|
-
const
|
|
376
|
+
const customModules = {
|
|
441
377
|
...modules,
|
|
442
378
|
'bundle-page': {
|
|
443
379
|
webpack: {
|
|
@@ -451,16 +387,11 @@ describe('Assets', function() {
|
|
|
451
387
|
}
|
|
452
388
|
}
|
|
453
389
|
}
|
|
454
|
-
},
|
|
455
|
-
'@apostrophecms/asset': {
|
|
456
|
-
options: {
|
|
457
|
-
es5: true
|
|
458
|
-
}
|
|
459
390
|
}
|
|
460
391
|
};
|
|
461
392
|
apos = await t.create({
|
|
462
393
|
root: module,
|
|
463
|
-
modules:
|
|
394
|
+
modules: customModules
|
|
464
395
|
});
|
|
465
396
|
await apos.asset.tasks.build.task({
|
|
466
397
|
'check-apos-build': false
|
|
@@ -468,11 +399,10 @@ describe('Assets', function() {
|
|
|
468
399
|
|
|
469
400
|
const { meta, folders } = getCacheMeta();
|
|
470
401
|
|
|
471
|
-
assert.equal(folders.length,
|
|
472
|
-
assert.equal(Object.keys(meta).length,
|
|
402
|
+
assert.equal(folders.length, 7);
|
|
403
|
+
assert.equal(Object.keys(meta).length, 7);
|
|
473
404
|
assert(!meta['default:apos_3']);
|
|
474
405
|
assert(meta['default:src_3']);
|
|
475
|
-
assert(meta['default:src-es5_3']);
|
|
476
406
|
});
|
|
477
407
|
|
|
478
408
|
it('should clear build cache', async function() {
|
|
@@ -583,7 +513,7 @@ describe('Assets', function() {
|
|
|
583
513
|
fs.writeFileSync(assetPath, assetContent, 'utf8');
|
|
584
514
|
});
|
|
585
515
|
|
|
586
|
-
it('should watch and rebuild assets and reload page in development (src
|
|
516
|
+
it('should watch and rebuild assets and reload page in development (src)', async function() {
|
|
587
517
|
await t.destroy(apos);
|
|
588
518
|
let result = {};
|
|
589
519
|
const setTestResult = (obj) => {
|
|
@@ -608,9 +538,6 @@ describe('Assets', function() {
|
|
|
608
538
|
modules: {
|
|
609
539
|
'default-page': {},
|
|
610
540
|
'@apostrophecms/asset': {
|
|
611
|
-
options: {
|
|
612
|
-
es5: true
|
|
613
|
-
},
|
|
614
541
|
extendMethods() {
|
|
615
542
|
return {
|
|
616
543
|
async watchUiAndRebuild(_super) {
|
|
@@ -678,10 +605,9 @@ describe('Assets', function() {
|
|
|
678
605
|
|
|
679
606
|
// * only src related builds were triggered
|
|
680
607
|
await retryAssertTrue(
|
|
681
|
-
() => result.builds.length ===
|
|
682
|
-
result.builds.includes('src')
|
|
683
|
-
|
|
684
|
-
'Unable to verify builds "src" and "src-es5" have been triggered',
|
|
608
|
+
() => result.builds.length === 1 &&
|
|
609
|
+
result.builds.includes('src'),
|
|
610
|
+
'Unable to verify build "src" has been triggered',
|
|
685
611
|
50,
|
|
686
612
|
1000
|
|
687
613
|
);
|
|
@@ -733,9 +659,6 @@ describe('Assets', function() {
|
|
|
733
659
|
modules: {
|
|
734
660
|
'default-page': {},
|
|
735
661
|
'@apostrophecms/asset': {
|
|
736
|
-
options: {
|
|
737
|
-
es5: true
|
|
738
|
-
},
|
|
739
662
|
extendMethods() {
|
|
740
663
|
return {
|
|
741
664
|
async watchUiAndRebuild(_super) {
|
|
@@ -856,9 +779,6 @@ describe('Assets', function() {
|
|
|
856
779
|
}
|
|
857
780
|
},
|
|
858
781
|
'@apostrophecms/asset': {
|
|
859
|
-
options: {
|
|
860
|
-
es5: true
|
|
861
|
-
},
|
|
862
782
|
extendMethods() {
|
|
863
783
|
return {
|
|
864
784
|
async watchUiAndRebuild(_super) {
|
|
@@ -1073,9 +993,6 @@ describe('Assets', function() {
|
|
|
1073
993
|
autoBuild: true,
|
|
1074
994
|
modules: {
|
|
1075
995
|
'@apostrophecms/asset': {
|
|
1076
|
-
options: {
|
|
1077
|
-
es5: true
|
|
1078
|
-
},
|
|
1079
996
|
extendMethods() {
|
|
1080
997
|
return {
|
|
1081
998
|
async watchUiAndRebuild(_super) {
|
|
@@ -1153,7 +1070,7 @@ describe('Assets', function() {
|
|
|
1153
1070
|
// * no builds were triggered
|
|
1154
1071
|
await retryAssertTrue(
|
|
1155
1072
|
() => result.builds.length === 0,
|
|
1156
|
-
'Unable to verify
|
|
1073
|
+
'Unable to verify build "src" has NOT been triggered',
|
|
1157
1074
|
50,
|
|
1158
1075
|
1000
|
|
1159
1076
|
);
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
module.exports = (options, apos) => {
|
|
2
|
-
return {
|
|
3
|
-
target: [ 'web', 'es5' ],
|
|
4
|
-
module: {
|
|
5
|
-
rules: [
|
|
6
|
-
{
|
|
7
|
-
test: /\.js$/,
|
|
8
|
-
exclude: [
|
|
9
|
-
/\/core-js($|\/)/,
|
|
10
|
-
/\/regenerator-runtime($|\/)/
|
|
11
|
-
],
|
|
12
|
-
use: [
|
|
13
|
-
{
|
|
14
|
-
loader: 'babel-loader',
|
|
15
|
-
options: {
|
|
16
|
-
presets: [
|
|
17
|
-
[
|
|
18
|
-
'@babel/preset-env',
|
|
19
|
-
{
|
|
20
|
-
targets: {
|
|
21
|
-
browsers: '> 1%, IE 11, not dead'
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
};
|