apostrophe 3.53.0 → 3.55.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +58 -1
  2. package/defaults.js +1 -0
  3. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +5 -2
  4. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +28 -19
  5. package/modules/@apostrophecms/any-doc-type/index.js +2 -2
  6. package/modules/@apostrophecms/any-page-type/index.js +2 -2
  7. package/modules/@apostrophecms/doc/index.js +55 -29
  8. package/modules/@apostrophecms/doc-type/index.js +11 -6
  9. package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocContextMenu.vue +4 -440
  10. package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +445 -0
  11. package/modules/@apostrophecms/i18n/i18n/de.json +113 -105
  12. package/modules/@apostrophecms/i18n/i18n/es.json +10 -0
  13. package/modules/@apostrophecms/i18n/i18n/fr.json +8 -0
  14. package/modules/@apostrophecms/i18n/i18n/pt-BR.json +10 -0
  15. package/modules/@apostrophecms/i18n/i18n/sk.json +8 -0
  16. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +1 -0
  17. package/modules/@apostrophecms/log/index.js +429 -0
  18. package/modules/@apostrophecms/login/index.js +47 -4
  19. package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +14 -1
  20. package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +1 -1
  21. package/modules/@apostrophecms/module/index.js +32 -6
  22. package/modules/@apostrophecms/module/lib/log.js +68 -0
  23. package/modules/@apostrophecms/page/index.js +71 -19
  24. package/modules/@apostrophecms/page/lib/legacy-migrations.js +0 -57
  25. package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +8 -285
  26. package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +291 -0
  27. package/modules/@apostrophecms/page-type/index.js +39 -26
  28. package/modules/@apostrophecms/piece-type/index.js +19 -11
  29. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +1 -0
  30. package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +2 -357
  31. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +2 -86
  32. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +2 -254
  33. package/modules/@apostrophecms/schema/ui/apos/components/AposInputAttachment.vue +2 -77
  34. package/modules/@apostrophecms/schema/ui/apos/components/AposInputBoolean.vue +2 -44
  35. package/modules/@apostrophecms/schema/ui/apos/components/AposInputCheckboxes.vue +2 -64
  36. package/modules/@apostrophecms/schema/ui/apos/components/AposInputColor.vue +2 -94
  37. package/modules/@apostrophecms/schema/ui/apos/components/AposInputDateAndTime.vue +3 -47
  38. package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +2 -82
  39. package/modules/@apostrophecms/schema/ui/apos/components/AposInputPassword.vue +2 -37
  40. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +2 -26
  41. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRange.vue +2 -57
  42. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +2 -259
  43. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSelect.vue +2 -38
  44. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +2 -275
  45. package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +2 -167
  46. package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +2 -115
  47. package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +3 -279
  48. package/modules/@apostrophecms/schema/ui/apos/components/AposSearchList.vue +2 -83
  49. package/modules/@apostrophecms/schema/ui/apos/lib/detectChange.js +10 -1
  50. package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +361 -0
  51. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArea.js +89 -0
  52. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArray.js +257 -0
  53. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputAttachment.js +81 -0
  54. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputBoolean.js +48 -0
  55. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputCheckboxes.js +68 -0
  56. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputColor.js +98 -0
  57. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputDateAndTime.js +49 -0
  58. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputObject.js +86 -0
  59. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputPassword.js +41 -0
  60. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRadio.js +29 -0
  61. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRange.js +60 -0
  62. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +262 -0
  63. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSelect.js +41 -0
  64. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSlug.js +278 -0
  65. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +170 -0
  66. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +118 -0
  67. package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +281 -0
  68. package/modules/@apostrophecms/schema/ui/apos/logic/AposSearchList.js +85 -0
  69. package/modules/@apostrophecms/template/index.js +1 -1
  70. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeHeader.vue +2 -2
  71. package/modules/@apostrophecms/util/index.js +83 -13
  72. package/modules/@apostrophecms/util/lib/logger.js +19 -17
  73. package/package.json +1 -1
  74. package/test/docs.js +35 -2
  75. package/test/log.js +1765 -0
  76. package/test/pages.js +57 -0
  77. package/test-lib/util.js +1 -1
@@ -19,448 +19,12 @@
19
19
  </template>
20
20
 
21
21
  <script>
22
- import { detectDocChange } from 'Modules/@apostrophecms/schema/lib/detectChange';
23
- import AposPublishMixin from 'Modules/@apostrophecms/ui/mixins/AposPublishMixin';
24
- import AposArchiveMixin from 'Modules/@apostrophecms/ui/mixins/AposArchiveMixin';
25
- import AposModifiedMixin from 'Modules/@apostrophecms/ui/mixins/AposModifiedMixin';
26
- import checkIfConditions from 'apostrophe/lib/check-if-conditions';
22
+ import AposDocContextMenuLogic from 'Modules/@apostrophecms/doc-type/logic/AposDocContextMenu';
27
23
 
