@strapi/content-releases 0.0.0-next.e9b6852d1c05518ff6e37d599321f7aa7aa0683b → 0.0.0-next.ec9b1b708d4d319f2b8b39d9397bd752d250d541

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.
Files changed (142) hide show
  1. package/dist/_chunks/App-FQyYFBJT.mjs +1559 -0
  2. package/dist/_chunks/App-FQyYFBJT.mjs.map +1 -0
  3. package/dist/_chunks/App-lx4Ucy9W.js +1580 -0
  4. package/dist/_chunks/App-lx4Ucy9W.js.map +1 -0
  5. package/dist/_chunks/{PurchaseContentReleases-bpIYXOfu.js → PurchaseContentReleases-Be3acS2L.js} +7 -6
  6. package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +1 -0
  7. package/dist/_chunks/{PurchaseContentReleases-3tRbmbY3.mjs → PurchaseContentReleases-_MxP6-Dt.mjs} +8 -7
  8. package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +1 -0
  9. package/dist/_chunks/ReleasesSettingsPage-DqBxvJ9i.mjs +178 -0
  10. package/dist/_chunks/ReleasesSettingsPage-DqBxvJ9i.mjs.map +1 -0
  11. package/dist/_chunks/ReleasesSettingsPage-T5VEAV03.js +178 -0
  12. package/dist/_chunks/ReleasesSettingsPage-T5VEAV03.js.map +1 -0
  13. package/dist/_chunks/{en-HrREghh3.js → en-BWPPsSH-.js} +18 -2
  14. package/dist/_chunks/en-BWPPsSH-.js.map +1 -0
  15. package/dist/_chunks/{en-ltT1TlKQ.mjs → en-D9Q4YW03.mjs} +18 -2
  16. package/dist/_chunks/en-D9Q4YW03.mjs.map +1 -0
  17. package/dist/_chunks/index-CK9G80CL.mjs +1380 -0
  18. package/dist/_chunks/index-CK9G80CL.mjs.map +1 -0
  19. package/dist/_chunks/index-Cl3tM1YW.js +1399 -0
  20. package/dist/_chunks/index-Cl3tM1YW.js.map +1 -0
  21. package/dist/_chunks/schemas-BE1LxE9J.js +62 -0
  22. package/dist/_chunks/schemas-BE1LxE9J.js.map +1 -0
  23. package/dist/_chunks/schemas-DdA2ic2U.mjs +44 -0
  24. package/dist/_chunks/schemas-DdA2ic2U.mjs.map +1 -0
  25. package/dist/admin/index.js +1 -15
  26. package/dist/admin/index.js.map +1 -1
  27. package/dist/admin/index.mjs +2 -16
  28. package/dist/admin/index.mjs.map +1 -1
  29. package/dist/admin/src/components/EntryValidationPopover.d.ts +13 -0
  30. package/dist/admin/src/components/RelativeTime.d.ts +28 -0
  31. package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
  32. package/dist/admin/src/components/ReleaseActionMenu.d.ts +26 -0
  33. package/dist/admin/src/components/ReleaseActionModal.d.ts +24 -0
  34. package/dist/admin/src/components/ReleaseActionOptions.d.ts +9 -0
  35. package/dist/admin/src/components/ReleaseListCell.d.ts +28 -0
  36. package/dist/admin/src/components/ReleaseModal.d.ts +17 -0
  37. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  38. package/dist/admin/src/constants.d.ts +76 -0
  39. package/dist/admin/src/index.d.ts +3 -0
  40. package/dist/admin/src/modules/hooks.d.ts +7 -0
  41. package/dist/admin/src/pages/App.d.ts +1 -0
  42. package/dist/admin/src/pages/PurchaseContentReleases.d.ts +2 -0
  43. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +2 -0
  44. package/dist/admin/src/pages/ReleasesPage.d.ts +8 -0
  45. package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +1 -0
  46. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +181 -0
  47. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +39 -0
  48. package/dist/admin/src/pluginId.d.ts +1 -0
  49. package/dist/admin/src/services/release.d.ts +112 -0
  50. package/dist/admin/src/store/hooks.d.ts +7 -0
  51. package/dist/admin/src/utils/api.d.ts +6 -0
  52. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
  53. package/dist/admin/src/utils/time.d.ts +10 -0
  54. package/dist/admin/src/validation/schemas.d.ts +6 -0
  55. package/dist/server/index.js +931 -658
  56. package/dist/server/index.js.map +1 -1
  57. package/dist/server/index.mjs +932 -658
  58. package/dist/server/index.mjs.map +1 -1
  59. package/dist/server/src/bootstrap.d.ts +5 -0
  60. package/dist/server/src/bootstrap.d.ts.map +1 -0
  61. package/dist/server/src/constants.d.ts +21 -0
  62. package/dist/server/src/constants.d.ts.map +1 -0
  63. package/dist/server/src/content-types/index.d.ts +97 -0
  64. package/dist/server/src/content-types/index.d.ts.map +1 -0
  65. package/dist/server/src/content-types/release/index.d.ts +48 -0
  66. package/dist/server/src/content-types/release/index.d.ts.map +1 -0
  67. package/dist/server/src/content-types/release/schema.d.ts +47 -0
  68. package/dist/server/src/content-types/release/schema.d.ts.map +1 -0
  69. package/dist/server/src/content-types/release-action/index.d.ts +48 -0
  70. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -0
  71. package/dist/server/src/content-types/release-action/schema.d.ts +47 -0
  72. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -0
  73. package/dist/server/src/controllers/index.d.ts +25 -0
  74. package/dist/server/src/controllers/index.d.ts.map +1 -0
  75. package/dist/server/src/controllers/release-action.d.ts +10 -0
  76. package/dist/server/src/controllers/release-action.d.ts.map +1 -0
  77. package/dist/server/src/controllers/release.d.ts +18 -0
  78. package/dist/server/src/controllers/release.d.ts.map +1 -0
  79. package/dist/server/src/controllers/settings.d.ts +11 -0
  80. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  81. package/dist/server/src/controllers/validation/release-action.d.ts +14 -0
  82. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -0
  83. package/dist/server/src/controllers/validation/release.d.ts +4 -0
  84. package/dist/server/src/controllers/validation/release.d.ts.map +1 -0
  85. package/dist/server/src/controllers/validation/settings.d.ts +3 -0
  86. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  87. package/dist/server/src/destroy.d.ts +5 -0
  88. package/dist/server/src/destroy.d.ts.map +1 -0
  89. package/dist/server/src/index.d.ts +2111 -0
  90. package/dist/server/src/index.d.ts.map +1 -0
  91. package/dist/server/src/middlewares/documents.d.ts +6 -0
  92. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  93. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  94. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  95. package/dist/server/src/migrations/index.d.ts +13 -0
  96. package/dist/server/src/migrations/index.d.ts.map +1 -0
  97. package/dist/server/src/register.d.ts +5 -0
  98. package/dist/server/src/register.d.ts.map +1 -0
  99. package/dist/server/src/routes/index.d.ts +51 -0
  100. package/dist/server/src/routes/index.d.ts.map +1 -0
  101. package/dist/server/src/routes/release-action.d.ts +18 -0
  102. package/dist/server/src/routes/release-action.d.ts.map +1 -0
  103. package/dist/server/src/routes/release.d.ts +18 -0
  104. package/dist/server/src/routes/release.d.ts.map +1 -0
  105. package/dist/server/src/routes/settings.d.ts +18 -0
  106. package/dist/server/src/routes/settings.d.ts.map +1 -0
  107. package/dist/server/src/services/index.d.ts +1824 -0
  108. package/dist/server/src/services/index.d.ts.map +1 -0
  109. package/dist/server/src/services/release-action.d.ts +34 -0
  110. package/dist/server/src/services/release-action.d.ts.map +1 -0
  111. package/dist/server/src/services/release.d.ts +31 -0
  112. package/dist/server/src/services/release.d.ts.map +1 -0
  113. package/dist/server/src/services/scheduling.d.ts +18 -0
  114. package/dist/server/src/services/scheduling.d.ts.map +1 -0
  115. package/dist/server/src/services/settings.d.ts +13 -0
  116. package/dist/server/src/services/settings.d.ts.map +1 -0
  117. package/dist/server/src/services/validation.d.ts +18 -0
  118. package/dist/server/src/services/validation.d.ts.map +1 -0
  119. package/dist/server/src/utils/index.d.ts +35 -0
  120. package/dist/server/src/utils/index.d.ts.map +1 -0
  121. package/dist/shared/contracts/release-actions.d.ts +137 -0
  122. package/dist/shared/contracts/release-actions.d.ts.map +1 -0
  123. package/dist/shared/contracts/releases.d.ts +184 -0
  124. package/dist/shared/contracts/releases.d.ts.map +1 -0
  125. package/dist/shared/contracts/settings.d.ts +39 -0
  126. package/dist/shared/contracts/settings.d.ts.map +1 -0
  127. package/dist/shared/types.d.ts +24 -0
  128. package/dist/shared/types.d.ts.map +1 -0
  129. package/package.json +34 -38
  130. package/dist/_chunks/App-dLXY5ei3.js +0 -1353
  131. package/dist/_chunks/App-dLXY5ei3.js.map +0 -1
  132. package/dist/_chunks/App-jrh58sXY.mjs +0 -1330
  133. package/dist/_chunks/App-jrh58sXY.mjs.map +0 -1
  134. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +0 -1
  135. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +0 -1
  136. package/dist/_chunks/en-HrREghh3.js.map +0 -1
  137. package/dist/_chunks/en-ltT1TlKQ.mjs.map +0 -1
  138. package/dist/_chunks/index-CVO0Rqdm.js +0 -1336
  139. package/dist/_chunks/index-CVO0Rqdm.js.map +0 -1
  140. package/dist/_chunks/index-PiOGBETy.mjs +0 -1315
  141. package/dist/_chunks/index-PiOGBETy.mjs.map +0 -1
  142. package/strapi-server.js +0 -3
