@strapi/content-releases 0.0.0-experimental.check-license → 0.0.0-experimental.d4cb32ce579e12a4436d68036f2327132fba1309

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 (34) hide show
  1. package/dist/_chunks/App-OK4Xac-O.js +1315 -0
  2. package/dist/_chunks/App-OK4Xac-O.js.map +1 -0
  3. package/dist/_chunks/App-xAkiD42p.mjs +1292 -0
  4. package/dist/_chunks/App-xAkiD42p.mjs.map +1 -0
  5. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs +51 -0
  6. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +1 -0
  7. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js +51 -0
  8. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +1 -0
  9. package/dist/_chunks/en-r0otWaln.js +77 -0
  10. package/dist/_chunks/en-r0otWaln.js.map +1 -0
  11. package/dist/_chunks/en-veqvqeEr.mjs +77 -0
  12. package/dist/_chunks/en-veqvqeEr.mjs.map +1 -0
  13. package/dist/_chunks/index-JvA2_26n.js +1015 -0
  14. package/dist/_chunks/index-JvA2_26n.js.map +1 -0
  15. package/dist/_chunks/index-exoiSU3V.mjs +994 -0
  16. package/dist/_chunks/index-exoiSU3V.mjs.map +1 -0
  17. package/dist/admin/index.js +17 -35
  18. package/dist/admin/index.js.map +1 -1
  19. package/dist/admin/index.mjs +17 -35
  20. package/dist/admin/index.mjs.map +1 -1
  21. package/dist/server/index.js +1332 -5
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/server/index.mjs +1310 -5
  24. package/dist/server/index.mjs.map +1 -1
  25. package/package.json +35 -19
  26. package/dist/_chunks/en-21947221.js +0 -5
  27. package/dist/_chunks/en-21947221.js.map +0 -1
  28. package/dist/_chunks/en-92157b33.mjs +0 -5
  29. package/dist/_chunks/en-92157b33.mjs.map +0 -1
  30. package/dist/admin/src/index.d.ts +0 -15
  31. package/dist/admin/src/tests/index.test.d.ts +0 -0
  32. package/dist/server/src/__tests__/index.test.d.ts +0 -2
  33. package/dist/server/src/index.d.ts +0 -4
  34. package/dist/server/src/register.d.ts +0 -1
