@strapi/content-releases 0.0.0-next.37dd1e3ff22e1635b69683abadd444912ae0dbff → 0.0.0-next.6a58621932ad3d83bf9d6928c1871e7906adcd59
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/dist/_chunks/{App-J4jrthEu.mjs → App-L1jSxCiL.mjs} +81 -16
- package/dist/_chunks/App-L1jSxCiL.mjs.map +1 -0
- package/dist/_chunks/{App-5PRKHpa2.js → App-_20W9dYa.js} +79 -14
- package/dist/_chunks/App-_20W9dYa.js.map +1 -0
- package/dist/_chunks/{en-ngTk74JV.mjs → en-MyLPoISH.mjs} +2 -1
- package/dist/_chunks/en-MyLPoISH.mjs.map +1 -0
- package/dist/_chunks/{en-haKSQIo8.js → en-gYDqKYFd.js} +2 -1
- package/dist/_chunks/en-gYDqKYFd.js.map +1 -0
- package/dist/_chunks/{index-PEkKIRyJ.js → index-KJa1Rb5F.js} +91 -32
- package/dist/_chunks/index-KJa1Rb5F.js.map +1 -0
- package/dist/_chunks/{index-_Zsj8MUA.mjs → index-c4zRX_sg.mjs} +102 -43
- package/dist/_chunks/index-c4zRX_sg.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +3 -2
- package/dist/admin/index.mjs.map +1 -1
- package/dist/server/index.js +236 -128
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +236 -129
- package/dist/server/index.mjs.map +1 -1
- package/package.json +10 -9
- package/dist/_chunks/App-5PRKHpa2.js.map +0 -1
- package/dist/_chunks/App-J4jrthEu.mjs.map +0 -1
- package/dist/_chunks/en-haKSQIo8.js.map +0 -1
- package/dist/_chunks/en-ngTk74JV.mjs.map +0 -1
- package/dist/_chunks/index-PEkKIRyJ.js.map +0 -1
- package/dist/_chunks/index-_Zsj8MUA.mjs.map +0 -1
package/dist/server/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
|
|
1
|
+
import { contentTypes as contentTypes$1, mapAsync, setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
|
|
2
|
+
import { difference, keys } from "lodash";
|
|
2
3
|
import _ from "lodash/fp";
|
|
4
|
+
import EE from "@strapi/strapi/dist/utils/ee";
|
|
3
5
|
import * as yup from "yup";
|
|
4
6
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
5
7
|
const RELEASE_ACTION_MODEL_UID = "plugin::content-releases.release-action";
|
|
@@ -47,40 +49,47 @@ const ACTIONS = [
|
|
|
47
49
|
pluginName: "content-releases"
|
|
48
50
|
}
|
|
49
51
|
];
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
async function deleteActionsOnDisableDraftAndPublish({
|
|
53
|
+
oldContentTypes,
|
|
54
|
+
contentTypes: contentTypes2
|
|
55
|
+
}) {
|
|
56
|
+
if (!oldContentTypes) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const uid in contentTypes2) {
|
|
60
|
+
if (!oldContentTypes[uid]) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const oldContentType = oldContentTypes[uid];
|
|
64
|
+
const contentType = contentTypes2[uid];
|
|
65
|
+
if (contentTypes$1.hasDraftAndPublish(oldContentType) && !contentTypes$1.hasDraftAndPublish(contentType)) {
|
|
66
|
+
await strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: uid }).execute();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
71
|
+
const deletedContentTypes = difference(keys(oldContentTypes), keys(contentTypes2)) ?? [];
|
|
72
|
+
if (deletedContentTypes.length) {
|
|
73
|
+
await mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
74
|
+
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
53
78
|
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
54
79
|
const register = async ({ strapi: strapi2 }) => {
|
|
55
|
-
if (features$2.isEnabled("cms-content-releases")
|
|
80
|
+
if (features$2.isEnabled("cms-content-releases")) {
|
|
56
81
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const destroyContentTypeUpdateListener = strapi2.eventHub.on(
|
|
60
|
-
"content-type.update",
|
|
61
|
-
async ({ contentType }) => {
|
|
62
|
-
if (contentType.schema.options.draftAndPublish === false) {
|
|
63
|
-
await releaseActionService.deleteManyForContentType(contentType.uid);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
);
|
|
67
|
-
eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);
|
|
68
|
-
const destroyContentTypeDeleteListener = strapi2.eventHub.on(
|
|
69
|
-
"content-type.delete",
|
|
70
|
-
async ({ contentType }) => {
|
|
71
|
-
await releaseActionService.deleteManyForContentType(contentType.uid);
|
|
72
|
-
}
|
|
73
|
-
);
|
|
74
|
-
eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);
|
|
82
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish);
|
|
83
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType);
|
|
75
84
|
}
|
|
76
85
|
};
|
|
77
86
|
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
78
87
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
79
|
-
if (features$1.isEnabled("cms-content-releases")
|
|
88
|
+
if (features$1.isEnabled("cms-content-releases")) {
|
|
80
89
|
strapi2.db.lifecycles.subscribe({
|
|
81
90
|
afterDelete(event) {
|
|
82
91
|
const { model, result } = event;
|
|
83
|
-
if (model.kind === "collectionType" && model.options
|
|
92
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
84
93
|
const { id } = result;
|
|
85
94
|
strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
86
95
|
where: {
|
|
@@ -96,7 +105,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
96
105
|
*/
|
|
97
106
|
async beforeDeleteMany(event) {
|
|
98
107
|
const { model, params } = event;
|
|
99
|
-
if (model.kind === "collectionType" && model.options
|
|
108
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
100
109
|
const { where } = params;
|
|
101
110
|
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
102
111
|
event.state.entriesToDelete = entriesToDelete;
|
|
@@ -211,30 +220,32 @@ const contentTypes = {
|
|
|
211
220
|
release: release$1,
|
|
212
221
|
"release-action": releaseAction$1
|
|
213
222
|
};
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
where: {
|
|
218
|
-
target_type: contentTypeUid
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
+
const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
224
|
+
return strapi2.plugin("content-releases").service(name);
|
|
225
|
+
};
|
|
223
226
|
const getGroupName = (queryValue) => {
|
|
224
227
|
switch (queryValue) {
|
|
225
228
|
case "contentType":
|
|
226
|
-
return "
|
|
229
|
+
return "contentType.displayName";
|
|
227
230
|
case "action":
|
|
228
231
|
return "type";
|
|
229
232
|
case "locale":
|
|
230
|
-
return _.getOr("No locale", "
|
|
233
|
+
return _.getOr("No locale", "locale.name");
|
|
231
234
|
default:
|
|
232
|
-
return "
|
|
235
|
+
return "contentType.displayName";
|
|
233
236
|
}
|
|
234
237
|
};
|
|
235
238
|
const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
236
239
|
async create(releaseData, { user }) {
|
|
237
240
|
const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);
|
|
241
|
+
const { validatePendingReleasesLimit, validateUniqueNameForPendingRelease } = getService(
|
|
242
|
+
"release-validation",
|
|
243
|
+
{ strapi: strapi2 }
|
|
244
|
+
);
|
|
245
|
+
await Promise.all([
|
|
246
|
+
validatePendingReleasesLimit(),
|
|
247
|
+
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name)
|
|
248
|
+
]);
|
|
238
249
|
return strapi2.entityService.create(RELEASE_MODEL_UID, {
|
|
239
250
|
data: releaseWithCreatorFields
|
|
240
251
|
});
|
|
@@ -256,51 +267,66 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
256
267
|
}
|
|
257
268
|
});
|
|
258
269
|
},
|
|
259
|
-
async
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
// Find all Releases where the content type entry is present
|
|
266
|
-
actions: {
|
|
267
|
-
target_type: contentTypeUid,
|
|
268
|
-
target_id: entryId
|
|
269
|
-
}
|
|
270
|
-
} : {
|
|
271
|
-
// Find all Releases where the content type entry is not present
|
|
272
|
-
$or: [
|
|
273
|
-
{
|
|
274
|
-
$not: {
|
|
275
|
-
actions: {
|
|
276
|
-
target_type: contentTypeUid,
|
|
277
|
-
target_id: entryId
|
|
278
|
-
}
|
|
279
|
-
}
|
|
270
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
271
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
272
|
+
where: {
|
|
273
|
+
actions: {
|
|
274
|
+
target_type: contentTypeUid,
|
|
275
|
+
target_id: entryId
|
|
280
276
|
},
|
|
281
|
-
{
|
|
282
|
-
|
|
277
|
+
releasedAt: {
|
|
278
|
+
$null: true
|
|
283
279
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
280
|
+
},
|
|
281
|
+
populate: {
|
|
282
|
+
// Filter the action to get only the content type entry
|
|
283
|
+
actions: {
|
|
284
|
+
where: {
|
|
285
|
+
target_type: contentTypeUid,
|
|
286
|
+
target_id: entryId
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
return releases.map((release2) => {
|
|
292
|
+
if (release2.actions?.length) {
|
|
293
|
+
const [actionForEntry] = release2.actions;
|
|
294
|
+
delete release2.actions;
|
|
295
|
+
return {
|
|
296
|
+
...release2,
|
|
297
|
+
action: actionForEntry
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
return release2;
|
|
301
|
+
});
|
|
302
|
+
},
|
|
303
|
+
async findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
304
|
+
const releasesRelated = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
305
|
+
where: {
|
|
306
|
+
releasedAt: {
|
|
307
|
+
$null: true
|
|
308
|
+
},
|
|
309
|
+
actions: {
|
|
290
310
|
target_type: contentTypeUid,
|
|
291
311
|
target_id: entryId
|
|
292
312
|
}
|
|
293
313
|
}
|
|
294
|
-
}
|
|
314
|
+
});
|
|
295
315
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
296
316
|
where: {
|
|
297
|
-
|
|
317
|
+
$or: [
|
|
318
|
+
{
|
|
319
|
+
id: {
|
|
320
|
+
$notIn: releasesRelated.map((release2) => release2.id)
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
actions: null
|
|
325
|
+
}
|
|
326
|
+
],
|
|
298
327
|
releasedAt: {
|
|
299
328
|
$null: true
|
|
300
329
|
}
|
|
301
|
-
},
|
|
302
|
-
populate: {
|
|
303
|
-
...populateAttachedAction
|
|
304
330
|
}
|
|
305
331
|
});
|
|
306
332
|
return releases.map((release2) => {
|
|
@@ -375,7 +401,9 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
375
401
|
return strapi2.entityService.findPage(RELEASE_ACTION_MODEL_UID, {
|
|
376
402
|
...query,
|
|
377
403
|
populate: {
|
|
378
|
-
entry:
|
|
404
|
+
entry: {
|
|
405
|
+
populate: "*"
|
|
406
|
+
}
|
|
379
407
|
},
|
|
380
408
|
filters: {
|
|
381
409
|
release: releaseId
|
|
@@ -395,29 +423,32 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
395
423
|
const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
|
|
396
424
|
contentTypeUids
|
|
397
425
|
);
|
|
398
|
-
const
|
|
399
|
-
const allLocalesDictionary = allLocales.reduce((acc, locale) => {
|
|
400
|
-
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
401
|
-
return acc;
|
|
402
|
-
}, {});
|
|
426
|
+
const allLocalesDictionary = await this.getLocalesDataForActions();
|
|
403
427
|
const formattedData = actions.map((action) => {
|
|
404
428
|
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
405
429
|
return {
|
|
406
430
|
...action,
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
},
|
|
413
|
-
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
414
|
-
status: action.entry.publishedAt ? "published" : "draft"
|
|
431
|
+
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
432
|
+
contentType: {
|
|
433
|
+
displayName,
|
|
434
|
+
mainFieldValue: action.entry[mainField],
|
|
435
|
+
uid: action.contentType
|
|
415
436
|
}
|
|
416
437
|
};
|
|
417
438
|
});
|
|
418
439
|
const groupName = getGroupName(groupBy);
|
|
419
440
|
return _.groupBy(groupName)(formattedData);
|
|
420
441
|
},
|
|
442
|
+
async getLocalesDataForActions() {
|
|
443
|
+
if (!strapi2.plugin("i18n")) {
|
|
444
|
+
return {};
|
|
445
|
+
}
|
|
446
|
+
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
447
|
+
return allLocales.reduce((acc, locale) => {
|
|
448
|
+
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
449
|
+
return acc;
|
|
450
|
+
}, {});
|
|
451
|
+
},
|
|
421
452
|
async getContentTypesDataForActions(contentTypesUids) {
|
|
422
453
|
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
423
454
|
const contentTypesData = {};
|
|
@@ -432,6 +463,34 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
432
463
|
}
|
|
433
464
|
return contentTypesData;
|
|
434
465
|
},
|
|
466
|
+
getContentTypeModelsFromActions(actions) {
|
|
467
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
468
|
+
if (!acc.includes(action.contentType)) {
|
|
469
|
+
acc.push(action.contentType);
|
|
470
|
+
}
|
|
471
|
+
return acc;
|
|
472
|
+
}, []);
|
|
473
|
+
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
474
|
+
(acc, contentTypeUid) => {
|
|
475
|
+
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
476
|
+
return acc;
|
|
477
|
+
},
|
|
478
|
+
{}
|
|
479
|
+
);
|
|
480
|
+
return contentTypeModelsMap;
|
|
481
|
+
},
|
|
482
|
+
async getAllComponents() {
|
|
483
|
+
const contentManagerComponentsService = strapi2.plugin("content-manager").service("components");
|
|
484
|
+
const components = await contentManagerComponentsService.findAllComponents();
|
|
485
|
+
const componentsMap = components.reduce(
|
|
486
|
+
(acc, component) => {
|
|
487
|
+
acc[component.uid] = component;
|
|
488
|
+
return acc;
|
|
489
|
+
},
|
|
490
|
+
{}
|
|
491
|
+
);
|
|
492
|
+
return componentsMap;
|
|
493
|
+
},
|
|
435
494
|
async delete(releaseId) {
|
|
436
495
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
437
496
|
populate: {
|
|
@@ -466,7 +525,9 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
466
525
|
populate: {
|
|
467
526
|
actions: {
|
|
468
527
|
populate: {
|
|
469
|
-
entry:
|
|
528
|
+
entry: {
|
|
529
|
+
fields: ["id"]
|
|
530
|
+
}
|
|
470
531
|
}
|
|
471
532
|
}
|
|
472
533
|
}
|
|
@@ -486,25 +547,49 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
486
547
|
const contentTypeUid = action.contentType;
|
|
487
548
|
if (!actions[contentTypeUid]) {
|
|
488
549
|
actions[contentTypeUid] = {
|
|
489
|
-
|
|
490
|
-
|
|
550
|
+
entriestoPublishIds: [],
|
|
551
|
+
entriesToUnpublishIds: []
|
|
491
552
|
};
|
|
492
553
|
}
|
|
493
554
|
if (action.type === "publish") {
|
|
494
|
-
actions[contentTypeUid].
|
|
555
|
+
actions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
495
556
|
} else {
|
|
496
|
-
actions[contentTypeUid].
|
|
557
|
+
actions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
497
558
|
}
|
|
498
559
|
}
|
|
499
560
|
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
561
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
500
562
|
await strapi2.db.transaction(async () => {
|
|
501
563
|
for (const contentTypeUid of Object.keys(actions)) {
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
564
|
+
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
565
|
+
const { entriestoPublishIds, entriesToUnpublishIds } = actions[contentTypeUid];
|
|
566
|
+
const entriesToPublish = await strapi2.entityService.findMany(
|
|
567
|
+
contentTypeUid,
|
|
568
|
+
{
|
|
569
|
+
filters: {
|
|
570
|
+
id: {
|
|
571
|
+
$in: entriestoPublishIds
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
populate
|
|
575
|
+
}
|
|
576
|
+
);
|
|
577
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
578
|
+
contentTypeUid,
|
|
579
|
+
{
|
|
580
|
+
filters: {
|
|
581
|
+
id: {
|
|
582
|
+
$in: entriesToUnpublishIds
|
|
583
|
+
}
|
|
584
|
+
},
|
|
585
|
+
populate
|
|
586
|
+
}
|
|
587
|
+
);
|
|
588
|
+
if (entriesToPublish.length > 0) {
|
|
589
|
+
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
505
590
|
}
|
|
506
|
-
if (
|
|
507
|
-
await entityManagerService.unpublishMany(
|
|
591
|
+
if (entriesToUnpublish.length > 0) {
|
|
592
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, contentTypeUid);
|
|
508
593
|
}
|
|
509
594
|
}
|
|
510
595
|
});
|
|
@@ -586,31 +671,41 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
586
671
|
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
|
587
672
|
);
|
|
588
673
|
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
if (!state.destroyListenerCallbacks.length) {
|
|
601
|
-
return;
|
|
674
|
+
},
|
|
675
|
+
async validatePendingReleasesLimit() {
|
|
676
|
+
const maximumPendingReleases = (
|
|
677
|
+
// @ts-expect-error - options is not typed into features
|
|
678
|
+
EE.features.get("cms-content-releases")?.options?.maximumReleases || 3
|
|
679
|
+
);
|
|
680
|
+
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
681
|
+
filters: {
|
|
682
|
+
releasedAt: {
|
|
683
|
+
$null: true
|
|
684
|
+
}
|
|
602
685
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
686
|
+
});
|
|
687
|
+
if (pendingReleasesCount >= maximumPendingReleases) {
|
|
688
|
+
throw new errors.ValidationError("You have reached the maximum number of pending releases");
|
|
606
689
|
}
|
|
607
|
-
}
|
|
608
|
-
|
|
690
|
+
},
|
|
691
|
+
async validateUniqueNameForPendingRelease(name) {
|
|
692
|
+
const pendingReleases = await strapi2.entityService.findMany(RELEASE_MODEL_UID, {
|
|
693
|
+
filters: {
|
|
694
|
+
releasedAt: {
|
|
695
|
+
$null: true
|
|
696
|
+
},
|
|
697
|
+
name
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
const isNameUnique = pendingReleases.length === 0;
|
|
701
|
+
if (!isNameUnique) {
|
|
702
|
+
throw new errors.ValidationError(`Release with name ${name} already exists`);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
});
|
|
609
706
|
const services = {
|
|
610
707
|
release: createReleaseService,
|
|
611
|
-
"release-
|
|
612
|
-
"release-validation": createReleaseValidationService,
|
|
613
|
-
"event-manager": createEventManagerService
|
|
708
|
+
"release-validation": createReleaseValidationService
|
|
614
709
|
};
|
|
615
710
|
const RELEASE_SCHEMA = yup.object().shape({
|
|
616
711
|
name: yup.string().trim().required()
|
|
@@ -630,9 +725,7 @@ const releaseController = {
|
|
|
630
725
|
const contentTypeUid = query.contentTypeUid;
|
|
631
726
|
const entryId = query.entryId;
|
|
632
727
|
const hasEntryAttached = typeof query.hasEntryAttached === "string" ? JSON.parse(query.hasEntryAttached) : false;
|
|
633
|
-
const data = await releaseService.
|
|
634
|
-
hasEntryAttached
|
|
635
|
-
});
|
|
728
|
+
const data = hasEntryAttached ? await releaseService.findManyWithContentTypeEntryAttached(contentTypeUid, entryId) : await releaseService.findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId);
|
|
636
729
|
ctx.body = { data };
|
|
637
730
|
} else {
|
|
638
731
|
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
@@ -760,11 +853,30 @@ const releaseActionController = {
|
|
|
760
853
|
sort: query.groupBy === "action" ? "type" : query.groupBy,
|
|
761
854
|
...query
|
|
762
855
|
});
|
|
763
|
-
const
|
|
856
|
+
const contentTypeOutputSanitizers = results.reduce((acc, action) => {
|
|
857
|
+
if (acc[action.contentType]) {
|
|
858
|
+
return acc;
|
|
859
|
+
}
|
|
860
|
+
const contentTypePermissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
861
|
+
ability: ctx.state.userAbility,
|
|
862
|
+
model: action.contentType
|
|
863
|
+
});
|
|
864
|
+
acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
|
|
865
|
+
return acc;
|
|
866
|
+
}, {});
|
|
867
|
+
const sanitizedResults = await mapAsync(results, async (action) => ({
|
|
868
|
+
...action,
|
|
869
|
+
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
870
|
+
}));
|
|
871
|
+
const groupedData = await releaseService.groupActions(sanitizedResults, query.groupBy);
|
|
872
|
+
const contentTypes2 = releaseService.getContentTypeModelsFromActions(results);
|
|
873
|
+
const components = await releaseService.getAllComponents();
|
|
764
874
|
ctx.body = {
|
|
765
875
|
data: groupedData,
|
|
766
876
|
meta: {
|
|
767
|
-
pagination
|
|
877
|
+
pagination,
|
|
878
|
+
contentTypes: contentTypes2,
|
|
879
|
+
components
|
|
768
880
|
}
|
|
769
881
|
};
|
|
770
882
|
},
|
|
@@ -970,19 +1082,14 @@ const routes = {
|
|
|
970
1082
|
};
|
|
971
1083
|
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
972
1084
|
const getPlugin = () => {
|
|
973
|
-
if (features.isEnabled("cms-content-releases")
|
|
1085
|
+
if (features.isEnabled("cms-content-releases")) {
|
|
974
1086
|
return {
|
|
975
1087
|
register,
|
|
976
1088
|
bootstrap,
|
|
977
1089
|
contentTypes,
|
|
978
1090
|
services,
|
|
979
1091
|
controllers,
|
|
980
|
-
routes
|
|
981
|
-
destroy() {
|
|
982
|
-
if (features.isEnabled("cms-content-releases") && strapi.features.future.isEnabled("contentReleases")) {
|
|
983
|
-
getService("event-manager").destroyAllListeners();
|
|
984
|
-
}
|
|
985
|
-
}
|
|
1092
|
+
routes
|
|
986
1093
|
};
|
|
987
1094
|
}
|
|
988
1095
|
return {
|