@strapi/content-releases 0.0.0-next.56199ab7a5f3320e0debcbe4a24fe0b8cd599e21 → 0.0.0-next.6d384ed205b7f0792d9bea79195f01b30463cfa0
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-YFvVMqB8.js → App-IQIHCiSO.js} +154 -93
- package/dist/_chunks/App-IQIHCiSO.js.map +1 -0
- package/dist/_chunks/{App-8J9a-MD5.mjs → App-WkwjSaDY.mjs} +157 -96
- package/dist/_chunks/App-WkwjSaDY.mjs.map +1 -0
- package/dist/_chunks/{en-MyLPoISH.mjs → en-m9eTk4UF.mjs} +7 -3
- package/dist/_chunks/en-m9eTk4UF.mjs.map +1 -0
- package/dist/_chunks/{en-gYDqKYFd.js → en-r9YocBH0.js} +7 -3
- package/dist/_chunks/en-r9YocBH0.js.map +1 -0
- package/dist/_chunks/{index-ej8MzbQl.mjs → index-CyVlvX8h.mjs} +43 -20
- package/dist/_chunks/index-CyVlvX8h.mjs.map +1 -0
- package/dist/_chunks/{index-vxli-E-l.js → index-u_da7WHb.js} +42 -19
- package/dist/_chunks/index-u_da7WHb.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +251 -121
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +252 -122
- package/dist/server/index.mjs.map +1 -1
- package/package.json +10 -9
- package/dist/_chunks/App-8J9a-MD5.mjs.map +0 -1
- package/dist/_chunks/App-YFvVMqB8.js.map +0 -1
- package/dist/_chunks/en-MyLPoISH.mjs.map +0 -1
- package/dist/_chunks/en-gYDqKYFd.js.map +0 -1
- package/dist/_chunks/index-ej8MzbQl.mjs.map +0 -1
- package/dist/_chunks/index-vxli-E-l.js.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const utils = require("@strapi/utils");
|
|
3
|
+
const lodash = require("lodash");
|
|
3
4
|
const _ = require("lodash/fp");
|
|
4
5
|
const EE = require("@strapi/strapi/dist/utils/ee");
|
|
6
|
+
const nodeSchedule = require("node-schedule");
|
|
5
7
|
const yup = require("yup");
|
|
6
8
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
7
9
|
function _interopNamespace(e) {
|
|
@@ -71,40 +73,47 @@ const ACTIONS = [
|
|
|
71
73
|
pluginName: "content-releases"
|
|
72
74
|
}
|
|
73
75
|
];
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
async function deleteActionsOnDisableDraftAndPublish({
|
|
77
|
+
oldContentTypes,
|
|
78
|
+
contentTypes: contentTypes2
|
|
79
|
+
}) {
|
|
80
|
+
if (!oldContentTypes) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
for (const uid in contentTypes2) {
|
|
84
|
+
if (!oldContentTypes[uid]) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const oldContentType = oldContentTypes[uid];
|
|
88
|
+
const contentType = contentTypes2[uid];
|
|
89
|
+
if (utils.contentTypes.hasDraftAndPublish(oldContentType) && !utils.contentTypes.hasDraftAndPublish(contentType)) {
|
|
90
|
+
await strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: uid }).execute();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
95
|
+
const deletedContentTypes = lodash.difference(lodash.keys(oldContentTypes), lodash.keys(contentTypes2)) ?? [];
|
|
96
|
+
if (deletedContentTypes.length) {
|
|
97
|
+
await utils.mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
98
|
+
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
77
102
|
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
78
103
|
const register = async ({ strapi: strapi2 }) => {
|
|
79
|
-
if (features$2.isEnabled("cms-content-releases")
|
|
104
|
+
if (features$2.isEnabled("cms-content-releases")) {
|
|
80
105
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const destroyContentTypeUpdateListener = strapi2.eventHub.on(
|
|
84
|
-
"content-type.update",
|
|
85
|
-
async ({ contentType }) => {
|
|
86
|
-
if (contentType.schema.options.draftAndPublish === false) {
|
|
87
|
-
await releaseActionService.deleteManyForContentType(contentType.uid);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
);
|
|
91
|
-
eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);
|
|
92
|
-
const destroyContentTypeDeleteListener = strapi2.eventHub.on(
|
|
93
|
-
"content-type.delete",
|
|
94
|
-
async ({ contentType }) => {
|
|
95
|
-
await releaseActionService.deleteManyForContentType(contentType.uid);
|
|
96
|
-
}
|
|
97
|
-
);
|
|
98
|
-
eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);
|
|
106
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish);
|
|
107
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType);
|
|
99
108
|
}
|
|
100
109
|
};
|
|
101
110
|
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
102
111
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
103
|
-
if (features$1.isEnabled("cms-content-releases")
|
|
112
|
+
if (features$1.isEnabled("cms-content-releases")) {
|
|
104
113
|
strapi2.db.lifecycles.subscribe({
|
|
105
114
|
afterDelete(event) {
|
|
106
115
|
const { model, result } = event;
|
|
107
|
-
if (model.kind === "collectionType" && model.options
|
|
116
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
108
117
|
const { id } = result;
|
|
109
118
|
strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
110
119
|
where: {
|
|
@@ -120,7 +129,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
120
129
|
*/
|
|
121
130
|
async beforeDeleteMany(event) {
|
|
122
131
|
const { model, params } = event;
|
|
123
|
-
if (model.kind === "collectionType" && model.options
|
|
132
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
124
133
|
const { where } = params;
|
|
125
134
|
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
126
135
|
event.state.entriesToDelete = entriesToDelete;
|
|
@@ -173,6 +182,9 @@ const schema$1 = {
|
|
|
173
182
|
releasedAt: {
|
|
174
183
|
type: "datetime"
|
|
175
184
|
},
|
|
185
|
+
scheduledAt: {
|
|
186
|
+
type: "datetime"
|
|
187
|
+
},
|
|
176
188
|
actions: {
|
|
177
189
|
type: "relation",
|
|
178
190
|
relation: "oneToMany",
|
|
@@ -235,15 +247,9 @@ const contentTypes = {
|
|
|
235
247
|
release: release$1,
|
|
236
248
|
"release-action": releaseAction$1
|
|
237
249
|
};
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
where: {
|
|
242
|
-
target_type: contentTypeUid
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
});
|
|
250
|
+
const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
251
|
+
return strapi2.plugin("content-releases").service(name);
|
|
252
|
+
};
|
|
247
253
|
const getGroupName = (queryValue) => {
|
|
248
254
|
switch (queryValue) {
|
|
249
255
|
case "contentType":
|
|
@@ -259,10 +265,24 @@ const getGroupName = (queryValue) => {
|
|
|
259
265
|
const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
260
266
|
async create(releaseData, { user }) {
|
|
261
267
|
const releaseWithCreatorFields = await utils.setCreatorFields({ user })(releaseData);
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
const {
|
|
269
|
+
validatePendingReleasesLimit,
|
|
270
|
+
validateUniqueNameForPendingRelease,
|
|
271
|
+
validateScheduledAtIsLaterThanNow
|
|
272
|
+
} = getService("release-validation", { strapi: strapi2 });
|
|
273
|
+
await Promise.all([
|
|
274
|
+
validatePendingReleasesLimit(),
|
|
275
|
+
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
|
|
276
|
+
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
277
|
+
]);
|
|
278
|
+
const release2 = await strapi2.entityService.create(RELEASE_MODEL_UID, {
|
|
264
279
|
data: releaseWithCreatorFields
|
|
265
280
|
});
|
|
281
|
+
if (strapi2.features.future.isEnabled("contentReleasesScheduling") && releaseWithCreatorFields.scheduledAt) {
|
|
282
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
283
|
+
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
284
|
+
}
|
|
285
|
+
return release2;
|
|
266
286
|
},
|
|
267
287
|
async findOne(id, query = {}) {
|
|
268
288
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id, {
|
|
@@ -281,51 +301,66 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
281
301
|
}
|
|
282
302
|
});
|
|
283
303
|
},
|
|
284
|
-
async
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// Find all Releases where the content type entry is present
|
|
291
|
-
actions: {
|
|
292
|
-
target_type: contentTypeUid,
|
|
293
|
-
target_id: entryId
|
|
294
|
-
}
|
|
295
|
-
} : {
|
|
296
|
-
// Find all Releases where the content type entry is not present
|
|
297
|
-
$or: [
|
|
298
|
-
{
|
|
299
|
-
$not: {
|
|
300
|
-
actions: {
|
|
301
|
-
target_type: contentTypeUid,
|
|
302
|
-
target_id: entryId
|
|
303
|
-
}
|
|
304
|
-
}
|
|
304
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
305
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
306
|
+
where: {
|
|
307
|
+
actions: {
|
|
308
|
+
target_type: contentTypeUid,
|
|
309
|
+
target_id: entryId
|
|
305
310
|
},
|
|
306
|
-
{
|
|
307
|
-
|
|
311
|
+
releasedAt: {
|
|
312
|
+
$null: true
|
|
308
313
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
314
|
+
},
|
|
315
|
+
populate: {
|
|
316
|
+
// Filter the action to get only the content type entry
|
|
317
|
+
actions: {
|
|
318
|
+
where: {
|
|
319
|
+
target_type: contentTypeUid,
|
|
320
|
+
target_id: entryId
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
return releases.map((release2) => {
|
|
326
|
+
if (release2.actions?.length) {
|
|
327
|
+
const [actionForEntry] = release2.actions;
|
|
328
|
+
delete release2.actions;
|
|
329
|
+
return {
|
|
330
|
+
...release2,
|
|
331
|
+
action: actionForEntry
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return release2;
|
|
335
|
+
});
|
|
336
|
+
},
|
|
337
|
+
async findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
338
|
+
const releasesRelated = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
339
|
+
where: {
|
|
340
|
+
releasedAt: {
|
|
341
|
+
$null: true
|
|
342
|
+
},
|
|
343
|
+
actions: {
|
|
315
344
|
target_type: contentTypeUid,
|
|
316
345
|
target_id: entryId
|
|
317
346
|
}
|
|
318
347
|
}
|
|
319
|
-
}
|
|
348
|
+
});
|
|
320
349
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
321
350
|
where: {
|
|
322
|
-
|
|
351
|
+
$or: [
|
|
352
|
+
{
|
|
353
|
+
id: {
|
|
354
|
+
$notIn: releasesRelated.map((release2) => release2.id)
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
actions: null
|
|
359
|
+
}
|
|
360
|
+
],
|
|
323
361
|
releasedAt: {
|
|
324
362
|
$null: true
|
|
325
363
|
}
|
|
326
|
-
},
|
|
327
|
-
populate: {
|
|
328
|
-
...populateAttachedAction
|
|
329
364
|
}
|
|
330
365
|
});
|
|
331
366
|
return releases.map((release2) => {
|
|
@@ -524,7 +559,9 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
524
559
|
populate: {
|
|
525
560
|
actions: {
|
|
526
561
|
populate: {
|
|
527
|
-
entry:
|
|
562
|
+
entry: {
|
|
563
|
+
fields: ["id"]
|
|
564
|
+
}
|
|
528
565
|
}
|
|
529
566
|
}
|
|
530
567
|
}
|
|
@@ -539,30 +576,80 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
539
576
|
if (releaseWithPopulatedActionEntries.actions.length === 0) {
|
|
540
577
|
throw new utils.errors.ValidationError("No entries to publish");
|
|
541
578
|
}
|
|
542
|
-
const
|
|
579
|
+
const collectionTypeActions = {};
|
|
580
|
+
const singleTypeActions = [];
|
|
543
581
|
for (const action of releaseWithPopulatedActionEntries.actions) {
|
|
544
582
|
const contentTypeUid = action.contentType;
|
|
545
|
-
if (
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
583
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
584
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
585
|
+
collectionTypeActions[contentTypeUid] = {
|
|
586
|
+
entriestoPublishIds: [],
|
|
587
|
+
entriesToUnpublishIds: []
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
if (action.type === "publish") {
|
|
591
|
+
collectionTypeActions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
592
|
+
} else {
|
|
593
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
594
|
+
}
|
|
553
595
|
} else {
|
|
554
|
-
|
|
596
|
+
singleTypeActions.push({
|
|
597
|
+
uid: contentTypeUid,
|
|
598
|
+
action: action.type,
|
|
599
|
+
id: action.entry.id
|
|
600
|
+
});
|
|
555
601
|
}
|
|
556
602
|
}
|
|
557
603
|
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
604
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
558
605
|
await strapi2.db.transaction(async () => {
|
|
559
|
-
for (const
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
606
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
607
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
608
|
+
const entry = await strapi2.entityService.findOne(uid, id, { populate });
|
|
609
|
+
try {
|
|
610
|
+
if (action === "publish") {
|
|
611
|
+
await entityManagerService.publish(entry, uid);
|
|
612
|
+
} else {
|
|
613
|
+
await entityManagerService.unpublish(entry, uid);
|
|
614
|
+
}
|
|
615
|
+
} catch (error) {
|
|
616
|
+
if (error instanceof utils.errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
617
|
+
;
|
|
618
|
+
else {
|
|
619
|
+
throw error;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
624
|
+
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
625
|
+
const { entriestoPublishIds, entriesToUnpublishIds } = collectionTypeActions[contentTypeUid];
|
|
626
|
+
const entriesToPublish = await strapi2.entityService.findMany(
|
|
627
|
+
contentTypeUid,
|
|
628
|
+
{
|
|
629
|
+
filters: {
|
|
630
|
+
id: {
|
|
631
|
+
$in: entriestoPublishIds
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
populate
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
638
|
+
contentTypeUid,
|
|
639
|
+
{
|
|
640
|
+
filters: {
|
|
641
|
+
id: {
|
|
642
|
+
$in: entriesToUnpublishIds
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
populate
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
if (entriesToPublish.length > 0) {
|
|
649
|
+
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
563
650
|
}
|
|
564
|
-
if (
|
|
565
|
-
await entityManagerService.unpublishMany(
|
|
651
|
+
if (entriesToUnpublish.length > 0) {
|
|
652
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, contentTypeUid);
|
|
566
653
|
}
|
|
567
654
|
}
|
|
568
655
|
});
|
|
@@ -660,34 +747,66 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
660
747
|
if (pendingReleasesCount >= maximumPendingReleases) {
|
|
661
748
|
throw new utils.errors.ValidationError("You have reached the maximum number of pending releases");
|
|
662
749
|
}
|
|
750
|
+
},
|
|
751
|
+
async validateUniqueNameForPendingRelease(name) {
|
|
752
|
+
const pendingReleases = await strapi2.entityService.findMany(RELEASE_MODEL_UID, {
|
|
753
|
+
filters: {
|
|
754
|
+
releasedAt: {
|
|
755
|
+
$null: true
|
|
756
|
+
},
|
|
757
|
+
name
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
const isNameUnique = pendingReleases.length === 0;
|
|
761
|
+
if (!isNameUnique) {
|
|
762
|
+
throw new utils.errors.ValidationError(`Release with name ${name} already exists`);
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
async validateScheduledAtIsLaterThanNow(scheduledAt) {
|
|
766
|
+
if (scheduledAt && new Date(scheduledAt) <= /* @__PURE__ */ new Date()) {
|
|
767
|
+
throw new utils.errors.ValidationError("Scheduled at must be later than now");
|
|
768
|
+
}
|
|
663
769
|
}
|
|
664
770
|
});
|
|
665
|
-
const
|
|
666
|
-
const
|
|
667
|
-
destroyListenerCallbacks: []
|
|
668
|
-
};
|
|
771
|
+
const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
772
|
+
const scheduledJobs = /* @__PURE__ */ new Map();
|
|
669
773
|
return {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (!state.destroyListenerCallbacks.length) {
|
|
675
|
-
return;
|
|
774
|
+
async set(releaseId, scheduleDate) {
|
|
775
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId, releasedAt: null } });
|
|
776
|
+
if (!release2) {
|
|
777
|
+
throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
676
778
|
}
|
|
677
|
-
|
|
678
|
-
|
|
779
|
+
const job = nodeSchedule.scheduleJob(scheduleDate, async () => {
|
|
780
|
+
try {
|
|
781
|
+
await getService("release").publish(releaseId);
|
|
782
|
+
} catch (error) {
|
|
783
|
+
}
|
|
784
|
+
this.cancel(releaseId);
|
|
679
785
|
});
|
|
786
|
+
if (scheduledJobs.has(releaseId)) {
|
|
787
|
+
this.cancel(releaseId);
|
|
788
|
+
}
|
|
789
|
+
scheduledJobs.set(releaseId, job);
|
|
790
|
+
return scheduledJobs;
|
|
791
|
+
},
|
|
792
|
+
cancel(releaseId) {
|
|
793
|
+
if (scheduledJobs.has(releaseId)) {
|
|
794
|
+
scheduledJobs.get(releaseId).cancel();
|
|
795
|
+
scheduledJobs.delete(releaseId);
|
|
796
|
+
}
|
|
797
|
+
return scheduledJobs;
|
|
680
798
|
}
|
|
681
799
|
};
|
|
682
800
|
};
|
|
683
801
|
const services = {
|
|
684
802
|
release: createReleaseService,
|
|
685
|
-
"release-action": createReleaseActionService,
|
|
686
803
|
"release-validation": createReleaseValidationService,
|
|
687
|
-
"
|
|
804
|
+
...strapi.features.future.isEnabled("contentReleasesScheduling") ? { scheduling: createSchedulingService } : {}
|
|
688
805
|
};
|
|
689
806
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
690
|
-
name: yup__namespace.string().trim().required()
|
|
807
|
+
name: yup__namespace.string().trim().required(),
|
|
808
|
+
// scheduledAt is a date, but we always receive strings from the client
|
|
809
|
+
scheduledAt: yup__namespace.string()
|
|
691
810
|
}).required().noUnknown();
|
|
692
811
|
const validateRelease = utils.validateYupSchema(RELEASE_SCHEMA);
|
|
693
812
|
const releaseController = {
|
|
@@ -704,9 +823,7 @@ const releaseController = {
|
|
|
704
823
|
const contentTypeUid = query.contentTypeUid;
|
|
705
824
|
const entryId = query.entryId;
|
|
706
825
|
const hasEntryAttached = typeof query.hasEntryAttached === "string" ? JSON.parse(query.hasEntryAttached) : false;
|
|
707
|
-
const data = await releaseService.
|
|
708
|
-
hasEntryAttached
|
|
709
|
-
});
|
|
826
|
+
const data = hasEntryAttached ? await releaseService.findManyWithContentTypeEntryAttached(contentTypeUid, entryId) : await releaseService.findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId);
|
|
710
827
|
ctx.body = { data };
|
|
711
828
|
} else {
|
|
712
829
|
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
@@ -729,19 +846,18 @@ const releaseController = {
|
|
|
729
846
|
const id = ctx.params.id;
|
|
730
847
|
const releaseService = getService("release", { strapi });
|
|
731
848
|
const release2 = await releaseService.findOne(id, { populate: ["createdBy"] });
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
});
|
|
736
|
-
const sanitizedRelease = await permissionsManager.sanitizeOutput(release2);
|
|
849
|
+
if (!release2) {
|
|
850
|
+
throw new utils.errors.NotFoundError(`Release not found for id: ${id}`);
|
|
851
|
+
}
|
|
737
852
|
const count = await releaseService.countActions({
|
|
738
853
|
filters: {
|
|
739
854
|
release: id
|
|
740
855
|
}
|
|
741
856
|
});
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
857
|
+
const sanitizedRelease = {
|
|
858
|
+
...release2,
|
|
859
|
+
createdBy: release2.createdBy ? strapi.admin.services.user.sanitizeUser(release2.createdBy) : null
|
|
860
|
+
};
|
|
745
861
|
const data = {
|
|
746
862
|
...sanitizedRelease,
|
|
747
863
|
actions: {
|
|
@@ -794,8 +910,27 @@ const releaseController = {
|
|
|
794
910
|
const id = ctx.params.id;
|
|
795
911
|
const releaseService = getService("release", { strapi });
|
|
796
912
|
const release2 = await releaseService.publish(id, { user });
|
|
913
|
+
const [countPublishActions, countUnpublishActions] = await Promise.all([
|
|
914
|
+
releaseService.countActions({
|
|
915
|
+
filters: {
|
|
916
|
+
release: id,
|
|
917
|
+
type: "publish"
|
|
918
|
+
}
|
|
919
|
+
}),
|
|
920
|
+
releaseService.countActions({
|
|
921
|
+
filters: {
|
|
922
|
+
release: id,
|
|
923
|
+
type: "unpublish"
|
|
924
|
+
}
|
|
925
|
+
})
|
|
926
|
+
]);
|
|
797
927
|
ctx.body = {
|
|
798
|
-
data: release2
|
|
928
|
+
data: release2,
|
|
929
|
+
meta: {
|
|
930
|
+
totalEntries: countPublishActions + countUnpublishActions,
|
|
931
|
+
totalPublishedEntries: countPublishActions,
|
|
932
|
+
totalUnpublishedEntries: countUnpublishActions
|
|
933
|
+
}
|
|
799
934
|
};
|
|
800
935
|
}
|
|
801
936
|
};
|
|
@@ -1063,19 +1198,14 @@ const routes = {
|
|
|
1063
1198
|
};
|
|
1064
1199
|
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1065
1200
|
const getPlugin = () => {
|
|
1066
|
-
if (features.isEnabled("cms-content-releases")
|
|
1201
|
+
if (features.isEnabled("cms-content-releases")) {
|
|
1067
1202
|
return {
|
|
1068
1203
|
register,
|
|
1069
1204
|
bootstrap,
|
|
1070
1205
|
contentTypes,
|
|
1071
1206
|
services,
|
|
1072
1207
|
controllers,
|
|
1073
|
-
routes
|
|
1074
|
-
destroy() {
|
|
1075
|
-
if (features.isEnabled("cms-content-releases") && strapi.features.future.isEnabled("contentReleases")) {
|
|
1076
|
-
getService("event-manager").destroyAllListeners();
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1208
|
+
routes
|
|
1079
1209
|
};
|
|
1080
1210
|
}
|
|
1081
1211
|
return {
|