@strapi/content-releases 0.0.0-experimental.e02b4637b3906c6d31048d00600d09a23a0edc3d → 0.0.0-experimental.e033e9b9c89837331a60b1b6a2c21a779fffc801
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-dLXY5ei3.js +1353 -0
- package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
- package/dist/_chunks/{App-BA2xDdy0.mjs → App-jrh58sXY.mjs} +558 -602
- package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-_MxP6-Dt.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +7 -8
- package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
- package/dist/_chunks/{PurchaseContentReleases-Be3acS2L.js → PurchaseContentReleases-bpIYXOfu.js} +6 -7
- package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
- package/dist/_chunks/{en-CmYoEnA7.js → en-HrREghh3.js} +2 -9
- package/dist/_chunks/en-HrREghh3.js.map +1 -0
- package/dist/_chunks/{en-D0yVZFqf.mjs → en-ltT1TlKQ.mjs} +2 -9
- package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
- package/dist/_chunks/index-CVO0Rqdm.js +1336 -0
- package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
- package/dist/_chunks/index-PiOGBETy.mjs +1315 -0
- package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
- package/dist/admin/index.js +15 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +16 -2
- package/dist/admin/index.mjs.map +1 -1
- package/dist/server/index.js +638 -830
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +638 -831
- package/dist/server/index.mjs.map +1 -1
- package/package.json +37 -31
- package/strapi-server.js +3 -0
- package/dist/_chunks/App-BA2xDdy0.mjs.map +0 -1
- package/dist/_chunks/App-D4Wira1X.js +0 -1395
- package/dist/_chunks/App-D4Wira1X.js.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +0 -1
- package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +0 -1
- package/dist/_chunks/ReleasesSettingsPage-BAlbMWpw.mjs +0 -178
- package/dist/_chunks/ReleasesSettingsPage-BAlbMWpw.mjs.map +0 -1
- package/dist/_chunks/ReleasesSettingsPage-xhFyRXCM.js +0 -178
- package/dist/_chunks/ReleasesSettingsPage-xhFyRXCM.js.map +0 -1
- package/dist/_chunks/en-CmYoEnA7.js.map +0 -1
- package/dist/_chunks/en-D0yVZFqf.mjs.map +0 -1
- package/dist/_chunks/index-CCFFG3Zs.mjs +0 -1365
- package/dist/_chunks/index-CCFFG3Zs.mjs.map +0 -1
- package/dist/_chunks/index-DxkQGp4N.js +0 -1384
- package/dist/_chunks/index-DxkQGp4N.js.map +0 -1
- package/dist/_chunks/schemas-BE1LxE9J.js +0 -62
- package/dist/_chunks/schemas-BE1LxE9J.js.map +0 -1
- package/dist/_chunks/schemas-DdA2ic2U.mjs +0 -44
- package/dist/_chunks/schemas-DdA2ic2U.mjs.map +0 -1
- package/dist/admin/src/components/RelativeTime.d.ts +0 -28
- package/dist/admin/src/components/ReleaseAction.d.ts +0 -3
- package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -26
- package/dist/admin/src/components/ReleaseActionModal.d.ts +0 -24
- package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -9
- package/dist/admin/src/components/ReleaseListCell.d.ts +0 -28
- package/dist/admin/src/components/ReleaseModal.d.ts +0 -17
- package/dist/admin/src/components/ReleasesPanel.d.ts +0 -3
- package/dist/admin/src/constants.d.ts +0 -76
- package/dist/admin/src/index.d.ts +0 -3
- package/dist/admin/src/modules/hooks.d.ts +0 -7
- package/dist/admin/src/pages/App.d.ts +0 -1
- package/dist/admin/src/pages/PurchaseContentReleases.d.ts +0 -2
- package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -2
- package/dist/admin/src/pages/ReleasesPage.d.ts +0 -8
- package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +0 -1
- package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -181
- package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -39
- package/dist/admin/src/pluginId.d.ts +0 -1
- package/dist/admin/src/services/release.d.ts +0 -112
- package/dist/admin/src/store/hooks.d.ts +0 -7
- package/dist/admin/src/utils/api.d.ts +0 -6
- package/dist/admin/src/utils/prefixPluginTranslations.d.ts +0 -3
- package/dist/admin/src/utils/time.d.ts +0 -10
- package/dist/admin/src/validation/schemas.d.ts +0 -6
- package/dist/server/src/bootstrap.d.ts +0 -5
- package/dist/server/src/bootstrap.d.ts.map +0 -1
- package/dist/server/src/constants.d.ts +0 -21
- package/dist/server/src/constants.d.ts.map +0 -1
- package/dist/server/src/content-types/index.d.ts +0 -97
- package/dist/server/src/content-types/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release/index.d.ts +0 -48
- package/dist/server/src/content-types/release/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release/schema.d.ts +0 -47
- package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
- package/dist/server/src/content-types/release-action/index.d.ts +0 -48
- package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
- package/dist/server/src/content-types/release-action/schema.d.ts +0 -47
- package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
- package/dist/server/src/controllers/index.d.ts +0 -25
- package/dist/server/src/controllers/index.d.ts.map +0 -1
- package/dist/server/src/controllers/release-action.d.ts +0 -10
- package/dist/server/src/controllers/release-action.d.ts.map +0 -1
- package/dist/server/src/controllers/release.d.ts +0 -18
- package/dist/server/src/controllers/release.d.ts.map +0 -1
- package/dist/server/src/controllers/settings.d.ts +0 -11
- package/dist/server/src/controllers/settings.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/release-action.d.ts +0 -14
- package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/release.d.ts +0 -4
- package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
- package/dist/server/src/controllers/validation/settings.d.ts +0 -3
- package/dist/server/src/controllers/validation/settings.d.ts.map +0 -1
- package/dist/server/src/destroy.d.ts +0 -5
- package/dist/server/src/destroy.d.ts.map +0 -1
- package/dist/server/src/index.d.ts +0 -2115
- package/dist/server/src/index.d.ts.map +0 -1
- package/dist/server/src/middlewares/documents.d.ts +0 -6
- package/dist/server/src/middlewares/documents.d.ts.map +0 -1
- package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +0 -9
- package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +0 -1
- package/dist/server/src/migrations/index.d.ts +0 -13
- package/dist/server/src/migrations/index.d.ts.map +0 -1
- package/dist/server/src/register.d.ts +0 -5
- package/dist/server/src/register.d.ts.map +0 -1
- package/dist/server/src/routes/index.d.ts +0 -51
- package/dist/server/src/routes/index.d.ts.map +0 -1
- package/dist/server/src/routes/release-action.d.ts +0 -18
- package/dist/server/src/routes/release-action.d.ts.map +0 -1
- package/dist/server/src/routes/release.d.ts +0 -18
- package/dist/server/src/routes/release.d.ts.map +0 -1
- package/dist/server/src/routes/settings.d.ts +0 -18
- package/dist/server/src/routes/settings.d.ts.map +0 -1
- package/dist/server/src/services/index.d.ts +0 -1828
- package/dist/server/src/services/index.d.ts.map +0 -1
- package/dist/server/src/services/release-action.d.ts +0 -38
- package/dist/server/src/services/release-action.d.ts.map +0 -1
- package/dist/server/src/services/release.d.ts +0 -31
- package/dist/server/src/services/release.d.ts.map +0 -1
- package/dist/server/src/services/scheduling.d.ts +0 -18
- package/dist/server/src/services/scheduling.d.ts.map +0 -1
- package/dist/server/src/services/settings.d.ts +0 -13
- package/dist/server/src/services/settings.d.ts.map +0 -1
- package/dist/server/src/services/validation.d.ts +0 -18
- package/dist/server/src/services/validation.d.ts.map +0 -1
- package/dist/server/src/utils/index.d.ts +0 -35
- package/dist/server/src/utils/index.d.ts.map +0 -1
- package/dist/shared/contracts/release-actions.d.ts +0 -130
- package/dist/shared/contracts/release-actions.d.ts.map +0 -1
- package/dist/shared/contracts/releases.d.ts +0 -184
- package/dist/shared/contracts/releases.d.ts.map +0 -1
- package/dist/shared/contracts/settings.d.ts +0 -39
- package/dist/shared/contracts/settings.d.ts.map +0 -1
- package/dist/shared/types.d.ts +0 -24
- package/dist/shared/types.d.ts.map +0 -1
package/dist/server/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { contentTypes as contentTypes$1,
|
|
1
|
+
import { contentTypes as contentTypes$1, mapAsync, setCreatorFields, errors, validateYupSchema, yup as yup$1 } from "@strapi/utils";
|
|
2
2
|
import isEqual from "lodash/isEqual";
|
|
3
3
|
import { difference, keys } from "lodash";
|
|
4
4
|
import _ from "lodash/fp";
|
|
5
|
+
import EE from "@strapi/strapi/dist/utils/ee";
|
|
5
6
|
import { scheduleJob } from "node-schedule";
|
|
6
7
|
import * as yup from "yup";
|
|
7
8
|
const RELEASE_MODEL_UID = "plugin::content-releases.release";
|
|
@@ -48,38 +49,21 @@ const ACTIONS = [
|
|
|
48
49
|
displayName: "Add an entry to a release",
|
|
49
50
|
uid: "create-action",
|
|
50
51
|
pluginName: "content-releases"
|
|
51
|
-
},
|
|
52
|
-
// Settings
|
|
53
|
-
{
|
|
54
|
-
uid: "settings.read",
|
|
55
|
-
section: "settings",
|
|
56
|
-
displayName: "Read",
|
|
57
|
-
category: "content releases",
|
|
58
|
-
subCategory: "options",
|
|
59
|
-
pluginName: "content-releases"
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
uid: "settings.update",
|
|
63
|
-
section: "settings",
|
|
64
|
-
displayName: "Edit",
|
|
65
|
-
category: "content releases",
|
|
66
|
-
subCategory: "options",
|
|
67
|
-
pluginName: "content-releases"
|
|
68
52
|
}
|
|
69
53
|
];
|
|
70
54
|
const ALLOWED_WEBHOOK_EVENTS = {
|
|
71
55
|
RELEASES_PUBLISH: "releases.publish"
|
|
72
56
|
};
|
|
73
|
-
const getService = (name, { strapi: strapi2 }) => {
|
|
57
|
+
const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
74
58
|
return strapi2.plugin("content-releases").service(name);
|
|
75
59
|
};
|
|
76
|
-
const
|
|
60
|
+
const getPopulatedEntry = async (contentTypeUid, entryId, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
77
61
|
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
78
|
-
const populate = await populateBuilderService(
|
|
79
|
-
const entry = await
|
|
80
|
-
return
|
|
62
|
+
const populate = await populateBuilderService(contentTypeUid).populateDeep(Infinity).build();
|
|
63
|
+
const entry = await strapi2.entityService.findOne(contentTypeUid, entryId, { populate });
|
|
64
|
+
return entry;
|
|
81
65
|
};
|
|
82
|
-
const
|
|
66
|
+
const getEntryValidStatus = async (contentTypeUid, entry, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
83
67
|
try {
|
|
84
68
|
await strapi2.entityValidator.validateEntityCreation(
|
|
85
69
|
strapi2.getModel(contentTypeUid),
|
|
@@ -93,38 +77,6 @@ const isEntryValid = async (contentTypeUid, entry, { strapi: strapi2 }) => {
|
|
|
93
77
|
return false;
|
|
94
78
|
}
|
|
95
79
|
};
|
|
96
|
-
const getEntry = async ({
|
|
97
|
-
contentType,
|
|
98
|
-
documentId,
|
|
99
|
-
locale,
|
|
100
|
-
populate,
|
|
101
|
-
status = "draft"
|
|
102
|
-
}, { strapi: strapi2 }) => {
|
|
103
|
-
if (documentId) {
|
|
104
|
-
return strapi2.documents(contentType).findOne({ documentId, locale, populate, status });
|
|
105
|
-
}
|
|
106
|
-
return strapi2.documents(contentType).findFirst({ locale, populate, status });
|
|
107
|
-
};
|
|
108
|
-
const getEntryStatus = async (contentType, entry) => {
|
|
109
|
-
if (entry.publishedAt) {
|
|
110
|
-
return "published";
|
|
111
|
-
}
|
|
112
|
-
const publishedEntry = await strapi.documents(contentType).findOne({
|
|
113
|
-
documentId: entry.documentId,
|
|
114
|
-
locale: entry.locale,
|
|
115
|
-
status: "published",
|
|
116
|
-
fields: ["updatedAt"]
|
|
117
|
-
});
|
|
118
|
-
if (!publishedEntry) {
|
|
119
|
-
return "draft";
|
|
120
|
-
}
|
|
121
|
-
const entryUpdatedAt = new Date(entry.updatedAt).getTime();
|
|
122
|
-
const publishedEntryUpdatedAt = new Date(publishedEntry.updatedAt).getTime();
|
|
123
|
-
if (entryUpdatedAt > publishedEntryUpdatedAt) {
|
|
124
|
-
return "modified";
|
|
125
|
-
}
|
|
126
|
-
return "published";
|
|
127
|
-
};
|
|
128
80
|
async function deleteActionsOnDisableDraftAndPublish({
|
|
129
81
|
oldContentTypes,
|
|
130
82
|
contentTypes: contentTypes2
|
|
@@ -146,7 +98,7 @@ async function deleteActionsOnDisableDraftAndPublish({
|
|
|
146
98
|
async function deleteActionsOnDeleteContentType({ oldContentTypes, contentTypes: contentTypes2 }) {
|
|
147
99
|
const deletedContentTypes = difference(keys(oldContentTypes), keys(contentTypes2)) ?? [];
|
|
148
100
|
if (deletedContentTypes.length) {
|
|
149
|
-
await
|
|
101
|
+
await mapAsync(deletedContentTypes, async (deletedContentTypeUID) => {
|
|
150
102
|
return strapi.db?.queryBuilder(RELEASE_ACTION_MODEL_UID).delete().where({ contentType: deletedContentTypeUID }).execute();
|
|
151
103
|
});
|
|
152
104
|
}
|
|
@@ -165,27 +117,25 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
165
117
|
}
|
|
166
118
|
}
|
|
167
119
|
});
|
|
168
|
-
|
|
120
|
+
mapAsync(releasesWithoutStatus, async (release2) => {
|
|
169
121
|
const actions = release2.actions;
|
|
170
122
|
const notValidatedActions = actions.filter((action) => action.isEntryValid === null);
|
|
171
123
|
for (const action of notValidatedActions) {
|
|
172
124
|
if (action.entry) {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
contentType: action.contentType,
|
|
176
|
-
documentId: action.entryDocumentId,
|
|
177
|
-
locale: action.locale
|
|
178
|
-
},
|
|
179
|
-
{ strapi }
|
|
180
|
-
);
|
|
181
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
182
|
-
where: {
|
|
183
|
-
id: action.id
|
|
184
|
-
},
|
|
185
|
-
data: {
|
|
186
|
-
isEntryValid: isEntryValid2
|
|
187
|
-
}
|
|
125
|
+
const populatedEntry = await getPopulatedEntry(action.contentType, action.entry.id, {
|
|
126
|
+
strapi
|
|
188
127
|
});
|
|
128
|
+
if (populatedEntry) {
|
|
129
|
+
const isEntryValid = getEntryValidStatus(action.contentType, populatedEntry, { strapi });
|
|
130
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
131
|
+
where: {
|
|
132
|
+
id: action.id
|
|
133
|
+
},
|
|
134
|
+
data: {
|
|
135
|
+
isEntryValid
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
189
139
|
}
|
|
190
140
|
}
|
|
191
141
|
return getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
@@ -198,7 +148,7 @@ async function migrateIsValidAndStatusReleases() {
|
|
|
198
148
|
}
|
|
199
149
|
}
|
|
200
150
|
});
|
|
201
|
-
|
|
151
|
+
mapAsync(publishedReleases, async (release2) => {
|
|
202
152
|
return strapi.db.query(RELEASE_MODEL_UID).update({
|
|
203
153
|
where: {
|
|
204
154
|
id: release2.id
|
|
@@ -215,7 +165,7 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
215
165
|
(uid) => oldContentTypes[uid]?.options?.draftAndPublish
|
|
216
166
|
);
|
|
217
167
|
const releasesAffected = /* @__PURE__ */ new Set();
|
|
218
|
-
|
|
168
|
+
mapAsync(contentTypesWithDraftAndPublish, async (contentTypeUID) => {
|
|
219
169
|
const oldContentType = oldContentTypes[contentTypeUID];
|
|
220
170
|
const contentType = contentTypes2[contentTypeUID];
|
|
221
171
|
if (!isEqual(oldContentType?.attributes, contentType?.attributes)) {
|
|
@@ -228,30 +178,30 @@ async function revalidateChangedContentTypes({ oldContentTypes, contentTypes: co
|
|
|
228
178
|
release: true
|
|
229
179
|
}
|
|
230
180
|
});
|
|
231
|
-
await
|
|
232
|
-
if (action.entry && action.release
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
contentType: contentTypeUID,
|
|
236
|
-
documentId: action.entryDocumentId,
|
|
237
|
-
locale: action.locale
|
|
238
|
-
},
|
|
239
|
-
{ strapi }
|
|
240
|
-
);
|
|
241
|
-
releasesAffected.add(action.release.id);
|
|
242
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
243
|
-
where: {
|
|
244
|
-
id: action.id
|
|
245
|
-
},
|
|
246
|
-
data: {
|
|
247
|
-
isEntryValid: isEntryValid2
|
|
248
|
-
}
|
|
181
|
+
await mapAsync(actions, async (action) => {
|
|
182
|
+
if (action.entry && action.release) {
|
|
183
|
+
const populatedEntry = await getPopulatedEntry(contentTypeUID, action.entry.id, {
|
|
184
|
+
strapi
|
|
249
185
|
});
|
|
186
|
+
if (populatedEntry) {
|
|
187
|
+
const isEntryValid = await getEntryValidStatus(contentTypeUID, populatedEntry, {
|
|
188
|
+
strapi
|
|
189
|
+
});
|
|
190
|
+
releasesAffected.add(action.release.id);
|
|
191
|
+
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
192
|
+
where: {
|
|
193
|
+
id: action.id
|
|
194
|
+
},
|
|
195
|
+
data: {
|
|
196
|
+
isEntryValid
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
250
200
|
}
|
|
251
201
|
});
|
|
252
202
|
}
|
|
253
203
|
}).then(() => {
|
|
254
|
-
|
|
204
|
+
mapAsync(releasesAffected, async (releaseId) => {
|
|
255
205
|
return getService("release", { strapi }).updateReleaseStatus(releaseId);
|
|
256
206
|
});
|
|
257
207
|
});
|
|
@@ -303,39 +253,11 @@ async function enableContentTypeLocalized({ oldContentTypes, contentTypes: conte
|
|
|
303
253
|
}
|
|
304
254
|
}
|
|
305
255
|
}
|
|
306
|
-
const
|
|
307
|
-
name: "content-releases::5.0.0-add-entry-document-id-to-release-actions",
|
|
308
|
-
async up(trx, db) {
|
|
309
|
-
const hasPolymorphicColumn = await trx.schema.hasColumn("strapi_release_actions", "target_id");
|
|
310
|
-
if (hasPolymorphicColumn) {
|
|
311
|
-
const hasEntryDocumentIdColumn = await trx.schema.hasColumn(
|
|
312
|
-
"strapi_release_actions",
|
|
313
|
-
"entry_document_id"
|
|
314
|
-
);
|
|
315
|
-
if (!hasEntryDocumentIdColumn) {
|
|
316
|
-
await trx.schema.alterTable("strapi_release_actions", (table) => {
|
|
317
|
-
table.string("entry_document_id");
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
const releaseActions = await trx.select("*").from("strapi_release_actions");
|
|
321
|
-
async.map(releaseActions, async (action) => {
|
|
322
|
-
const { target_type, target_id } = action;
|
|
323
|
-
const entry = await db.query(target_type).findOne({ where: { id: target_id } });
|
|
324
|
-
if (entry) {
|
|
325
|
-
await trx("strapi_release_actions").update({ entry_document_id: entry.documentId }).where("id", action.id);
|
|
326
|
-
}
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
async down() {
|
|
331
|
-
throw new Error("not implemented");
|
|
332
|
-
}
|
|
333
|
-
};
|
|
256
|
+
const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
|
|
334
257
|
const register = async ({ strapi: strapi2 }) => {
|
|
335
|
-
if (
|
|
336
|
-
await strapi2.
|
|
337
|
-
strapi2.
|
|
338
|
-
strapi2.hook("strapi::content-types.beforeSync").register(disableContentTypeLocalized).register(deleteActionsOnDisableDraftAndPublish);
|
|
258
|
+
if (features$2.isEnabled("cms-content-releases")) {
|
|
259
|
+
await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
|
|
260
|
+
strapi2.hook("strapi::content-types.beforeSync").register(deleteActionsOnDisableDraftAndPublish).register(disableContentTypeLocalized);
|
|
339
261
|
strapi2.hook("strapi::content-types.afterSync").register(deleteActionsOnDeleteContentType).register(enableContentTypeLocalized).register(revalidateChangedContentTypes).register(migrateIsValidAndStatusReleases);
|
|
340
262
|
}
|
|
341
263
|
if (strapi2.plugin("graphql")) {
|
|
@@ -344,134 +266,129 @@ const register = async ({ strapi: strapi2 }) => {
|
|
|
344
266
|
graphqlExtensionService.shadowCRUD(RELEASE_ACTION_MODEL_UID).disable();
|
|
345
267
|
}
|
|
346
268
|
};
|
|
347
|
-
const
|
|
348
|
-
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
349
|
-
where: {
|
|
350
|
-
actions: {
|
|
351
|
-
contentType,
|
|
352
|
-
entryDocumentId: entry.documentId,
|
|
353
|
-
locale: entry.locale
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
const entryStatus = await isEntryValid(contentType, entry, { strapi });
|
|
358
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
359
|
-
where: {
|
|
360
|
-
contentType,
|
|
361
|
-
entryDocumentId: entry.documentId,
|
|
362
|
-
locale: entry.locale
|
|
363
|
-
},
|
|
364
|
-
data: {
|
|
365
|
-
isEntryValid: entryStatus
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
for (const release2 of releases) {
|
|
369
|
-
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
const deleteActionsAndUpdateReleaseStatus = async (params) => {
|
|
373
|
-
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
374
|
-
where: {
|
|
375
|
-
actions: params
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
379
|
-
where: params
|
|
380
|
-
});
|
|
381
|
-
for (const release2 of releases) {
|
|
382
|
-
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
const deleteActionsOnDelete = async (ctx, next) => {
|
|
386
|
-
if (ctx.action !== "delete") {
|
|
387
|
-
return next();
|
|
388
|
-
}
|
|
389
|
-
if (!contentTypes$1.hasDraftAndPublish(ctx.contentType)) {
|
|
390
|
-
return next();
|
|
391
|
-
}
|
|
392
|
-
const contentType = ctx.contentType.uid;
|
|
393
|
-
const { documentId, locale } = ctx.params;
|
|
394
|
-
const result = await next();
|
|
395
|
-
if (!result) {
|
|
396
|
-
return result;
|
|
397
|
-
}
|
|
398
|
-
try {
|
|
399
|
-
deleteActionsAndUpdateReleaseStatus({
|
|
400
|
-
contentType,
|
|
401
|
-
entryDocumentId: documentId,
|
|
402
|
-
...locale !== "*" && { locale }
|
|
403
|
-
});
|
|
404
|
-
} catch (error) {
|
|
405
|
-
strapi.log.error("Error while deleting release actions after delete", {
|
|
406
|
-
error
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
return result;
|
|
410
|
-
};
|
|
411
|
-
const updateActionsOnUpdate = async (ctx, next) => {
|
|
412
|
-
if (ctx.action !== "update") {
|
|
413
|
-
return next();
|
|
414
|
-
}
|
|
415
|
-
if (!contentTypes$1.hasDraftAndPublish(ctx.contentType)) {
|
|
416
|
-
return next();
|
|
417
|
-
}
|
|
418
|
-
const contentType = ctx.contentType.uid;
|
|
419
|
-
const result = await next();
|
|
420
|
-
if (!result) {
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
try {
|
|
424
|
-
updateActionsStatusAndUpdateReleaseStatus(contentType, result);
|
|
425
|
-
} catch (error) {
|
|
426
|
-
strapi.log.error("Error while updating release actions after update", {
|
|
427
|
-
error
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
return result;
|
|
431
|
-
};
|
|
432
|
-
const deleteReleasesActionsAndUpdateReleaseStatus = async (params) => {
|
|
433
|
-
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
|
|
434
|
-
where: {
|
|
435
|
-
actions: params
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
await strapi.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
439
|
-
where: params
|
|
440
|
-
});
|
|
441
|
-
for (const release2 of releases) {
|
|
442
|
-
getService("release", { strapi }).updateReleaseStatus(release2.id);
|
|
443
|
-
}
|
|
444
|
-
};
|
|
269
|
+
const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
|
|
445
270
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
446
|
-
if (
|
|
271
|
+
if (features$1.isEnabled("cms-content-releases")) {
|
|
447
272
|
const contentTypesWithDraftAndPublish = Object.keys(strapi2.contentTypes).filter(
|
|
448
273
|
(uid) => strapi2.contentTypes[uid]?.options?.draftAndPublish
|
|
449
274
|
);
|
|
450
275
|
strapi2.db.lifecycles.subscribe({
|
|
451
276
|
models: contentTypesWithDraftAndPublish,
|
|
277
|
+
async afterDelete(event) {
|
|
278
|
+
try {
|
|
279
|
+
const { model, result } = event;
|
|
280
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
281
|
+
const { id } = result;
|
|
282
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
283
|
+
where: {
|
|
284
|
+
actions: {
|
|
285
|
+
target_type: model.uid,
|
|
286
|
+
target_id: id
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
291
|
+
where: {
|
|
292
|
+
target_type: model.uid,
|
|
293
|
+
target_id: id
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
for (const release2 of releases) {
|
|
297
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
} catch (error) {
|
|
301
|
+
strapi2.log.error("Error while deleting release actions after entry delete", { error });
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
/**
|
|
305
|
+
* deleteMany hook doesn't return the deleted entries ids
|
|
306
|
+
* so we need to fetch them before deleting the entries to save the ids on our state
|
|
307
|
+
*/
|
|
308
|
+
async beforeDeleteMany(event) {
|
|
309
|
+
const { model, params } = event;
|
|
310
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
311
|
+
const { where } = params;
|
|
312
|
+
const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
|
|
313
|
+
event.state.entriesToDelete = entriesToDelete;
|
|
314
|
+
}
|
|
315
|
+
},
|
|
452
316
|
/**
|
|
453
|
-
*
|
|
317
|
+
* We delete the release actions related to deleted entries
|
|
318
|
+
* We make this only after deleteMany is succesfully executed to avoid errors
|
|
454
319
|
*/
|
|
455
320
|
async afterDeleteMany(event) {
|
|
456
321
|
try {
|
|
457
|
-
const model =
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
322
|
+
const { model, state } = event;
|
|
323
|
+
const entriesToDelete = state.entriesToDelete;
|
|
324
|
+
if (entriesToDelete) {
|
|
325
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
326
|
+
where: {
|
|
327
|
+
actions: {
|
|
328
|
+
target_type: model.uid,
|
|
329
|
+
target_id: {
|
|
330
|
+
$in: entriesToDelete.map(
|
|
331
|
+
(entry) => entry.id
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
|
|
338
|
+
where: {
|
|
339
|
+
target_type: model.uid,
|
|
340
|
+
target_id: {
|
|
341
|
+
$in: entriesToDelete.map((entry) => entry.id)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
464
344
|
});
|
|
345
|
+
for (const release2 of releases) {
|
|
346
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
347
|
+
}
|
|
465
348
|
}
|
|
466
349
|
} catch (error) {
|
|
467
350
|
strapi2.log.error("Error while deleting release actions after entry deleteMany", {
|
|
468
351
|
error
|
|
469
352
|
});
|
|
470
353
|
}
|
|
354
|
+
},
|
|
355
|
+
async afterUpdate(event) {
|
|
356
|
+
try {
|
|
357
|
+
const { model, result } = event;
|
|
358
|
+
if (model.kind === "collectionType" && model.options?.draftAndPublish) {
|
|
359
|
+
const isEntryValid = await getEntryValidStatus(
|
|
360
|
+
model.uid,
|
|
361
|
+
result,
|
|
362
|
+
{
|
|
363
|
+
strapi: strapi2
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
367
|
+
where: {
|
|
368
|
+
target_type: model.uid,
|
|
369
|
+
target_id: result.id
|
|
370
|
+
},
|
|
371
|
+
data: {
|
|
372
|
+
isEntryValid
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
376
|
+
where: {
|
|
377
|
+
actions: {
|
|
378
|
+
target_type: model.uid,
|
|
379
|
+
target_id: result.id
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
for (const release2 of releases) {
|
|
384
|
+
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
} catch (error) {
|
|
388
|
+
strapi2.log.error("Error while updating release actions after entry update", { error });
|
|
389
|
+
}
|
|
471
390
|
}
|
|
472
391
|
});
|
|
473
|
-
strapi2.documents.use(deleteActionsOnDelete);
|
|
474
|
-
strapi2.documents.use(updateActionsOnUpdate);
|
|
475
392
|
getService("scheduling", { strapi: strapi2 }).syncFromDatabase().catch((err) => {
|
|
476
393
|
strapi2.log.error(
|
|
477
394
|
"Error while syncing scheduled jobs from the database in the content-releases plugin. This could lead to errors in the releases scheduling."
|
|
@@ -479,7 +396,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
479
396
|
throw err;
|
|
480
397
|
});
|
|
481
398
|
Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
|
|
482
|
-
strapi2.
|
|
399
|
+
strapi2.webhookStore.addAllowedEvent(key, value);
|
|
483
400
|
});
|
|
484
401
|
}
|
|
485
402
|
};
|
|
@@ -563,13 +480,15 @@ const schema = {
|
|
|
563
480
|
enum: ["publish", "unpublish"],
|
|
564
481
|
required: true
|
|
565
482
|
},
|
|
483
|
+
entry: {
|
|
484
|
+
type: "relation",
|
|
485
|
+
relation: "morphToOne",
|
|
486
|
+
configurable: false
|
|
487
|
+
},
|
|
566
488
|
contentType: {
|
|
567
489
|
type: "string",
|
|
568
490
|
required: true
|
|
569
491
|
},
|
|
570
|
-
entryDocumentId: {
|
|
571
|
-
type: "string"
|
|
572
|
-
},
|
|
573
492
|
locale: {
|
|
574
493
|
type: "string"
|
|
575
494
|
},
|
|
@@ -591,6 +510,18 @@ const contentTypes = {
|
|
|
591
510
|
release: release$1,
|
|
592
511
|
"release-action": releaseAction$1
|
|
593
512
|
};
|
|
513
|
+
const getGroupName = (queryValue) => {
|
|
514
|
+
switch (queryValue) {
|
|
515
|
+
case "contentType":
|
|
516
|
+
return "contentType.displayName";
|
|
517
|
+
case "action":
|
|
518
|
+
return "type";
|
|
519
|
+
case "locale":
|
|
520
|
+
return _.getOr("No locale", "locale.name");
|
|
521
|
+
default:
|
|
522
|
+
return "contentType.displayName";
|
|
523
|
+
}
|
|
524
|
+
};
|
|
594
525
|
const createReleaseService = ({ strapi: strapi2 }) => {
|
|
595
526
|
const dispatchWebhook = (event, { isPublished, release: release2, error }) => {
|
|
596
527
|
strapi2.eventHub.emit(event, {
|
|
@@ -599,32 +530,93 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
599
530
|
release: release2
|
|
600
531
|
});
|
|
601
532
|
};
|
|
533
|
+
const publishSingleTypeAction = async (uid, actionType, entryId) => {
|
|
534
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
535
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
536
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
537
|
+
const entry = await strapi2.entityService.findOne(uid, entryId, { populate });
|
|
538
|
+
try {
|
|
539
|
+
if (actionType === "publish") {
|
|
540
|
+
await entityManagerService.publish(entry, uid);
|
|
541
|
+
} else {
|
|
542
|
+
await entityManagerService.unpublish(entry, uid);
|
|
543
|
+
}
|
|
544
|
+
} catch (error) {
|
|
545
|
+
if (error instanceof errors.ApplicationError && (error.message === "already.published" || error.message === "already.draft"))
|
|
546
|
+
;
|
|
547
|
+
else {
|
|
548
|
+
throw error;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
const publishCollectionTypeAction = async (uid, entriesToPublishIds, entriestoUnpublishIds) => {
|
|
553
|
+
const entityManagerService = strapi2.plugin("content-manager").service("entity-manager");
|
|
554
|
+
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
555
|
+
const populate = await populateBuilderService(uid).populateDeep(Infinity).build();
|
|
556
|
+
const entriesToPublish = await strapi2.entityService.findMany(uid, {
|
|
557
|
+
filters: {
|
|
558
|
+
id: {
|
|
559
|
+
$in: entriesToPublishIds
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
populate
|
|
563
|
+
});
|
|
564
|
+
const entriesToUnpublish = await strapi2.entityService.findMany(uid, {
|
|
565
|
+
filters: {
|
|
566
|
+
id: {
|
|
567
|
+
$in: entriestoUnpublishIds
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
populate
|
|
571
|
+
});
|
|
572
|
+
if (entriesToPublish.length > 0) {
|
|
573
|
+
await entityManagerService.publishMany(entriesToPublish, uid);
|
|
574
|
+
}
|
|
575
|
+
if (entriesToUnpublish.length > 0) {
|
|
576
|
+
await entityManagerService.unpublishMany(entriesToUnpublish, uid);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
602
579
|
const getFormattedActions = async (releaseId) => {
|
|
603
580
|
const actions = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findMany({
|
|
604
581
|
where: {
|
|
605
582
|
release: {
|
|
606
583
|
id: releaseId
|
|
607
584
|
}
|
|
585
|
+
},
|
|
586
|
+
populate: {
|
|
587
|
+
entry: {
|
|
588
|
+
fields: ["id"]
|
|
589
|
+
}
|
|
608
590
|
}
|
|
609
591
|
});
|
|
610
592
|
if (actions.length === 0) {
|
|
611
593
|
throw new errors.ValidationError("No entries to publish");
|
|
612
594
|
}
|
|
613
|
-
const
|
|
595
|
+
const collectionTypeActions = {};
|
|
596
|
+
const singleTypeActions = [];
|
|
614
597
|
for (const action of actions) {
|
|
615
598
|
const contentTypeUid = action.contentType;
|
|
616
|
-
if (
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
599
|
+
if (strapi2.contentTypes[contentTypeUid].kind === "collectionType") {
|
|
600
|
+
if (!collectionTypeActions[contentTypeUid]) {
|
|
601
|
+
collectionTypeActions[contentTypeUid] = {
|
|
602
|
+
entriesToPublishIds: [],
|
|
603
|
+
entriesToUnpublishIds: []
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
if (action.type === "publish") {
|
|
607
|
+
collectionTypeActions[contentTypeUid].entriesToPublishIds.push(action.entry.id);
|
|
608
|
+
} else {
|
|
609
|
+
collectionTypeActions[contentTypeUid].entriesToUnpublishIds.push(action.entry.id);
|
|
610
|
+
}
|
|
611
|
+
} else {
|
|
612
|
+
singleTypeActions.push({
|
|
613
|
+
uid: contentTypeUid,
|
|
614
|
+
action: action.type,
|
|
615
|
+
id: action.entry.id
|
|
616
|
+
});
|
|
621
617
|
}
|
|
622
|
-
formattedActions[contentTypeUid][action.type].push({
|
|
623
|
-
documentId: action.entryDocumentId,
|
|
624
|
-
locale: action.locale
|
|
625
|
-
});
|
|
626
618
|
}
|
|
627
|
-
return
|
|
619
|
+
return { collectionTypeActions, singleTypeActions };
|
|
628
620
|
};
|
|
629
621
|
return {
|
|
630
622
|
async create(releaseData, { user }) {
|
|
@@ -639,7 +631,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
639
631
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name),
|
|
640
632
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
641
633
|
]);
|
|
642
|
-
const release2 = await strapi2.
|
|
634
|
+
const release2 = await strapi2.entityService.create(RELEASE_MODEL_UID, {
|
|
643
635
|
data: {
|
|
644
636
|
...releaseWithCreatorFields,
|
|
645
637
|
status: "empty"
|
|
@@ -653,28 +645,107 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
653
645
|
return release2;
|
|
654
646
|
},
|
|
655
647
|
async findOne(id, query = {}) {
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
...dbQuery,
|
|
659
|
-
where: { id }
|
|
648
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id, {
|
|
649
|
+
...query
|
|
660
650
|
});
|
|
661
651
|
return release2;
|
|
662
652
|
},
|
|
663
653
|
findPage(query) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
...dbQuery,
|
|
654
|
+
return strapi2.entityService.findPage(RELEASE_MODEL_UID, {
|
|
655
|
+
...query,
|
|
667
656
|
populate: {
|
|
668
657
|
actions: {
|
|
658
|
+
// @ts-expect-error Ignore missing properties
|
|
669
659
|
count: true
|
|
670
660
|
}
|
|
671
661
|
}
|
|
672
662
|
});
|
|
673
663
|
},
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
664
|
+
async findManyWithContentTypeEntryAttached(contentTypeUid, entriesIds) {
|
|
665
|
+
let entries = entriesIds;
|
|
666
|
+
if (!Array.isArray(entriesIds)) {
|
|
667
|
+
entries = [entriesIds];
|
|
668
|
+
}
|
|
669
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
670
|
+
where: {
|
|
671
|
+
actions: {
|
|
672
|
+
target_type: contentTypeUid,
|
|
673
|
+
target_id: {
|
|
674
|
+
$in: entries
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
releasedAt: {
|
|
678
|
+
$null: true
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
populate: {
|
|
682
|
+
// Filter the action to get only the content type entry
|
|
683
|
+
actions: {
|
|
684
|
+
where: {
|
|
685
|
+
target_type: contentTypeUid,
|
|
686
|
+
target_id: {
|
|
687
|
+
$in: entries
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
populate: {
|
|
691
|
+
entry: {
|
|
692
|
+
select: ["id"]
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
return releases.map((release2) => {
|
|
699
|
+
if (release2.actions?.length) {
|
|
700
|
+
const actionsForEntry = release2.actions;
|
|
701
|
+
delete release2.actions;
|
|
702
|
+
return {
|
|
703
|
+
...release2,
|
|
704
|
+
actions: actionsForEntry
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
return release2;
|
|
708
|
+
});
|
|
709
|
+
},
|
|
710
|
+
async findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId) {
|
|
711
|
+
const releasesRelated = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
712
|
+
where: {
|
|
713
|
+
releasedAt: {
|
|
714
|
+
$null: true
|
|
715
|
+
},
|
|
716
|
+
actions: {
|
|
717
|
+
target_type: contentTypeUid,
|
|
718
|
+
target_id: entryId
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
const releases = await strapi2.db.query(RELEASE_MODEL_UID).findMany({
|
|
723
|
+
where: {
|
|
724
|
+
$or: [
|
|
725
|
+
{
|
|
726
|
+
id: {
|
|
727
|
+
$notIn: releasesRelated.map((release2) => release2.id)
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
actions: null
|
|
732
|
+
}
|
|
733
|
+
],
|
|
734
|
+
releasedAt: {
|
|
735
|
+
$null: true
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
return releases.map((release2) => {
|
|
740
|
+
if (release2.actions?.length) {
|
|
741
|
+
const [actionForEntry] = release2.actions;
|
|
742
|
+
delete release2.actions;
|
|
743
|
+
return {
|
|
744
|
+
...release2,
|
|
745
|
+
action: actionForEntry
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
return release2;
|
|
678
749
|
});
|
|
679
750
|
},
|
|
680
751
|
async update(id, releaseData, { user }) {
|
|
@@ -689,15 +760,19 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
689
760
|
validateUniqueNameForPendingRelease(releaseWithCreatorFields.name, id),
|
|
690
761
|
validateScheduledAtIsLaterThanNow(releaseWithCreatorFields.scheduledAt)
|
|
691
762
|
]);
|
|
692
|
-
const release2 = await strapi2.
|
|
763
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id);
|
|
693
764
|
if (!release2) {
|
|
694
765
|
throw new errors.NotFoundError(`No release found for id ${id}`);
|
|
695
766
|
}
|
|
696
767
|
if (release2.releasedAt) {
|
|
697
768
|
throw new errors.ValidationError("Release already published");
|
|
698
769
|
}
|
|
699
|
-
const updatedRelease = await strapi2.
|
|
700
|
-
|
|
770
|
+
const updatedRelease = await strapi2.entityService.update(RELEASE_MODEL_UID, id, {
|
|
771
|
+
/*
|
|
772
|
+
* The type returned from the entity service: Partial<Input<"plugin::content-releases.release">>
|
|
773
|
+
* is not compatible with the type we are passing here: UpdateRelease.Request['body']
|
|
774
|
+
*/
|
|
775
|
+
// @ts-expect-error see above
|
|
701
776
|
data: releaseWithCreatorFields
|
|
702
777
|
});
|
|
703
778
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
@@ -710,6 +785,132 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
710
785
|
strapi2.telemetry.send("didUpdateContentRelease");
|
|
711
786
|
return updatedRelease;
|
|
712
787
|
},
|
|
788
|
+
async createAction(releaseId, action, { disableUpdateReleaseStatus = false } = {}) {
|
|
789
|
+
const { validateEntryContentType, validateUniqueEntry } = getService("release-validation", {
|
|
790
|
+
strapi: strapi2
|
|
791
|
+
});
|
|
792
|
+
await Promise.all([
|
|
793
|
+
validateEntryContentType(action.entry.contentType),
|
|
794
|
+
validateUniqueEntry(releaseId, action)
|
|
795
|
+
]);
|
|
796
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId);
|
|
797
|
+
if (!release2) {
|
|
798
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
799
|
+
}
|
|
800
|
+
if (release2.releasedAt) {
|
|
801
|
+
throw new errors.ValidationError("Release already published");
|
|
802
|
+
}
|
|
803
|
+
const { entry, type } = action;
|
|
804
|
+
const populatedEntry = await getPopulatedEntry(entry.contentType, entry.id, { strapi: strapi2 });
|
|
805
|
+
const isEntryValid = await getEntryValidStatus(entry.contentType, populatedEntry, { strapi: strapi2 });
|
|
806
|
+
const releaseAction2 = await strapi2.entityService.create(RELEASE_ACTION_MODEL_UID, {
|
|
807
|
+
data: {
|
|
808
|
+
type,
|
|
809
|
+
contentType: entry.contentType,
|
|
810
|
+
locale: entry.locale,
|
|
811
|
+
isEntryValid,
|
|
812
|
+
entry: {
|
|
813
|
+
id: entry.id,
|
|
814
|
+
__type: entry.contentType,
|
|
815
|
+
__pivot: { field: "entry" }
|
|
816
|
+
},
|
|
817
|
+
release: releaseId
|
|
818
|
+
},
|
|
819
|
+
populate: { release: { fields: ["id"] }, entry: { fields: ["id"] } }
|
|
820
|
+
});
|
|
821
|
+
if (!disableUpdateReleaseStatus) {
|
|
822
|
+
this.updateReleaseStatus(releaseId);
|
|
823
|
+
}
|
|
824
|
+
return releaseAction2;
|
|
825
|
+
},
|
|
826
|
+
async findActions(releaseId, query) {
|
|
827
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
828
|
+
fields: ["id"]
|
|
829
|
+
});
|
|
830
|
+
if (!release2) {
|
|
831
|
+
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
832
|
+
}
|
|
833
|
+
return strapi2.entityService.findPage(RELEASE_ACTION_MODEL_UID, {
|
|
834
|
+
...query,
|
|
835
|
+
populate: {
|
|
836
|
+
entry: {
|
|
837
|
+
populate: "*"
|
|
838
|
+
}
|
|
839
|
+
},
|
|
840
|
+
filters: {
|
|
841
|
+
release: releaseId
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
},
|
|
845
|
+
async countActions(query) {
|
|
846
|
+
return strapi2.entityService.count(RELEASE_ACTION_MODEL_UID, query);
|
|
847
|
+
},
|
|
848
|
+
async groupActions(actions, groupBy) {
|
|
849
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
850
|
+
if (!acc.includes(action.contentType)) {
|
|
851
|
+
acc.push(action.contentType);
|
|
852
|
+
}
|
|
853
|
+
return acc;
|
|
854
|
+
}, []);
|
|
855
|
+
const allReleaseContentTypesDictionary = await this.getContentTypesDataForActions(
|
|
856
|
+
contentTypeUids
|
|
857
|
+
);
|
|
858
|
+
const allLocalesDictionary = await this.getLocalesDataForActions();
|
|
859
|
+
const formattedData = actions.map((action) => {
|
|
860
|
+
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
861
|
+
return {
|
|
862
|
+
...action,
|
|
863
|
+
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
864
|
+
contentType: {
|
|
865
|
+
displayName,
|
|
866
|
+
mainFieldValue: action.entry[mainField],
|
|
867
|
+
uid: action.contentType
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
});
|
|
871
|
+
const groupName = getGroupName(groupBy);
|
|
872
|
+
return _.groupBy(groupName)(formattedData);
|
|
873
|
+
},
|
|
874
|
+
async getLocalesDataForActions() {
|
|
875
|
+
if (!strapi2.plugin("i18n")) {
|
|
876
|
+
return {};
|
|
877
|
+
}
|
|
878
|
+
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
879
|
+
return allLocales.reduce((acc, locale) => {
|
|
880
|
+
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
881
|
+
return acc;
|
|
882
|
+
}, {});
|
|
883
|
+
},
|
|
884
|
+
async getContentTypesDataForActions(contentTypesUids) {
|
|
885
|
+
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
886
|
+
const contentTypesData = {};
|
|
887
|
+
for (const contentTypeUid of contentTypesUids) {
|
|
888
|
+
const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({
|
|
889
|
+
uid: contentTypeUid
|
|
890
|
+
});
|
|
891
|
+
contentTypesData[contentTypeUid] = {
|
|
892
|
+
mainField: contentTypeConfig.settings.mainField,
|
|
893
|
+
displayName: strapi2.getModel(contentTypeUid).info.displayName
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
return contentTypesData;
|
|
897
|
+
},
|
|
898
|
+
getContentTypeModelsFromActions(actions) {
|
|
899
|
+
const contentTypeUids = actions.reduce((acc, action) => {
|
|
900
|
+
if (!acc.includes(action.contentType)) {
|
|
901
|
+
acc.push(action.contentType);
|
|
902
|
+
}
|
|
903
|
+
return acc;
|
|
904
|
+
}, []);
|
|
905
|
+
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
906
|
+
(acc, contentTypeUid) => {
|
|
907
|
+
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
908
|
+
return acc;
|
|
909
|
+
},
|
|
910
|
+
{}
|
|
911
|
+
);
|
|
912
|
+
return contentTypeModelsMap;
|
|
913
|
+
},
|
|
713
914
|
async getAllComponents() {
|
|
714
915
|
const contentManagerComponentsService = strapi2.plugin("content-manager").service("components");
|
|
715
916
|
const components = await contentManagerComponentsService.findAllComponents();
|
|
@@ -723,11 +924,10 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
723
924
|
return componentsMap;
|
|
724
925
|
},
|
|
725
926
|
async delete(releaseId) {
|
|
726
|
-
const release2 = await strapi2.
|
|
727
|
-
where: { id: releaseId },
|
|
927
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
728
928
|
populate: {
|
|
729
929
|
actions: {
|
|
730
|
-
|
|
930
|
+
fields: ["id"]
|
|
731
931
|
}
|
|
732
932
|
}
|
|
733
933
|
});
|
|
@@ -745,11 +945,7 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
745
945
|
}
|
|
746
946
|
}
|
|
747
947
|
});
|
|
748
|
-
await strapi2.
|
|
749
|
-
where: {
|
|
750
|
-
id: releaseId
|
|
751
|
-
}
|
|
752
|
-
});
|
|
948
|
+
await strapi2.entityService.delete(RELEASE_MODEL_UID, releaseId);
|
|
753
949
|
});
|
|
754
950
|
if (release2.scheduledAt) {
|
|
755
951
|
const schedulingService = getService("scheduling", { strapi: strapi2 });
|
|
@@ -775,19 +971,22 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
775
971
|
}
|
|
776
972
|
try {
|
|
777
973
|
strapi2.log.info(`[Content Releases] Starting to publish release ${lockedRelease.name}`);
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
async () => Promise.all(
|
|
781
|
-
Object.keys(formattedActions).map(async (contentTypeUid) => {
|
|
782
|
-
const contentType = contentTypeUid;
|
|
783
|
-
const { publish, unpublish } = formattedActions[contentType];
|
|
784
|
-
return Promise.all([
|
|
785
|
-
...publish.map((params) => strapi2.documents(contentType).publish(params)),
|
|
786
|
-
...unpublish.map((params) => strapi2.documents(contentType).unpublish(params))
|
|
787
|
-
]);
|
|
788
|
-
})
|
|
789
|
-
)
|
|
974
|
+
const { collectionTypeActions, singleTypeActions } = await getFormattedActions(
|
|
975
|
+
releaseId
|
|
790
976
|
);
|
|
977
|
+
await strapi2.db.transaction(async () => {
|
|
978
|
+
for (const { uid, action, id } of singleTypeActions) {
|
|
979
|
+
await publishSingleTypeAction(uid, action, id);
|
|
980
|
+
}
|
|
981
|
+
for (const contentTypeUid of Object.keys(collectionTypeActions)) {
|
|
982
|
+
const uid = contentTypeUid;
|
|
983
|
+
await publishCollectionTypeAction(
|
|
984
|
+
uid,
|
|
985
|
+
collectionTypeActions[uid].entriesToPublishIds,
|
|
986
|
+
collectionTypeActions[uid].entriesToUnpublishIds
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
});
|
|
791
990
|
const release22 = await strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
792
991
|
where: {
|
|
793
992
|
id: releaseId
|
|
@@ -817,226 +1016,13 @@ const createReleaseService = ({ strapi: strapi2 }) => {
|
|
|
817
1016
|
};
|
|
818
1017
|
}
|
|
819
1018
|
});
|
|
820
|
-
if (error
|
|
821
|
-
throw error;
|
|
822
|
-
}
|
|
823
|
-
return release2;
|
|
824
|
-
},
|
|
825
|
-
async updateReleaseStatus(releaseId) {
|
|
826
|
-
const releaseActionService = getService("release-action", { strapi: strapi2 });
|
|
827
|
-
const [totalActions, invalidActions] = await Promise.all([
|
|
828
|
-
releaseActionService.countActions({
|
|
829
|
-
filters: {
|
|
830
|
-
release: releaseId
|
|
831
|
-
}
|
|
832
|
-
}),
|
|
833
|
-
releaseActionService.countActions({
|
|
834
|
-
filters: {
|
|
835
|
-
release: releaseId,
|
|
836
|
-
isEntryValid: false
|
|
837
|
-
}
|
|
838
|
-
})
|
|
839
|
-
]);
|
|
840
|
-
if (totalActions > 0) {
|
|
841
|
-
if (invalidActions > 0) {
|
|
842
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
843
|
-
where: {
|
|
844
|
-
id: releaseId
|
|
845
|
-
},
|
|
846
|
-
data: {
|
|
847
|
-
status: "blocked"
|
|
848
|
-
}
|
|
849
|
-
});
|
|
850
|
-
}
|
|
851
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
852
|
-
where: {
|
|
853
|
-
id: releaseId
|
|
854
|
-
},
|
|
855
|
-
data: {
|
|
856
|
-
status: "ready"
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
861
|
-
where: {
|
|
862
|
-
id: releaseId
|
|
863
|
-
},
|
|
864
|
-
data: {
|
|
865
|
-
status: "empty"
|
|
866
|
-
}
|
|
867
|
-
});
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
};
|
|
871
|
-
const getGroupName = (queryValue) => {
|
|
872
|
-
switch (queryValue) {
|
|
873
|
-
case "contentType":
|
|
874
|
-
return "contentType.displayName";
|
|
875
|
-
case "type":
|
|
876
|
-
return "type";
|
|
877
|
-
case "locale":
|
|
878
|
-
return _.getOr("No locale", "locale.name");
|
|
879
|
-
default:
|
|
880
|
-
return "contentType.displayName";
|
|
881
|
-
}
|
|
882
|
-
};
|
|
883
|
-
const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
884
|
-
const getLocalesDataForActions = async () => {
|
|
885
|
-
if (!strapi2.plugin("i18n")) {
|
|
886
|
-
return {};
|
|
887
|
-
}
|
|
888
|
-
const allLocales = await strapi2.plugin("i18n").service("locales").find() || [];
|
|
889
|
-
return allLocales.reduce((acc, locale) => {
|
|
890
|
-
acc[locale.code] = { name: locale.name, code: locale.code };
|
|
891
|
-
return acc;
|
|
892
|
-
}, {});
|
|
893
|
-
};
|
|
894
|
-
const getContentTypesDataForActions = async (contentTypesUids) => {
|
|
895
|
-
const contentManagerContentTypeService = strapi2.plugin("content-manager").service("content-types");
|
|
896
|
-
const contentTypesData = {};
|
|
897
|
-
for (const contentTypeUid of contentTypesUids) {
|
|
898
|
-
const contentTypeConfig = await contentManagerContentTypeService.findConfiguration({
|
|
899
|
-
uid: contentTypeUid
|
|
900
|
-
});
|
|
901
|
-
contentTypesData[contentTypeUid] = {
|
|
902
|
-
mainField: contentTypeConfig.settings.mainField,
|
|
903
|
-
displayName: strapi2.getModel(contentTypeUid).info.displayName
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
return contentTypesData;
|
|
907
|
-
};
|
|
908
|
-
return {
|
|
909
|
-
async create(releaseId, action, { disableUpdateReleaseStatus = false } = {}) {
|
|
910
|
-
const { validateEntryData, validateUniqueEntry } = getService("release-validation", {
|
|
911
|
-
strapi: strapi2
|
|
912
|
-
});
|
|
913
|
-
await Promise.all([
|
|
914
|
-
validateEntryData(action.contentType, action.entryDocumentId),
|
|
915
|
-
validateUniqueEntry(releaseId, action)
|
|
916
|
-
]);
|
|
917
|
-
const model = strapi2.contentType(action.contentType);
|
|
918
|
-
if (model.kind === "singleType") {
|
|
919
|
-
const document = await strapi2.db.query(model.uid).findOne({ select: ["documentId"] });
|
|
920
|
-
if (!document) {
|
|
921
|
-
throw new errors.NotFoundError(`No entry found for contentType ${action.contentType}`);
|
|
922
|
-
}
|
|
923
|
-
action.entryDocumentId = document.documentId;
|
|
924
|
-
}
|
|
925
|
-
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({ where: { id: releaseId } });
|
|
926
|
-
if (!release2) {
|
|
927
|
-
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
928
|
-
}
|
|
929
|
-
if (release2.releasedAt) {
|
|
930
|
-
throw new errors.ValidationError("Release already published");
|
|
931
|
-
}
|
|
932
|
-
const actionStatus = action.type === "publish" ? await getDraftEntryValidStatus(
|
|
933
|
-
{
|
|
934
|
-
contentType: action.contentType,
|
|
935
|
-
documentId: action.entryDocumentId,
|
|
936
|
-
locale: action.locale
|
|
937
|
-
},
|
|
938
|
-
{
|
|
939
|
-
strapi: strapi2
|
|
940
|
-
}
|
|
941
|
-
) : true;
|
|
942
|
-
const releaseAction2 = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).create({
|
|
943
|
-
data: {
|
|
944
|
-
...action,
|
|
945
|
-
release: release2.id,
|
|
946
|
-
isEntryValid: actionStatus
|
|
947
|
-
},
|
|
948
|
-
populate: { release: { select: ["id"] } }
|
|
949
|
-
});
|
|
950
|
-
if (!disableUpdateReleaseStatus) {
|
|
951
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(release2.id);
|
|
952
|
-
}
|
|
953
|
-
return releaseAction2;
|
|
954
|
-
},
|
|
955
|
-
async findPage(releaseId, query) {
|
|
956
|
-
const release2 = await strapi2.db.query(RELEASE_MODEL_UID).findOne({
|
|
957
|
-
where: { id: releaseId },
|
|
958
|
-
select: ["id"]
|
|
959
|
-
});
|
|
960
|
-
if (!release2) {
|
|
961
|
-
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
1019
|
+
if (error) {
|
|
1020
|
+
throw error;
|
|
962
1021
|
}
|
|
963
|
-
|
|
964
|
-
const { results: actions, pagination } = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).findPage({
|
|
965
|
-
...dbQuery,
|
|
966
|
-
where: {
|
|
967
|
-
release: releaseId
|
|
968
|
-
}
|
|
969
|
-
});
|
|
970
|
-
const populateBuilderService = strapi2.plugin("content-manager").service("populate-builder");
|
|
971
|
-
const actionsWithEntry = await async.map(actions, async (action) => {
|
|
972
|
-
const populate = await populateBuilderService(action.contentType).populateDeep(Infinity).build();
|
|
973
|
-
const entry = await getEntry(
|
|
974
|
-
{
|
|
975
|
-
contentType: action.contentType,
|
|
976
|
-
documentId: action.entryDocumentId,
|
|
977
|
-
locale: action.locale,
|
|
978
|
-
populate,
|
|
979
|
-
status: action.type === "publish" ? "draft" : "published"
|
|
980
|
-
},
|
|
981
|
-
{ strapi: strapi2 }
|
|
982
|
-
);
|
|
983
|
-
return {
|
|
984
|
-
...action,
|
|
985
|
-
entry,
|
|
986
|
-
status: entry ? await getEntryStatus(action.contentType, entry) : null
|
|
987
|
-
};
|
|
988
|
-
});
|
|
989
|
-
return {
|
|
990
|
-
results: actionsWithEntry,
|
|
991
|
-
pagination
|
|
992
|
-
};
|
|
993
|
-
},
|
|
994
|
-
async groupActions(actions, groupBy) {
|
|
995
|
-
const contentTypeUids = actions.reduce((acc, action) => {
|
|
996
|
-
if (!acc.includes(action.contentType)) {
|
|
997
|
-
acc.push(action.contentType);
|
|
998
|
-
}
|
|
999
|
-
return acc;
|
|
1000
|
-
}, []);
|
|
1001
|
-
const allReleaseContentTypesDictionary = await getContentTypesDataForActions(contentTypeUids);
|
|
1002
|
-
const allLocalesDictionary = await getLocalesDataForActions();
|
|
1003
|
-
const formattedData = actions.map((action) => {
|
|
1004
|
-
const { mainField, displayName } = allReleaseContentTypesDictionary[action.contentType];
|
|
1005
|
-
return {
|
|
1006
|
-
...action,
|
|
1007
|
-
locale: action.locale ? allLocalesDictionary[action.locale] : null,
|
|
1008
|
-
contentType: {
|
|
1009
|
-
displayName,
|
|
1010
|
-
mainFieldValue: action.entry[mainField],
|
|
1011
|
-
uid: action.contentType
|
|
1012
|
-
}
|
|
1013
|
-
};
|
|
1014
|
-
});
|
|
1015
|
-
const groupName = getGroupName(groupBy);
|
|
1016
|
-
return _.groupBy(groupName)(formattedData);
|
|
1017
|
-
},
|
|
1018
|
-
getContentTypeModelsFromActions(actions) {
|
|
1019
|
-
const contentTypeUids = actions.reduce((acc, action) => {
|
|
1020
|
-
if (!acc.includes(action.contentType)) {
|
|
1021
|
-
acc.push(action.contentType);
|
|
1022
|
-
}
|
|
1023
|
-
return acc;
|
|
1024
|
-
}, []);
|
|
1025
|
-
const contentTypeModelsMap = contentTypeUids.reduce(
|
|
1026
|
-
(acc, contentTypeUid) => {
|
|
1027
|
-
acc[contentTypeUid] = strapi2.getModel(contentTypeUid);
|
|
1028
|
-
return acc;
|
|
1029
|
-
},
|
|
1030
|
-
{}
|
|
1031
|
-
);
|
|
1032
|
-
return contentTypeModelsMap;
|
|
1033
|
-
},
|
|
1034
|
-
async countActions(query) {
|
|
1035
|
-
const dbQuery = strapi2.get("query-params").transform(RELEASE_ACTION_MODEL_UID, query ?? {});
|
|
1036
|
-
return strapi2.db.query(RELEASE_ACTION_MODEL_UID).count(dbQuery);
|
|
1022
|
+
return release2;
|
|
1037
1023
|
},
|
|
1038
|
-
async
|
|
1039
|
-
const
|
|
1024
|
+
async updateAction(actionId, releaseId, update) {
|
|
1025
|
+
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
1040
1026
|
where: {
|
|
1041
1027
|
id: actionId,
|
|
1042
1028
|
release: {
|
|
@@ -1045,42 +1031,17 @@ const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
|
1045
1031
|
$null: true
|
|
1046
1032
|
}
|
|
1047
1033
|
}
|
|
1048
|
-
}
|
|
1034
|
+
},
|
|
1035
|
+
data: update
|
|
1049
1036
|
});
|
|
1050
|
-
if (!
|
|
1037
|
+
if (!updatedAction) {
|
|
1051
1038
|
throw new errors.NotFoundError(
|
|
1052
1039
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
1053
1040
|
);
|
|
1054
1041
|
}
|
|
1055
|
-
const actionStatus = update.type === "publish" ? await getDraftEntryValidStatus(
|
|
1056
|
-
{
|
|
1057
|
-
contentType: action.contentType,
|
|
1058
|
-
documentId: action.entryDocumentId,
|
|
1059
|
-
locale: action.locale
|
|
1060
|
-
},
|
|
1061
|
-
{
|
|
1062
|
-
strapi: strapi2
|
|
1063
|
-
}
|
|
1064
|
-
) : true;
|
|
1065
|
-
const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
|
|
1066
|
-
where: {
|
|
1067
|
-
id: actionId,
|
|
1068
|
-
release: {
|
|
1069
|
-
id: releaseId,
|
|
1070
|
-
releasedAt: {
|
|
1071
|
-
$null: true
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
},
|
|
1075
|
-
data: {
|
|
1076
|
-
...update,
|
|
1077
|
-
isEntryValid: actionStatus
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
getService("release", { strapi: strapi2 }).updateReleaseStatus(releaseId);
|
|
1081
1042
|
return updatedAction;
|
|
1082
1043
|
},
|
|
1083
|
-
async
|
|
1044
|
+
async deleteAction(actionId, releaseId) {
|
|
1084
1045
|
const deletedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).delete({
|
|
1085
1046
|
where: {
|
|
1086
1047
|
id: actionId,
|
|
@@ -1097,8 +1058,51 @@ const createReleaseActionService = ({ strapi: strapi2 }) => {
|
|
|
1097
1058
|
`Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
|
|
1098
1059
|
);
|
|
1099
1060
|
}
|
|
1100
|
-
|
|
1061
|
+
this.updateReleaseStatus(releaseId);
|
|
1101
1062
|
return deletedAction;
|
|
1063
|
+
},
|
|
1064
|
+
async updateReleaseStatus(releaseId) {
|
|
1065
|
+
const [totalActions, invalidActions] = await Promise.all([
|
|
1066
|
+
this.countActions({
|
|
1067
|
+
filters: {
|
|
1068
|
+
release: releaseId
|
|
1069
|
+
}
|
|
1070
|
+
}),
|
|
1071
|
+
this.countActions({
|
|
1072
|
+
filters: {
|
|
1073
|
+
release: releaseId,
|
|
1074
|
+
isEntryValid: false
|
|
1075
|
+
}
|
|
1076
|
+
})
|
|
1077
|
+
]);
|
|
1078
|
+
if (totalActions > 0) {
|
|
1079
|
+
if (invalidActions > 0) {
|
|
1080
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1081
|
+
where: {
|
|
1082
|
+
id: releaseId
|
|
1083
|
+
},
|
|
1084
|
+
data: {
|
|
1085
|
+
status: "blocked"
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1090
|
+
where: {
|
|
1091
|
+
id: releaseId
|
|
1092
|
+
},
|
|
1093
|
+
data: {
|
|
1094
|
+
status: "ready"
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
return strapi2.db.query(RELEASE_MODEL_UID).update({
|
|
1099
|
+
where: {
|
|
1100
|
+
id: releaseId
|
|
1101
|
+
},
|
|
1102
|
+
data: {
|
|
1103
|
+
status: "empty"
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1102
1106
|
}
|
|
1103
1107
|
};
|
|
1104
1108
|
};
|
|
@@ -1110,43 +1114,37 @@ class AlreadyOnReleaseError extends errors.ApplicationError {
|
|
|
1110
1114
|
}
|
|
1111
1115
|
const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
1112
1116
|
async validateUniqueEntry(releaseId, releaseActionArgs) {
|
|
1113
|
-
const release2 = await strapi2.
|
|
1114
|
-
|
|
1115
|
-
id: releaseId
|
|
1116
|
-
},
|
|
1117
|
-
populate: {
|
|
1118
|
-
actions: true
|
|
1119
|
-
}
|
|
1117
|
+
const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
|
1118
|
+
populate: { actions: { populate: { entry: { fields: ["id"] } } } }
|
|
1120
1119
|
});
|
|
1121
1120
|
if (!release2) {
|
|
1122
1121
|
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
|
1123
1122
|
}
|
|
1124
1123
|
const isEntryInRelease = release2.actions.some(
|
|
1125
|
-
(action) => action.
|
|
1124
|
+
(action) => Number(action.entry.id) === Number(releaseActionArgs.entry.id) && action.contentType === releaseActionArgs.entry.contentType
|
|
1126
1125
|
);
|
|
1127
1126
|
if (isEntryInRelease) {
|
|
1128
1127
|
throw new AlreadyOnReleaseError(
|
|
1129
|
-
`Entry with
|
|
1128
|
+
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
|
1130
1129
|
);
|
|
1131
1130
|
}
|
|
1132
1131
|
},
|
|
1133
|
-
|
|
1132
|
+
validateEntryContentType(contentTypeUid) {
|
|
1134
1133
|
const contentType = strapi2.contentType(contentTypeUid);
|
|
1135
1134
|
if (!contentType) {
|
|
1136
1135
|
throw new errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);
|
|
1137
1136
|
}
|
|
1138
|
-
if (!
|
|
1137
|
+
if (!contentType.options?.draftAndPublish) {
|
|
1139
1138
|
throw new errors.ValidationError(
|
|
1140
1139
|
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
|
1141
1140
|
);
|
|
1142
1141
|
}
|
|
1143
|
-
if (contentType.kind === "collectionType" && !entryDocumentId) {
|
|
1144
|
-
throw new errors.ValidationError("Document id is required for collection type");
|
|
1145
|
-
}
|
|
1146
1142
|
},
|
|
1147
1143
|
async validatePendingReleasesLimit() {
|
|
1148
|
-
const
|
|
1149
|
-
|
|
1144
|
+
const maximumPendingReleases = (
|
|
1145
|
+
// @ts-expect-error - options is not typed into features
|
|
1146
|
+
EE.features.get("cms-content-releases")?.options?.maximumReleases || 3
|
|
1147
|
+
);
|
|
1150
1148
|
const [, pendingReleasesCount] = await strapi2.db.query(RELEASE_MODEL_UID).findWithCount({
|
|
1151
1149
|
filters: {
|
|
1152
1150
|
releasedAt: {
|
|
@@ -1159,8 +1157,8 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
|
|
|
1159
1157
|
}
|
|
1160
1158
|
},
|
|
1161
1159
|
async validateUniqueNameForPendingRelease(name, id) {
|
|
1162
|
-
const pendingReleases = await strapi2.
|
|
1163
|
-
|
|
1160
|
+
const pendingReleases = await strapi2.entityService.findMany(RELEASE_MODEL_UID, {
|
|
1161
|
+
filters: {
|
|
1164
1162
|
releasedAt: {
|
|
1165
1163
|
$null: true
|
|
1166
1164
|
},
|
|
@@ -1189,7 +1187,7 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1189
1187
|
}
|
|
1190
1188
|
const job = scheduleJob(scheduleDate, async () => {
|
|
1191
1189
|
try {
|
|
1192
|
-
await getService("release"
|
|
1190
|
+
await getService("release").publish(releaseId);
|
|
1193
1191
|
} catch (error) {
|
|
1194
1192
|
}
|
|
1195
1193
|
this.cancel(releaseId);
|
|
@@ -1231,172 +1229,85 @@ const createSchedulingService = ({ strapi: strapi2 }) => {
|
|
|
1231
1229
|
}
|
|
1232
1230
|
};
|
|
1233
1231
|
};
|
|
1234
|
-
const DEFAULT_SETTINGS = {
|
|
1235
|
-
defaultTimezone: null
|
|
1236
|
-
};
|
|
1237
|
-
const createSettingsService = ({ strapi: strapi2 }) => {
|
|
1238
|
-
const getStore = async () => strapi2.store({ type: "core", name: "content-releases" });
|
|
1239
|
-
return {
|
|
1240
|
-
async update({ settings: settings2 }) {
|
|
1241
|
-
const store = await getStore();
|
|
1242
|
-
store.set({ key: "settings", value: settings2 });
|
|
1243
|
-
return settings2;
|
|
1244
|
-
},
|
|
1245
|
-
async find() {
|
|
1246
|
-
const store = await getStore();
|
|
1247
|
-
const settings2 = await store.get({ key: "settings" });
|
|
1248
|
-
return {
|
|
1249
|
-
...DEFAULT_SETTINGS,
|
|
1250
|
-
...settings2 || {}
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
};
|
|
1254
|
-
};
|
|
1255
1232
|
const services = {
|
|
1256
1233
|
release: createReleaseService,
|
|
1257
|
-
"release-action": createReleaseActionService,
|
|
1258
1234
|
"release-validation": createReleaseValidationService,
|
|
1259
|
-
scheduling: createSchedulingService
|
|
1260
|
-
settings: createSettingsService
|
|
1235
|
+
scheduling: createSchedulingService
|
|
1261
1236
|
};
|
|
1262
|
-
const RELEASE_SCHEMA = yup
|
|
1263
|
-
name: yup
|
|
1264
|
-
scheduledAt: yup
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1237
|
+
const RELEASE_SCHEMA = yup.object().shape({
|
|
1238
|
+
name: yup.string().trim().required(),
|
|
1239
|
+
scheduledAt: yup.string().nullable(),
|
|
1240
|
+
isScheduled: yup.boolean().optional(),
|
|
1241
|
+
time: yup.string().when("isScheduled", {
|
|
1242
|
+
is: true,
|
|
1243
|
+
then: yup.string().trim().required(),
|
|
1244
|
+
otherwise: yup.string().nullable()
|
|
1245
|
+
}),
|
|
1246
|
+
timezone: yup.string().when("isScheduled", {
|
|
1247
|
+
is: true,
|
|
1248
|
+
then: yup.string().required().nullable(),
|
|
1249
|
+
otherwise: yup.string().nullable()
|
|
1250
|
+
}),
|
|
1251
|
+
date: yup.string().when("isScheduled", {
|
|
1252
|
+
is: true,
|
|
1253
|
+
then: yup.string().required().nullable(),
|
|
1254
|
+
otherwise: yup.string().nullable()
|
|
1269
1255
|
})
|
|
1270
1256
|
}).required().noUnknown();
|
|
1271
|
-
const FIND_BY_DOCUMENT_ATTACHED_PARAMS_SCHEMA = yup$1.object().shape({
|
|
1272
|
-
contentType: yup$1.string().required(),
|
|
1273
|
-
entryDocumentId: yup$1.string().nullable(),
|
|
1274
|
-
hasEntryAttached: yup$1.string().nullable(),
|
|
1275
|
-
locale: yup$1.string().nullable()
|
|
1276
|
-
}).required().noUnknown();
|
|
1277
1257
|
const validateRelease = validateYupSchema(RELEASE_SCHEMA);
|
|
1278
|
-
const validatefindByDocumentAttachedParams = validateYupSchema(
|
|
1279
|
-
FIND_BY_DOCUMENT_ATTACHED_PARAMS_SCHEMA
|
|
1280
|
-
);
|
|
1281
1258
|
const releaseController = {
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
* If `hasEntryAttached` is true, it will return all releases that have the entry attached.
|
|
1285
|
-
* If `hasEntryAttached` is false, it will return all releases that don't have the entry attached.
|
|
1286
|
-
*/
|
|
1287
|
-
async findByDocumentAttached(ctx) {
|
|
1288
|
-
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1259
|
+
async findMany(ctx) {
|
|
1260
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1289
1261
|
ability: ctx.state.userAbility,
|
|
1290
1262
|
model: RELEASE_MODEL_UID
|
|
1291
1263
|
});
|
|
1292
1264
|
await permissionsManager.validateQuery(ctx.query);
|
|
1293
1265
|
const releaseService = getService("release", { strapi });
|
|
1294
|
-
const
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
}
|
|
1302
|
-
query.entryDocumentId = document.documentId;
|
|
1303
|
-
}
|
|
1304
|
-
const { contentType, hasEntryAttached, entryDocumentId, locale } = query;
|
|
1305
|
-
const isEntryAttached = typeof hasEntryAttached === "string" ? Boolean(JSON.parse(hasEntryAttached)) : false;
|
|
1306
|
-
if (isEntryAttached) {
|
|
1307
|
-
const releases = await releaseService.findMany({
|
|
1308
|
-
where: {
|
|
1309
|
-
releasedAt: null,
|
|
1310
|
-
actions: {
|
|
1311
|
-
contentType,
|
|
1312
|
-
entryDocumentId: entryDocumentId ?? null,
|
|
1313
|
-
locale: locale ?? null
|
|
1314
|
-
}
|
|
1315
|
-
},
|
|
1316
|
-
populate: {
|
|
1317
|
-
actions: {
|
|
1318
|
-
fields: ["type"],
|
|
1319
|
-
filters: {
|
|
1320
|
-
contentType,
|
|
1321
|
-
entryDocumentId: entryDocumentId ?? null,
|
|
1322
|
-
locale: locale ?? null
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
});
|
|
1327
|
-
ctx.body = { data: releases };
|
|
1266
|
+
const isFindManyForContentTypeEntry = Boolean(ctx.query?.contentTypeUid && ctx.query?.entryId);
|
|
1267
|
+
if (isFindManyForContentTypeEntry) {
|
|
1268
|
+
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1269
|
+
const contentTypeUid = query.contentTypeUid;
|
|
1270
|
+
const entryId = query.entryId;
|
|
1271
|
+
const hasEntryAttached = typeof query.hasEntryAttached === "string" ? JSON.parse(query.hasEntryAttached) : false;
|
|
1272
|
+
const data = hasEntryAttached ? await releaseService.findManyWithContentTypeEntryAttached(contentTypeUid, entryId) : await releaseService.findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId);
|
|
1273
|
+
ctx.body = { data };
|
|
1328
1274
|
} else {
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1331
|
-
|
|
1275
|
+
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1276
|
+
const { results, pagination } = await releaseService.findPage(query);
|
|
1277
|
+
const data = results.map((release2) => {
|
|
1278
|
+
const { actions, ...releaseData } = release2;
|
|
1279
|
+
return {
|
|
1280
|
+
...releaseData,
|
|
1332
1281
|
actions: {
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1282
|
+
meta: {
|
|
1283
|
+
count: actions.count
|
|
1284
|
+
}
|
|
1336
1285
|
}
|
|
1337
|
-
}
|
|
1286
|
+
};
|
|
1338
1287
|
});
|
|
1339
|
-
const
|
|
1288
|
+
const pendingReleasesCount = await strapi.query(RELEASE_MODEL_UID).count({
|
|
1340
1289
|
where: {
|
|
1341
|
-
$or: [
|
|
1342
|
-
{
|
|
1343
|
-
id: {
|
|
1344
|
-
$notIn: relatedReleases.map((release2) => release2.id)
|
|
1345
|
-
}
|
|
1346
|
-
},
|
|
1347
|
-
{
|
|
1348
|
-
actions: null
|
|
1349
|
-
}
|
|
1350
|
-
],
|
|
1351
1290
|
releasedAt: null
|
|
1352
1291
|
}
|
|
1353
1292
|
});
|
|
1354
|
-
ctx.body = { data:
|
|
1293
|
+
ctx.body = { data, meta: { pagination, pendingReleasesCount } };
|
|
1355
1294
|
}
|
|
1356
1295
|
},
|
|
1357
|
-
async findPage(ctx) {
|
|
1358
|
-
const permissionsManager = strapi.service("admin::permission").createPermissionsManager({
|
|
1359
|
-
ability: ctx.state.userAbility,
|
|
1360
|
-
model: RELEASE_MODEL_UID
|
|
1361
|
-
});
|
|
1362
|
-
await permissionsManager.validateQuery(ctx.query);
|
|
1363
|
-
const releaseService = getService("release", { strapi });
|
|
1364
|
-
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1365
|
-
const { results, pagination } = await releaseService.findPage(query);
|
|
1366
|
-
const data = results.map((release2) => {
|
|
1367
|
-
const { actions, ...releaseData } = release2;
|
|
1368
|
-
return {
|
|
1369
|
-
...releaseData,
|
|
1370
|
-
actions: {
|
|
1371
|
-
meta: {
|
|
1372
|
-
count: actions.count
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
};
|
|
1376
|
-
});
|
|
1377
|
-
const pendingReleasesCount = await strapi.db.query(RELEASE_MODEL_UID).count({
|
|
1378
|
-
where: {
|
|
1379
|
-
releasedAt: null
|
|
1380
|
-
}
|
|
1381
|
-
});
|
|
1382
|
-
ctx.body = { data, meta: { pagination, pendingReleasesCount } };
|
|
1383
|
-
},
|
|
1384
1296
|
async findOne(ctx) {
|
|
1385
1297
|
const id = ctx.params.id;
|
|
1386
1298
|
const releaseService = getService("release", { strapi });
|
|
1387
|
-
const releaseActionService = getService("release-action", { strapi });
|
|
1388
1299
|
const release2 = await releaseService.findOne(id, { populate: ["createdBy"] });
|
|
1389
1300
|
if (!release2) {
|
|
1390
1301
|
throw new errors.NotFoundError(`Release not found for id: ${id}`);
|
|
1391
1302
|
}
|
|
1392
|
-
const count = await
|
|
1303
|
+
const count = await releaseService.countActions({
|
|
1393
1304
|
filters: {
|
|
1394
1305
|
release: id
|
|
1395
1306
|
}
|
|
1396
1307
|
});
|
|
1397
1308
|
const sanitizedRelease = {
|
|
1398
1309
|
...release2,
|
|
1399
|
-
createdBy: release2.createdBy ? strapi.
|
|
1310
|
+
createdBy: release2.createdBy ? strapi.admin.services.user.sanitizeUser(release2.createdBy) : null
|
|
1400
1311
|
};
|
|
1401
1312
|
const data = {
|
|
1402
1313
|
...sanitizedRelease,
|
|
@@ -1409,39 +1320,22 @@ const releaseController = {
|
|
|
1409
1320
|
ctx.body = { data };
|
|
1410
1321
|
},
|
|
1411
1322
|
async mapEntriesToReleases(ctx) {
|
|
1412
|
-
const { contentTypeUid,
|
|
1413
|
-
if (!contentTypeUid || !
|
|
1323
|
+
const { contentTypeUid, entriesIds } = ctx.query;
|
|
1324
|
+
if (!contentTypeUid || !entriesIds) {
|
|
1414
1325
|
throw new errors.ValidationError("Missing required query parameters");
|
|
1415
1326
|
}
|
|
1416
1327
|
const releaseService = getService("release", { strapi });
|
|
1417
|
-
const releasesWithActions = await releaseService.
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
contentType: contentTypeUid,
|
|
1422
|
-
entryDocumentId: {
|
|
1423
|
-
$in: documentIds
|
|
1424
|
-
},
|
|
1425
|
-
locale
|
|
1426
|
-
}
|
|
1427
|
-
},
|
|
1428
|
-
populate: {
|
|
1429
|
-
actions: true
|
|
1430
|
-
}
|
|
1431
|
-
});
|
|
1328
|
+
const releasesWithActions = await releaseService.findManyWithContentTypeEntryAttached(
|
|
1329
|
+
contentTypeUid,
|
|
1330
|
+
entriesIds
|
|
1331
|
+
);
|
|
1432
1332
|
const mappedEntriesInReleases = releasesWithActions.reduce(
|
|
1433
1333
|
(acc, release2) => {
|
|
1434
1334
|
release2.actions.forEach((action) => {
|
|
1435
|
-
if (action.
|
|
1436
|
-
|
|
1437
|
-
}
|
|
1438
|
-
if (locale && action.locale !== locale) {
|
|
1439
|
-
return;
|
|
1440
|
-
}
|
|
1441
|
-
if (!acc[action.entryDocumentId]) {
|
|
1442
|
-
acc[action.entryDocumentId] = [{ id: release2.id, name: release2.name }];
|
|
1335
|
+
if (!acc[action.entry.id]) {
|
|
1336
|
+
acc[action.entry.id] = [{ id: release2.id, name: release2.name }];
|
|
1443
1337
|
} else {
|
|
1444
|
-
acc[action.
|
|
1338
|
+
acc[action.entry.id].push({ id: release2.id, name: release2.name });
|
|
1445
1339
|
}
|
|
1446
1340
|
});
|
|
1447
1341
|
return acc;
|
|
@@ -1458,13 +1352,13 @@ const releaseController = {
|
|
|
1458
1352
|
await validateRelease(releaseArgs);
|
|
1459
1353
|
const releaseService = getService("release", { strapi });
|
|
1460
1354
|
const release2 = await releaseService.create(releaseArgs, { user });
|
|
1461
|
-
const permissionsManager = strapi.
|
|
1355
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1462
1356
|
ability: ctx.state.userAbility,
|
|
1463
1357
|
model: RELEASE_MODEL_UID
|
|
1464
1358
|
});
|
|
1465
|
-
ctx.
|
|
1359
|
+
ctx.body = {
|
|
1466
1360
|
data: await permissionsManager.sanitizeOutput(release2)
|
|
1467
|
-
}
|
|
1361
|
+
};
|
|
1468
1362
|
},
|
|
1469
1363
|
async update(ctx) {
|
|
1470
1364
|
const user = ctx.state.user;
|
|
@@ -1473,7 +1367,7 @@ const releaseController = {
|
|
|
1473
1367
|
await validateRelease(releaseArgs);
|
|
1474
1368
|
const releaseService = getService("release", { strapi });
|
|
1475
1369
|
const release2 = await releaseService.update(id, releaseArgs, { user });
|
|
1476
|
-
const permissionsManager = strapi.
|
|
1370
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1477
1371
|
ability: ctx.state.userAbility,
|
|
1478
1372
|
model: RELEASE_MODEL_UID
|
|
1479
1373
|
});
|
|
@@ -1490,18 +1384,18 @@ const releaseController = {
|
|
|
1490
1384
|
};
|
|
1491
1385
|
},
|
|
1492
1386
|
async publish(ctx) {
|
|
1387
|
+
const user = ctx.state.user;
|
|
1493
1388
|
const id = ctx.params.id;
|
|
1494
1389
|
const releaseService = getService("release", { strapi });
|
|
1495
|
-
const
|
|
1496
|
-
const release2 = await releaseService.publish(id);
|
|
1390
|
+
const release2 = await releaseService.publish(id, { user });
|
|
1497
1391
|
const [countPublishActions, countUnpublishActions] = await Promise.all([
|
|
1498
|
-
|
|
1392
|
+
releaseService.countActions({
|
|
1499
1393
|
filters: {
|
|
1500
1394
|
release: id,
|
|
1501
1395
|
type: "publish"
|
|
1502
1396
|
}
|
|
1503
1397
|
}),
|
|
1504
|
-
|
|
1398
|
+
releaseService.countActions({
|
|
1505
1399
|
filters: {
|
|
1506
1400
|
release: id,
|
|
1507
1401
|
type: "unpublish"
|
|
@@ -1519,30 +1413,27 @@ const releaseController = {
|
|
|
1519
1413
|
}
|
|
1520
1414
|
};
|
|
1521
1415
|
const RELEASE_ACTION_SCHEMA = yup$1.object().shape({
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1416
|
+
entry: yup$1.object().shape({
|
|
1417
|
+
id: yup$1.strapiID().required(),
|
|
1418
|
+
contentType: yup$1.string().required()
|
|
1419
|
+
}).required(),
|
|
1525
1420
|
type: yup$1.string().oneOf(["publish", "unpublish"]).required()
|
|
1526
1421
|
});
|
|
1527
1422
|
const RELEASE_ACTION_UPDATE_SCHEMA = yup$1.object().shape({
|
|
1528
1423
|
type: yup$1.string().oneOf(["publish", "unpublish"]).required()
|
|
1529
1424
|
});
|
|
1530
|
-
const FIND_MANY_ACTIONS_PARAMS = yup$1.object().shape({
|
|
1531
|
-
groupBy: yup$1.string().oneOf(["action", "contentType", "locale"])
|
|
1532
|
-
});
|
|
1533
1425
|
const validateReleaseAction = validateYupSchema(RELEASE_ACTION_SCHEMA);
|
|
1534
1426
|
const validateReleaseActionUpdateSchema = validateYupSchema(RELEASE_ACTION_UPDATE_SCHEMA);
|
|
1535
|
-
const validateFindManyActionsParams = validateYupSchema(FIND_MANY_ACTIONS_PARAMS);
|
|
1536
1427
|
const releaseActionController = {
|
|
1537
1428
|
async create(ctx) {
|
|
1538
1429
|
const releaseId = ctx.params.releaseId;
|
|
1539
1430
|
const releaseActionArgs = ctx.request.body;
|
|
1540
1431
|
await validateReleaseAction(releaseActionArgs);
|
|
1541
|
-
const
|
|
1542
|
-
const releaseAction2 = await
|
|
1543
|
-
ctx.
|
|
1432
|
+
const releaseService = getService("release", { strapi });
|
|
1433
|
+
const releaseAction2 = await releaseService.createAction(releaseId, releaseActionArgs);
|
|
1434
|
+
ctx.body = {
|
|
1544
1435
|
data: releaseAction2
|
|
1545
|
-
}
|
|
1436
|
+
};
|
|
1546
1437
|
},
|
|
1547
1438
|
async createMany(ctx) {
|
|
1548
1439
|
const releaseId = ctx.params.releaseId;
|
|
@@ -1550,13 +1441,12 @@ const releaseActionController = {
|
|
|
1550
1441
|
await Promise.all(
|
|
1551
1442
|
releaseActionsArgs.map((releaseActionArgs) => validateReleaseAction(releaseActionArgs))
|
|
1552
1443
|
);
|
|
1553
|
-
const releaseActionService = getService("release-action", { strapi });
|
|
1554
1444
|
const releaseService = getService("release", { strapi });
|
|
1555
1445
|
const releaseActions = await strapi.db.transaction(async () => {
|
|
1556
1446
|
const releaseActions2 = await Promise.all(
|
|
1557
1447
|
releaseActionsArgs.map(async (releaseActionArgs) => {
|
|
1558
1448
|
try {
|
|
1559
|
-
const action = await
|
|
1449
|
+
const action = await releaseService.createAction(releaseId, releaseActionArgs, {
|
|
1560
1450
|
disableUpdateReleaseStatus: true
|
|
1561
1451
|
});
|
|
1562
1452
|
return action;
|
|
@@ -1574,51 +1464,43 @@ const releaseActionController = {
|
|
|
1574
1464
|
if (newReleaseActions.length > 0) {
|
|
1575
1465
|
releaseService.updateReleaseStatus(releaseId);
|
|
1576
1466
|
}
|
|
1577
|
-
ctx.
|
|
1467
|
+
ctx.body = {
|
|
1578
1468
|
data: newReleaseActions,
|
|
1579
1469
|
meta: {
|
|
1580
1470
|
entriesAlreadyInRelease: releaseActions.length - newReleaseActions.length,
|
|
1581
1471
|
totalEntries: releaseActions.length
|
|
1582
1472
|
}
|
|
1583
|
-
}
|
|
1473
|
+
};
|
|
1584
1474
|
},
|
|
1585
1475
|
async findMany(ctx) {
|
|
1586
1476
|
const releaseId = ctx.params.releaseId;
|
|
1587
|
-
const permissionsManager = strapi.
|
|
1477
|
+
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1588
1478
|
ability: ctx.state.userAbility,
|
|
1589
1479
|
model: RELEASE_ACTION_MODEL_UID
|
|
1590
1480
|
});
|
|
1591
|
-
await validateFindManyActionsParams(ctx.query);
|
|
1592
|
-
if (ctx.query.groupBy) {
|
|
1593
|
-
if (!["action", "contentType", "locale"].includes(ctx.query.groupBy)) {
|
|
1594
|
-
ctx.badRequest("Invalid groupBy parameter");
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
ctx.query.sort = ctx.query.groupBy === "action" ? "type" : ctx.query.groupBy;
|
|
1598
|
-
delete ctx.query.groupBy;
|
|
1599
1481
|
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
1600
|
-
const
|
|
1601
|
-
const { results, pagination } = await
|
|
1482
|
+
const releaseService = getService("release", { strapi });
|
|
1483
|
+
const { results, pagination } = await releaseService.findActions(releaseId, {
|
|
1484
|
+
sort: query.groupBy === "action" ? "type" : query.groupBy,
|
|
1602
1485
|
...query
|
|
1603
1486
|
});
|
|
1604
1487
|
const contentTypeOutputSanitizers = results.reduce((acc, action) => {
|
|
1605
1488
|
if (acc[action.contentType]) {
|
|
1606
1489
|
return acc;
|
|
1607
1490
|
}
|
|
1608
|
-
const contentTypePermissionsManager = strapi.
|
|
1491
|
+
const contentTypePermissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
|
1609
1492
|
ability: ctx.state.userAbility,
|
|
1610
1493
|
model: action.contentType
|
|
1611
1494
|
});
|
|
1612
1495
|
acc[action.contentType] = contentTypePermissionsManager.sanitizeOutput;
|
|
1613
1496
|
return acc;
|
|
1614
1497
|
}, {});
|
|
1615
|
-
const sanitizedResults = await
|
|
1498
|
+
const sanitizedResults = await mapAsync(results, async (action) => ({
|
|
1616
1499
|
...action,
|
|
1617
|
-
entry:
|
|
1500
|
+
entry: await contentTypeOutputSanitizers[action.contentType](action.entry)
|
|
1618
1501
|
}));
|
|
1619
|
-
const groupedData = await
|
|
1620
|
-
const contentTypes2 =
|
|
1621
|
-
const releaseService = getService("release", { strapi });
|
|
1502
|
+
const groupedData = await releaseService.groupActions(sanitizedResults, query.groupBy);
|
|
1503
|
+
const contentTypes2 = releaseService.getContentTypeModelsFromActions(results);
|
|
1622
1504
|
const components = await releaseService.getAllComponents();
|
|
1623
1505
|
ctx.body = {
|
|
1624
1506
|
data: groupedData,
|
|
@@ -1634,8 +1516,8 @@ const releaseActionController = {
|
|
|
1634
1516
|
const releaseId = ctx.params.releaseId;
|
|
1635
1517
|
const releaseActionUpdateArgs = ctx.request.body;
|
|
1636
1518
|
await validateReleaseActionUpdateSchema(releaseActionUpdateArgs);
|
|
1637
|
-
const
|
|
1638
|
-
const updatedAction = await
|
|
1519
|
+
const releaseService = getService("release", { strapi });
|
|
1520
|
+
const updatedAction = await releaseService.updateAction(
|
|
1639
1521
|
actionId,
|
|
1640
1522
|
releaseId,
|
|
1641
1523
|
releaseActionUpdateArgs
|
|
@@ -1647,36 +1529,14 @@ const releaseActionController = {
|
|
|
1647
1529
|
async delete(ctx) {
|
|
1648
1530
|
const actionId = ctx.params.actionId;
|
|
1649
1531
|
const releaseId = ctx.params.releaseId;
|
|
1650
|
-
const
|
|
1651
|
-
const deletedReleaseAction = await
|
|
1532
|
+
const releaseService = getService("release", { strapi });
|
|
1533
|
+
const deletedReleaseAction = await releaseService.deleteAction(actionId, releaseId);
|
|
1652
1534
|
ctx.body = {
|
|
1653
1535
|
data: deletedReleaseAction
|
|
1654
1536
|
};
|
|
1655
1537
|
}
|
|
1656
1538
|
};
|
|
1657
|
-
const
|
|
1658
|
-
defaultTimezone: yup.string().nullable().default(null)
|
|
1659
|
-
}).required().noUnknown();
|
|
1660
|
-
const validateSettings = validateYupSchema(SETTINGS_SCHEMA);
|
|
1661
|
-
const settingsController = {
|
|
1662
|
-
async find(ctx) {
|
|
1663
|
-
const settingsService = getService("settings", { strapi });
|
|
1664
|
-
const settings2 = await settingsService.find();
|
|
1665
|
-
ctx.body = { data: settings2 };
|
|
1666
|
-
},
|
|
1667
|
-
async update(ctx) {
|
|
1668
|
-
const settingsBody = ctx.request.body;
|
|
1669
|
-
const settings2 = await validateSettings(settingsBody);
|
|
1670
|
-
const settingsService = getService("settings", { strapi });
|
|
1671
|
-
const updatedSettings = await settingsService.update({ settings: settings2 });
|
|
1672
|
-
ctx.body = { data: updatedSettings };
|
|
1673
|
-
}
|
|
1674
|
-
};
|
|
1675
|
-
const controllers = {
|
|
1676
|
-
release: releaseController,
|
|
1677
|
-
"release-action": releaseActionController,
|
|
1678
|
-
settings: settingsController
|
|
1679
|
-
};
|
|
1539
|
+
const controllers = { release: releaseController, "release-action": releaseActionController };
|
|
1680
1540
|
const release = {
|
|
1681
1541
|
type: "admin",
|
|
1682
1542
|
routes: [
|
|
@@ -1696,22 +1556,6 @@ const release = {
|
|
|
1696
1556
|
]
|
|
1697
1557
|
}
|
|
1698
1558
|
},
|
|
1699
|
-
{
|
|
1700
|
-
method: "GET",
|
|
1701
|
-
path: "/getByDocumentAttached",
|
|
1702
|
-
handler: "release.findByDocumentAttached",
|
|
1703
|
-
config: {
|
|
1704
|
-
policies: [
|
|
1705
|
-
"admin::isAuthenticatedAdmin",
|
|
1706
|
-
{
|
|
1707
|
-
name: "admin::hasPermissions",
|
|
1708
|
-
config: {
|
|
1709
|
-
actions: ["plugin::content-releases.read"]
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
]
|
|
1713
|
-
}
|
|
1714
|
-
},
|
|
1715
1559
|
{
|
|
1716
1560
|
method: "POST",
|
|
1717
1561
|
path: "/",
|
|
@@ -1731,7 +1575,7 @@ const release = {
|
|
|
1731
1575
|
{
|
|
1732
1576
|
method: "GET",
|
|
1733
1577
|
path: "/",
|
|
1734
|
-
handler: "release.
|
|
1578
|
+
handler: "release.findMany",
|
|
1735
1579
|
config: {
|
|
1736
1580
|
policies: [
|
|
1737
1581
|
"admin::isAuthenticatedAdmin",
|
|
@@ -1895,50 +1739,13 @@ const releaseAction = {
|
|
|
1895
1739
|
}
|
|
1896
1740
|
]
|
|
1897
1741
|
};
|
|
1898
|
-
const settings = {
|
|
1899
|
-
type: "admin",
|
|
1900
|
-
routes: [
|
|
1901
|
-
{
|
|
1902
|
-
method: "GET",
|
|
1903
|
-
path: "/settings",
|
|
1904
|
-
handler: "settings.find",
|
|
1905
|
-
config: {
|
|
1906
|
-
policies: [
|
|
1907
|
-
"admin::isAuthenticatedAdmin",
|
|
1908
|
-
{
|
|
1909
|
-
name: "admin::hasPermissions",
|
|
1910
|
-
config: {
|
|
1911
|
-
actions: ["plugin::content-releases.settings.read"]
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
]
|
|
1915
|
-
}
|
|
1916
|
-
},
|
|
1917
|
-
{
|
|
1918
|
-
method: "PUT",
|
|
1919
|
-
path: "/settings",
|
|
1920
|
-
handler: "settings.update",
|
|
1921
|
-
config: {
|
|
1922
|
-
policies: [
|
|
1923
|
-
"admin::isAuthenticatedAdmin",
|
|
1924
|
-
{
|
|
1925
|
-
name: "admin::hasPermissions",
|
|
1926
|
-
config: {
|
|
1927
|
-
actions: ["plugin::content-releases.settings.update"]
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
]
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
]
|
|
1934
|
-
};
|
|
1935
1742
|
const routes = {
|
|
1936
|
-
settings,
|
|
1937
1743
|
release,
|
|
1938
1744
|
"release-action": releaseAction
|
|
1939
1745
|
};
|
|
1746
|
+
const { features } = require("@strapi/strapi/dist/utils/ee");
|
|
1940
1747
|
const getPlugin = () => {
|
|
1941
|
-
if (
|
|
1748
|
+
if (features.isEnabled("cms-content-releases")) {
|
|
1942
1749
|
return {
|
|
1943
1750
|
register,
|
|
1944
1751
|
bootstrap,
|