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