apostrophe 3.5.0 → 3.8.1
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/.eslintrc +4 -0
- package/.scratch.md +2 -0
- package/CHANGELOG.md +96 -3
- package/README.md +1 -1
- package/index.js +108 -3
- package/lib/moog-require.js +23 -0
- package/lib/moog.js +1 -0
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBar.vue +30 -14
- package/modules/@apostrophecms/area/lib/custom-tags/area.js +1 -1
- package/modules/@apostrophecms/area/lib/custom-tags/widget.js +1 -1
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +2 -2
- package/modules/@apostrophecms/asset/index.js +77 -13
- package/modules/@apostrophecms/attachment/index.js +1 -0
- package/modules/@apostrophecms/db/index.js +5 -6
- package/modules/@apostrophecms/doc/index.js +2 -0
- package/modules/@apostrophecms/doc-type/index.js +39 -16
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocContextMenu.vue +13 -1
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +3 -0
- package/modules/@apostrophecms/i18n/i18n/en.json +19 -6
- package/modules/@apostrophecms/i18n/i18n/es.json +382 -0
- package/modules/@apostrophecms/i18n/i18n/pt-BR.json +379 -0
- package/modules/@apostrophecms/i18n/i18n/sk.json +380 -0
- package/modules/@apostrophecms/i18n/index.js +10 -1
- package/modules/@apostrophecms/image/index.js +2 -1
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +6 -3
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerEditor.vue +2 -1
- package/modules/@apostrophecms/image-widget/index.js +2 -1
- package/modules/@apostrophecms/image-widget/views/widget.html +12 -2
- package/modules/@apostrophecms/job/index.js +164 -212
- package/modules/@apostrophecms/login/index.js +1 -16
- package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +5 -0
- package/modules/@apostrophecms/migration/index.js +1 -1
- package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +151 -61
- package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +6 -2
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +8 -6
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +12 -15
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +6 -0
- package/modules/@apostrophecms/notification/index.js +116 -8
- package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +89 -11
- package/modules/@apostrophecms/notification/ui/apos/components/TheAposNotifications.vue +1 -1
- package/modules/@apostrophecms/page/index.js +37 -30
- package/modules/@apostrophecms/permission/index.js +1 -1
- package/modules/@apostrophecms/permission/ui/apos/components/AposInputRole.vue +4 -2
- package/modules/@apostrophecms/piece-type/index.js +178 -61
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +179 -47
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerDisplay.vue +1 -3
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +138 -0
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +35 -6
- package/modules/@apostrophecms/rich-text-widget/ui/apos/tiptap-extensions/Classes.js +1 -3
- package/modules/@apostrophecms/schema/index.js +97 -20
- package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +1 -0
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +4 -1
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputAttachment.vue +11 -160
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +24 -2
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputSelect.vue +24 -6
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +0 -4
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +0 -7
- package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +25 -3
- package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +10 -2
- package/modules/@apostrophecms/task/index.js +2 -2
- package/modules/@apostrophecms/template/index.js +63 -36
- package/modules/@apostrophecms/template/lib/custom-tags/component.js +1 -1
- package/modules/@apostrophecms/template/lib/custom-tags/render.js +6 -2
- package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +5 -2
- package/modules/@apostrophecms/ui/ui/apos/components/AposCellContextMenu.vue +1 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposFile.vue +205 -0
- package/modules/@apostrophecms/ui/ui/apos/lib/i18next.js +16 -2
- package/modules/@apostrophecms/ui/ui/apos/scss/global/_tables.scss +4 -3
- package/modules/@apostrophecms/util/index.js +2 -2
- package/modules/@apostrophecms/util/ui/src/http.js +12 -8
- package/modules/@apostrophecms/util/ui/src/util.js +15 -0
- package/modules/@apostrophecms/widget-type/index.js +1 -1
- package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +1 -0
- package/modules/@apostrophecms/widget-type/ui/apos/mixins/AposWidgetMixin.js +15 -7
- package/package.json +3 -3
- package/test/extra_node_modules/improve-global/index.js +7 -0
- package/test/extra_node_modules/improve-piece-type/index.js +7 -0
- package/test/improve-overrides.js +30 -0
- package/test/job.js +224 -0
- package/test/modules/@apostrophecms/global/index.js +8 -0
- package/test/modules/fragment-all/views/aux-test.html +7 -0
- package/test/modules/fragment-all/views/fragment.html +5 -0
- package/test/package.json +5 -4
- package/test/pieces.js +34 -0
- package/test/reverse-relationship.js +170 -0
- package/test/templates.js +7 -1
- package/test-lib/test.js +23 -12
- package/test-lib/util.js +33 -0
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
</template>
|
|
20
20
|
<template #primaryControls>
|
|
21
21
|
<AposContextMenu
|
|
22
|
-
v-if="
|
|
23
|
-
:button="
|
|
24
|
-
:menu="
|
|
25
|
-
@item-clicked="
|
|
22
|
+
v-if="utilityOperations.menu.length"
|
|
23
|
+
:button="utilityOperations.button"
|
|
24
|
+
:menu="utilityOperations.menu"
|
|
25
|
+
@item-clicked="utilityOperationsHandler"
|
|
26
26
|
/>
|
|
27
27
|
<AposButton
|
|
28
28
|
v-if="relationshipField"
|
|
@@ -66,19 +66,33 @@
|
|
|
66
66
|
:selected-state="selectAllState"
|
|
67
67
|
:total-pages="totalPages"
|
|
68
68
|
:current-page="currentPage"
|
|
69
|
-
:filters="moduleOptions.filters"
|
|
70
69
|
:filter-choices="filterChoices"
|
|
71
70
|
:filter-values="filterValues"
|
|
71
|
+
:filters="moduleOptions.filters"
|
|
72
72
|
:labels="moduleLabels"
|
|
73
|
+
:displayed-items="items.length"
|
|
74
|
+
:is-relationship="!!relationshipField"
|
|
75
|
+
:checked-count="checked.length"
|
|
76
|
+
:batch-operations="moduleOptions.batchOperations"
|
|
73
77
|
@select-click="selectAll"
|
|
74
78
|
@search="search"
|
|
75
79
|
@page-change="updatePage"
|
|
76
80
|
@filter="filter"
|
|
81
|
+
@batch="handleBatchAction"
|
|
77
82
|
:options="{
|
|
78
|
-
disableUnchecked: maxReached()
|
|
79
|
-
hideSelectAll: !relationshipField
|
|
83
|
+
disableUnchecked: maxReached()
|
|
80
84
|
}"
|
|
81
85
|
/>
|
|
86
|
+
<AposDocsManagerSelectBox
|
|
87
|
+
:selected-state="selectAllState"
|
|
88
|
+
:module-labels="moduleLabels"
|
|
89
|
+
:filter-values="filterValues"
|
|
90
|
+
:checked-ids="checked"
|
|
91
|
+
:all-pieces-selection="allPiecesSelection"
|
|
92
|
+
:displayed-items="items.length"
|
|
93
|
+
@select-all="selectAllPieces"
|
|
94
|
+
@set-all-pieces-selection="setAllPiecesSelection"
|
|
95
|
+
/>
|
|
82
96
|
</template>
|
|
83
97
|
<template #bodyMain>
|
|
84
98
|
<AposDocsManagerDisplay
|
|
@@ -90,7 +104,6 @@
|
|
|
90
104
|
:options="{
|
|
91
105
|
...moduleOptions,
|
|
92
106
|
disableUnchecked: maxReached(),
|
|
93
|
-
hideCheckboxes: !relationshipField,
|
|
94
107
|
disableUnpublished: disableUnpublished,
|
|
95
108
|
manuallyPublished: manuallyPublished
|
|
96
109
|
}"
|
|
@@ -136,7 +149,7 @@ export default {
|
|
|
136
149
|
filterValues: {},
|
|
137
150
|
queryExtras: {},
|
|
138
151
|
holdQueries: false,
|
|
139
|
-
|
|
152
|
+
utilityOperations: {
|
|
140
153
|
button: {
|
|
141
154
|
label: 'apostrophe:moreOperations',
|
|
142
155
|
iconOnly: true,
|
|
@@ -145,7 +158,11 @@ export default {
|
|
|
145
158
|
},
|
|
146
159
|
menu: []
|
|
147
160
|
},
|
|
148
|
-
filterChoices: {}
|
|
161
|
+
filterChoices: {},
|
|
162
|
+
allPiecesSelection: {
|
|
163
|
+
isSelected: false,
|
|
164
|
+
total: 0
|
|
165
|
+
}
|
|
149
166
|
};
|
|
150
167
|
},
|
|
151
168
|
computed: {
|
|
@@ -190,6 +207,16 @@ export default {
|
|
|
190
207
|
},
|
|
191
208
|
disableUnpublished() {
|
|
192
209
|
return this.relationshipField && apos.modules[this.relationshipField.withType].localized;
|
|
210
|
+
},
|
|
211
|
+
selectAllChoice() {
|
|
212
|
+
const checkCount = this.checked.length;
|
|
213
|
+
const pageNotFullyChecked = this.items
|
|
214
|
+
.some((item) => !this.checked.includes(item._id));
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
value: 'checked',
|
|
218
|
+
indeterminate: checkCount && pageNotFullyChecked
|
|
219
|
+
};
|
|
193
220
|
}
|
|
194
221
|
},
|
|
195
222
|
created() {
|
|
@@ -206,14 +233,10 @@ export default {
|
|
|
206
233
|
this.headers = this.computeHeaders();
|
|
207
234
|
// Get the data. This will be more complex in actuality.
|
|
208
235
|
this.modal.active = true;
|
|
209
|
-
this.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
action: 'new',
|
|
214
|
-
label: `New ${this.moduleLabels.singular}`
|
|
215
|
-
});
|
|
216
|
-
}
|
|
236
|
+
this.setUtilityOperations();
|
|
237
|
+
await this.getPieces();
|
|
238
|
+
await this.getAllPiecesTotal();
|
|
239
|
+
|
|
217
240
|
apos.bus.$on('content-changed', this.getPieces);
|
|
218
241
|
},
|
|
219
242
|
destroyed() {
|
|
@@ -221,10 +244,13 @@ export default {
|
|
|
221
244
|
apos.bus.$off('content-changed', this.getPieces);
|
|
222
245
|
},
|
|
223
246
|
methods: {
|
|
224
|
-
|
|
247
|
+
utilityOperationsHandler(action) {
|
|
225
248
|
if (action === 'new') {
|
|
226
249
|
this.create();
|
|
250
|
+
return;
|
|
227
251
|
}
|
|
252
|
+
|
|
253
|
+
this.handleUtilityOperation(action);
|
|
228
254
|
},
|
|
229
255
|
setCheckedDocs(checked) {
|
|
230
256
|
this.checkedDocs = checked;
|
|
@@ -235,6 +261,29 @@ export default {
|
|
|
235
261
|
async create() {
|
|
236
262
|
await this.edit(null);
|
|
237
263
|
},
|
|
264
|
+
async handleUtilityOperation(action) {
|
|
265
|
+
const operation = this.utilityOperations.menu
|
|
266
|
+
.find((op) => op.action === action);
|
|
267
|
+
|
|
268
|
+
if (!operation) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const {
|
|
273
|
+
modal, ...modalOptions
|
|
274
|
+
} = operation.modalOptions || {};
|
|
275
|
+
|
|
276
|
+
if (modal) {
|
|
277
|
+
await apos.modal.execute(modal, {
|
|
278
|
+
moduleAction: this.moduleOptions.action,
|
|
279
|
+
action,
|
|
280
|
+
labels: this.moduleLabels,
|
|
281
|
+
messages: operation.messages,
|
|
282
|
+
...modalOptions
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
|
|
238
287
|
// If pieceOrId is null, a new piece is created
|
|
239
288
|
async edit(pieceOrId) {
|
|
240
289
|
let piece;
|
|
@@ -268,42 +317,68 @@ export default {
|
|
|
268
317
|
async finishSaved() {
|
|
269
318
|
await this.getPieces();
|
|
270
319
|
},
|
|
271
|
-
async
|
|
272
|
-
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
this.holdQueries = true;
|
|
277
|
-
|
|
278
|
-
const qs = {
|
|
320
|
+
async request (mergeOptions) {
|
|
321
|
+
const options = {
|
|
279
322
|
...this.filterValues,
|
|
280
|
-
page: this.currentPage,
|
|
281
323
|
...this.queryExtras,
|
|
282
|
-
|
|
324
|
+
...mergeOptions,
|
|
283
325
|
withPublished: 1
|
|
284
326
|
};
|
|
285
327
|
|
|
286
328
|
// Avoid undefined properties.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
329
|
+
const qs = Object.entries(options)
|
|
330
|
+
.reduce((acc, [ key, val ]) => ({
|
|
331
|
+
...acc,
|
|
332
|
+
...val !== undefined && { [key]: val }
|
|
333
|
+
}), {});
|
|
334
|
+
|
|
335
|
+
return apos.http.get(this.moduleOptions.action, {
|
|
336
|
+
qs,
|
|
337
|
+
busy: true,
|
|
338
|
+
draft: true
|
|
339
|
+
});
|
|
340
|
+
},
|
|
341
|
+
async getPieces () {
|
|
342
|
+
if (this.holdQueries) {
|
|
343
|
+
return;
|
|
291
344
|
}
|
|
292
345
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
);
|
|
346
|
+
this.holdQueries = true;
|
|
347
|
+
|
|
348
|
+
const {
|
|
349
|
+
currentPage, pages, results, choices
|
|
350
|
+
} = await this.request({
|
|
351
|
+
page: this.currentPage
|
|
352
|
+
});
|
|
300
353
|
|
|
301
|
-
this.currentPage =
|
|
302
|
-
this.totalPages =
|
|
303
|
-
this.items =
|
|
304
|
-
this.filterChoices =
|
|
354
|
+
this.currentPage = currentPage;
|
|
355
|
+
this.totalPages = pages;
|
|
356
|
+
this.items = results;
|
|
357
|
+
this.filterChoices = choices;
|
|
305
358
|
this.holdQueries = false;
|
|
306
359
|
},
|
|
360
|
+
async getAllPiecesTotal () {
|
|
361
|
+
const { count: total } = await this.request({ count: 1 });
|
|
362
|
+
|
|
363
|
+
this.setAllPiecesSelection({
|
|
364
|
+
isSelected: false,
|
|
365
|
+
total
|
|
366
|
+
});
|
|
367
|
+
},
|
|
368
|
+
async selectAllPieces () {
|
|
369
|
+
const { results: docs } = await this.request({
|
|
370
|
+
project: {
|
|
371
|
+
_id: 1
|
|
372
|
+
},
|
|
373
|
+
attachments: false,
|
|
374
|
+
perPage: this.allPiecesSelection.total
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
this.setAllPiecesSelection({
|
|
378
|
+
isSelected: true,
|
|
379
|
+
docs
|
|
380
|
+
});
|
|
381
|
+
},
|
|
307
382
|
updatePage(num) {
|
|
308
383
|
if (num) {
|
|
309
384
|
this.currentPage = num;
|
|
@@ -322,6 +397,7 @@ export default {
|
|
|
322
397
|
this.currentPage = 1;
|
|
323
398
|
|
|
324
399
|
await this.getPieces();
|
|
400
|
+
await this.getAllPiecesTotal();
|
|
325
401
|
},
|
|
326
402
|
async filter(filter, value) {
|
|
327
403
|
if (this.filterValues[filter] === value) {
|
|
@@ -331,10 +407,12 @@ export default {
|
|
|
331
407
|
this.filterValues[filter] = value;
|
|
332
408
|
this.currentPage = 1;
|
|
333
409
|
|
|
334
|
-
this.getPieces();
|
|
410
|
+
await this.getPieces();
|
|
411
|
+
await this.getAllPiecesTotal();
|
|
335
412
|
this.headers = this.computeHeaders();
|
|
336
|
-
},
|
|
337
413
|
|
|
414
|
+
this.setCheckedDocs([]);
|
|
415
|
+
},
|
|
338
416
|
shortcutNew(event) {
|
|
339
417
|
const interesting = (event.keyCode === 78 || event.keyCode === 67); // C(reate) or N(ew)
|
|
340
418
|
const topModal = apos.modal.stack[apos.modal.stack.length - 1] ? apos.modal.stack[apos.modal.stack.length - 1].id : null;
|
|
@@ -346,7 +424,6 @@ export default {
|
|
|
346
424
|
this.create();
|
|
347
425
|
}
|
|
348
426
|
},
|
|
349
|
-
|
|
350
427
|
bindShortcuts() {
|
|
351
428
|
window.addEventListener('keydown', this.shortcutNew);
|
|
352
429
|
},
|
|
@@ -373,6 +450,61 @@ export default {
|
|
|
373
450
|
_fields: result
|
|
374
451
|
});
|
|
375
452
|
}
|
|
453
|
+
},
|
|
454
|
+
setAllPiecesSelection ({
|
|
455
|
+
isSelected, total, docs
|
|
456
|
+
}) {
|
|
457
|
+
if (typeof isSelected === 'boolean') {
|
|
458
|
+
this.allPiecesSelection.isSelected = isSelected;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (typeof total === 'number') {
|
|
462
|
+
this.allPiecesSelection.total = total;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (docs) {
|
|
466
|
+
this.setCheckedDocs(docs);
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
async handleBatchAction({
|
|
470
|
+
label, action, requestOptions = {}, messages
|
|
471
|
+
}) {
|
|
472
|
+
if (action) {
|
|
473
|
+
try {
|
|
474
|
+
await apos.http.post(`${this.moduleOptions.action}/${action}`, {
|
|
475
|
+
body: {
|
|
476
|
+
...requestOptions,
|
|
477
|
+
_ids: this.checked,
|
|
478
|
+
messages: messages,
|
|
479
|
+
type: this.checked.length === 1 ? this.moduleLabels.singular
|
|
480
|
+
: this.moduleLabels.plural
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
apos.notify('Batch operation {{ operation }} failed.', {
|
|
485
|
+
interpolate: { operation: label },
|
|
486
|
+
type: 'danger'
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
setUtilityOperations () {
|
|
492
|
+
const { utilityOperations } = this.moduleOptions;
|
|
493
|
+
|
|
494
|
+
const newPiece = {
|
|
495
|
+
action: 'new',
|
|
496
|
+
label: {
|
|
497
|
+
key: 'apostrophe:newDocType',
|
|
498
|
+
type: this.$t(this.moduleLabels.singular)
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
this.utilityOperations.menu = [
|
|
503
|
+
...this.relationshipField && this.moduleOptions.canEdit
|
|
504
|
+
? [ newPiece ] : [],
|
|
505
|
+
...this.utilityOperations.menu,
|
|
506
|
+
...(!this.relationshipField && Array.isArray(utilityOperations) && utilityOperations) || []
|
|
507
|
+
];
|
|
376
508
|
}
|
|
377
509
|
}
|
|
378
510
|
};
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
<tr>
|
|
5
5
|
<th
|
|
6
6
|
class="apos-table__header"
|
|
7
|
-
v-if="!options.hideCheckboxes"
|
|
8
7
|
/>
|
|
9
8
|
<th
|
|
10
9
|
v-for="header in headers" scope="col"
|
|
@@ -26,7 +25,7 @@
|
|
|
26
25
|
<th class="apos-table__header" key="contextMenu">
|
|
27
26
|
<component
|
|
28
27
|
:is="getEl({})"
|
|
29
|
-
class="apos-table__header-label is-hidden"
|
|
28
|
+
class="apos-table__header-label apos-is-hidden"
|
|
30
29
|
>
|
|
31
30
|
{{ $t('apostrophe:moreOperations') }}
|
|
32
31
|
</component>
|
|
@@ -41,7 +40,6 @@
|
|
|
41
40
|
>
|
|
42
41
|
<td
|
|
43
42
|
class="apos-table__cell"
|
|
44
|
-
v-if="!options.hideCheckboxes"
|
|
45
43
|
>
|
|
46
44
|
<AposCheckbox
|
|
47
45
|
v-if="item._id"
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<transition
|
|
3
|
+
name="collapse"
|
|
4
|
+
:duration="300"
|
|
5
|
+
>
|
|
6
|
+
<div
|
|
7
|
+
v-if="selectedState === 'checked' || allPiecesSelection.isSelected"
|
|
8
|
+
class="apos-select-box"
|
|
9
|
+
>
|
|
10
|
+
<div class="apos-select-box__content">
|
|
11
|
+
<p class="apos-select-box__text">
|
|
12
|
+
{{ selectBoxMessage }}
|
|
13
|
+
<button
|
|
14
|
+
v-if="!allPiecesSelection.isSelected"
|
|
15
|
+
class="apos-select-box__select-all"
|
|
16
|
+
@click="$emit('select-all')"
|
|
17
|
+
>
|
|
18
|
+
{{ selectBoxMessageButton }}
|
|
19
|
+
</button>
|
|
20
|
+
<button
|
|
21
|
+
v-else
|
|
22
|
+
class="apos-select-box__select-all"
|
|
23
|
+
@click="clearSelection"
|
|
24
|
+
>
|
|
25
|
+
{{ $t('apostrophe:clearSelection') }}.
|
|
26
|
+
</button>
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</transition>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script>
|
|
34
|
+
export default {
|
|
35
|
+
props: {
|
|
36
|
+
selectedState: {
|
|
37
|
+
type: String,
|
|
38
|
+
required: true
|
|
39
|
+
},
|
|
40
|
+
moduleLabels: {
|
|
41
|
+
type: Object,
|
|
42
|
+
required: true
|
|
43
|
+
},
|
|
44
|
+
checkedIds: {
|
|
45
|
+
type: Array,
|
|
46
|
+
required: true
|
|
47
|
+
},
|
|
48
|
+
allPiecesSelection: {
|
|
49
|
+
type: Object,
|
|
50
|
+
required: true
|
|
51
|
+
},
|
|
52
|
+
displayedItems: {
|
|
53
|
+
type: Number,
|
|
54
|
+
required: true
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
emits: [ 'select-all', 'clear-select', 'set-all-pieces-selection' ],
|
|
58
|
+
computed: {
|
|
59
|
+
selectBoxMessage () {
|
|
60
|
+
const checkedCount = this.checkedIds.length;
|
|
61
|
+
const showAllWord = (checkedCount === this.allPiecesSelection.total) &&
|
|
62
|
+
checkedCount !== 1;
|
|
63
|
+
|
|
64
|
+
const translationKey = this.allPiecesSelection.isSelected
|
|
65
|
+
? showAllWord
|
|
66
|
+
? 'apostrophe:selectBoxMessageAllSelected'
|
|
67
|
+
: 'apostrophe:selectBoxMessageSelected'
|
|
68
|
+
: checkedCount > this.displayedItems
|
|
69
|
+
? 'apostrophe:selectBoxMessage'
|
|
70
|
+
: 'apostrophe:selectBoxMessagePage';
|
|
71
|
+
|
|
72
|
+
return this.$t(translationKey, {
|
|
73
|
+
num: this.checkedIds.length,
|
|
74
|
+
label: this.getLabel(this.checkedIds.length)
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
selectBoxMessageButton () {
|
|
78
|
+
const translationKey = this.allPiecesSelection.total === 1
|
|
79
|
+
? 'apostrophe:selectBoxMessageButton'
|
|
80
|
+
: 'apostrophe:selectBoxMessageAllButton';
|
|
81
|
+
|
|
82
|
+
return this.$t(translationKey, {
|
|
83
|
+
num: this.allPiecesSelection.total,
|
|
84
|
+
label: this.getLabel(this.allPiecesSelection.total)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
methods: {
|
|
89
|
+
getLabel(number) {
|
|
90
|
+
return number === 1
|
|
91
|
+
? this.$t(this.moduleLabels.singular).toLowerCase()
|
|
92
|
+
: this.$t(this.moduleLabels.plural).toLowerCase();
|
|
93
|
+
},
|
|
94
|
+
clearSelection () {
|
|
95
|
+
this.$emit('set-all-pieces-selection', {
|
|
96
|
+
isSelected: false,
|
|
97
|
+
docs: []
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
</script>
|
|
103
|
+
<style lang='scss' scoped>
|
|
104
|
+
.apos-select-box {
|
|
105
|
+
box-sizing: border-box;
|
|
106
|
+
overflow: hidden;
|
|
107
|
+
height: 5rem;
|
|
108
|
+
transition: all 0.3s linear;
|
|
109
|
+
|
|
110
|
+
&.collapse-enter, &.collapse-leave-to {
|
|
111
|
+
height: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&__content {
|
|
115
|
+
display: flex;
|
|
116
|
+
align-items: center;
|
|
117
|
+
justify-content: center;
|
|
118
|
+
background-color: var(--a-base-9);
|
|
119
|
+
margin-top: 1rem;
|
|
120
|
+
color: var(--a-text-primary);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&__text {
|
|
124
|
+
@include type-large;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&__select-all {
|
|
128
|
+
color: var(--a-primary);
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
margin-left: 0.4rem;
|
|
131
|
+
border: none;
|
|
132
|
+
|
|
133
|
+
&:hover {
|
|
134
|
+
text-decoration: underline;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
</style>
|
package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
</AposContextMenuDialog>
|
|
27
27
|
</bubble-menu>
|
|
28
28
|
<div class="apos-rich-text-editor__editor" :class="editorModifiers">
|
|
29
|
-
<editor-content :editor="editor" :class="
|
|
29
|
+
<editor-content :editor="editor" :class="editorOptions.className" />
|
|
30
30
|
</div>
|
|
31
31
|
<div class="apos-rich-text-editor__editor_after" :class="editorModifiers">
|
|
32
32
|
{{ $t('apostrophe:emptyRichTextWidget') }}
|
|
@@ -100,13 +100,34 @@ export default {
|
|
|
100
100
|
activeOptions.toolbar = (activeOptions.toolbar !== undefined)
|
|
101
101
|
? activeOptions.toolbar : this.defaultOptions.toolbar;
|
|
102
102
|
|
|
103
|
-
activeOptions.styles = this.enhanceStyles(
|
|
103
|
+
activeOptions.styles = this.enhanceStyles(
|
|
104
|
+
activeOptions.styles?.length ?
|
|
105
|
+
activeOptions.styles :
|
|
106
|
+
this.defaultOptions.styles
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
activeOptions.className = (activeOptions.className !== undefined)
|
|
110
|
+
? activeOptions.className : this.moduleOptions.className;
|
|
104
111
|
|
|
105
112
|
return activeOptions;
|
|
106
113
|
},
|
|
107
|
-
|
|
114
|
+
autofocus() {
|
|
115
|
+
// Only true for a new rich text widget
|
|
116
|
+
return !this.stripPlaceholderBrs(this.value.content).length;
|
|
117
|
+
},
|
|
108
118
|
initialContent() {
|
|
109
|
-
|
|
119
|
+
const content = this.stripPlaceholderBrs(this.value.content);
|
|
120
|
+
if (!content.length) {
|
|
121
|
+
// If we don't supply a valid instance of the first style, then
|
|
122
|
+
// the text align control will not work until the user manually
|
|
123
|
+
// applies a style or refreshes the page
|
|
124
|
+
const defaultStyle = this.editorOptions.styles.find(style => style.def);
|
|
125
|
+
|
|
126
|
+
const _class = defaultStyle.class ? ` class="${defaultStyle.class}"` : '';
|
|
127
|
+
return `<${defaultStyle.tag}${_class}></${defaultStyle.tag}>`;
|
|
128
|
+
} else {
|
|
129
|
+
return content;
|
|
130
|
+
}
|
|
110
131
|
},
|
|
111
132
|
toolbar() {
|
|
112
133
|
return this.editorOptions.toolbar;
|
|
@@ -135,7 +156,7 @@ export default {
|
|
|
135
156
|
aposTiptapExtensions() {
|
|
136
157
|
return (apos.tiptapExtensions || [])
|
|
137
158
|
.map(extension => extension({
|
|
138
|
-
styles: this.editorOptions.styles,
|
|
159
|
+
styles: this.editorOptions.styles.map(this.localizeStyle),
|
|
139
160
|
types: this.tiptapTypes
|
|
140
161
|
}));
|
|
141
162
|
}
|
|
@@ -152,7 +173,7 @@ export default {
|
|
|
152
173
|
mounted() {
|
|
153
174
|
this.editor = new Editor({
|
|
154
175
|
content: this.initialContent,
|
|
155
|
-
autofocus:
|
|
176
|
+
autofocus: this.autofocus,
|
|
156
177
|
onUpdate: this.editorUpdate,
|
|
157
178
|
extensions: [
|
|
158
179
|
StarterKit,
|
|
@@ -265,6 +286,14 @@ export default {
|
|
|
265
286
|
}
|
|
266
287
|
}
|
|
267
288
|
return styles;
|
|
289
|
+
},
|
|
290
|
+
localizeStyle(style) {
|
|
291
|
+
style.label = this.$t(style.label);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
...style,
|
|
295
|
+
label: this.$t(style.label)
|
|
296
|
+
};
|
|
268
297
|
}
|
|
269
298
|
}
|
|
270
299
|
};
|
|
@@ -25,9 +25,7 @@ export default (options) => {
|
|
|
25
25
|
const tag = element.tagName.toLowerCase();
|
|
26
26
|
// This tag is not configured
|
|
27
27
|
if (!allow[tag]) {
|
|
28
|
-
return
|
|
29
|
-
class: null
|
|
30
|
-
};
|
|
28
|
+
return null;
|
|
31
29
|
}
|
|
32
30
|
const classes = (element.getAttribute('class') || '')
|
|
33
31
|
.split(' ')
|