@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.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { setCreatorFields, errors, validateYupSchema, yup as yup$1
|
|
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";
|
|
3
4
|
import EE from "@strapi/strapi/dist/utils/ee";
|
|
5
|
+
import { scheduleJob } from "node-schedule";
|
|
4
6
|
import * as yup from "yup";
|
|
5
7
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
6
8
|
const RELEASE_ACTION_MODEL_UID = "plugin::content-releases.release-action";
|
|
@@ -48,40 +50,47 @@ const ACTIONS = [
|
|
|
48
50
|
pluginName: "content-releases"
|
|
49
51
|
}
|
|
50
52
|
];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
async function deleteActionsOnDisableDraftAndPublish({
|
|
54
|
+
oldContentTypes,
|
|
55
|
+
contentTypes: contentTypes2
|
|
56
|
+
}) {
|
|
57
|
+
if (!oldContentTypes) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
for (const uid in contentTypes2) {
|
|
61
|
+
if (!oldContentTypes[uid]) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const oldContentType = oldContentTypes[uid];
|
|
65
|
+
const contentType = contentTypes2[uid];
|
|
66
|
+
if (contentTypes$1.hasDraftAndPublish(oldContentType) && !contentTypes$1.hasDraftAndPublish(contentType)) {
|
|
67
|
+
await strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: uid }).execute();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
72
|
+
const deletedContentTypes = difference(keys(oldContentTypes), keys(contentTypes2)) ?? [];
|
|
73
|
+
if (deletedContentTypes.length) {
|
|
74
|
+
await mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
75
|
+
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
54
79
|
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
55
80
|
const register = async ({ strapi: strapi2 }) => {
|
|
56
|
-
if (features$2.isEnabled("cms-content-releases")
|
|
81
|
+
if (features$2.isEnabled("cms-content-releases")) {
|
|
57
82
|
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const destroyContentTypeUpdateListener = strapi2.eventHub.on(
|
|
61
|
-
"content-type.update",
|
|
62
|
-
async ({ contentType }) => {
|
|
63
|
-
if (contentType.schema.options.draftAndPublish === false) {
|
|
64
|
-
await releaseActionService.deleteManyForContentType(contentType.uid);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);
|
|
69
|
-
const destroyContentTypeDeleteListener = strapi2.eventHub.on(
|
|
70
|
-
"content-type.delete",
|
|
71
|
-
async ({ contentType }) => {
|
|
72
|
-
await releaseActionService.deleteManyForContentType(contentType.uid);
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);
|
|
83
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish);
|
|
84
|
+
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType);
|
|
76
85
|
}
|
|
77
86
|
};
|
|
78
87
|
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
79
88
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
80
|
-
if (features$1.isEnabled("cms-content-releases")
|
|
89
|
+
if (features$1.isEnabled("cms-content-releases")) {
|
|
81
90
|
strapi2.db.lifecycles.subscribe({
|
|
82
91
|
afterDelete(event) {
|
|
83
92
|
const { model, result } = event;
|
|
84
|
-
if (model.kind === "collectionType" && model.options
|
|
93
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
85
94
|
const { id } = result;
|
|
86
95
|
strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
87
96
|
where: {
|
|
@@ -97,7 +106,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
97
106
|
*/
|
|
98
107
|
async beforeDeleteMany(event) {
|
|
99
108
|
const { model, params } = event;
|
|
100
|
-
if (model.kind === "collectionType" && model.options
|
|
109
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
101
110
|
const { where } = params;
|
|
102
111
|
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
103
112
|
event.state.entriesToDelete = entriesToDelete;
|
|
@@ -150,6 +159,9 @@ const schema$1 = {
|
|
|
150
159
|
releasedAt: {
|
|
151
160
|
type: "datetime"
|
|
152
161
|
},
|
|
162
|
+
scheduledAt: {
|
|
163
|
+
type: "datetime"
|
|
164
|
+
},
|
|
153
165
|
actions: {
|
|
154
166
|
type: "relation",
|
|
155
167
|
relation: "oneToMany",
|
|
@@ -212,15 +224,9 @@ const contentTypes = {
|
|
|
212
224
|
release: release$1,
|
|
213
225
|
"release-action": releaseAction$1
|
|
214
226
|
};
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
where: {
|
|
219
|
-
target_type: contentTypeUid
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
});
|
|
227
|
+
const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
228
|
+
return strapi2.plugin("content-releases").service(name);
|
|
229
|
+
};
|
|
224
230
|
const getGroupName = (queryValue) => {
|
|
225
231
|
switch (queryValue) {
|
|
226
232
|
case "contentType":
|
|
@@ -236,10 +242,24 @@ const getGroupName = (queryValue) => {
|
|
|
236
242
|
const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
237
243
|
async create(releaseData, { user }) {
|
|
238
244
|
const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);
|
|
239
|
-
|
|
240
|
-
|
|
245
|
+
const {
|
|
246
|
+
validatePendingReleasesLimit,
|
|
247
|
+
validateUniqueNameForPendingRelease,
|
|
248
|
+
validateScheduledAtIsLaterThanNow
|
|
249
|
+
} = getService("release-validation", { strapi: strapi2 });
|
|
250
|
+
await Promise.all([
|
|
251
|
+
validatePendingReleasesLimit(),
|
|
252
|
+
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
|
|
253
|
+
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
254
|
+
]);
|
|
255
|
+
const release2 = await strapi2.entityService.create(RELEASE_MODEL_UID, {
|
|
241
256
|
data: releaseWithCreatorFields
|
|
242
257
|
});
|
|
258
|
+
if (strapi2.features.future.isEnabled("contentReleasesScheduling") && releaseWithCreatorFields.scheduledAt) {
|
|
259
|
+
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
260
|
+
await schedulingService.set(release2.id, release2.scheduledAt);
|
|
261
|
+
}
|
|
262
|
+
return release2;
|
|
243
263
|
},
|
|
244
264
|
async findOne(id, query = {}) {
|
|
245
265
|
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id, {
|
|
@@ -258,51 +278,66 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
258
278
|
}
|
|
259
279
|
});
|
|
260
280
|
},
|
|
261
|
-
async
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
// Find all Releases where the content type entry is present
|
|
268
|
-
actions: {
|
|
269
|
-
target_type: contentTypeUid,
|
|
270
|
-
target_id: entryId
|
|
271
|
-
}
|
|
272
|
-
} : {
|
|
273
|
-
// Find all Releases where the content type entry is not present
|
|
274
|
-
$or: [
|
|
275
|
-
{
|
|
276
|
-
$not: {
|
|
277
|
-
actions: {
|
|
278
|
-
target_type: contentTypeUid,
|
|
279
|
-
target_id: entryId
|
|
280
|
-
}
|
|
281
|
-
}
|
|
281
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
282
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
283
|
+
where: {
|
|
284
|
+
actions: {
|
|
285
|
+
target_type: contentTypeUid,
|
|
286
|
+
target_id: entryId
|
|
282
287
|
},
|
|
283
|
-
{
|
|
284
|
-
|
|
288
|
+
releasedAt: {
|
|
289
|
+
$null: true
|
|
285
290
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
291
|
+
},
|
|
292
|
+
populate: {
|
|
293
|
+
// Filter the action to get only the content type entry
|
|
294
|
+
actions: {
|
|
295
|
+
where: {
|
|
296
|
+
target_type: contentTypeUid,
|
|
297
|
+
target_id: entryId
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
return releases.map((release2) => {
|
|
303
|
+
if (release2.actions?.length) {
|
|
304
|
+
const [actionForEntry] = release2.actions;
|
|
305
|
+
delete release2.actions;
|
|
306
|
+
return {
|
|
307
|
+
...release2,
|
|
308
|
+
action: actionForEntry
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return release2;
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
async findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
315
|
+
const releasesRelated = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
316
|
+
where: {
|
|
317
|
+
releasedAt: {
|
|
318
|
+
$null: true
|
|
319
|
+
},
|
|
320
|
+
actions: {
|
|
292
321
|
target_type: contentTypeUid,
|
|
293
322
|
target_id: entryId
|
|
294
323
|
}
|
|
295
324
|
}
|
|
296
|
-
}
|
|
325
|
+
});
|
|
297
326
|
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
298
327
|
where: {
|
|
299
|
-
|
|
328
|
+
$or: [
|
|
329
|
+
{
|
|
330
|
+
id: {
|
|
331
|
+
$notIn: releasesRelated.map((release2) => release2.id)
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
actions: null
|
|
336
|
+
}
|
|
337
|
+
],
|
|
300
338
|
releasedAt: {
|
|
301
339
|
$null: true
|
|
302
340
|
}
|
|
303
|
-
},
|
|
304
|
-
populate: {
|
|
305
|
-
...populateAttachedAction
|
|
306
341
|
}
|
|
307
342
|
});
|
|
308
343
|
return releases.map((release2) => {
|
|
@@ -501,7 +536,9 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
501
536
|
populate: {
|
|
502
537
|
actions: {
|
|
503
538
|
populate: {
|
|
504
|
-
entry:
|
|
539
|
+
entry: {
|
|
540
|
+
fields: ["id"]
|
|
541
|
+
}
|
|
505
542
|
}
|
|
506
543
|
}
|
|
507
544
|
}
|
|
@@ -516,30 +553,80 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
|
|
|
516
553
|
if (releaseWithPopulatedActionEntries.actions.length === 0) {
|
|
517
554
|
throw new errors.ValidationError("No entries to publish");
|
|
518
555
|
}
|
|
519
|
-
const
|
|
556
|
+
const collectionTypeActions = {};
|
|
557
|
+
const singleTypeActions = [];
|
|
520
558
|
for (const action of releaseWithPopulatedActionEntries.actions) {
|
|
521
559
|
const contentTypeUid = action.contentType;
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
560
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
561
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
562
|
+
collectionTypeActions[contentTypeUid] = {
|
|
563
|
+
entriestoPublishIds: [],
|
|
564
|
+
entriesToUnpublishIds: []
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
if (action.type === "publish") {
|
|
568
|
+
collectionTypeActions[contentTypeUid].entriestoPublishIds.push(action.entry.id);
|
|
569
|
+
} else {
|
|
570
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
571
|
+
}
|
|
530
572
|
} else {
|
|
531
|
-
|
|
573
|
+
singleTypeActions.push({
|
|
574
|
+
uid: contentTypeUid,
|
|
575
|
+
action: action.type,
|
|
576
|
+
id: action.entry.id
|
|
577
|
+
});
|
|
532
578
|
}
|
|
533
579
|
}
|
|
534
580
|
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
581
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
535
582
|
await strapi2.db.transaction(async () => {
|
|
536
|
-
for (const
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
583
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
584
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
585
|
+
const entry = await strapi2.entityService.findOne(uid, id, { populate });
|
|
586
|
+
try {
|
|
587
|
+
if (action === "publish") {
|
|
588
|
+
await entityManagerService.publish(entry, uid);
|
|
589
|
+
} else {
|
|
590
|
+
await entityManagerService.unpublish(entry, uid);
|
|
591
|
+
}
|
|
592
|
+
} catch (error) {
|
|
593
|
+
if (error instanceof errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
594
|
+
;
|
|
595
|
+
else {
|
|
596
|
+
throw error;
|
|
597
|
+
}
|
|
540
598
|
}
|
|
541
|
-
|
|
542
|
-
|
|
599
|
+
}
|
|
600
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
601
|
+
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
602
|
+
const { entriestoPublishIds, entriesToUnpublishIds } = collectionTypeActions[contentTypeUid];
|
|
603
|
+
const entriesToPublish = await strapi2.entityService.findMany(
|
|
604
|
+
contentTypeUid,
|
|
605
|
+
{
|
|
606
|
+
filters: {
|
|
607
|
+
id: {
|
|
608
|
+
$in: entriestoPublishIds
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
populate
|
|
612
|
+
}
|
|
613
|
+
);
|
|
614
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(
|
|
615
|
+
contentTypeUid,
|
|
616
|
+
{
|
|
617
|
+
filters: {
|
|
618
|
+
id: {
|
|
619
|
+
$in: entriesToUnpublishIds
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
populate
|
|
623
|
+
}
|
|
624
|
+
);
|
|
625
|
+
if (entriesToPublish.length > 0) {
|
|
626
|
+
await entityManagerService.publishMany(entriesToPublish, contentTypeUid);
|
|
627
|
+
}
|
|
628
|
+
if (entriesToUnpublish.length > 0) {
|
|
629
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, contentTypeUid);
|
|
543
630
|
}
|
|
544
631
|
}
|
|
545
632
|
});
|
|
@@ -637,34 +724,66 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
637
724
|
if (pendingReleasesCount >= maximumPendingReleases) {
|
|
638
725
|
throw new errors.ValidationError("You have reached the maximum number of pending releases");
|
|
639
726
|
}
|
|
727
|
+
},
|
|
728
|
+
async validateUniqueNameForPendingRelease(name) {
|
|
729
|
+
const pendingReleases = await strapi2.entityService.findMany(RELEASE_MODEL_UID, {
|
|
730
|
+
filters: {
|
|
731
|
+
releasedAt: {
|
|
732
|
+
$null: true
|
|
733
|
+
},
|
|
734
|
+
name
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
const isNameUnique = pendingReleases.length === 0;
|
|
738
|
+
if (!isNameUnique) {
|
|
739
|
+
throw new errors.ValidationError(`Release with name ${name} already exists`);
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
async validateScheduledAtIsLaterThanNow(scheduledAt) {
|
|
743
|
+
if (scheduledAt && new Date(scheduledAt) <= /* @__PURE__ */ new Date()) {
|
|
744
|
+
throw new errors.ValidationError("Scheduled at must be later than now");
|
|
745
|
+
}
|
|
640
746
|
}
|
|
641
747
|
});
|
|
642
|
-
const
|
|
643
|
-
const
|
|
644
|
-
destroyListenerCallbacks: []
|
|
645
|
-
};
|
|
748
|
+
const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
749
|
+
const scheduledJobs = /* @__PURE__ */ new Map();
|
|
646
750
|
return {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
if (!state.destroyListenerCallbacks.length) {
|
|
652
|
-
return;
|
|
751
|
+
async set(releaseId, scheduleDate) {
|
|
752
|
+
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId, releasedAt: null } });
|
|
753
|
+
if (!release2) {
|
|
754
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
653
755
|
}
|
|
654
|
-
|
|
655
|
-
|
|
756
|
+
const job = scheduleJob(scheduleDate, async () => {
|
|
757
|
+
try {
|
|
758
|
+
await getService("release").publish(releaseId);
|
|
759
|
+
} catch (error) {
|
|
760
|
+
}
|
|
761
|
+
this.cancel(releaseId);
|
|
656
762
|
});
|
|
763
|
+
if (scheduledJobs.has(releaseId)) {
|
|
764
|
+
this.cancel(releaseId);
|
|
765
|
+
}
|
|
766
|
+
scheduledJobs.set(releaseId, job);
|
|
767
|
+
return scheduledJobs;
|
|
768
|
+
},
|
|
769
|
+
cancel(releaseId) {
|
|
770
|
+
if (scheduledJobs.has(releaseId)) {
|
|
771
|
+
scheduledJobs.get(releaseId).cancel();
|
|
772
|
+
scheduledJobs.delete(releaseId);
|
|
773
|
+
}
|
|
774
|
+
return scheduledJobs;
|
|
657
775
|
}
|
|
658
776
|
};
|
|
659
777
|
};
|
|
660
778
|
const services = {
|
|
661
779
|
release: createReleaseService,
|
|
662
|
-
"release-action": createReleaseActionService,
|
|
663
780
|
"release-validation": createReleaseValidationService,
|
|
664
|
-
"
|
|
781
|
+
...strapi.features.future.isEnabled("contentReleasesScheduling") ? { scheduling: createSchedulingService } : {}
|
|
665
782
|
};
|
|
666
783
|
const RELEASE_SCHEMA = yup.object().shape({
|
|
667
|
-
name: yup.string().trim().required()
|
|
784
|
+
name: yup.string().trim().required(),
|
|
785
|
+
// scheduledAt is a date, but we always receive strings from the client
|
|
786
|
+
scheduledAt: yup.string()
|
|
668
787
|
}).required().noUnknown();
|
|
669
788
|
const validateRelease = validateYupSchema(RELEASE_SCHEMA);
|
|
670
789
|
const releaseController = {
|
|
@@ -681,9 +800,7 @@ const releaseController = {
|
|
|
681
800
|
const contentTypeUid = query.contentTypeUid;
|
|
682
801
|
const entryId = query.entryId;
|
|
683
802
|
const hasEntryAttached = typeof query.hasEntryAttached === "string" ? JSON.parse(query.hasEntryAttached) : false;
|
|
684
|
-
const data = await releaseService.
|
|
685
|
-
hasEntryAttached
|
|
686
|
-
});
|
|
803
|
+
const data = hasEntryAttached ? await releaseService.findManyWithContentTypeEntryAttached(contentTypeUid, entryId) : await releaseService.findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId);
|
|
687
804
|
ctx.body = { data };
|
|
688
805
|
} else {
|
|
689
806
|
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
@@ -706,19 +823,18 @@ const releaseController = {
|
|
|
706
823
|
const id = ctx.params.id;
|
|
707
824
|
const releaseService = getService("release", { strapi });
|
|
708
825
|
const release2 = await releaseService.findOne(id, { populate: ["createdBy"] });
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
});
|
|
713
|
-
const sanitizedRelease = await permissionsManager.sanitizeOutput(release2);
|
|
826
|
+
if (!release2) {
|
|
827
|
+
throw new errors.NotFoundError(`Release not found for id: ${id}`);
|
|
828
|
+
}
|
|
714
829
|
const count = await releaseService.countActions({
|
|
715
830
|
filters: {
|
|
716
831
|
release: id
|
|
717
832
|
}
|
|
718
833
|
});
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
834
|
+
const sanitizedRelease = {
|
|
835
|
+
...release2,
|
|
836
|
+
createdBy: release2.createdBy ? strapi.admin.services.user.sanitizeUser(release2.createdBy) : null
|
|
837
|
+
};
|
|
722
838
|
const data = {
|
|
723
839
|
...sanitizedRelease,
|
|
724
840
|
actions: {
|
|
@@ -771,8 +887,27 @@ const releaseController = {
|
|
|
771
887
|
const id = ctx.params.id;
|
|
772
888
|
const releaseService = getService("release", { strapi });
|
|
773
889
|
const release2 = await releaseService.publish(id, { user });
|
|
890
|
+
const [countPublishActions, countUnpublishActions] = await Promise.all([
|
|
891
|
+
releaseService.countActions({
|
|
892
|
+
filters: {
|
|
893
|
+
release: id,
|
|
894
|
+
type: "publish"
|
|
895
|
+
}
|
|
896
|
+
}),
|
|
897
|
+
releaseService.countActions({
|
|
898
|
+
filters: {
|
|
899
|
+
release: id,
|
|
900
|
+
type: "unpublish"
|
|
901
|
+
}
|
|
902
|
+
})
|
|
903
|
+
]);
|
|
774
904
|
ctx.body = {
|
|
775
|
-
data: release2
|
|
905
|
+
data: release2,
|
|
906
|
+
meta: {
|
|
907
|
+
totalEntries: countPublishActions + countUnpublishActions,
|
|
908
|
+
totalPublishedEntries: countPublishActions,
|
|
909
|
+
totalUnpublishedEntries: countUnpublishActions
|
|
910
|
+
}
|
|
776
911
|
};
|
|
777
912
|
}
|
|
778
913
|
};
|
|
@@ -1040,19 +1175,14 @@ const routes = {
|
|
|
1040
1175
|
};
|
|
1041
1176
|
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1042
1177
|
const getPlugin = () => {
|
|
1043
|
-
if (features.isEnabled("cms-content-releases")
|
|
1178
|
+
if (features.isEnabled("cms-content-releases")) {
|
|
1044
1179
|
return {
|
|
1045
1180
|
register,
|
|
1046
1181
|
bootstrap,
|
|
1047
1182
|
contentTypes,
|
|
1048
1183
|
services,
|
|
1049
1184
|
controllers,
|
|
1050
|
-
routes
|
|
1051
|
-
destroy() {
|
|
1052
|
-
if (features.isEnabled("cms-content-releases") && strapi.features.future.isEnabled("contentReleases")) {
|
|
1053
|
-
getService("event-manager").destroyAllListeners();
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1185
|
+
routes
|
|
1056
1186
|
};
|
|
1057
1187
|
}
|
|
1058
1188
|
return {
|