@strapi/content-releases 0.0.0-experimental.e576af447d9f97e89e24c6daa32d8f714376cd5f → 0.0.0-experimental.e86ac7192458208dc921b643405f97aeba7cccb9

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