apostrophe 4.5.3 → 4.6.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 +33 -0
- package/lib/mongodb-connect.js +9 -2
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBar.vue +6 -1
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarLocale.vue +18 -180
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarMenu.vue +6 -2
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBar.vue +1 -1
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +11 -0
- package/modules/@apostrophecms/any-page-type/index.js +6 -1
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +2 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +6 -1
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +63 -11
- package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +12 -15
- package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.config.js +10 -1
- package/modules/@apostrophecms/db/index.js +2 -3
- package/modules/@apostrophecms/doc-type/index.js +7 -1
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +183 -109
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocLocalePicker.vue +177 -0
- package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +4 -0
- package/modules/@apostrophecms/i18n/i18n/de.json +1 -0
- package/modules/@apostrophecms/i18n/i18n/en.json +7 -1
- package/modules/@apostrophecms/i18n/i18n/es.json +1 -0
- package/modules/@apostrophecms/i18n/i18n/fr.json +1 -0
- package/modules/@apostrophecms/i18n/i18n/it.json +1 -0
- package/modules/@apostrophecms/i18n/i18n/pt-BR.json +1 -0
- package/modules/@apostrophecms/i18n/i18n/sk.json +1 -0
- package/modules/@apostrophecms/i18n/index.js +22 -0
- package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +1 -0
- package/modules/@apostrophecms/i18n/ui/src/index.js +3 -0
- package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +1 -0
- package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +22 -30
- package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +24 -1
- package/modules/@apostrophecms/modal/ui/apos/components/TheAposModals.vue +48 -38
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +7 -0
- package/modules/@apostrophecms/page/index.js +5 -3
- package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +1 -0
- package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +17 -3
- package/modules/@apostrophecms/piece-type/index.js +5 -3
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +25 -4
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +1 -1
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapLink.vue +4 -3
- package/modules/@apostrophecms/search/index.js +36 -2
- package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +17 -10
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +36 -23
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +1 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +1 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposLocale.vue +36 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposLocalePicker.vue +283 -0
- package/modules/@apostrophecms/ui/ui/apos/components/AposSlat.vue +56 -18
- package/modules/@apostrophecms/ui/ui/apos/lib/tooltip.js +2 -1
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposArchiveMixin.js +4 -2
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposPublishMixin.js +12 -6
- package/modules/@apostrophecms/ui/ui/apos/stores/modal.js +10 -1
- package/modules/@apostrophecms/util/ui/src/http.js +12 -5
- package/package.json +4 -4
- package/test/search.js +64 -0
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
content: (!disabled && !first) ? 'apostrophe:nudgeUp' : null,
|
|
12
12
|
placement: 'left'
|
|
13
13
|
}"
|
|
14
|
-
:modifiers="[ 'inline' ]"
|
|
15
14
|
@click="$emit('up')"
|
|
16
15
|
/>
|
|
17
16
|
<AposButton
|
|
@@ -22,7 +21,6 @@
|
|
|
22
21
|
content: 'apostrophe:editWidget',
|
|
23
22
|
placement: 'left'
|
|
24
23
|
}"
|
|
25
|
-
:modifiers="[ 'inline' ]"
|
|
26
24
|
@click="$emit('edit')"
|
|
27
25
|
/>
|
|
28
26
|
<AposButton
|
|
@@ -32,7 +30,6 @@
|
|
|
32
30
|
content: 'apostrophe:cut',
|
|
33
31
|
placement: 'left'
|
|
34
32
|
}"
|
|
35
|
-
:modifiers="[ 'inline' ]"
|
|
36
33
|
@click="$emit('cut')"
|
|
37
34
|
/>
|
|
38
35
|
<AposButton
|
|
@@ -52,7 +49,6 @@
|
|
|
52
49
|
content: 'apostrophe:duplicate',
|
|
53
50
|
placement: 'left'
|
|
54
51
|
}"
|
|
55
|
-
:modifiers="[ 'inline' ]"
|
|
56
52
|
@click="$emit('clone')"
|
|
57
53
|
/>
|
|
58
54
|
<AposButton
|
|
@@ -63,7 +59,6 @@
|
|
|
63
59
|
content: 'apostrophe:delete',
|
|
64
60
|
placement: 'left'
|
|
65
61
|
}"
|
|
66
|
-
:modifiers="[ 'inline' ]"
|
|
67
62
|
@click="$emit('remove')"
|
|
68
63
|
/>
|
|
69
64
|
<AposButton
|
|
@@ -74,7 +69,6 @@
|
|
|
74
69
|
content: (!disabled && !last) ? 'apostrophe:nudgeDown' : null,
|
|
75
70
|
placement: 'left'
|
|
76
71
|
}"
|
|
77
|
-
:modifiers="[ 'inline' ]"
|
|
78
72
|
@click="$emit('down')"
|
|
79
73
|
/>
|
|
80
74
|
</AposButtonGroup>
|
|
@@ -110,23 +104,26 @@ export default {
|
|
|
110
104
|
maxReached: {
|
|
111
105
|
type: Boolean,
|
|
112
106
|
default: false
|
|
107
|
+
},
|
|
108
|
+
tabbable: {
|
|
109
|
+
type: Boolean,
|
|
110
|
+
default: false
|
|
113
111
|
}
|
|
114
112
|
},
|
|
115
113
|
emits: [ 'remove', 'edit', 'cut', 'copy', 'clone', 'up', 'down' ],
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
computed: {
|
|
115
|
+
buttonDefaults() {
|
|
116
|
+
return {
|
|
119
117
|
iconOnly: true,
|
|
120
118
|
icon: 'plus-icon',
|
|
121
119
|
type: 'group',
|
|
122
|
-
modifiers: [ 'small' ],
|
|
120
|
+
modifiers: [ 'small', 'inline' ],
|
|
123
121
|
role: 'menuitem',
|
|
124
122
|
class: 'apos-area-modify-controls__button',
|
|
125
|
-
iconSize: 16
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
computed: {
|
|
123
|
+
iconSize: 16,
|
|
124
|
+
disableFocus: !this.tabbable
|
|
125
|
+
};
|
|
126
|
+
},
|
|
130
127
|
upButton() {
|
|
131
128
|
return {
|
|
132
129
|
...this.buttonDefaults,
|
|
@@ -25,6 +25,15 @@ module.exports = ({
|
|
|
25
25
|
|
|
26
26
|
const mode = process.env.NODE_ENV || 'development';
|
|
27
27
|
const pnpmModulePath = apos.isPnpm ? [ path.join(apos.selfDir, '../') ] : [];
|
|
28
|
+
const dev = (mode === 'development');
|
|
29
|
+
// The default behavior of the security-headers module
|
|
30
|
+
// blocks eval, and only eval-source-map currently associates
|
|
31
|
+
// errors with the right file. With regular source-map the
|
|
32
|
+
// results are worse than no source map. A developer who wishes
|
|
33
|
+
// to experiment can set the devSourceMap option of the asset module
|
|
34
|
+
const csp = apos.modules['@apostrophecms/security-headers'];
|
|
35
|
+
const fallbackSourceMap = csp ? false : 'eval-source-map';
|
|
36
|
+
const devtool = dev ? (apos.asset.options.devSourceMap || fallbackSourceMap) : false;
|
|
28
37
|
const config = {
|
|
29
38
|
performance: {
|
|
30
39
|
hints: false
|
|
@@ -36,7 +45,7 @@ module.exports = ({
|
|
|
36
45
|
optimization: {
|
|
37
46
|
minimize: process.env.NODE_ENV === 'production'
|
|
38
47
|
},
|
|
39
|
-
devtool
|
|
48
|
+
devtool,
|
|
40
49
|
output: {
|
|
41
50
|
path: outputPath,
|
|
42
51
|
filename: outputFilename
|
|
@@ -119,9 +119,8 @@ module.exports = {
|
|
|
119
119
|
|
|
120
120
|
self.apos.dbClient = await mongodbConnect(uri, self.options.connect);
|
|
121
121
|
self.uri = uri;
|
|
122
|
-
|
|
123
|
-
self.apos.db = self.apos.dbClient.db(
|
|
124
|
-
|
|
122
|
+
// Automatically uses the db name in the connection string
|
|
123
|
+
self.apos.db = self.apos.dbClient.db();
|
|
125
124
|
},
|
|
126
125
|
async versionCheck() {
|
|
127
126
|
if (!self.options.versionCheck) {
|
|
@@ -759,7 +759,9 @@ module.exports = {
|
|
|
759
759
|
|
|
760
760
|
async convert(req, input, doc, options = {
|
|
761
761
|
presentFieldsOnly: false,
|
|
762
|
-
|
|
762
|
+
type: null,
|
|
763
|
+
copyingId: null,
|
|
764
|
+
createId: null
|
|
763
765
|
}) {
|
|
764
766
|
const fullSchema = self.apos.doc.getManager(options.type || self.name)
|
|
765
767
|
.allowedSchema(req, doc);
|
|
@@ -784,6 +786,10 @@ module.exports = {
|
|
|
784
786
|
|
|
785
787
|
await self.apos.schema.convert(req, schema, input, doc);
|
|
786
788
|
|
|
789
|
+
if (options.createId) {
|
|
790
|
+
doc.aposDocId = options.createId;
|
|
791
|
+
}
|
|
792
|
+
|
|
787
793
|
if (copyOf) {
|
|
788
794
|
if (copyOf._id) {
|
|
789
795
|
doc.copyOfId = copyOf._id;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
class="apos-doc-editor"
|
|
4
4
|
:modal="modal"
|
|
5
5
|
:modal-title="modalTitle"
|
|
6
|
+
:modal-data="modalData"
|
|
6
7
|
@inactive="modal.active = false"
|
|
7
8
|
@show-modal="modal.showModal = true"
|
|
8
9
|
@esc="confirmAndCancel"
|
|
@@ -14,6 +15,15 @@
|
|
|
14
15
|
@click="confirmAndCancel"
|
|
15
16
|
/>
|
|
16
17
|
</template>
|
|
18
|
+
<template v-if="showLocalePicker" #localeDisplay>
|
|
19
|
+
<AposDocLocalePicker
|
|
20
|
+
:locale="modalData.locale"
|
|
21
|
+
:doc-id="referenceDocId"
|
|
22
|
+
:module-options="moduleOptions"
|
|
23
|
+
:is-modified="isModified"
|
|
24
|
+
@switch-locale="switchLocale"
|
|
25
|
+
/>
|
|
26
|
+
</template>
|
|
17
27
|
<template #primaryControls>
|
|
18
28
|
<AposDocContextMenu
|
|
19
29
|
v-if="original"
|
|
@@ -23,6 +33,7 @@
|
|
|
23
33
|
:published="published"
|
|
24
34
|
:show-edit="false"
|
|
25
35
|
:can-delete-draft="moduleOptions.canDeleteDraft"
|
|
36
|
+
:locale-switched="localeSwitched"
|
|
26
37
|
@close="close"
|
|
27
38
|
/>
|
|
28
39
|
<AposButton
|
|
@@ -71,7 +82,7 @@
|
|
|
71
82
|
:utility-rail="false"
|
|
72
83
|
:following-values="followingValues('other')"
|
|
73
84
|
:conditional-fields="conditionalFields"
|
|
74
|
-
:doc-id="
|
|
85
|
+
:doc-id="currentId"
|
|
75
86
|
:model-value="docFields"
|
|
76
87
|
:meta="docMeta"
|
|
77
88
|
:server-errors="serverErrors"
|
|
@@ -97,7 +108,7 @@
|
|
|
97
108
|
:utility-rail="true"
|
|
98
109
|
:following-values="followingUtils"
|
|
99
110
|
:conditional-fields="conditionalFields"
|
|
100
|
-
:doc-id="
|
|
111
|
+
:doc-id="currentId"
|
|
101
112
|
:model-value="docFields"
|
|
102
113
|
:meta="docMeta"
|
|
103
114
|
:modifiers="['small', 'inverted']"
|
|
@@ -114,6 +125,7 @@
|
|
|
114
125
|
|
|
115
126
|
<script>
|
|
116
127
|
import { klona } from 'klona';
|
|
128
|
+
import { mapActions } from 'pinia';
|
|
117
129
|
import AposModifiedMixin from 'Modules/@apostrophecms/ui/mixins/AposModifiedMixin';
|
|
118
130
|
import AposModalTabsMixin from 'Modules/@apostrophecms/modal/mixins/AposModalTabsMixin';
|
|
119
131
|
import AposEditorMixin from 'Modules/@apostrophecms/modal/mixins/AposEditorMixin';
|
|
@@ -122,6 +134,7 @@ import AposArchiveMixin from 'Modules/@apostrophecms/ui/mixins/AposArchiveMixin'
|
|
|
122
134
|
import AposAdvisoryLockMixin from 'Modules/@apostrophecms/ui/mixins/AposAdvisoryLockMixin';
|
|
123
135
|
import AposDocErrorsMixin from 'Modules/@apostrophecms/modal/mixins/AposDocErrorsMixin';
|
|
124
136
|
import { detectDocChange } from 'Modules/@apostrophecms/schema/lib/detectChange';
|
|
137
|
+
import { useModalStore } from 'Modules/@apostrophecms/ui/stores/modal';
|
|
125
138
|
|
|
126
139
|
export default {
|
|
127
140
|
name: 'AposDocEditor',
|
|
@@ -156,6 +169,10 @@ export default {
|
|
|
156
169
|
copyOfId: {
|
|
157
170
|
type: String,
|
|
158
171
|
default: null
|
|
172
|
+
},
|
|
173
|
+
modalData: {
|
|
174
|
+
type: Object,
|
|
175
|
+
required: true
|
|
159
176
|
}
|
|
160
177
|
},
|
|
161
178
|
emits: [ 'modal-result' ],
|
|
@@ -168,7 +185,8 @@ export default {
|
|
|
168
185
|
active: false,
|
|
169
186
|
triggerFocusRefresh: 0,
|
|
170
187
|
type: 'overlay',
|
|
171
|
-
showModal: false
|
|
188
|
+
showModal: false,
|
|
189
|
+
componentType: 'editorModal'
|
|
172
190
|
},
|
|
173
191
|
triggerValidation: false,
|
|
174
192
|
original: null,
|
|
@@ -179,12 +197,15 @@ export default {
|
|
|
179
197
|
readOnly: false,
|
|
180
198
|
restoreOnly: false,
|
|
181
199
|
saveMenu: null,
|
|
182
|
-
generation: 0
|
|
200
|
+
generation: 0,
|
|
201
|
+
localeSwitched: this.modalData.hasContextLocale,
|
|
202
|
+
referenceDocId: this.docId,
|
|
203
|
+
currentId: this.docId
|
|
183
204
|
};
|
|
184
205
|
},
|
|
185
206
|
computed: {
|
|
186
207
|
getOnePath() {
|
|
187
|
-
return `${this.moduleAction}/${this.
|
|
208
|
+
return `${this.moduleAction}/${this.currentId}`;
|
|
188
209
|
},
|
|
189
210
|
followingUtils() {
|
|
190
211
|
return this.followingValues('utility');
|
|
@@ -220,7 +241,7 @@ export default {
|
|
|
220
241
|
// Always block save if there are errors in the modal
|
|
221
242
|
return true;
|
|
222
243
|
}
|
|
223
|
-
if (!this.
|
|
244
|
+
if (!this.currentId) {
|
|
224
245
|
// If it is new you can always save it, even just to insert it with
|
|
225
246
|
// defaults is sometimes useful
|
|
226
247
|
return false;
|
|
@@ -272,17 +293,10 @@ export default {
|
|
|
272
293
|
return this.filterOutParkedFields(fields);
|
|
273
294
|
},
|
|
274
295
|
modalTitle() {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
};
|
|
280
|
-
} else {
|
|
281
|
-
return {
|
|
282
|
-
key: 'apostrophe:newDocType',
|
|
283
|
-
type: this.$t(this.moduleOptions.label)
|
|
284
|
-
};
|
|
285
|
-
}
|
|
296
|
+
return {
|
|
297
|
+
key: this.currentId ? 'apostrophe:editType' : 'apostrophe:newDocType',
|
|
298
|
+
type: this.$t(this.moduleOptions.label)
|
|
299
|
+
};
|
|
286
300
|
},
|
|
287
301
|
saveLabel() {
|
|
288
302
|
if (this.restoreOnly) {
|
|
@@ -330,6 +344,11 @@ export default {
|
|
|
330
344
|
pref = null;
|
|
331
345
|
}
|
|
332
346
|
return pref;
|
|
347
|
+
},
|
|
348
|
+
showLocalePicker() {
|
|
349
|
+
return Object.keys(window.apos.i18n.locales).length > 1 &&
|
|
350
|
+
this.moduleOptions.localized !== false &&
|
|
351
|
+
!this.modalData.hasContextLocale;
|
|
333
352
|
}
|
|
334
353
|
},
|
|
335
354
|
watch: {
|
|
@@ -363,6 +382,21 @@ export default {
|
|
|
363
382
|
type: this.$t(this.moduleOptions.label)
|
|
364
383
|
};
|
|
365
384
|
if (this.docId) {
|
|
385
|
+
await this.instantiateExistingDoc();
|
|
386
|
+
} else if (this.copyOfId) {
|
|
387
|
+
this.instantiateCopiedDoc();
|
|
388
|
+
} else {
|
|
389
|
+
await this.$nextTick();
|
|
390
|
+
await this.instantiateNewDoc();
|
|
391
|
+
}
|
|
392
|
+
apos.bus.$on('content-changed', this.onContentChanged);
|
|
393
|
+
},
|
|
394
|
+
unmounted() {
|
|
395
|
+
apos.bus.$off('content-changed', this.onContentChanged);
|
|
396
|
+
},
|
|
397
|
+
methods: {
|
|
398
|
+
...mapActions(useModalStore, [ 'updateModalData' ]),
|
|
399
|
+
async instantiateExistingDoc() {
|
|
366
400
|
await this.loadDoc();
|
|
367
401
|
this.evaluateConditions();
|
|
368
402
|
try {
|
|
@@ -386,7 +420,8 @@ export default {
|
|
|
386
420
|
}
|
|
387
421
|
}
|
|
388
422
|
this.modal.triggerFocusRefresh++;
|
|
389
|
-
}
|
|
423
|
+
},
|
|
424
|
+
async instantiateCopiedDoc() {
|
|
390
425
|
this.evaluateConditions();
|
|
391
426
|
|
|
392
427
|
// Because the page or piece manager might give us just a projected,
|
|
@@ -419,37 +454,44 @@ export default {
|
|
|
419
454
|
this.prepErrors();
|
|
420
455
|
this.docReady = true;
|
|
421
456
|
this.modal.triggerFocusRefresh++;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
457
|
+
},
|
|
458
|
+
async instantiateNewDoc () {
|
|
459
|
+
this.docReady = false;
|
|
460
|
+
const newInstance = await this.getNewInstance();
|
|
461
|
+
this.original = newInstance;
|
|
462
|
+
if (newInstance && newInstance.type !== this.docType) {
|
|
463
|
+
this.docType = newInstance.type;
|
|
464
|
+
}
|
|
465
|
+
this.docFields.data = newInstance;
|
|
466
|
+
const slugField = this.schema.find(field => field.name === 'slug');
|
|
467
|
+
if (slugField) {
|
|
468
|
+
// As a matter of UI implementation, we know our slug input field will
|
|
469
|
+
// automatically change the empty string to the prefix, so to
|
|
470
|
+
// prevent a false positive for this being considered a change,
|
|
471
|
+
// do it earlier when creating a new doc.
|
|
472
|
+
this.original.slug = this.original.slug || slugField.def || slugField.prefix || '';
|
|
473
|
+
}
|
|
474
|
+
this.prepErrors();
|
|
475
|
+
this.docReady = true;
|
|
476
|
+
this.evaluateConditions();
|
|
477
|
+
},
|
|
478
|
+
async saveHandler(action, saveOpts = {}) {
|
|
436
479
|
this.triggerValidation = true;
|
|
437
|
-
this.$nextTick(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
});
|
|
480
|
+
await this.$nextTick();
|
|
481
|
+
if (this.savePreference !== action) {
|
|
482
|
+
this.setSavePreference(action);
|
|
483
|
+
}
|
|
484
|
+
if (!this.errorCount) {
|
|
485
|
+
return this[action](saveOpts);
|
|
486
|
+
} else {
|
|
487
|
+
this.triggerValidation = false;
|
|
488
|
+
await apos.notify('apostrophe:resolveErrorsBeforeSaving', {
|
|
489
|
+
type: 'warning',
|
|
490
|
+
icon: 'alert-circle-icon',
|
|
491
|
+
dismiss: true
|
|
492
|
+
});
|
|
493
|
+
this.focusNextError();
|
|
494
|
+
}
|
|
453
495
|
},
|
|
454
496
|
async loadDoc() {
|
|
455
497
|
let docData;
|
|
@@ -469,7 +511,7 @@ export default {
|
|
|
469
511
|
}
|
|
470
512
|
const canEdit = docData._edit || this.moduleOptions.canEdit;
|
|
471
513
|
this.readOnly = canEdit === false;
|
|
472
|
-
if (canEdit && !await this.lock(this.getOnePath, this.
|
|
514
|
+
if (canEdit && !await this.lock(this.getOnePath, this.currentId)) {
|
|
473
515
|
this.lockNotAvailable();
|
|
474
516
|
return;
|
|
475
517
|
}
|
|
@@ -490,8 +532,14 @@ export default {
|
|
|
490
532
|
...this.getDefault(),
|
|
491
533
|
...docData
|
|
492
534
|
};
|
|
535
|
+
// TODO: Is this block even useful since published is fetched after loadDoc?
|
|
493
536
|
if (this.published) {
|
|
494
|
-
this.changed = detectDocChange(
|
|
537
|
+
this.changed = detectDocChange(
|
|
538
|
+
this.schema,
|
|
539
|
+
this.original,
|
|
540
|
+
this.published,
|
|
541
|
+
{ differences: true }
|
|
542
|
+
);
|
|
495
543
|
}
|
|
496
544
|
this.docReady = true;
|
|
497
545
|
this.prepErrors();
|
|
@@ -527,17 +575,21 @@ export default {
|
|
|
527
575
|
await this.restore(this.original);
|
|
528
576
|
await this.loadDoc();
|
|
529
577
|
},
|
|
530
|
-
async onSave({
|
|
578
|
+
async onSave({
|
|
579
|
+
navigate = false, keepOpen = false, andPublish = null
|
|
580
|
+
} = {}) {
|
|
531
581
|
if (this.canPublish || !this.manuallyPublished) {
|
|
532
|
-
|
|
533
|
-
andPublish: this.manuallyPublished,
|
|
534
|
-
navigate
|
|
582
|
+
return this.save({
|
|
583
|
+
andPublish: andPublish ?? this.manuallyPublished,
|
|
584
|
+
navigate,
|
|
585
|
+
keepOpen
|
|
535
586
|
});
|
|
536
587
|
} else {
|
|
537
|
-
|
|
588
|
+
return this.save({
|
|
538
589
|
andPublish: false,
|
|
539
590
|
andSubmit: true,
|
|
540
|
-
navigate
|
|
591
|
+
navigate,
|
|
592
|
+
keepOpen
|
|
541
593
|
});
|
|
542
594
|
}
|
|
543
595
|
},
|
|
@@ -555,7 +607,7 @@ export default {
|
|
|
555
607
|
async onSaveDraftAndView() {
|
|
556
608
|
await this.onSaveDraft({ navigate: true });
|
|
557
609
|
},
|
|
558
|
-
async onSaveDraft(navigate = false) {
|
|
610
|
+
async onSaveDraft({ navigate = false } = {}) {
|
|
559
611
|
await this.save({
|
|
560
612
|
andPublish: false,
|
|
561
613
|
navigate
|
|
@@ -566,32 +618,22 @@ export default {
|
|
|
566
618
|
icon: 'file-document-icon'
|
|
567
619
|
});
|
|
568
620
|
},
|
|
569
|
-
// If andPublish is true, publish after saving.
|
|
570
621
|
async save({
|
|
571
622
|
andPublish = false,
|
|
572
623
|
navigate = false,
|
|
573
|
-
andSubmit = false
|
|
624
|
+
andSubmit = false,
|
|
625
|
+
keepOpen = false
|
|
574
626
|
}) {
|
|
575
|
-
const body = this.
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
requestMethod = apos.http.put;
|
|
581
|
-
this.addLockToRequest(body);
|
|
582
|
-
} else {
|
|
583
|
-
route = this.moduleAction;
|
|
584
|
-
requestMethod = apos.http.post;
|
|
627
|
+
const body = this.getRequestBody({ update: Boolean(this.currentId) });
|
|
628
|
+
const route = this.currentId
|
|
629
|
+
? `${this.moduleAction}/${this.currentId}`
|
|
630
|
+
: this.moduleAction;
|
|
631
|
+
const requestMethod = this.currentId ? apos.http.put : apos.http.post;
|
|
585
632
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
body._targetId = apos.page.page._id.replace(':published', ':draft');
|
|
589
|
-
body._position = 'lastChild';
|
|
590
|
-
}
|
|
591
|
-
if (this.copyOfId) {
|
|
592
|
-
body._copyingId = this.copyOfId;
|
|
593
|
-
}
|
|
633
|
+
if (this.currentId) {
|
|
634
|
+
this.addLockToRequest(body);
|
|
594
635
|
}
|
|
636
|
+
|
|
595
637
|
let doc;
|
|
596
638
|
try {
|
|
597
639
|
await this.postprocess();
|
|
@@ -607,7 +649,8 @@ export default {
|
|
|
607
649
|
}
|
|
608
650
|
apos.bus.$emit('content-changed', {
|
|
609
651
|
doc,
|
|
610
|
-
action: (requestMethod === apos.http.put) ? 'update' : 'insert'
|
|
652
|
+
action: (requestMethod === apos.http.put) ? 'update' : 'insert',
|
|
653
|
+
localeSwitched: this.localeSwitched
|
|
611
654
|
});
|
|
612
655
|
} catch (e) {
|
|
613
656
|
if (this.isLockedError(e)) {
|
|
@@ -621,8 +664,10 @@ export default {
|
|
|
621
664
|
return;
|
|
622
665
|
}
|
|
623
666
|
}
|
|
624
|
-
|
|
625
|
-
|
|
667
|
+
if (!keepOpen) {
|
|
668
|
+
this.$emit('modal-result', doc);
|
|
669
|
+
this.modal.showModal = false;
|
|
670
|
+
}
|
|
626
671
|
if (navigate) {
|
|
627
672
|
if (doc._url) {
|
|
628
673
|
window.location = doc._url;
|
|
@@ -633,18 +678,11 @@ export default {
|
|
|
633
678
|
});
|
|
634
679
|
}
|
|
635
680
|
}
|
|
681
|
+
return doc;
|
|
636
682
|
},
|
|
637
683
|
async getNewInstance() {
|
|
638
684
|
try {
|
|
639
|
-
const body = {
|
|
640
|
-
_newInstance: true
|
|
641
|
-
};
|
|
642
|
-
|
|
643
|
-
if (this.moduleName === '@apostrophecms/page') {
|
|
644
|
-
// New pages are always born as drafts
|
|
645
|
-
body._targetId = apos.page.page._id.replace(':published', ':draft');
|
|
646
|
-
body._position = 'lastChild';
|
|
647
|
-
}
|
|
685
|
+
const body = this.getRequestBody({ newInstance: true });
|
|
648
686
|
const newDoc = await apos.http.post(this.moduleAction, {
|
|
649
687
|
body,
|
|
650
688
|
draft: true
|
|
@@ -662,25 +700,6 @@ export default {
|
|
|
662
700
|
this.modal.showModal = false;
|
|
663
701
|
}
|
|
664
702
|
},
|
|
665
|
-
async loadNewInstance () {
|
|
666
|
-
this.docReady = false;
|
|
667
|
-
const newInstance = await this.getNewInstance();
|
|
668
|
-
this.original = newInstance;
|
|
669
|
-
if (newInstance && newInstance.type !== this.docType) {
|
|
670
|
-
this.docType = newInstance.type;
|
|
671
|
-
}
|
|
672
|
-
this.docFields.data = newInstance;
|
|
673
|
-
const slugField = this.schema.find(field => field.name === 'slug');
|
|
674
|
-
if (slugField) {
|
|
675
|
-
// As a matter of UI implementation, we know our slug input field will
|
|
676
|
-
// automatically change the empty string to the prefix, so to
|
|
677
|
-
// prevent a false positive for this being considered a change,
|
|
678
|
-
// do it earlier when creating a new doc.
|
|
679
|
-
this.original.slug = this.original.slug || slugField.def || slugField.prefix || '';
|
|
680
|
-
}
|
|
681
|
-
this.prepErrors();
|
|
682
|
-
this.docReady = true;
|
|
683
|
-
},
|
|
684
703
|
startNew() {
|
|
685
704
|
this.modal.showModal = false;
|
|
686
705
|
apos.bus.$emit('admin-menu-click', {
|
|
@@ -719,7 +738,7 @@ export default {
|
|
|
719
738
|
const typeLabel = this.$t(this.moduleOptions
|
|
720
739
|
? this.moduleOptions.label
|
|
721
740
|
: 'document');
|
|
722
|
-
const isNew = !this.
|
|
741
|
+
const isNew = !this.currentId;
|
|
723
742
|
// this.original takes a moment to populate, don't crash
|
|
724
743
|
const canPreview = this.original && (this.original._id ? this.original._url : this.original._previewable);
|
|
725
744
|
const canNew = this.moduleOptions.showCreate;
|
|
@@ -823,6 +842,61 @@ export default {
|
|
|
823
842
|
},
|
|
824
843
|
close() {
|
|
825
844
|
this.modal.showModal = false;
|
|
845
|
+
},
|
|
846
|
+
async switchLocale({
|
|
847
|
+
locale, localized, save
|
|
848
|
+
}) {
|
|
849
|
+
if (save) {
|
|
850
|
+
const saved = await this.saveHandler('onSave', {
|
|
851
|
+
keepOpen: true,
|
|
852
|
+
andPublish: false
|
|
853
|
+
});
|
|
854
|
+
if (this.errorCount > 0) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
if (!this.referenceDocId && saved) {
|
|
858
|
+
this.referenceDocId = saved._id;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
this.updateModalData(this.modalData.id, { locale });
|
|
862
|
+
this.localeSwitched = locale !== apos.i18n.locale;
|
|
863
|
+
this.published = null;
|
|
864
|
+
if (localized) {
|
|
865
|
+
this.currentId = localized._id;
|
|
866
|
+
await this.instantiateExistingDoc();
|
|
867
|
+
} else {
|
|
868
|
+
this.currentId = '';
|
|
869
|
+
this.docType = this.moduleName;
|
|
870
|
+
await this.instantiateNewDoc();
|
|
871
|
+
}
|
|
872
|
+
},
|
|
873
|
+
getRequestBody({ newInstance = false, update = false }) {
|
|
874
|
+
const body = newInstance
|
|
875
|
+
? { _newInstance: true }
|
|
876
|
+
: this.docFields.data;
|
|
877
|
+
|
|
878
|
+
if (update) {
|
|
879
|
+
return body;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
if (this.moduleName === '@apostrophecms/page') {
|
|
883
|
+
// New pages are always born as drafts
|
|
884
|
+
// When in another locale we don't know if the current page exist
|
|
885
|
+
body._targetId = this.localeSwitched
|
|
886
|
+
? '_home'
|
|
887
|
+
: apos.page.page._id.replace(':published', ':draft');
|
|
888
|
+
body._position = 'lastChild';
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
if (!newInstance) {
|
|
892
|
+
if (this.copyOfId) {
|
|
893
|
+
body._copyingId = this.copyOfId;
|
|
894
|
+
} else if (this.localeSwitched && this.referenceDocId) {
|
|
895
|
+
body._createId = this.referenceDocId.split(':')[0];
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
return body;
|
|
826
900
|
}
|
|
827
901
|
}
|
|
828
902
|
};
|