28
24
  export default {
29
25
  name: 'AposDocContextMenu',
30
- mixins: [ AposPublishMixin, AposArchiveMixin, AposModifiedMixin ],
31
- props: {
32
- doc: {
33
- type: Object,
34
- required: true
35
- },
36
- // If editing in a modal, pass the current value object from the editor here
37
- // so that the visibility of options takes unsaved changes into account
38
- current: {
39
- type: Object,
40
- default() {
41
- return null;
42
- }
43
- },
44
- // Existing published version of doc, if there is one
45
- published: {
46
- type: Object,
47
- default() {
48
- return null;
49
- }
50
- },
51
- // These props all default to true, and can be passed with a value of false to hide
52
- // functionality even if the user can otherwise perform the action on this document.
53
- // The component will figure out on its own if the user can perform each action or not.
54
- showEdit: {
55
- type: Boolean,
56
- default() {
57
- return true;
58
- }
59
- },
60
- showPreview: {
61
- type: Boolean,
62
- default() {
63
- return true;
64
- }
65
- },
66
- showDiscardDraft: {
67
- type: Boolean,
68
- default() {
69
- return true;
70
- }
71
- },
72
- showCopy: {
73
- type: Boolean,
74
- default() {
75
- return true;
76
- }
77
- },
78
- showArchive: {
79
- type: Boolean,
80
- default() {
81
- return true;
82
- }
83
- },
84
- showRestore: {
85
- type: Boolean,
86
- default() {
87
- return true;
88
- }
89
- },
90
- // Unlike the others, this one defaults to false because it is
91
- // generally only allowed in the Manage Submissions view.
92
- showDismissSubmission: {
93
- type: Boolean,
94
- default() {
95
- return false;
96
- }
97
- },
98
- disabled: {
99
- type: Boolean,
100
- default: false
101
- }
102
- },
103
- emits: [ 'menu-open', 'menu-close', 'close' ],
104
- data() {
105
- return {
106
- // Updated by both the context prop and any content-changed apos events
107
- context: this.doc,
108
- // Custom context menu operations
109
- customOperations: apos.modules['@apostrophecms/doc'].contextOperations
110
- };
111
- },
112
- computed: {
113
- menu() {
114
- const menu = [
115
- // TODO
116
- // ...(this.isModifiedFromPublished ? [
117
- // {
118
- // label: 'Share Draft',
119
- // action: 'share'
120
- // }
121
- // ] : []),
122
- ...((this.showEdit && this.context._edit) ? [
123
- {
124
- // When archived the edit action opens a read-only "editor"
125
- label: this.context.archived ? 'apostrophe:view' : 'apostrophe:edit',
126
- action: 'edit'
127
- }
128
- ] : []),
129
- ...((this.showPreview && this.hasUrl) ? [
130
- {
131
- label: 'apostrophe:preview',
132
- action: 'preview'
133
- }
134
- ] : []),
135
- ...((this.showDismissSubmission && this.canDismissSubmission) ? [
136
- {
137
- label: 'apostrophe:dismissSubmission',
138
- action: 'dismissSubmission'
139
- }
140
- ] : []),
141
- ...(this.showCopy && this.canCopy ? [
142
- {
143
- label: 'apostrophe:duplicate',
144
- action: 'copy'
145
- }
146
- ] : []),
147
- ...(this.canLocalize ? [
148
- {
149
- label: 'apostrophe:localize',
150
- action: 'localize'
151
- }
152
- ] : []),
153
- ...this.customMenusByContext,
154
- ...((this.showDiscardDraft && this.canDiscardDraft) ? [
155
- {
156
- label: this.context.lastPublishedAt ? 'apostrophe:discardDraft' : 'apostrophe:deleteDraft',
157
- action: 'discardDraft',
158
- modifiers: [ 'danger' ]
159
- }
160
- ] : []),
161
- ...(this.showArchive && this.canArchive ? [
162
- {
163
- label: 'apostrophe:archive',
164
- action: 'archive',
165
- modifiers: [ 'danger' ]
166
- }
167
- ] : []),
168
- ...(this.canUnpublish ? [
169
- {
170
- label: 'apostrophe:unpublish',
171
- action: 'unpublish',
172
- modifiers: [ 'danger' ]
173
- }
174
- ] : []),
175
- ...(this.showRestore && this.canRestore ? [
176
- {
177
- label: 'apostrophe:restore',
178
- action: 'restore'
179
- }
180
- ] : [])
181
- ];
182
- return menu;
183
- },
184
- customMenusByContext() {
185
- if (!this.canEdit) {
186
- return [];
187
- }
188
-
189
- const menus = this.customOperationsByContext
190
- .map(op => ({
191
- label: op.label,
192
- action: op.action,
193
- modifiers: op.modifiers || []
194
- }));
195
- menus.sort((a, b) => a.modifiers.length - b.modifiers.length);
196
- return menus;
197
- },
198
- customOperationsByContext() {
199
- return this.customOperations.filter(({
200
- manuallyPublished, hasUrl, conditions, context, if: ifProps
201
- }) => {
202
- if (typeof manuallyPublished === 'boolean' && manuallyPublished !== this.manuallyPublished) {
203
- return false;
204
- }
205
-
206
- if (typeof hasUrl === 'boolean' && hasUrl !== this.hasUrl) {
207
- return false;
208
- }
209
-
210
- if (conditions) {
211
- const notAllowed = conditions.some((action) => !this[action]);
212
-
213
- if (notAllowed) {
214
- return false;
215
- }
216
- }
217
-
218
- if (ifProps) {
219
- const canSeeOperation = checkIfConditions(this.doc, ifProps);
220
-
221
- if (!canSeeOperation) {
222
- return false;
223
- }
224
- }
225
-
226
- return context === 'update' && this.isUpdateOperation;
227
- });
228
- },
229
- moduleName() {
230
- if (apos.modules[this.context.type].action === apos.modules['@apostrophecms/page'].action) {
231
- return '@apostrophecms/page';
232
- } else {
233
- return this.context.type;
234
- }
235
- },
236
- moduleOptions() {
237
- return apos.modules[this.moduleName];
238
- },
239
- isUpdateOperation() {
240
- return !!this.context._id;
241
- },
242
- hasUrl() {
243
- return !!this.context._url;
244
- },
245
- canPublish() {
246
- if (this.context._id) {
247
- return this.context._publish;
248
- } else {
249
- return this.moduleOptions.canPublish;
250
- }
251
- },
252
- canEdit() {
253
- if (this.context._id) {
254
- return this.context._edit;
255
- } else {
256
- return true;
257
- }
258
- },
259
- canDismissSubmission() {
260
- return this.canEdit && this.context.submitted && (this.canPublish || (this.context.submitted.byId === apos.login.user._id));
261
- },
262
- canDiscardDraft() {
263
- if (!this.manuallyPublished) {
264
- return false;
265
- }
266
- if (!this.context._id) {
267
- return false;
268
- }
269
- if (!this.canEdit) {
270
- return false;
271
- }
272
- return (
273
- (!this.context.lastPublishedAt) &&
274
- !this.moduleOptions.singleton
275
- ) || (
276
- this.context.lastPublishedAt &&
277
- this.isModifiedFromPublished
278
- );
279
- },
280
- canLocalize() {
281
- return this.moduleOptions.canLocalize &&
282
- this.context._id;
283
- },
284
- canArchive() {
285
- return (
286
- this.canEdit &&
287
- this.context._id &&
288
- !this.moduleOptions.singleton &&
289
- !this.context.archived &&
290
- !this.context.parked &&
291
- ((this.moduleOptions.canPublish && this.context.lastPublishedAt) || !this.manuallyPublished)
292
- );
293
- },
294
- canUnpublish() {
295
- return (
296
- this.canEdit &&
297
- !this.context.parked &&
298
- this.moduleOptions.canPublish &&
299
- this.context.lastPublishedAt &&
300
- this.manuallyPublished
301
- );
302
- },
303
- canCopy() {
304
- return this.canEdit &&
305
- this.moduleOptions.canEdit &&
306
- !this.moduleOptions.singleton &&
307
- this.context._id;
308
- },
309
- canRestore() {
310
- return (
311
- this.canEdit &&
312
- this.context._id &&
313
- this.context.archived &&
314
- ((this.moduleOptions.canPublish && this.context.lastPublishedAt) || !this.manuallyPublished)
315
- );
316
- },
317
- manuallyPublished() {
318
- return this.moduleOptions.localized && !this.autopublish;
319
- },
320
- autopublish() {
321
- return this.context._aposAutopublish ?? this.moduleOptions.autopublish;
322
- },
323
- isModified() {
324
- if (!this.current) {
325
- return false;
326
- }
327
- return detectDocChange(this.schema, this.context, this.current);
328
- },
329
- isModifiedFromPublished() {
330
- if (this.context.modified) {
331
- // In a list context, we won't have every area property to
332
- // compare, but we will have this previously set flag
333
- return true;
334
- }
335
- if (!this.context.lastPublishedAt) {
336
- return false;
337
- }
338
- if (!this.published) {
339
- return false;
340
- }
341
- const result = detectDocChange(this.schema, this.published, this.context);
342
- return result;
343
- },
344
- schema() {
345
- // moduleOptions gives us the action, etc. but here we need the schema
346
- // which is always type specific, even for pages so get it ourselves
347
- let schema = (apos.modules[this.context.type].schema || []).filter(field => apos.schema.components.fields[field.type]);
348
- // Archive UI is handled via action buttons
349
- schema = schema.filter(field => field.name !== 'archived');
350
- return schema;
351
- }
352
- },
353
- watch: {
354
- doc() {
355
- this.context = this.doc;
356
- }
357
- },
358
- mounted() {
359
- apos.bus.$on('content-changed', this.onContentChanged);
360
- apos.bus.$on('command-menu-admin-bar-discard-draft', this.customDiscardDraft);
361
- },
362
- destroyed() {
363
- apos.bus.$off('content-changed', this.onContentChanged);
364
- apos.bus.$off('command-menu-admin-bar-discard-draft', this.customDiscardDraft);
365
- },
366
- methods: {
367
- customDiscardDraft() {
368
- if (this.showDiscardDraft && this.canDiscardDraft) {
369
- this.menuHandler('discardDraft');
370
- }
371
- },
372
- async onContentChanged(e) {
373
- if (e.doc && (e.doc._id === this.context._id)) {
374
- this.context = e.doc;
375
- } else if (e.docIds && e.docIds.includes(this.context._id)) {
376
- try {
377
- this.context = await apos.http.get(`${this.moduleOptions.action}/${this.context._id}`, {
378
- busy: true
379
- });
380
- } catch (error) {
381
- // If not found it is likely that there was an archiving or restoring
382
- // batch operation.
383
- if (error.name !== 'notfound') {
384
- console.error(error);
385
- }
386
- }
387
- }
388
- },
389
- menuHandler(action) {
390
- const operation = this.customOperations.find(op => op.action === action);
391
- if (operation) {
392
- this.customAction(this.context, operation);
393
- return;
394
- }
395
- this[action](this.context);
396
- },
397
- async edit(doc) {
398
- await apos.modal.execute(doc._aposEditorModal || this.moduleOptions.components.editorModal, {
399
- moduleName: this.moduleName,
400
- docId: doc._id,
401
- type: doc.type
402
- });
403
- },
404
- preview(doc) {
405
- window.open(doc._url, '_blank').focus();
406
- },
407
- async copy(doc) {
408
- // If there are changes warn the user before discarding them before
409
- // the copy operation
410
- if (this.current) {
411
- if (!await this.confirmAndCancel()) {
412
- return;
413
- } else {
414
- this.$emit('close', doc);
415
- }
416
- }
417
-
418
- await apos.modal.execute(doc._aposEditorModal || this.moduleOptions.components.editorModal, {
419
- moduleName: this.moduleName,
420
- copyOfId: doc._id,
421
- // Passed for bc
422
- copyOf: {
423
- ...this.current || doc,
424
- _id: doc._id
425
- },
426
- type: doc.type
427
- });
428
-
429
- },
430
- async customAction(doc, operation) {
431
- await apos.modal.execute(operation.modal, {
432
- moduleName: operation.moduleName,
433
- // For backwards compatibility
434
- doc,
435
- ...docProps(doc),
436
- ...operation.props
437
- });
438
- function docProps(doc) {
439
- return Object.fromEntries(Object.entries(operation.docProps || {}).map(([ key, value ]) => {
440
- return [ key, doc[value] ];
441
- }));
442
- }
443
- },
444
- async localize(doc) {
445
- // If there are changes warn the user before discarding them before
446
- // the localize operation
447
- if (this.current) {
448
- if (!await this.confirmAndCancel()) {
449
- return;
450
- } else {
451
- this.$emit('close', doc);
452
- }
453
- }
454
- apos.bus.$emit('admin-menu-click', {
455
- itemName: '@apostrophecms/i18n:localize',
456
- props: {
457
- doc
458
- }
459
- });
460
- },
461
- close() {
462
- this.$emit('close', this.doc);
463
- }
464
- }
26
+ mixins: [ AposDocContextMenuLogic ],
27
+ // Satisfy linting.
28
+ emits: [ 'menu-open', 'menu-close', 'close' ]
465
29
  };
466
30
  </script>