@@ -0,0 +1,1380 @@
1
+ import { PaperPlane, CaretDown, Cross, Pencil, More } from "@strapi/icons";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { adminApi, useRBAC, useNotification, useAPIErrorHandler, useQueryParams, isFetchError, useTable, useAuth } from "@strapi/admin/strapi-admin";
4
+ import { Field, Flex, VisuallyHidden, Modal, Button, EmptyStateLayout, LinkButton, Box, SingleSelect, SingleSelectOption, Popover, Typography, Link as Link$1, Menu, AccessibleIcon } from "@strapi/design-system";
5
+ import { useFormik, Formik, Form } from "formik";
6
+ import { useIntl } from "react-intl";
7
+ import { unstable_useDocumentLayout } from "@strapi/content-manager/strapi-admin";
8
+ import { EmptyDocuments } from "@strapi/icons/symbols";
9
+ import { Link, NavLink } from "react-router-dom";
10
+ import * as yup from "yup";
11
+ import { styled } from "styled-components";
12
+ import * as React from "react";
13
+ const __variableDynamicImportRuntimeHelper = (glob, path) => {
14
+ const v = glob[path];
15
+ if (v) {
16
+ return typeof v === "function" ? v() : Promise.resolve(v);
17
+ }
18
+ return new Promise((_, reject) => {
19
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
20
+ });
21
+ };
22
+ const PERMISSIONS = {
23
+ main: [
24
+ {
25
+ action: "plugin::content-releases.read",
26
+ subject: null,
27
+ id: "",
28
+ actionParameters: {},
29
+ properties: {},
30
+ conditions: []
31
+ }
32
+ ],
33
+ create: [
34
+ {
35
+ action: "plugin::content-releases.create",
36
+ subject: null,
37
+ id: "",
38
+ actionParameters: {},
39
+ properties: {},
40
+ conditions: []
41
+ }
42
+ ],
43
+ update: [
44
+ {
45
+ action: "plugin::content-releases.update",
46
+ subject: null,
47
+ id: "",
48
+ actionParameters: {},
49
+ properties: {},
50
+ conditions: []
51
+ }
52
+ ],
53
+ delete: [
54
+ {
55
+ action: "plugin::content-releases.delete",
56
+ subject: null,
57
+ id: "",
58
+ actionParameters: {},
59
+ properties: {},
60
+ conditions: []
61
+ }
62
+ ],
63
+ createAction: [
64
+ {
65
+ action: "plugin::content-releases.create-action",
66
+ subject: null,
67
+ id: "",
68
+ actionParameters: {},
69
+ properties: {},
70
+ conditions: []
71
+ }
72
+ ],
73
+ deleteAction: [
74
+ {
75
+ action: "plugin::content-releases.delete-action",
76
+ subject: null,
77
+ id: "",
78
+ actionParameters: {},
79
+ properties: {},
80
+ conditions: []
81
+ }
82
+ ],
83
+ publish: [
84
+ {
85
+ action: "plugin::content-releases.publish",
86
+ subject: null,
87
+ id: "",
88
+ actionParameters: {},
89
+ properties: {},
90
+ conditions: []
91
+ }
92
+ ]
93
+ };
94
+ const extendInvalidatesTags = (endpoint, extraTags) => {
95
+ if (!endpoint) {
96
+ return;
97
+ }
98
+ const originalInvalidatesTags = endpoint.invalidatesTags;
99
+ const newInvalidatesTags = (result, err, args, meta) => {
100
+ const originalTags = typeof originalInvalidatesTags === "function" ? originalInvalidatesTags(result, err, args, meta) : originalInvalidatesTags;
101
+ return [...originalTags ?? [], ...extraTags];
102
+ };
103
+ Object.assign(endpoint, { invalidatesTags: newInvalidatesTags });
104
+ };
105
+ const releaseApi = adminApi.enhanceEndpoints({
106
+ addTagTypes: ["Release", "ReleaseAction", "EntriesInRelease", "ReleaseSettings", "Document"],
107
+ endpoints: {
108
+ updateDocument(endpoint) {
109
+ extendInvalidatesTags(endpoint, [
110
+ { type: "Release", id: "LIST" },
111
+ { type: "ReleaseAction", id: "LIST" }
112
+ ]);
113
+ },
114
+ deleteDocument(endpoint) {
115
+ extendInvalidatesTags(endpoint, [
116
+ { type: "Release", id: "LIST" },
117
+ { type: "ReleaseAction", id: "LIST" }
118
+ ]);
119
+ },
120
+ deleteManyDocuments(endpoint) {
121
+ extendInvalidatesTags(endpoint, [
122
+ { type: "Release", id: "LIST" },
123
+ { type: "ReleaseAction", id: "LIST" }
124
+ ]);
125
+ },
126
+ discardDocument(endpoint) {
127
+ extendInvalidatesTags(endpoint, [
128
+ { type: "Release", id: "LIST" },
129
+ { type: "ReleaseAction", id: "LIST" }
130
+ ]);
131
+ },
132
+ createWorkflow(endpoint) {
133
+ extendInvalidatesTags(endpoint, [
134
+ { type: "Release", id: "LIST" },
135
+ { type: "ReleaseAction", id: "LIST" }
136
+ ]);
137
+ },
138
+ updateWorkflow(endpoint) {
139
+ extendInvalidatesTags(endpoint, [
140
+ { type: "Release", id: "LIST" },
141
+ { type: "ReleaseAction", id: "LIST" }
142
+ ]);
143
+ },
144
+ deleteWorkflow(endpoint) {
145
+ extendInvalidatesTags(endpoint, [
146
+ { type: "Release", id: "LIST" },
147
+ { type: "ReleaseAction", id: "LIST" }
148
+ ]);
149
+ }
150
+ }
151
+ }).injectEndpoints({
152
+ endpoints: (build) => {
153
+ return {
154
+ getReleasesForEntry: build.query({
155
+ query(params) {
156
+ return {
157
+ url: "/content-releases/getByDocumentAttached",
158
+ method: "GET",
159
+ config: {
160
+ params
161
+ }
162
+ };
163
+ },
164
+ providesTags: (result) => result ? [
165
+ ...result.data.map(({ id }) => ({ type: "Release", id })),
166
+ { type: "Release", id: "LIST" }
167
+ ] : []
168
+ }),
169
+ getReleases: build.query({
170
+ query({ page, pageSize, filters } = {
171
+ page: 1,
172
+ pageSize: 16,
173
+ filters: {
174
+ releasedAt: {
175
+ $notNull: false
176
+ }
177
+ }
178
+ }) {
179
+ return {
180
+ url: "/content-releases",
181
+ method: "GET",
182
+ config: {
183
+ params: {
184
+ page: page || 1,
185
+ pageSize: pageSize || 16,
186
+ filters: filters || {
187
+ releasedAt: {
188
+ $notNull: false
189
+ }
190
+ }
191
+ }
192
+ }
193
+ };
194
+ },
195
+ transformResponse(response, meta, arg) {
196
+ const releasedAtValue = arg?.filters?.releasedAt?.$notNull;
197
+ const isActiveDoneTab = releasedAtValue === "true";
198
+ const newResponse = {
199
+ ...response,
200
+ meta: {
201
+ ...response.meta,
202
+ activeTab: isActiveDoneTab ? "done" : "pending"
203
+ }
204
+ };
205
+ return newResponse;
206
+ },
207
+ providesTags: (result) => result ? [
208
+ ...result.data.map(({ id }) => ({ type: "Release", id })),
209
+ { type: "Release", id: "LIST" }
210
+ ] : [{ type: "Release", id: "LIST" }]
211
+ }),
212
+ getRelease: build.query({
213
+ query({ id }) {
214
+ return {
215
+ url: `/content-releases/${id}`,
216
+ method: "GET"
217
+ };
218
+ },
219
+ providesTags: (result, error, arg) => [
220
+ { type: "Release", id: "LIST" },
221
+ { type: "Release", id: arg.id }
222
+ ]
223
+ }),
224
+ getReleaseActions: build.query({
225
+ query({ releaseId, ...params }) {
226
+ return {
227
+ url: `/content-releases/${releaseId}/actions`,
228
+ method: "GET",
229
+ config: {
230
+ params
231
+ }
232
+ };
233
+ },
234
+ providesTags: [{ type: "ReleaseAction", id: "LIST" }]
235
+ }),
236
+ createRelease: build.mutation({
237
+ query(data) {
238
+ return {
239
+ url: "/content-releases",
240
+ method: "POST",
241
+ data
242
+ };
243
+ },
244
+ invalidatesTags: [{ type: "Release", id: "LIST" }]
245
+ }),
246
+ updateRelease: build.mutation({
247
+ query({ id, ...data }) {
248
+ return {
249
+ url: `/content-releases/${id}`,
250
+ method: "PUT",
251
+ data
252
+ };
253
+ },
254
+ invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
255
+ }),
256
+ createReleaseAction: build.mutation({
257
+ query({ body, params }) {
258
+ return {
259
+ url: `/content-releases/${params.releaseId}/actions`,
260
+ method: "POST",
261
+ data: body
262
+ };
263
+ },
264
+ invalidatesTags: [
265
+ { type: "Release", id: "LIST" },
266
+ { type: "ReleaseAction", id: "LIST" }
267
+ ]
268
+ }),
269
+ createManyReleaseActions: build.mutation({
270
+ query({ body, params }) {
271
+ return {
272
+ url: `/content-releases/${params.releaseId}/actions/bulk`,
273
+ method: "POST",
274
+ data: body
275
+ };
276
+ },
277
+ invalidatesTags: [
278
+ { type: "Release", id: "LIST" },
279
+ { type: "ReleaseAction", id: "LIST" },
280
+ { type: "EntriesInRelease" }
281
+ ]
282
+ }),
283
+ updateReleaseAction: build.mutation({
284
+ query({ body, params }) {
285
+ return {
286
+ url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,
287
+ method: "PUT",
288
+ data: body
289
+ };
290
+ },
291
+ invalidatesTags: (res, error, arg) => [
292
+ { type: "ReleaseAction", id: "LIST" },
293
+ { type: "Release", id: "LIST" },
294
+ { type: "Release", id: arg.params.releaseId }
295
+ ],
296
+ async onQueryStarted({ body, params, query, actionPath }, { dispatch, queryFulfilled }) {
297
+ const paramsWithoutActionId = {
298
+ releaseId: params.releaseId,
299
+ ...query
300
+ };
301
+ const patchResult = dispatch(
302
+ releaseApi.util.updateQueryData(
303
+ "getReleaseActions",
304
+ paramsWithoutActionId,
305
+ (draft) => {
306
+ const [key, index] = actionPath;
307
+ const action = draft.data[key][index];
308
+ if (action) {
309
+ action.type = body.type;
310
+ }
311
+ }
312
+ )
313
+ );
314
+ try {
315
+ await queryFulfilled;
316
+ } catch {
317
+ patchResult.undo();
318
+ }
319
+ }
320
+ }),
321
+ deleteReleaseAction: build.mutation({
322
+ query({ params }) {
323
+ return {
324
+ url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,
325
+ method: "DELETE"
326
+ };
327
+ },
328
+ invalidatesTags: (result, error, arg) => [
329
+ { type: "Release", id: "LIST" },
330
+ { type: "Release", id: arg.params.releaseId },
331
+ { type: "ReleaseAction", id: "LIST" },
332
+ { type: "EntriesInRelease" }
333
+ ]
334
+ }),
335
+ publishRelease: build.mutation({
336
+ query({ id }) {
337
+ return {
338
+ url: `/content-releases/${id}/publish`,
339
+ method: "POST"
340
+ };
341
+ },
342
+ invalidatesTags: (result, error, arg) => [
343
+ { type: "Release", id: arg.id },
344
+ { type: "Document", id: `ALL_LIST` }
345
+ ]
346
+ }),
347
+ deleteRelease: build.mutation({
348
+ query({ id }) {
349
+ return {
350
+ url: `/content-releases/${id}`,
351
+ method: "DELETE"
352
+ };
353
+ },
354
+ invalidatesTags: () => [{ type: "Release", id: "LIST" }, { type: "EntriesInRelease" }]
355
+ }),
356
+ getMappedEntriesInReleases: build.query({
357
+ query(params) {
358
+ return {
359
+ url: "/content-releases/mapEntriesToReleases",
360
+ method: "GET",
361
+ config: {
362
+ params
363
+ }
364
+ };
365
+ },
366
+ transformResponse(response) {
367
+ return response.data;
368
+ },
369
+ providesTags: [{ type: "EntriesInRelease" }]
370
+ }),
371
+ getReleaseSettings: build.query({
372
+ query: () => "/content-releases/settings",
373
+ providesTags: [{ type: "ReleaseSettings" }]
374
+ }),
375
+ updateReleaseSettings: build.mutation({
376
+ query(data) {
377
+ return {
378
+ url: "/content-releases/settings",
379
+ method: "PUT",
380
+ data
381
+ };
382
+ },
383
+ invalidatesTags: [{ type: "ReleaseSettings" }]
384
+ })
385
+ };
386
+ }
387
+ });
388
+ const {
389
+ useGetReleasesQuery,
390
+ useGetReleasesForEntryQuery,
391
+ useGetReleaseQuery,
392
+ useGetReleaseActionsQuery,
393
+ useCreateReleaseMutation,
394
+ useCreateReleaseActionMutation,
395
+ useCreateManyReleaseActionsMutation,
396
+ useUpdateReleaseMutation,
397
+ useUpdateReleaseActionMutation,
398
+ usePublishReleaseMutation,
399
+ useDeleteReleaseActionMutation,
400
+ useDeleteReleaseMutation,
401
+ useGetMappedEntriesInReleasesQuery,
402
+ useGetReleaseSettingsQuery,
403
+ useUpdateReleaseSettingsMutation
404
+ } = releaseApi;
405
+ const getBorderLeftRadiusValue = (actionType) => {
406
+ return actionType === "publish" ? 1 : 0;
407
+ };
408
+ const getBorderRightRadiusValue = (actionType) => {
409
+ return actionType === "publish" ? 0 : 1;
410
+ };
411
+ const FieldWrapper = styled(Field.Root)`
412
+ border-top-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
413
+ border-bottom-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
414
+ border-top-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
415
+ border-bottom-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
416
+
417
+ > label {
418
+ color: inherit;
419
+ padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};
420
+ text-align: center;
421
+ vertical-align: middle;
422
+ text-transform: capitalize;
423
+ }
424
+
425
+ &[data-checked='true'] {
426
+ color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
427
+ background-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
428
+ border-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
429
+ }
430
+
431
+ &[data-checked='false'] {
432
+ border-left: ${({ $actionType }) => $actionType === "unpublish" && "none"};
433
+ border-right: ${({ $actionType }) => $actionType === "publish" && "none"};
434
+ }
435
+
436
+ &[data-checked='false'][data-disabled='false']:hover {
437
+ color: ${({ theme }) => theme.colors.neutral700};
438
+ background-color: ${({ theme }) => theme.colors.neutral100};
439
+ border-color: ${({ theme }) => theme.colors.neutral200};
440
+
441
+ & > label {
442
+ cursor: pointer;
443
+ }
444
+ }
445
+
446
+ &[data-disabled='true'] {
447
+ color: ${({ theme }) => theme.colors.neutral600};
448
+ background-color: ${({ theme }) => theme.colors.neutral150};
449
+ border-color: ${({ theme }) => theme.colors.neutral300};
450
+ }
451
+ `;
452
+ const ActionOption = ({
453
+ selected,
454
+ actionType,
455
+ handleChange,
456
+ name,
457
+ disabled = false
458
+ }) => {
459
+ return /* @__PURE__ */ jsx(
460
+ FieldWrapper,
461
+ {
462
+ $actionType: actionType,
463
+ background: "primary0",
464
+ borderColor: "neutral200",
465
+ color: selected === actionType ? "primary600" : "neutral600",
466
+ position: "relative",
467
+ cursor: "pointer",
468
+ "data-checked": selected === actionType,
469
+ "data-disabled": disabled && selected !== actionType,
470
+ children: /* @__PURE__ */ jsxs(Field.Label, { children: [
471
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
472
+ Field.Input,
473
+ {
474
+ type: "radio",
475
+ name,
476
+ checked: selected === actionType,
477
+ onChange: handleChange,
478
+ value: actionType,
479
+ disabled
480
+ }
481
+ ) }),
482
+ actionType
483
+ ] })
484
+ }
485
+ );
486
+ };
487
+ const ReleaseActionOptions = ({
488
+ selected,
489
+ handleChange,
490
+ name,
491
+ disabled = false
492
+ }) => {
493
+ return /* @__PURE__ */ jsxs(Flex, { children: [
494
+ /* @__PURE__ */ jsx(
495
+ ActionOption,
496
+ {
497
+ actionType: "publish",
498
+ selected,
499
+ handleChange,
500
+ name,
501
+ disabled
502
+ }
503
+ ),
504
+ /* @__PURE__ */ jsx(
505
+ ActionOption,
506
+ {
507
+ actionType: "unpublish",
508
+ selected,
509
+ handleChange,
510
+ name,
511
+ disabled
512
+ }
513
+ )
514
+ ] });
515
+ };
516
+ const RELEASE_ACTION_FORM_SCHEMA = yup.object().shape({
517
+ type: yup.string().oneOf(["publish", "unpublish"]).required(),
518
+ releaseId: yup.string().required()
519
+ });
520
+ const INITIAL_VALUES = {
521
+ type: "publish",
522
+ releaseId: ""
523
+ };
524
+ const NoReleases = () => {
525
+ const { formatMessage } = useIntl();
526
+ return /* @__PURE__ */ jsx(
527
+ EmptyStateLayout,
528
+ {
529
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" }),
530
+ content: formatMessage({
531
+ id: "content-releases.content-manager-edit-view.add-to-release.no-releases-message",
532
+ defaultMessage: "No available releases. Open the list of releases and create a new one from there."
533
+ }),
534
+ action: /* @__PURE__ */ jsx(
535
+ LinkButton,
536
+ {
537
+ to: {
538
+ pathname: "/plugins/content-releases"
539
+ },
540
+ tag: Link,
541
+ variant: "secondary",
542
+ children: formatMessage({
543
+ id: "content-releases.content-manager-edit-view.add-to-release.redirect-button",
544
+ defaultMessage: "Open the list of releases"
545
+ })
546
+ }
547
+ ),
548
+ shadow: "none"
549
+ }
550
+ );
551
+ };
552
+ const AddActionToReleaseModal = ({
553
+ contentType,
554
+ documentId,
555
+ onInputChange,
556
+ values
557
+ }) => {
558
+ const { formatMessage } = useIntl();
559
+ const [{ query }] = useQueryParams();
560
+ const locale = query.plugins?.i18n?.locale;
561
+ const response = useGetReleasesForEntryQuery({
562
+ contentType,
563
+ entryDocumentId: documentId,
564
+ hasEntryAttached: false,
565
+ locale
566
+ });
567
+ const releases = response.data?.data;
568
+ if (releases?.length === 0) {
569
+ return /* @__PURE__ */ jsx(NoReleases, {});
570
+ }
571
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
572
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
573
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
574
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
575
+ defaultMessage: "Select a release"
576
+ }) }),
577
+ /* @__PURE__ */ jsx(
578
+ SingleSelect,
579
+ {
580
+ required: true,
581
+ placeholder: formatMessage({
582
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
583
+ defaultMessage: "Select"
584
+ }),
585
+ name: "releaseId",
586
+ onChange: (value) => onInputChange("releaseId", value),
587
+ value: values.releaseId,
588
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
589
+ }
590
+ )
591
+ ] }) }),
592
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
593
+ id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
594
+ defaultMessage: "What do you want to do with this entry?"
595
+ }) }),
596
+ /* @__PURE__ */ jsx(
597
+ ReleaseActionOptions,
598
+ {
599
+ selected: values.type,
600
+ handleChange: (e) => onInputChange("type", e.target.value),
601
+ name: "type"
602
+ }
603
+ )
604
+ ] });
605
+ };
606
+ const ReleaseActionModalForm = ({
607
+ documentId,
608
+ document,
609
+ model,
610
+ collectionType
611
+ }) => {
612
+ const { formatMessage } = useIntl();
613
+ const { allowedActions } = useRBAC(PERMISSIONS);
614
+ const { canCreateAction } = allowedActions;
615
+ const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
616
+ const { toggleNotification } = useNotification();
617
+ const { formatAPIError } = useAPIErrorHandler();
618
+ const [{ query }] = useQueryParams();
619
+ const locale = query.plugins?.i18n?.locale;
620
+ const handleSubmit = async (e, onClose) => {
621
+ try {
622
+ await formik.handleSubmit(e);
623
+ onClose();
624
+ } catch (error) {
625
+ if (isFetchError(error)) {
626
+ toggleNotification({
627
+ type: "danger",
628
+ message: formatAPIError(error)
629
+ });
630
+ } else {
631
+ toggleNotification({
632
+ type: "danger",
633
+ message: formatMessage({
634
+ id: "notification.error",
635
+ defaultMessage: "An error occurred"
636
+ })
637
+ });
638
+ }
639
+ }
640
+ };
641
+ const formik = useFormik({
642
+ initialValues: INITIAL_VALUES,
643
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
644
+ onSubmit: async (values) => {
645
+ if (collectionType === "collection-types" && !documentId) {
646
+ throw new Error("Document id is required");
647
+ }
648
+ const response = await createReleaseAction({
649
+ body: {
650
+ type: values.type,
651
+ contentType: model,
652
+ entryDocumentId: documentId,
653
+ locale
654
+ },
655
+ params: { releaseId: values.releaseId }
656
+ });
657
+ if ("data" in response) {
658
+ toggleNotification({
659
+ type: "success",
660
+ message: formatMessage({
661
+ id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
662
+ defaultMessage: "Entry added to release"
663
+ })
664
+ });
665
+ return;
666
+ }
667
+ if ("error" in response) {
668
+ throw response.error;
669
+ }
670
+ }
671
+ });
672
+ const {
673
+ edit: { options }
674
+ } = unstable_useDocumentLayout(model);
675
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canCreateAction) {
676
+ return null;
677
+ }
678
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
679
+ return null;
680
+ }
681
+ return {
682
+ label: formatMessage({
683
+ id: "content-releases.content-manager-edit-view.add-to-release",
684
+ defaultMessage: "Add to release"
685
+ }),
686
+ icon: /* @__PURE__ */ jsx(PaperPlane, {}),
687
+ // Entry is creating so we don't want to allow adding it to a release
688
+ disabled: !document,
689
+ position: ["panel", "table-row"],
690
+ dialog: {
691
+ type: "modal",
692
+ title: formatMessage({
693
+ id: "content-releases.content-manager-edit-view.add-to-release",
694
+ defaultMessage: "Add to release"
695
+ }),
696
+ content: /* @__PURE__ */ jsx(
697
+ AddActionToReleaseModal,
698
+ {
699
+ contentType: model,
700
+ documentId,
701
+ onInputChange: formik.setFieldValue,
702
+ values: formik.values
703
+ }
704
+ ),
705
+ footer: ({ onClose }) => /* @__PURE__ */ jsxs(Modal.Footer, { children: [
706
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
707
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
708
+ defaultMessage: "Cancel"
709
+ }) }),
710
+ /* @__PURE__ */ jsx(
711
+ Button,
712
+ {
713
+ type: "submit",
714
+ onClick: (e) => handleSubmit(e, onClose),
715
+ disabled: !formik.values.releaseId,
716
+ loading: isLoading,
717
+ children: formatMessage({
718
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
719
+ defaultMessage: "Continue"
720
+ })
721
+ }
722
+ )
723
+ ] })
724
+ }
725
+ };
726
+ };
727
+ const getContentPermissions = (subject) => {
728
+ const permissions = {
729
+ publish: [
730
+ {
731
+ action: "plugin::content-manager.explorer.publish",
732
+ subject,
733
+ id: "",
734
+ actionParameters: {},
735
+ properties: {},
736
+ conditions: []
737
+ }
738
+ ]
739
+ };
740
+ return permissions;
741
+ };
742
+ const ReleaseAction = ({ documents, model }) => {
743
+ const { formatMessage } = useIntl();
744
+ const { toggleNotification } = useNotification();
745
+ const { formatAPIError } = useAPIErrorHandler();
746
+ const [{ query }] = useQueryParams();
747
+ const contentPermissions = getContentPermissions(model);
748
+ const {
749
+ allowedActions: { canPublish }
750
+ } = useRBAC(contentPermissions);
751
+ const {
752
+ allowedActions: { canCreate }
753
+ } = useRBAC(PERMISSIONS);
754
+ const response = useGetReleasesQuery();
755
+ const releases = response.data?.data;
756
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
757
+ const documentIds = documents.map((doc) => doc.documentId);
758
+ const handleSubmit = async (values) => {
759
+ const locale = query.plugins?.i18n?.locale;
760
+ const releaseActionEntries = documentIds.map(
761
+ (entryDocumentId) => ({
762
+ type: values.type,
763
+ contentType: model,
764
+ entryDocumentId,
765
+ locale
766
+ })
767
+ );
768
+ const response2 = await createManyReleaseActions({
769
+ body: releaseActionEntries,
770
+ params: { releaseId: values.releaseId }
771
+ });
772
+ if ("data" in response2) {
773
+ const notificationMessage = formatMessage(
774
+ {
775
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
776
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
777
+ },
778
+ {
779
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
780
+ totalEntries: response2.data.meta.totalEntries
781
+ }
782
+ );
783
+ const notification = {
784
+ type: "success",
785
+ title: formatMessage(
786
+ {
787
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
788
+ defaultMessage: "Successfully added to release."
789
+ },
790
+ {
791
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
792
+ totalEntries: response2.data.meta.totalEntries
793
+ }
794
+ ),
795
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
796
+ };
797
+ toggleNotification(notification);
798
+ return true;
799
+ }
800
+ if ("error" in response2) {
801
+ if (isFetchError(response2.error)) {
802
+ toggleNotification({
803
+ type: "warning",
804
+ message: formatAPIError(response2.error)
805
+ });
806
+ } else {
807
+ toggleNotification({
808
+ type: "warning",
809
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
810
+ });
811
+ }
812
+ }
813
+ };
814
+ if (!canCreate || !canPublish)
815
+ return null;
816
+ return {
817
+ actionType: "release",
818
+ variant: "tertiary",
819
+ label: formatMessage({
820
+ id: "content-manager-list-view.add-to-release",
821
+ defaultMessage: "Add to Release"
822
+ }),
823
+ dialog: {
824
+ type: "modal",
825
+ title: formatMessage({
826
+ id: "content-manager-list-view.add-to-release",
827
+ defaultMessage: "Add to Release"
828
+ }),
829
+ content: ({ onClose }) => {
830
+ return /* @__PURE__ */ jsx(
831
+ Formik,
832
+ {
833
+ onSubmit: async (values) => {
834
+ const data = await handleSubmit(values);
835
+ if (data) {
836
+ return onClose();
837
+ }
838
+ },
839
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
840
+ initialValues: INITIAL_VALUES,
841
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
842
+ releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
843
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
844
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
845
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
846
+ defaultMessage: "Select a release"
847
+ }) }),
848
+ /* @__PURE__ */ jsx(
849
+ SingleSelect,
850
+ {
851
+ placeholder: formatMessage({
852
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
853
+ defaultMessage: "Select"
854
+ }),
855
+ onChange: (value) => setFieldValue("releaseId", value),
856
+ value: values.releaseId,
857
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
858
+ }
859
+ )
860
+ ] }) }),
861
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
862
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
863
+ defaultMessage: "What do you want to do with these entries?"
864
+ }) }),
865
+ /* @__PURE__ */ jsx(
866
+ ReleaseActionOptions,
867
+ {
868
+ selected: values.type,
869
+ handleChange: (e) => setFieldValue("type", e.target.value),
870
+ name: "type"
871
+ }
872
+ )
873
+ ] }) }),
874
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
875
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
876
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
877
+ defaultMessage: "Cancel"
878
+ }) }),
879
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
880
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
881
+ defaultMessage: "Continue"
882
+ }) })
883
+ ] })
884
+ ] })
885
+ }
886
+ );
887
+ }
888
+ }
889
+ };
890
+ };
891
+ const useReleasesList = (contentTypeUid, documentId) => {
892
+ const listViewData = useTable("ListView", (state) => state.rows);
893
+ const documentIds = listViewData.map((entry) => entry.documentId);
894
+ const [{ query }] = useQueryParams();
895
+ const locale = query?.plugins?.i18n?.locale || void 0;
896
+ const response = useGetMappedEntriesInReleasesQuery(
897
+ { contentTypeUid, documentIds, locale },
898
+ { skip: !documentIds || !contentTypeUid || documentIds.length === 0 }
899
+ );
900
+ const mappedEntriesInReleases = response.data || {};
901
+ return mappedEntriesInReleases?.[documentId] || [];
902
+ };
903
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
904
+ const { options } = layout;
905
+ if (!options?.draftAndPublish) {
906
+ return { displayedHeaders, layout };
907
+ }
908
+ return {
909
+ displayedHeaders: [
910
+ ...displayedHeaders,
911
+ {
912
+ searchable: false,
913
+ sortable: false,
914
+ name: "releases",
915
+ label: {
916
+ id: "content-releases.content-manager.list-view.releases.header",
917
+ defaultMessage: "To be released in"
918
+ },
919
+ cellFormatter: (props, _, { model }) => /* @__PURE__ */ jsx(ReleaseListCell, { ...props, model })
920
+ }
921
+ ],
922
+ layout
923
+ };
924
+ };
925
+ const ReleaseListCell = ({ documentId, model }) => {
926
+ const releases = useReleasesList(model, documentId);
927
+ const { formatMessage } = useIntl();
928
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
929
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(
930
+ Button,
931
+ {
932
+ variant: "ghost",
933
+ onClick: (e) => e.stopPropagation(),
934
+ endIcon: releases.length > 0 ? /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) : null,
935
+ children: /* @__PURE__ */ jsx(
936
+ Typography,
937
+ {
938
+ style: { maxWidth: "252px", cursor: "pointer" },
939
+ textColor: "neutral800",
940
+ fontWeight: "regular",
941
+ children: releases.length > 0 ? formatMessage(
942
+ {
943
+ id: "content-releases.content-manager.list-view.releases-number",
944
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
945
+ },
946
+ {
947
+ number: releases.length
948
+ }
949
+ ) : "-"
950
+ }
951
+ )
952
+ }
953
+ ) }),
954
+ /* @__PURE__ */ jsx(Popover.Content, { children: /* @__PURE__ */ jsx("ul", { children: releases.map(({ id, name }) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Link$1, { href: `/admin/plugins/content-releases/${id}`, isExternal: false, children: name }) }, id)) }) })
955
+ ] });
956
+ };
957
+ const getTimezoneOffset = (timezone, date) => {
958
+ try {
959
+ const offsetPart = new Intl.DateTimeFormat("en", {
960
+ timeZone: timezone,
961
+ timeZoneName: "longOffset"
962
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
963
+ const offset = offsetPart ? offsetPart.value : "";
964
+ let utcOffset = offset.replace("GMT", "UTC");
965
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
966
+ utcOffset = `${utcOffset}+00:00`;
967
+ }
968
+ return utcOffset;
969
+ } catch (error) {
970
+ return "";
971
+ }
972
+ };
973
+ const getTimezones = (selectedDate) => {
974
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
975
+ const utcOffset = getTimezoneOffset(timezone, selectedDate);
976
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
977
+ });
978
+ const systemTimezone = timezoneList.find(
979
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
980
+ );
981
+ return { timezoneList, systemTimezone };
982
+ };
983
+ const StyledMenuItem = styled(Menu.Item)`
984
+ &:hover {
985
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
986
+
987
+ svg {
988
+ fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
989
+ }
990
+
991
+ a {
992
+ color: ${({ theme }) => theme.colors.neutral800};
993
+ }
994
+ }
995
+
996
+ svg {
997
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}500`]};
998
+ }
999
+
1000
+ span {
1001
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}800`]};
1002
+ }
1003
+
1004
+ span,
1005
+ a {
1006
+ width: 100%;
1007
+ }
1008
+ `;
1009
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
1010
+ const { formatMessage } = useIntl();
1011
+ const { toggleNotification } = useNotification();
1012
+ const { formatAPIError } = useAPIErrorHandler();
1013
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
1014
+ const {
1015
+ allowedActions: { canDeleteAction }
1016
+ } = useRBAC(PERMISSIONS);
1017
+ const handleDeleteAction = async () => {
1018
+ const response = await deleteReleaseAction({
1019
+ params: { releaseId, actionId }
1020
+ });
1021
+ if ("data" in response) {
1022
+ toggleNotification({
1023
+ type: "success",
1024
+ message: formatMessage({
1025
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
1026
+ defaultMessage: "Entry removed from release"
1027
+ })
1028
+ });
1029
+ return;
1030
+ }
1031
+ if ("error" in response) {
1032
+ if (isFetchError(response.error)) {
1033
+ toggleNotification({
1034
+ type: "danger",
1035
+ message: formatAPIError(response.error)
1036
+ });
1037
+ } else {
1038
+ toggleNotification({
1039
+ type: "danger",
1040
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1041
+ });
1042
+ }
1043
+ }
1044
+ };
1045
+ if (!canDeleteAction) {
1046
+ return null;
1047
+ }
1048
+ return /* @__PURE__ */ jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1049
+ /* @__PURE__ */ jsx(Cross, { width: "1.6rem", height: "1.6rem" }),
1050
+ /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
1051
+ id: "content-releases.content-manager-edit-view.remove-from-release",
1052
+ defaultMessage: "Remove from release"
1053
+ }) })
1054
+ ] }) });
1055
+ };
1056
+ const ReleaseActionEntryLinkItem = ({
1057
+ contentTypeUid,
1058
+ documentId,
1059
+ locale
1060
+ }) => {
1061
+ const { formatMessage } = useIntl();
1062
+ const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
1063
+ const canUpdateEntryForLocale = React.useMemo(() => {
1064
+ const updatePermissions = userPermissions.find(
1065
+ (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
1066
+ );
1067
+ if (!updatePermissions) {
1068
+ return false;
1069
+ }
1070
+ return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
1071
+ }, [contentTypeUid, locale, userPermissions]);
1072
+ const {
1073
+ allowedActions: { canUpdate: canUpdateContentType }
1074
+ } = useRBAC({
1075
+ updateContentType: [
1076
+ {
1077
+ action: "plugin::content-manager.explorer.update",
1078
+ subject: contentTypeUid
1079
+ }
1080
+ ]
1081
+ });
1082
+ if (!canUpdateContentType || !canUpdateEntryForLocale) {
1083
+ return null;
1084
+ }
1085
+ return /* @__PURE__ */ jsx(
1086
+ StyledMenuItem,
1087
+ {
1088
+ tag: NavLink,
1089
+ isLink: true,
1090
+ to: {
1091
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${documentId}`,
1092
+ search: locale && `?plugins[i18n][locale]=${locale}`
1093
+ },
1094
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1095
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
1096
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
1097
+ id: "content-releases.content-manager-edit-view.edit-entry",
1098
+ defaultMessage: "Edit entry"
1099
+ }) })
1100
+ ] })
1101
+ }
1102
+ );
1103
+ };
1104
+ const EditReleaseItem = ({ releaseId }) => {
1105
+ const { formatMessage } = useIntl();
1106
+ return (
1107
+ /* @ts-expect-error inference isn't working in DS */
1108
+ /* @__PURE__ */ jsx(StyledMenuItem, { tag: NavLink, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1109
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
1110
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", variant: "omega", children: formatMessage({
1111
+ id: "content-releases.content-manager-edit-view.edit-release",
1112
+ defaultMessage: "Edit release"
1113
+ }) })
1114
+ ] }) })
1115
+ );
1116
+ };
1117
+ const Root = ({ children }) => {
1118
+ const { formatMessage } = useIntl();
1119
+ const { allowedActions } = useRBAC(PERMISSIONS);
1120
+ return (
1121
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
1122
+ allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
1123
+ /* @__PURE__ */ jsx(StyledMoreButton, { variant: "tertiary", endIcon: null, paddingLeft: "7px", paddingRight: "7px", children: /* @__PURE__ */ jsx(
1124
+ AccessibleIcon,
1125
+ {
1126
+ label: formatMessage({
1127
+ id: "content-releases.content-manager-edit-view.release-action-menu",
1128
+ defaultMessage: "Release action options"
1129
+ }),
1130
+ children: /* @__PURE__ */ jsx(More, {})
1131
+ }
1132
+ ) }),
1133
+ /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
1134
+ ] }) : null
1135
+ );
1136
+ };
1137
+ const StyledMoreButton = styled(Menu.Trigger)`
1138
+ & > span {
1139
+ display: flex;
1140
+ }
1141
+ `;
1142
+ const ReleaseActionMenu = {
1143
+ Root,
1144
+ EditReleaseItem,
1145
+ DeleteReleaseActionItem,
1146
+ ReleaseActionEntryLinkItem
1147
+ };
1148
+ const Panel = ({
1149
+ model,
1150
+ document,
1151
+ documentId,
1152
+ collectionType
1153
+ }) => {
1154
+ const [{ query }] = useQueryParams();
1155
+ const locale = query.plugins?.i18n?.locale;
1156
+ const {
1157
+ edit: { options }
1158
+ } = unstable_useDocumentLayout(model);
1159
+ const { formatMessage, formatDate, formatTime } = useIntl();
1160
+ const { allowedActions } = useRBAC(PERMISSIONS);
1161
+ const { canRead, canDeleteAction } = allowedActions;
1162
+ const response = useGetReleasesForEntryQuery(
1163
+ {
1164
+ contentType: model,
1165
+ entryDocumentId: documentId,
1166
+ locale,
1167
+ hasEntryAttached: true
1168
+ },
1169
+ {
1170
+ skip: !document
1171
+ }
1172
+ );
1173
+ const releases = response.data?.data;
1174
+ const getReleaseColorVariant = (actionType, shade) => {
1175
+ if (actionType === "unpublish") {
1176
+ return `secondary${shade}`;
1177
+ }
1178
+ return `success${shade}`;
1179
+ };
1180
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canRead) {
1181
+ return null;
1182
+ }
1183
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
1184
+ return null;
1185
+ }
1186
+ if (!releases || releases.length === 0) {
1187
+ return null;
1188
+ }
1189
+ return {
1190
+ title: formatMessage({
1191
+ id: "content-releases.plugin.name",
1192
+ defaultMessage: "Releases"
1193
+ }),
1194
+ content: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 3, width: "100%", children: releases?.map((release) => /* @__PURE__ */ jsxs(
1195
+ Flex,
1196
+ {
1197
+ direction: "column",
1198
+ alignItems: "start",
1199
+ borderWidth: "1px",
1200
+ borderStyle: "solid",
1201
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
1202
+ overflow: "hidden",
1203
+ hasRadius: true,
1204
+ children: [
1205
+ /* @__PURE__ */ jsx(
1206
+ Box,
1207
+ {
1208
+ paddingTop: 3,
1209
+ paddingBottom: 3,
1210
+ paddingLeft: 4,
1211
+ paddingRight: 4,
1212
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
1213
+ width: "100%",
1214
+ children: /* @__PURE__ */ jsx(
1215
+ Typography,
1216
+ {
1217
+ fontSize: 1,
1218
+ variant: "pi",
1219
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
1220
+ children: formatMessage(
1221
+ {
1222
+ id: "content-releases.content-manager-edit-view.list-releases.title",
1223
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
1224
+ },
1225
+ { isPublish: release.actions[0].type === "publish" }
1226
+ )
1227
+ }
1228
+ )
1229
+ }
1230
+ ),
1231
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
1232
+ /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
1233
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
1234
+ {
1235
+ id: "content-releases.content-manager-edit-view.scheduled.date",
1236
+ defaultMessage: "{date} at {time} ({offset})"
1237
+ },
1238
+ {
1239
+ date: formatDate(new Date(release.scheduledAt), {
1240
+ day: "2-digit",
1241
+ month: "2-digit",
1242
+ year: "numeric",
1243
+ timeZone: release.timezone
1244
+ }),
1245
+ time: formatTime(new Date(release.scheduledAt), {
1246
+ hourCycle: "h23",
1247
+ timeZone: release.timezone
1248
+ }),
1249
+ offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
1250
+ }
1251
+ ) }),
1252
+ canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
1253
+ /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
1254
+ /* @__PURE__ */ jsx(
1255
+ ReleaseActionMenu.DeleteReleaseActionItem,
1256
+ {
1257
+ releaseId: release.id,
1258
+ actionId: release.actions[0].id
1259
+ }
1260
+ )
1261
+ ] }) : null
1262
+ ] })
1263
+ ]
1264
+ },
1265
+ release.id
1266
+ )) })
1267
+ };
1268
+ };
1269
+ const pluginId = "content-releases";
1270
+ const prefixPluginTranslations = (trad, pluginId2) => {
1271
+ return Object.keys(trad).reduce((acc, current) => {
1272
+ acc[`${pluginId2}.${current}`] = trad[current];
1273
+ return acc;
1274
+ }, {});
1275
+ };
1276
+ const admin = {
1277
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1278
+ register(app) {
1279
+ app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
1280
+ if (window.strapi.features.isEnabled("cms-content-releases")) {
1281
+ app.addMenuLink({
1282
+ to: `plugins/${pluginId}`,
1283
+ icon: PaperPlane,
1284
+ intlLabel: {
1285
+ id: `${pluginId}.plugin.name`,
1286
+ defaultMessage: "Releases"
1287
+ },
1288
+ Component: () => import("./App-FQyYFBJT.mjs").then((mod) => ({ default: mod.App })),
1289
+ permissions: PERMISSIONS.main,
1290
+ position: 2
1291
+ });
1292
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
1293
+ if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
1294
+ contentManagerPluginApis.addEditViewSidePanel([Panel]);
1295
+ }
1296
+ if ("addDocumentAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addDocumentAction === "function") {
1297
+ contentManagerPluginApis.addDocumentAction((actions) => {
1298
+ const indexOfDeleteAction = actions.findIndex((action) => action.type === "unpublish");
1299
+ actions.splice(indexOfDeleteAction, 0, ReleaseActionModalForm);
1300
+ return actions;
1301
+ });
1302
+ }
1303
+ app.addSettingsLink("global", {
1304
+ id: pluginId,
1305
+ to: "releases",
1306
+ intlLabel: {
1307
+ id: `${pluginId}.plugin.name`,
1308
+ defaultMessage: "Releases"
1309
+ },
1310
+ permissions: [],
1311
+ async Component() {
1312
+ const { ProtectedReleasesSettingsPage } = await import("./ReleasesSettingsPage-DqBxvJ9i.mjs");
1313
+ return { default: ProtectedReleasesSettingsPage };
1314
+ }
1315
+ });
1316
+ if ("addBulkAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addBulkAction === "function") {
1317
+ contentManagerPluginApis.addBulkAction((actions) => {
1318
+ const deleteActionIndex = actions.findIndex((action) => action.type === "delete");
1319
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1320
+ return actions;
1321
+ });
1322
+ }
1323
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
1324
+ } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
1325
+ app.addSettingsLink("global", {
1326
+ id: pluginId,
1327
+ to: "/plugins/purchase-content-releases",
1328
+ intlLabel: {
1329
+ id: `${pluginId}.plugin.name`,
1330
+ defaultMessage: "Releases"
1331
+ },
1332
+ permissions: [],
1333
+ async Component() {
1334
+ const { PurchaseContentReleases } = await import("./PurchaseContentReleases-_MxP6-Dt.mjs");
1335
+ return { default: PurchaseContentReleases };
1336
+ },
1337
+ licenseOnly: true
1338
+ });
1339
+ }
1340
+ },
1341
+ async registerTrads({ locales }) {
1342
+ const importedTrads = await Promise.all(
1343
+ locales.map((locale) => {
1344
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-D9Q4YW03.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1345
+ return {
1346
+ data: prefixPluginTranslations(data, "content-releases"),
1347
+ locale
1348
+ };
1349
+ }).catch(() => {
1350
+ return {
1351
+ data: {},
1352
+ locale
1353
+ };
1354
+ });
1355
+ })
1356
+ );
1357
+ return Promise.resolve(importedTrads);
1358
+ }
1359
+ };
1360
+ export {
1361
+ PERMISSIONS as P,
1362
+ ReleaseActionOptions as R,
1363
+ useGetReleaseSettingsQuery as a,
1364
+ useCreateReleaseMutation as b,
1365
+ useGetReleaseQuery as c,
1366
+ useUpdateReleaseMutation as d,
1367
+ useDeleteReleaseMutation as e,
1368
+ usePublishReleaseMutation as f,
1369
+ getTimezones as g,
1370
+ getTimezoneOffset as h,
1371
+ useGetReleaseActionsQuery as i,
1372
+ useUpdateReleaseActionMutation as j,
1373
+ ReleaseActionMenu as k,
1374
+ useUpdateReleaseSettingsMutation as l,
1375
+ admin as m,
1376
+ pluginId as p,
1377
+ releaseApi as r,
1378
+ useGetReleasesQuery as u
1379
+ };
1380
+ //# sourceMappingURL=index-CK9G80CL.mjs.map