@@ -0,0 +1,994 @@
1
+ import { getFetchClient, useNotification, useAPIErrorHandler, CheckPermissions, useCMEditViewDataManager, NoContent, 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, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter } 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"],
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
+ updateReleaseAction: build.mutation({
255
+ query({ body, params }) {
256
+ return {
257
+ url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,
258
+ method: "PUT",
259
+ data: body
260
+ };
261
+ },
262
+ invalidatesTags: () => [{ type: "ReleaseAction", id: "LIST" }],
263
+ async onQueryStarted({ body, params, query, actionPath }, { dispatch, queryFulfilled }) {
264
+ const paramsWithoutActionId = {
265
+ releaseId: params.releaseId,
266
+ ...query
267
+ };
268
+ const patchResult = dispatch(
269
+ releaseApi.util.updateQueryData("getReleaseActions", paramsWithoutActionId, (draft) => {
270
+ const [key, index] = actionPath;
271
+ const action = draft.data[key][index];
272
+ if (action) {
273
+ action.type = body.type;
274
+ }
275
+ })
276
+ );
277
+ try {
278
+ await queryFulfilled;
279
+ } catch {
280
+ patchResult.undo();
281
+ }
282
+ }
283
+ }),
284
+ deleteReleaseAction: build.mutation({
285
+ query({ params }) {
286
+ return {
287
+ url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,
288
+ method: "DELETE"
289
+ };
290
+ },
291
+ invalidatesTags: [
292
+ { type: "Release", id: "LIST" },
293
+ { type: "ReleaseAction", id: "LIST" }
294
+ ]
295
+ }),
296
+ publishRelease: build.mutation({
297
+ query({ id }) {
298
+ return {
299
+ url: `/content-releases/${id}/publish`,
300
+ method: "POST"
301
+ };
302
+ },
303
+ invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
304
+ }),
305
+ deleteRelease: build.mutation({
306
+ query({ id }) {
307
+ return {
308
+ url: `/content-releases/${id}`,
309
+ method: "DELETE"
310
+ };
311
+ },
312
+ invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
313
+ })
314
+ };
315
+ }
316
+ });
317
+ const {
318
+ useGetReleasesQuery,
319
+ useGetReleasesForEntryQuery,
320
+ useGetReleaseQuery,
321
+ useGetReleaseActionsQuery,
322
+ useCreateReleaseMutation,
323
+ useCreateReleaseActionMutation,
324
+ useUpdateReleaseMutation,
325
+ useUpdateReleaseActionMutation,
326
+ usePublishReleaseMutation,
327
+ useDeleteReleaseActionMutation,
328
+ useDeleteReleaseMutation
329
+ } = releaseApi;
330
+ const getTimezoneOffset = (timezone, date) => {
331
+ try {
332
+ const offsetPart = new Intl.DateTimeFormat("en", {
333
+ timeZone: timezone,
334
+ timeZoneName: "longOffset"
335
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
336
+ const offset = offsetPart ? offsetPart.value : "";
337
+ let utcOffset = offset.replace("GMT", "UTC");
338
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
339
+ utcOffset = `${utcOffset}+00:00`;
340
+ }
341
+ return utcOffset;
342
+ } catch (error) {
343
+ return "";
344
+ }
345
+ };
346
+ const useTypedDispatch = useDispatch;
347
+ const useTypedSelector = useSelector;
348
+ const StyledMenuItem = styled(Menu.Item)`
349
+ &:hover {
350
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
351
+
352
+ svg {
353
+ path {
354
+ fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
355
+ }
356
+ }
357
+
358
+ a {
359
+ color: ${({ theme }) => theme.colors.neutral800};
360
+ }
361
+ }
362
+
363
+ svg {
364
+ path {
365
+ fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
366
+ }
367
+ }
368
+
369
+ a {
370
+ color: ${({ theme }) => theme.colors.neutral800};
371
+ }
372
+
373
+ span,
374
+ a {
375
+ width: 100%;
376
+ }
377
+ `;
378
+ const StyledIconButton = styled(IconButton)`
379
+ /* Setting this style inline with borderColor will not apply the style */
380
+ border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};
381
+ `;
382
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
383
+ const { formatMessage } = useIntl();
384
+ const toggleNotification = useNotification();
385
+ const { formatAPIError } = useAPIErrorHandler();
386
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
387
+ const handleDeleteAction = async () => {
388
+ const response = await deleteReleaseAction({
389
+ params: { releaseId, actionId }
390
+ });
391
+ if ("data" in response) {
392
+ toggleNotification({
393
+ type: "success",
394
+ message: formatMessage({
395
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
396
+ defaultMessage: "Entry removed from release"
397
+ })
398
+ });
399
+ return;
400
+ }
401
+ if ("error" in response) {
402
+ if (isAxiosError$1(response.error)) {
403
+ toggleNotification({
404
+ type: "warning",
405
+ message: formatAPIError(response.error)
406
+ });
407
+ } else {
408
+ toggleNotification({
409
+ type: "warning",
410
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
411
+ });
412
+ }
413
+ }
414
+ };
415
+ return /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
416
+ /* @__PURE__ */ jsx(Icon, { as: Cross, width: 3, height: 3 }),
417
+ /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
418
+ id: "content-releases.content-manager-edit-view.remove-from-release",
419
+ defaultMessage: "Remove from release"
420
+ }) })
421
+ ] }) }) });
422
+ };
423
+ const ReleaseActionEntryLinkItem = ({
424
+ contentTypeUid,
425
+ entryId,
426
+ locale
427
+ }) => {
428
+ const { formatMessage } = useIntl();
429
+ const collectionTypePermissions = useTypedSelector(
430
+ (state) => state.rbacProvider.collectionTypesRelatedPermissions
431
+ );
432
+ const updatePermissions = contentTypeUid ? collectionTypePermissions[contentTypeUid]?.["plugin::content-manager.explorer.update"] : [];
433
+ const canUpdateEntryForLocale = Boolean(
434
+ !locale || updatePermissions?.find(
435
+ (permission) => permission.properties?.locales?.includes(locale)
436
+ )
437
+ );
438
+ return /* @__PURE__ */ jsx(
439
+ CheckPermissions,
440
+ {
441
+ permissions: [
442
+ {
443
+ action: "plugin::content-manager.explorer.update",
444
+ subject: contentTypeUid
445
+ }
446
+ ],
447
+ children: canUpdateEntryForLocale && /* @__PURE__ */ jsx(StyledMenuItem, { children: /* @__PURE__ */ jsx(
448
+ Link,
449
+ {
450
+ as: NavLink,
451
+ to: {
452
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
453
+ search: locale && `?plugins[i18n][locale]=${locale}`
454
+ },
455
+ startIcon: /* @__PURE__ */ jsx(Icon, { as: Pencil, width: 3, height: 3 }),
456
+ children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
457
+ id: "content-releases.content-manager-edit-view.edit-entry",
458
+ defaultMessage: "Edit entry"
459
+ }) })
460
+ }
461
+ ) })
462
+ }
463
+ );
464
+ };
465
+ const Root = ({ children, hasTriggerBorder = false }) => {
466
+ const { formatMessage } = useIntl();
467
+ return (
468
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
469
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: [...PERMISSIONS.deleteAction, ...PERMISSIONS.update], children: /* @__PURE__ */ jsxs(Menu.Root, { children: [
470
+ /* @__PURE__ */ jsx(
471
+ Menu.Trigger,
472
+ {
473
+ as: hasTriggerBorder ? StyledIconButton : IconButton,
474
+ paddingLeft: 2,
475
+ paddingRight: 2,
476
+ "aria-label": formatMessage({
477
+ id: "content-releases.content-manager-edit-view.release-action-menu",
478
+ defaultMessage: "Release action options"
479
+ }),
480
+ icon: /* @__PURE__ */ jsx(More, {})
481
+ }
482
+ ),
483
+ /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
484
+ ] }) })
485
+ );
486
+ };
487
+ const ReleaseActionMenu = {
488
+ Root,
489
+ DeleteReleaseActionItem,
490
+ ReleaseActionEntryLinkItem
491
+ };
492
+ const getBorderLeftRadiusValue = (actionType) => {
493
+ return actionType === "publish" ? 1 : 0;
494
+ };
495
+ const getBorderRightRadiusValue = (actionType) => {
496
+ return actionType === "publish" ? 0 : 1;
497
+ };
498
+ const FieldWrapper = styled(Field)`
499
+ border-top-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
500
+ border-bottom-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
501
+ border-top-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
502
+ border-bottom-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
503
+
504
+ > label {
505
+ color: inherit;
506
+ padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};
507
+ text-align: center;
508
+ vertical-align: middle;
509
+ text-transform: capitalize;
510
+ }
511
+
512
+ &[data-checked='true'] {
513
+ color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
514
+ background-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
515
+ border-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
516
+ }
517
+
518
+ &[data-checked='false'] {
519
+ border-left: ${({ actionType }) => actionType === "unpublish" && "none"};
520
+ border-right: ${({ actionType }) => actionType === "publish" && "none"};
521
+ }
522
+
523
+ &[data-checked='false'][data-disabled='false']:hover {
524
+ color: ${({ theme }) => theme.colors.neutral700};
525
+ background-color: ${({ theme }) => theme.colors.neutral100};
526
+ border-color: ${({ theme }) => theme.colors.neutral200};
527
+
528
+ & > label {
529
+ cursor: pointer;
530
+ }
531
+ }
532
+
533
+ &[data-disabled='true'] {
534
+ color: ${({ theme }) => theme.colors.neutral600};
535
+ background-color: ${({ theme }) => theme.colors.neutral150};
536
+ border-color: ${({ theme }) => theme.colors.neutral300};
537
+ }
538
+ `;
539
+ const ActionOption = ({
540
+ selected,
541
+ actionType,
542
+ handleChange,
543
+ name,
544
+ disabled = false
545
+ }) => {
546
+ return /* @__PURE__ */ jsx(
547
+ FieldWrapper,
548
+ {
549
+ actionType,
550
+ background: "primary0",
551
+ borderColor: "neutral200",
552
+ color: selected === actionType ? "primary600" : "neutral600",
553
+ position: "relative",
554
+ cursor: "pointer",
555
+ "data-checked": selected === actionType,
556
+ "data-disabled": disabled && selected !== actionType,
557
+ children: /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: `${name}-${actionType}`, children: [
558
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
559
+ FieldInput,
560
+ {
561
+ type: "radio",
562
+ id: `${name}-${actionType}`,
563
+ name,
564
+ checked: selected === actionType,
565
+ onChange: handleChange,
566
+ value: actionType,
567
+ disabled
568
+ }
569
+ ) }),
570
+ actionType
571
+ ] })
572
+ }
573
+ );
574
+ };
575
+ const ReleaseActionOptions = ({
576
+ selected,
577
+ handleChange,
578
+ name,
579
+ disabled = false
580
+ }) => {
581
+ return /* @__PURE__ */ jsxs(Flex, { children: [
582
+ /* @__PURE__ */ jsx(
583
+ ActionOption,
584
+ {
585
+ actionType: "publish",
586
+ selected,
587
+ handleChange,
588
+ name,
589
+ disabled
590
+ }
591
+ ),
592
+ /* @__PURE__ */ jsx(
593
+ ActionOption,
594
+ {
595
+ actionType: "unpublish",
596
+ selected,
597
+ handleChange,
598
+ name,
599
+ disabled
600
+ }
601
+ )
602
+ ] });
603
+ };
604
+ const RELEASE_ACTION_FORM_SCHEMA = yup.object().shape({
605
+ type: yup.string().oneOf(["publish", "unpublish"]).required(),
606
+ releaseId: yup.string().required()
607
+ });
608
+ const INITIAL_VALUES = {
609
+ type: "publish",
610
+ releaseId: ""
611
+ };
612
+ const NoReleases = () => {
613
+ const { formatMessage } = useIntl();
614
+ return /* @__PURE__ */ jsx(
615
+ NoContent,
616
+ {
617
+ content: {
618
+ id: "content-releases.content-manager-edit-view.add-to-release.no-releases-message",
619
+ defaultMessage: "No available releases. Open the list of releases and create a new one from there."
620
+ },
621
+ action: /* @__PURE__ */ jsx(
622
+ LinkButton,
623
+ {
624
+ to: {
625
+ pathname: "/plugins/content-releases"
626
+ },
627
+ as: Link$1,
628
+ variant: "secondary",
629
+ children: formatMessage({
630
+ id: "content-releases.content-manager-edit-view.add-to-release.redirect-button",
631
+ defaultMessage: "Open the list of releases"
632
+ })
633
+ }
634
+ )
635
+ }
636
+ );
637
+ };
638
+ const AddActionToReleaseModal = ({
639
+ handleClose,
640
+ contentTypeUid,
641
+ entryId
642
+ }) => {
643
+ const releaseHeaderId = React.useId();
644
+ const { formatMessage } = useIntl();
645
+ const toggleNotification = useNotification();
646
+ const { formatAPIError } = useAPIErrorHandler();
647
+ const { modifiedData } = useCMEditViewDataManager();
648
+ const response = useGetReleasesForEntryQuery({
649
+ contentTypeUid,
650
+ entryId,
651
+ hasEntryAttached: false
652
+ });
653
+ const releases = response.data?.data;
654
+ const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
655
+ const handleSubmit = async (values) => {
656
+ const locale = modifiedData.locale;
657
+ const releaseActionEntry = {
658
+ contentType: contentTypeUid,
659
+ id: entryId,
660
+ locale
661
+ };
662
+ const response2 = await createReleaseAction({
663
+ body: { type: values.type, entry: releaseActionEntry },
664
+ params: { releaseId: values.releaseId }
665
+ });
666
+ if ("data" in response2) {
667
+ toggleNotification({
668
+ type: "success",
669
+ message: formatMessage({
670
+ id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
671
+ defaultMessage: "Entry added to release"
672
+ })
673
+ });
674
+ handleClose();
675
+ return;
676
+ }
677
+ if ("error" in response2) {
678
+ if (isAxiosError$1(response2.error)) {
679
+ toggleNotification({
680
+ type: "warning",
681
+ message: formatAPIError(response2.error)
682
+ });
683
+ } else {
684
+ toggleNotification({
685
+ type: "warning",
686
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
687
+ });
688
+ }
689
+ }
690
+ };
691
+ return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
692
+ /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
693
+ id: "content-releases.content-manager-edit-view.add-to-release",
694
+ defaultMessage: "Add to release"
695
+ }) }) }),
696
+ /* @__PURE__ */ jsx(
697
+ Formik,
698
+ {
699
+ onSubmit: handleSubmit,
700
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
701
+ initialValues: INITIAL_VALUES,
702
+ children: ({ values, setFieldValue }) => {
703
+ return /* @__PURE__ */ jsxs(Form, { children: [
704
+ releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
705
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsx(
706
+ SingleSelect,
707
+ {
708
+ required: true,
709
+ label: formatMessage({
710
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
711
+ defaultMessage: "Select a release"
712
+ }),
713
+ placeholder: formatMessage({
714
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
715
+ defaultMessage: "Select"
716
+ }),
717
+ onChange: (value) => setFieldValue("releaseId", value),
718
+ value: values.releaseId,
719
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
720
+ }
721
+ ) }),
722
+ /* @__PURE__ */ jsx(FieldLabel, { children: formatMessage({
723
+ id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
724
+ defaultMessage: "What do you want to do with this entry?"
725
+ }) }),
726
+ /* @__PURE__ */ jsx(
727
+ ReleaseActionOptions,
728
+ {
729
+ selected: values.type,
730
+ handleChange: (e) => setFieldValue("type", e.target.value),
731
+ name: "type"
732
+ }
733
+ )
734
+ ] }) }),
735
+ /* @__PURE__ */ jsx(
736
+ ModalFooter,
737
+ {
738
+ startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
739
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
740
+ defaultMessage: "Cancel"
741
+ }) }),
742
+ endActions: (
743
+ /**
744
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
745
+ * for yup.string().required(), even when the value is falsy (including empty string)
746
+ */
747
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
748
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
749
+ defaultMessage: "Continue"
750
+ }) })
751
+ )
752
+ }
753
+ )
754
+ ] });
755
+ }
756
+ }
757
+ )
758
+ ] });
759
+ };
760
+ const CMReleasesContainer = () => {
761
+ const [isModalOpen, setIsModalOpen] = React.useState(false);
762
+ const { formatMessage, formatDate, formatTime } = useIntl();
763
+ const {
764
+ isCreatingEntry,
765
+ hasDraftAndPublish,
766
+ initialData: { id: entryId },
767
+ slug
768
+ } = useCMEditViewDataManager();
769
+ const contentTypeUid = slug;
770
+ const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
771
+ const canFetch = entryId != null && contentTypeUid != null;
772
+ const fetchParams = canFetch ? {
773
+ contentTypeUid,
774
+ entryId,
775
+ hasEntryAttached: true
776
+ } : skipToken;
777
+ const response = useGetReleasesForEntryQuery(fetchParams);
778
+ const releases = response.data?.data;
779
+ if (!canFetch) {
780
+ return null;
781
+ }
782
+ if (isCreatingEntry || !hasDraftAndPublish) {
783
+ return null;
784
+ }
785
+ const toggleModal = () => setIsModalOpen((prev) => !prev);
786
+ const getReleaseColorVariant = (actionType, shade) => {
787
+ if (actionType === "unpublish") {
788
+ return `secondary${shade}`;
789
+ }
790
+ return `success${shade}`;
791
+ };
792
+ return /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(
793
+ Box,
794
+ {
795
+ as: "aside",
796
+ "aria-label": formatMessage({
797
+ id: "content-releases.plugin.name",
798
+ defaultMessage: "Releases"
799
+ }),
800
+ background: "neutral0",
801
+ borderColor: "neutral150",
802
+ hasRadius: true,
803
+ padding: 4,
804
+ shadow: "tableShadow",
805
+ children: [
806
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
807
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", children: formatMessage({
808
+ id: "content-releases.plugin.name",
809
+ defaultMessage: "Releases"
810
+ }) }),
811
+ releases?.map((release) => {
812
+ return /* @__PURE__ */ jsxs(
813
+ Flex,
814
+ {
815
+ direction: "column",
816
+ alignItems: "start",
817
+ borderWidth: "1px",
818
+ borderStyle: "solid",
819
+ borderColor: getReleaseColorVariant(release.action.type, "200"),
820
+ overflow: "hidden",
821
+ hasRadius: true,
822
+ children: [
823
+ /* @__PURE__ */ jsx(
824
+ Box,
825
+ {
826
+ paddingTop: 3,
827
+ paddingBottom: 3,
828
+ paddingLeft: 4,
829
+ paddingRight: 4,
830
+ background: getReleaseColorVariant(release.action.type, "100"),
831
+ width: "100%",
832
+ children: /* @__PURE__ */ jsx(
833
+ Typography,
834
+ {
835
+ fontSize: 1,
836
+ variant: "pi",
837
+ textColor: getReleaseColorVariant(release.action.type, "600"),
838
+ children: formatMessage(
839
+ {
840
+ id: "content-releases.content-manager-edit-view.list-releases.title",
841
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
842
+ },
843
+ { isPublish: release.action.type === "publish" }
844
+ )
845
+ }
846
+ )
847
+ }
848
+ ),
849
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
850
+ /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
851
+ IsSchedulingEnabled && release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
852
+ {
853
+ id: "content-releases.content-manager-edit-view.scheduled.date",
854
+ defaultMessage: "{date} at {time} ({offset})"
855
+ },
856
+ {
857
+ date: formatDate(new Date(release.scheduledAt), {
858
+ day: "2-digit",
859
+ month: "2-digit",
860
+ year: "numeric",
861
+ timeZone: release.timezone
862
+ }),
863
+ time: formatTime(new Date(release.scheduledAt), {
864
+ hourCycle: "h23",
865
+ timeZone: release.timezone
866
+ }),
867
+ offset: getTimezoneOffset(
868
+ release.timezone,
869
+ new Date(release.scheduledAt)
870
+ )
871
+ }
872
+ ) }),
873
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsx(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: /* @__PURE__ */ jsx(
874
+ ReleaseActionMenu.DeleteReleaseActionItem,
875
+ {
876
+ releaseId: release.id,
877
+ actionId: release.action.id
878
+ }
879
+ ) }) })
880
+ ] })
881
+ ]
882
+ },
883
+ release.id
884
+ );
885
+ }),
886
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.createAction, children: /* @__PURE__ */ jsx(
887
+ Button,
888
+ {
889
+ justifyContent: "center",
890
+ paddingLeft: 4,
891
+ paddingRight: 4,
892
+ color: "neutral700",
893
+ variant: "tertiary",
894
+ startIcon: /* @__PURE__ */ jsx(Plus, {}),
895
+ onClick: toggleModal,
896
+ children: formatMessage({
897
+ id: "content-releases.content-manager-edit-view.add-to-release",
898
+ defaultMessage: "Add to release"
899
+ })
900
+ }
901
+ ) })
902
+ ] }),
903
+ isModalOpen && /* @__PURE__ */ jsx(
904
+ AddActionToReleaseModal,
905
+ {
906
+ handleClose: toggleModal,
907
+ contentTypeUid,
908
+ entryId
909
+ }
910
+ )
911
+ ]
912
+ }
913
+ ) });
914
+ };
915
+ const admin = {
916
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
917
+ register(app) {
918
+ if (window.strapi.features.isEnabled("cms-content-releases")) {
919
+ app.addMenuLink({
920
+ to: `/plugins/${pluginId}`,
921
+ icon: PaperPlane,
922
+ intlLabel: {
923
+ id: `${pluginId}.plugin.name`,
924
+ defaultMessage: "Releases"
925
+ },
926
+ async Component() {
927
+ const { App } = await import("./App-xAkiD42p.mjs");
928
+ return App;
929
+ },
930
+ permissions: PERMISSIONS.main
931
+ });
932
+ app.addMiddlewares([() => releaseApi.middleware]);
933
+ app.addReducers({
934
+ [releaseApi.reducerPath]: releaseApi.reducer
935
+ });
936
+ app.injectContentManagerComponent("editView", "right-links", {
937
+ name: `${pluginId}-link`,
938
+ Component: CMReleasesContainer
939
+ });
940
+ } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
941
+ app.addMenuLink({
942
+ to: `/plugins/purchase-content-releases`,
943
+ icon: PaperPlane,
944
+ intlLabel: {
945
+ id: `${pluginId}.plugin.name`,
946
+ defaultMessage: "Releases"
947
+ },
948
+ async Component() {
949
+ const { PurchaseContentReleases } = await import("./PurchaseContentReleases-Clm0iACO.mjs");
950
+ return PurchaseContentReleases;
951
+ },
952
+ lockIcon: true
953
+ });
954
+ }
955
+ },
956
+ async registerTrads({ locales }) {
957
+ const importedTrads = await Promise.all(
958
+ locales.map((locale) => {
959
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-veqvqeEr.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
960
+ return {
961
+ data: prefixPluginTranslations(data, "content-releases"),
962
+ locale
963
+ };
964
+ }).catch(() => {
965
+ return {
966
+ data: {},
967
+ locale
968
+ };
969
+ });
970
+ })
971
+ );
972
+ return Promise.resolve(importedTrads);
973
+ }
974
+ };
975
+ export {
976
+ PERMISSIONS as P,
977
+ ReleaseActionOptions as R,
978
+ useUpdateReleaseMutation as a,
979
+ useDeleteReleaseMutation as b,
980
+ usePublishReleaseMutation as c,
981
+ useTypedDispatch as d,
982
+ useGetReleaseActionsQuery as e,
983
+ useUpdateReleaseActionMutation as f,
984
+ getTimezoneOffset as g,
985
+ ReleaseActionMenu as h,
986
+ isAxiosError as i,
987
+ useGetReleasesQuery as j,
988
+ useCreateReleaseMutation as k,
989
+ admin as l,
990
+ pluginId as p,
991
+ releaseApi as r,
992
+ useGetReleaseQuery as u
993
+ };
994
+ //# sourceMappingURL=index-exoiSU3V.mjs.map