@strapi/content-releases 0.0.0-next.09b9d36b22a205d90c9303f2e37134938cf76c90 → 0.0.0-next.37dd1e3ff22e1635b69683abadd444912ae0dbff

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-PEkKIRyJ.js","sources":["../../admin/src/constants.ts","../../admin/src/pluginId.ts","../../admin/src/services/axios.ts","../../admin/src/services/release.ts","../../admin/src/components/ReleaseActionMenu.tsx","../../admin/src/components/ReleaseActionOptions.tsx","../../admin/src/components/CMReleasesContainer.tsx","../../admin/src/index.ts"],"sourcesContent":["import { Permission as StrapiPermission } from '@strapi/helper-plugin';\n\nexport const PERMISSIONS = {\n main: [\n {\n action: 'plugin::content-releases.read',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n create: [\n {\n action: 'plugin::content-releases.create',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n update: [\n {\n action: 'plugin::content-releases.update',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n delete: [\n {\n action: 'plugin::content-releases.delete',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n createAction: [\n {\n action: 'plugin::content-releases.create-action',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n deleteAction: [\n {\n action: 'plugin::content-releases.delete-action',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n publish: [\n {\n action: 'plugin::content-releases.publish',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n} satisfies Record<string, StrapiPermission[]>;\n","export const pluginId = 'content-releases';\n","import { getFetchClient } from '@strapi/helper-plugin';\n\nimport type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';\n\n/* -------------------------------------------------------------------------------------------------\n * Axios data\n * -----------------------------------------------------------------------------------------------*/\nexport interface QueryArguments<TSend> {\n url: string;\n method: 'PUT' | 'GET' | 'POST' | 'DELETE';\n data?: TSend;\n config?: AxiosRequestConfig<TSend>;\n}\n\nconst axiosBaseQuery = async <TData = any, TSend = any>({\n url,\n method,\n data,\n config,\n}: QueryArguments<TSend>) => {\n try {\n const { get, post, del, put } = getFetchClient();\n\n if (method === 'POST') {\n const result = await post<TData, AxiosResponse<TData>, TSend>(url, data, config);\n return { data: result.data };\n }\n\n if (method === 'DELETE') {\n const result = await del<TData, AxiosResponse<TData>, TSend>(url, config);\n return { data: result.data };\n }\n\n if (method === 'PUT') {\n const result = await put<TData, AxiosResponse<TData>, TSend>(url, data, config);\n return { data: result.data };\n }\n\n /**\n * Default is GET.\n */\n const result = await get<TData, AxiosResponse<TData>, TSend>(url, config);\n return { data: result.data };\n } catch (error) {\n const err = error as AxiosError;\n /**\n * Handle error of type AxiosError\n *\n * This format mimics what we want from an AxiosError which is what the\n * rest of the app works with, except this format is \"serializable\" since\n * it goes into the redux store.\n *\n * NOTE – passing the whole response will highlight this \"serializability\" issue.\n */\n return {\n error: {\n status: err.response?.status,\n code: err.code,\n response: {\n data: err.response?.data,\n },\n },\n };\n }\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Axios error\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * This asserts the errors from redux-toolkit-query are\n * axios errors so we can pass them to our utility functions\n * to correctly render error messages.\n */\nconst isAxiosError = (err: unknown): err is AxiosError<{ error: any }> => {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'response' in err &&\n typeof err.response === 'object' &&\n err.response !== null &&\n 'data' in err.response\n );\n};\n\nexport { isAxiosError, axiosBaseQuery };\n","import { createApi } from '@reduxjs/toolkit/query/react';\n\nimport {\n CreateReleaseAction,\n DeleteReleaseAction,\n} from '../../../shared/contracts/release-actions';\nimport { pluginId } from '../pluginId';\n\nimport { axiosBaseQuery } from './axios';\n\nimport type {\n GetReleaseActions,\n UpdateReleaseAction,\n ReleaseActionGroupBy,\n} from '../../../shared/contracts/release-actions';\nimport type {\n CreateRelease,\n DeleteRelease,\n GetContentTypeEntryReleases,\n GetReleases,\n UpdateRelease,\n GetRelease,\n PublishRelease,\n} from '../../../shared/contracts/releases';\n\nexport interface GetReleasesQueryParams {\n page?: number;\n pageSize?: number;\n filters?: {\n releasedAt?: {\n // TODO: this should be a boolean, find a way to avoid strings\n $notNull?: boolean | 'true' | 'false';\n };\n };\n}\n\nexport interface GetReleaseActionsQueryParams {\n page?: number;\n pageSize?: number;\n groupBy?: ReleaseActionGroupBy;\n}\n\ntype GetReleasesTabResponse = GetReleases.Response & {\n meta: {\n activeTab: 'pending' | 'done';\n };\n};\n\nconst releaseApi = createApi({\n reducerPath: pluginId,\n baseQuery: axiosBaseQuery,\n tagTypes: ['Release', 'ReleaseAction'],\n endpoints: (build) => {\n return {\n getReleasesForEntry: build.query<\n GetContentTypeEntryReleases.Response,\n Partial<GetContentTypeEntryReleases.Request['query']>\n >({\n query(params) {\n return {\n url: '/content-releases',\n method: 'GET',\n config: {\n params,\n },\n };\n },\n providesTags: (result) =>\n result\n ? [\n ...result.data.map(({ id }) => ({ type: 'Release' as const, id })),\n { type: 'Release', id: 'LIST' },\n ]\n : [],\n }),\n getReleases: build.query<GetReleasesTabResponse, GetReleasesQueryParams | void>({\n query(\n { page, pageSize, filters } = {\n page: 1,\n pageSize: 16,\n filters: {\n releasedAt: {\n $notNull: false,\n },\n },\n }\n ) {\n return {\n url: '/content-releases',\n method: 'GET',\n config: {\n params: {\n page: page || 1,\n pageSize: pageSize || 16,\n filters: filters || {\n releasedAt: {\n $notNull: false,\n },\n },\n },\n },\n };\n },\n transformResponse(response: GetReleasesTabResponse, meta, arg) {\n const releasedAtValue = arg?.filters?.releasedAt?.$notNull;\n const isActiveDoneTab = releasedAtValue === 'true';\n const newResponse: GetReleasesTabResponse = {\n ...response,\n meta: {\n ...response.meta,\n activeTab: isActiveDoneTab ? 'done' : 'pending',\n },\n };\n\n return newResponse;\n },\n providesTags: (result) =>\n result\n ? [\n ...result.data.map(({ id }) => ({ type: 'Release' as const, id })),\n { type: 'Release', id: 'LIST' },\n ]\n : [{ type: 'Release', id: 'LIST' }],\n }),\n getRelease: build.query<GetRelease.Response, GetRelease.Request['params']>({\n query({ id }) {\n return {\n url: `/content-releases/${id}`,\n method: 'GET',\n };\n },\n providesTags: (result, error, arg) => [{ type: 'Release' as const, id: arg.id }],\n }),\n getReleaseActions: build.query<\n GetReleaseActions.Response,\n GetReleaseActions.Request['params'] & GetReleaseActions.Request['query']\n >({\n query({ releaseId, ...params }) {\n return {\n url: `/content-releases/${releaseId}/actions`,\n method: 'GET',\n config: {\n params,\n },\n };\n },\n providesTags: [{ type: 'ReleaseAction', id: 'LIST' }],\n }),\n createRelease: build.mutation<CreateRelease.Response, CreateRelease.Request['body']>({\n query(data) {\n return {\n url: '/content-releases',\n method: 'POST',\n data,\n };\n },\n invalidatesTags: [{ type: 'Release', id: 'LIST' }],\n }),\n updateRelease: build.mutation<\n void,\n UpdateRelease.Request['params'] & UpdateRelease.Request['body']\n >({\n query({ id, ...data }) {\n return {\n url: `/content-releases/${id}`,\n method: 'PUT',\n data,\n };\n },\n invalidatesTags: (result, error, arg) => [{ type: 'Release', id: arg.id }],\n }),\n createReleaseAction: build.mutation<\n CreateReleaseAction.Response,\n CreateReleaseAction.Request\n >({\n query({ body, params }) {\n return {\n url: `/content-releases/${params.releaseId}/actions`,\n method: 'POST',\n data: body,\n };\n },\n invalidatesTags: [\n { type: 'Release', id: 'LIST' },\n { type: 'ReleaseAction', id: 'LIST' },\n ],\n }),\n updateReleaseAction: build.mutation<\n UpdateReleaseAction.Response,\n UpdateReleaseAction.Request\n >({\n query({ body, params }) {\n return {\n url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,\n method: 'PUT',\n data: body,\n };\n },\n invalidatesTags: () => [{ type: 'ReleaseAction', id: 'LIST' }],\n }),\n deleteReleaseAction: build.mutation<\n DeleteReleaseAction.Response,\n DeleteReleaseAction.Request\n >({\n query({ params }) {\n return {\n url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,\n method: 'DELETE',\n };\n },\n invalidatesTags: [\n { type: 'Release', id: 'LIST' },\n { type: 'ReleaseAction', id: 'LIST' },\n ],\n }),\n publishRelease: build.mutation<PublishRelease.Response, PublishRelease.Request['params']>({\n query({ id }) {\n return {\n url: `/content-releases/${id}/publish`,\n method: 'POST',\n };\n },\n invalidatesTags: (result, error, arg) => [{ type: 'Release', id: arg.id }],\n }),\n deleteRelease: build.mutation<DeleteRelease.Response, DeleteRelease.Request['params']>({\n query({ id }) {\n return {\n url: `/content-releases/${id}`,\n method: 'DELETE',\n };\n },\n invalidatesTags: (result, error, arg) => [{ type: 'Release', id: arg.id }],\n }),\n };\n },\n});\n\nconst {\n useGetReleasesQuery,\n useGetReleasesForEntryQuery,\n useGetReleaseQuery,\n useGetReleaseActionsQuery,\n useCreateReleaseMutation,\n useCreateReleaseActionMutation,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseActionMutation,\n useDeleteReleaseMutation,\n} = releaseApi;\n\nexport {\n useGetReleasesQuery,\n useGetReleasesForEntryQuery,\n useGetReleaseQuery,\n useGetReleaseActionsQuery,\n useCreateReleaseMutation,\n useCreateReleaseActionMutation,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseActionMutation,\n useDeleteReleaseMutation,\n releaseApi,\n};\n","import { Flex, IconButton, Typography } from '@strapi/design-system';\nimport { Menu } from '@strapi/design-system/v2';\nimport { CheckPermissions, useAPIErrorHandler, useNotification } from '@strapi/helper-plugin';\nimport { Cross, More } from '@strapi/icons';\nimport { isAxiosError } from 'axios';\nimport { useIntl } from 'react-intl';\nimport styled from 'styled-components';\n\nimport { DeleteReleaseAction } from '../../../shared/contracts/release-actions';\nimport { PERMISSIONS } from '../constants';\nimport { useDeleteReleaseActionMutation } from '../services/release';\n\nconst StyledMenuItem = styled(Menu.Item)`\n &:hover {\n background: ${({ theme }) => theme.colors.danger100};\n }\n\n svg {\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n }\n\n &:hover {\n svg {\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n }\n }\n`;\n\nconst StyledCross = styled(Cross)`\n padding: ${({ theme }) => theme.spaces[1]};\n`;\n\nconst StyledIconButton = styled(IconButton)`\n /* Setting this style inline with borderColor will not apply the style */\n border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};\n`;\n\ninterface ReleaseActionMenuProps {\n releaseId: DeleteReleaseAction.Request['params']['releaseId'];\n actionId: DeleteReleaseAction.Request['params']['actionId'];\n hasTriggerBorder?: boolean;\n}\n\nexport const ReleaseActionMenu = ({\n releaseId,\n actionId,\n hasTriggerBorder = false,\n}: ReleaseActionMenuProps) => {\n const { formatMessage } = useIntl();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const [deleteReleaseAction] = useDeleteReleaseActionMutation();\n\n const handleDeleteAction = async () => {\n const response = await deleteReleaseAction({\n params: { releaseId, actionId },\n });\n\n if ('data' in response) {\n // Handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.content-manager-edit-view.remove-from-release.notification.success',\n defaultMessage: 'Entry removed from release',\n }),\n });\n\n return;\n }\n\n if ('error' in response) {\n if (isAxiosError(response.error)) {\n // Handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Handle generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n return (\n // A user can access the dropdown if they have permissions to delete a release-action OR update a release\n <CheckPermissions permissions={[...PERMISSIONS.deleteAction, ...PERMISSIONS.update]}>\n <Menu.Root>\n {/* \n TODO Fix in the DS\n - as={IconButton} has TS error: Property 'icon' does not exist on type 'IntrinsicAttributes & TriggerProps & RefAttributes<HTMLButtonElement>'\n - The Icon doesn't actually show unless you hack it with some padding...and it's still a little strange\n */}\n <Menu.Trigger\n as={hasTriggerBorder ? StyledIconButton : IconButton}\n paddingLeft={2}\n paddingRight={2}\n aria-label={formatMessage({\n id: 'content-releases.content-manager-edit-view.release-action-menu',\n defaultMessage: 'Release action options',\n })}\n // @ts-expect-error See above\n icon={<More />}\n />\n {/*\n TODO: Using Menu instead of SimpleMenu mainly because there is no positioning provided from the DS,\n Refactor this once fixed in the DS\n */}\n <Menu.Content top={1} popoverPlacement=\"bottom-end\">\n <CheckPermissions permissions={PERMISSIONS.deleteAction}>\n <StyledMenuItem onSelect={handleDeleteAction}>\n <Flex gap={2}>\n <StyledCross />\n <Typography textColor=\"danger600\" variant=\"omega\">\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.remove-from-release',\n defaultMessage: 'Remove from release',\n })}\n </Typography>\n </Flex>\n </StyledMenuItem>\n </CheckPermissions>\n </Menu.Content>\n </Menu.Root>\n </CheckPermissions>\n );\n};\n","import * as React from 'react';\n\nimport {\n FieldInput,\n FieldLabel,\n VisuallyHidden,\n Field,\n Flex,\n type FieldProps,\n} from '@strapi/design-system';\nimport styled from 'styled-components';\n\ninterface FieldWrapperProps extends FieldProps {\n actionType: 'publish' | 'unpublish';\n}\n\nconst getBorderLeftRadiusValue = (actionType: FieldWrapperProps['actionType']) => {\n return actionType === 'publish' ? 1 : 0;\n};\n\nconst getBorderRightRadiusValue = (actionType: FieldWrapperProps['actionType']) => {\n return actionType === 'publish' ? 0 : 1;\n};\n\nconst FieldWrapper = styled(Field)<FieldWrapperProps>`\n border-top-left-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderLeftRadiusValue(actionType)]};\n border-bottom-left-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderLeftRadiusValue(actionType)]};\n border-top-right-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderRightRadiusValue(actionType)]};\n border-bottom-right-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderRightRadiusValue(actionType)]};\n\n > label {\n color: inherit;\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};\n text-align: center;\n vertical-align: middle;\n text-transform: capitalize;\n }\n\n &:active,\n &[data-checked='true'] {\n color: ${({ theme }) => theme.colors.primary700};\n background-color: ${({ theme }) => theme.colors.primary100};\n border-color: ${({ theme }) => theme.colors.primary700};\n }\n\n &[data-checked='false'] {\n border-left: ${({ actionType }) => actionType === 'unpublish' && 'none'};\n border-right: ${({ actionType }) => actionType === 'publish' && 'none'};\n }\n`;\n\ninterface ActionOptionProps {\n selected: 'publish' | 'unpublish';\n handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n name: string;\n}\n\ninterface OptionProps extends ActionOptionProps {\n actionType: 'publish' | 'unpublish';\n}\n\nconst ActionOption = ({ selected, actionType, handleChange, name }: OptionProps) => {\n return (\n <FieldWrapper\n actionType={actionType}\n background=\"primary0\"\n borderColor=\"neutral200\"\n color={selected === actionType ? 'primary600' : 'neutral600'}\n position=\"relative\"\n cursor=\"pointer\"\n data-checked={selected === actionType}\n >\n <FieldLabel htmlFor={`${name}-${actionType}`}>\n <VisuallyHidden>\n <FieldInput\n type=\"radio\"\n id={`${name}-${actionType}`}\n name={name}\n checked={selected === actionType}\n onChange={handleChange}\n value={actionType}\n />\n </VisuallyHidden>\n {actionType}\n </FieldLabel>\n </FieldWrapper>\n );\n};\n\nexport const ReleaseActionOptions = ({ selected, handleChange, name }: ActionOptionProps) => {\n return (\n <Flex>\n <ActionOption\n actionType=\"publish\"\n selected={selected}\n handleChange={handleChange}\n name={name}\n />\n <ActionOption\n actionType=\"unpublish\"\n selected={selected}\n handleChange={handleChange}\n name={name}\n />\n </Flex>\n );\n};\n","import * as React from 'react';\n\nimport { skipToken } from '@reduxjs/toolkit/query';\nimport {\n Box,\n Button,\n FieldLabel,\n Flex,\n ModalBody,\n ModalHeader,\n ModalLayout,\n SingleSelect,\n SingleSelectOption,\n Typography,\n ModalFooter,\n} from '@strapi/design-system';\nimport { LinkButton } from '@strapi/design-system/v2';\nimport {\n CheckPermissions,\n NoContent,\n useAPIErrorHandler,\n useCMEditViewDataManager,\n useNotification,\n} from '@strapi/helper-plugin';\nimport { Plus } from '@strapi/icons';\nimport { isAxiosError } from 'axios';\nimport { Formik, Form } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useParams, Link as ReactRouterLink } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { CreateReleaseAction } from '../../../shared/contracts/release-actions';\nimport { GetContentTypeEntryReleases } from '../../../shared/contracts/releases';\nimport { PERMISSIONS } from '../constants';\nimport { useCreateReleaseActionMutation, useGetReleasesForEntryQuery } from '../services/release';\n\nimport { ReleaseActionMenu } from './ReleaseActionMenu';\nimport { ReleaseActionOptions } from './ReleaseActionOptions';\n\n/* -------------------------------------------------------------------------------------------------\n * AddActionToReleaseModal\n * -----------------------------------------------------------------------------------------------*/\n\nconst RELEASE_ACTION_FORM_SCHEMA = yup.object().shape({\n type: yup.string().oneOf(['publish', 'unpublish']).required(),\n releaseId: yup.string().required(),\n});\n\ninterface FormValues {\n type: CreateReleaseAction.Request['body']['type'];\n releaseId: CreateReleaseAction.Request['params']['releaseId'];\n}\n\nconst INITIAL_VALUES = {\n type: 'publish',\n releaseId: '',\n} satisfies FormValues;\n\ninterface AddActionToReleaseModalProps {\n handleClose: () => void;\n contentTypeUid: GetContentTypeEntryReleases.Request['query']['contentTypeUid'];\n entryId: GetContentTypeEntryReleases.Request['query']['entryId'];\n}\n\nconst NoReleases = () => {\n const { formatMessage } = useIntl();\n return (\n <NoContent\n content={{\n id: 'content-releases.content-manager-edit-view.add-to-release.no-releases-message',\n defaultMessage:\n 'No available releases. Open the list of releases and create a new one from there.',\n }}\n action={\n <LinkButton\n // @ts-expect-error - types are not inferred correctly through the as prop.\n to={{\n pathname: '/plugins/content-releases',\n }}\n as={ReactRouterLink}\n variant=\"secondary\"\n >\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.redirect-button',\n defaultMessage: 'Open the list of releases',\n })}\n </LinkButton>\n }\n />\n );\n};\n\nconst AddActionToReleaseModal = ({\n handleClose,\n contentTypeUid,\n entryId,\n}: AddActionToReleaseModalProps) => {\n const { formatMessage } = useIntl();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const { modifiedData } = useCMEditViewDataManager();\n\n // Get all 'pending' releases that do not have the entry attached\n const response = useGetReleasesForEntryQuery({\n contentTypeUid,\n entryId,\n hasEntryAttached: false,\n });\n\n const releases = response.data?.data;\n const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();\n\n const handleSubmit = async (values: FormValues) => {\n const locale = modifiedData.locale as string | undefined;\n const releaseActionEntry = {\n contentType: contentTypeUid,\n id: entryId,\n locale,\n };\n const response = await createReleaseAction({\n body: { type: values.type, entry: releaseActionEntry },\n params: { releaseId: values.releaseId },\n });\n\n if ('data' in response) {\n // Handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.notification.success',\n defaultMessage: 'Entry added to release',\n }),\n });\n\n handleClose();\n return;\n }\n\n if ('error' in response) {\n if (isAxiosError(response.error)) {\n // Handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Handle generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n return (\n <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release',\n defaultMessage: 'Add to release',\n })}\n </Typography>\n </ModalHeader>\n <Formik\n onSubmit={handleSubmit}\n validationSchema={RELEASE_ACTION_FORM_SCHEMA}\n initialValues={INITIAL_VALUES}\n >\n {({ values, setFieldValue }) => {\n return (\n <Form>\n {releases?.length === 0 ? (\n <NoReleases />\n ) : (\n <ModalBody>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={2}>\n <Box paddingBottom={6}>\n <SingleSelect\n required\n label={formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.select-label',\n defaultMessage: 'Select a release',\n })}\n placeholder={formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.select-placeholder',\n defaultMessage: 'Select',\n })}\n onChange={(value) => setFieldValue('releaseId', value)}\n value={values.releaseId}\n >\n {releases?.map((release) => (\n <SingleSelectOption key={release.id} value={release.id}>\n {release.name}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n </Box>\n <FieldLabel>\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.action-type-label',\n defaultMessage: 'What do you want to do with this entry?',\n })}\n </FieldLabel>\n <ReleaseActionOptions\n selected={values.type}\n handleChange={(e) => setFieldValue('type', e.target.value)}\n name=\"type\"\n />\n </Flex>\n </ModalBody>\n )}\n <ModalFooter\n startActions={\n <Button onClick={handleClose} variant=\"tertiary\" name=\"cancel\">\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.cancel-button',\n defaultMessage: 'Cancel',\n })}\n </Button>\n }\n endActions={\n /**\n * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true\n * for yup.string().required(), even when the value is falsy (including empty string)\n */\n <Button type=\"submit\" disabled={!values.releaseId} loading={isLoading}>\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.continue-button',\n defaultMessage: 'Continue',\n })}\n </Button>\n }\n />\n </Form>\n );\n }}\n </Formik>\n </ModalLayout>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * CMReleasesContainer\n * -----------------------------------------------------------------------------------------------*/\n\nexport const CMReleasesContainer = () => {\n const [isModalOpen, setIsModalOpen] = React.useState(false);\n const { formatMessage } = useIntl();\n const {\n isCreatingEntry,\n allLayoutData: { contentType },\n } = useCMEditViewDataManager();\n const params = useParams<{ id: string }>();\n\n const canFetch = params?.id != null && contentType?.uid != null;\n const fetchParams = canFetch\n ? {\n contentTypeUid: contentType.uid,\n entryId: params.id,\n hasEntryAttached: true,\n }\n : skipToken;\n // Get all 'pending' releases that have the entry attached\n const response = useGetReleasesForEntryQuery(fetchParams);\n const releases = response.data?.data;\n\n /**\n * If we don't have a contentType.uid or params.id then the data was never fetched\n * TODO: Should we handle this with an error message in the UI or just not show the container?\n */\n if (!canFetch) {\n return null;\n }\n\n /**\n * - Impossible to add entry to release before it exists\n * - Content types without draft and publish cannot add entries to release\n * TODO v5: All contentTypes will have draft and publish enabled\n */\n if (isCreatingEntry || !contentType?.options?.draftAndPublish) {\n return null;\n }\n\n const toggleModal = () => setIsModalOpen((prev) => !prev);\n\n const getReleaseColorVariant = (\n actionType: 'publish' | 'unpublish',\n shade: '100' | '200' | '600'\n ) => {\n if (actionType === 'unpublish') {\n return `secondary${shade}`;\n }\n\n return `success${shade}`;\n };\n\n return (\n <CheckPermissions permissions={PERMISSIONS.main}>\n <Box\n as=\"aside\"\n aria-label={formatMessage({\n id: 'content-releases.plugin.name',\n defaultMessage: 'Releases',\n })}\n background=\"neutral0\"\n borderColor=\"neutral150\"\n hasRadius\n padding={4}\n shadow=\"tableShadow\"\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={3}>\n <Typography variant=\"sigma\" textColor=\"neutral600\" textTransform=\"uppercase\">\n {formatMessage({\n id: 'content-releases.plugin.name',\n defaultMessage: 'Releases',\n })}\n </Typography>\n {releases?.map((release) => {\n return (\n <Flex\n key={release.id}\n direction=\"column\"\n alignItems=\"start\"\n borderWidth=\"1px\"\n borderStyle=\"solid\"\n borderColor={getReleaseColorVariant(release.action.type, '200')}\n overflow=\"hidden\"\n hasRadius\n >\n <Box\n paddingTop={3}\n paddingBottom={3}\n paddingLeft={4}\n paddingRight={4}\n background={getReleaseColorVariant(release.action.type, '100')}\n width=\"100%\"\n >\n <Typography\n fontSize={1}\n variant=\"pi\"\n textColor={getReleaseColorVariant(release.action.type, '600')}\n >\n {formatMessage(\n {\n id: 'content-releases.content-manager-edit-view.list-releases.title',\n defaultMessage:\n '{isPublish, select, true {Will be published in} other {Will be unpublished in}}',\n },\n { isPublish: release.action.type === 'publish' }\n )}\n </Typography>\n </Box>\n <Flex padding={4} direction=\"column\" gap={3} width=\"100%\" alignItems=\"flex-start\">\n <Typography fontSize={2} fontWeight=\"bold\" variant=\"omega\" textColor=\"neutral700\">\n {release.name}\n </Typography>\n <ReleaseActionMenu\n releaseId={release.id}\n actionId={release.action.id}\n hasTriggerBorder\n />\n </Flex>\n </Flex>\n );\n })}\n <CheckPermissions permissions={PERMISSIONS.createAction}>\n <Button\n justifyContent=\"center\"\n paddingLeft={4}\n paddingRight={4}\n color=\"neutral700\"\n variant=\"tertiary\"\n startIcon={<Plus />}\n onClick={toggleModal}\n >\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release',\n defaultMessage: 'Add to release',\n })}\n </Button>\n </CheckPermissions>\n </Flex>\n {isModalOpen && (\n <AddActionToReleaseModal\n handleClose={toggleModal}\n contentTypeUid={contentType.uid}\n entryId={params.id}\n />\n )}\n </Box>\n </CheckPermissions>\n );\n};\n","import { prefixPluginTranslations } from '@strapi/helper-plugin';\nimport { PaperPlane } from '@strapi/icons';\n\nimport { CMReleasesContainer } from './components/CMReleasesContainer';\nimport { PERMISSIONS } from './constants';\nimport { pluginId } from './pluginId';\nimport { releaseApi } from './services/release';\n\nimport type { Plugin } from '@strapi/types';\n\n// eslint-disable-next-line import/no-default-export\nconst admin: Plugin.Config.AdminInput = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register(app: any) {\n if (\n window.strapi.features.isEnabled('cms-content-releases') &&\n window.strapi.future.isEnabled('contentReleases')\n ) {\n app.addMenuLink({\n to: `/plugins/${pluginId}`,\n icon: PaperPlane,\n intlLabel: {\n id: `${pluginId}.plugin.name`,\n defaultMessage: 'Releases',\n },\n async Component() {\n const { App } = await import('./pages/App');\n return App;\n },\n permissions: PERMISSIONS.main,\n });\n\n /**\n * For some reason every middleware you pass has to a function\n * that returns the actual middleware. It's annoying but no one knows why....\n */\n app.addMiddlewares([() => releaseApi.middleware]);\n\n app.addReducers({\n [releaseApi.reducerPath]: releaseApi.reducer,\n });\n\n // Insert the Releases container in the 'right-links' zone of the Content Manager's edit view\n app.injectContentManagerComponent('editView', 'right-links', {\n name: `${pluginId}-link`,\n Component: CMReleasesContainer,\n });\n }\n },\n async registerTrads({ locales }: { locales: string[] }) {\n const importedTrads = await Promise.all(\n locales.map((locale) => {\n return import(`./translations/${locale}.json`)\n .then(({ default: data }) => {\n return {\n data: prefixPluginTranslations(data, 'content-releases'),\n locale,\n };\n })\n .catch(() => {\n return {\n data: {},\n locale,\n };\n });\n })\n );\n\n return Promise.resolve(importedTrads);\n },\n};\n\n// eslint-disable-next-line import/no-default-export\nexport default admin;\n"],"names":["getFetchClient","result","createApi","styled","Menu","Cross","IconButton","useIntl","useNotification","useAPIErrorHandler","isAxiosError","jsx","CheckPermissions","jsxs","More","Flex","Typography","Field","FieldLabel","VisuallyHidden","FieldInput","yup","NoContent","LinkButton","ReactRouterLink","useCMEditViewDataManager","response","ModalLayout","ModalHeader","Formik","Form","ModalBody","Box","SingleSelect","SingleSelectOption","ModalFooter","Button","React","useParams","skipToken","Plus","PaperPlane","prefixPluginTranslations"],"mappings":"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"}
@@ -328,7 +328,15 @@ const StyledMenuItem = styled(Menu.Item)`
328
328
  const StyledCross = styled(Cross)`
329
329
  padding: ${({ theme }) => theme.spaces[1]};
330
330
  `;
331
- const ReleaseActionMenu = ({ releaseId, actionId }) => {
331
+ const StyledIconButton = styled(IconButton)`
332
+ /* Setting this style inline with borderColor will not apply the style */
333
+ border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};
334
+ `;
335
+ const ReleaseActionMenu = ({
336
+ releaseId,
337
+ actionId,
338
+ hasTriggerBorder = false
339
+ }) => {
332
340
  const { formatMessage } = useIntl();
333
341
  const toggleNotification = useNotification();
334
342
  const { formatAPIError } = useAPIErrorHandler();
@@ -367,7 +375,7 @@ const ReleaseActionMenu = ({ releaseId, actionId }) => {
367
375
  /* @__PURE__ */ jsx(
368
376
  Menu.Trigger,
369
377
  {
370
- as: IconButton,
378
+ as: hasTriggerBorder ? StyledIconButton : IconButton,
371
379
  paddingLeft: 2,
372
380
  paddingRight: 2,
373
381
  "aria-label": formatMessage({
@@ -377,9 +385,9 @@ const ReleaseActionMenu = ({ releaseId, actionId }) => {
377
385
  icon: /* @__PURE__ */ jsx(More, {})
378
386
  }
379
387
  ),
380
- /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsx(StyledMenuItem, { color: "danger600", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
388
+ /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsx(StyledMenuItem, { onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
381
389
  /* @__PURE__ */ jsx(StyledCross, {}),
382
- /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
390
+ /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
383
391
  id: "content-releases.content-manager-edit-view.remove-from-release",
384
392
  defaultMessage: "Remove from release"
385
393
  }) })
@@ -712,7 +720,14 @@ const CMReleasesContainer = () => {
712
720
  ),
713
721
  /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 3, width: "100%", alignItems: "flex-start", children: [
714
722
  /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
715
- /* @__PURE__ */ jsx(ReleaseActionMenu, { releaseId: release.id, actionId: release.action.id })
723
+ /* @__PURE__ */ jsx(
724
+ ReleaseActionMenu,
725
+ {
726
+ releaseId: release.id,
727
+ actionId: release.action.id,
728
+ hasTriggerBorder: true
729
+ }
730
+ )
716
731
  ] })
717
732
  ]
718
733
  },
@@ -760,7 +775,7 @@ const admin = {
760
775
  defaultMessage: "Releases"
761
776
  },
762
777
  async Component() {
763
- const { App } = await import("./App-c3fca40f.mjs");
778
+ const { App } = await import("./App-J4jrthEu.mjs");
764
779
  return App;
765
780
  },
766
781
  permissions: PERMISSIONS.main
@@ -778,7 +793,7 @@ const admin = {
778
793
  async registerTrads({ locales }) {
779
794
  const importedTrads = await Promise.all(
780
795
  locales.map((locale) => {
781
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-142f336a.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
796
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-ngTk74JV.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
782
797
  return {
783
798
  data: prefixPluginTranslations(data, "content-releases"),
784
799
  locale
@@ -810,4 +825,4 @@ export {
810
825
  pluginId as p,
811
826
  useGetReleaseQuery as u
812
827
  };
813
- //# sourceMappingURL=index-e14e1ea9.mjs.map
828
+ //# sourceMappingURL=index-_Zsj8MUA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-_Zsj8MUA.mjs","sources":["../../admin/src/constants.ts","../../admin/src/pluginId.ts","../../admin/src/services/axios.ts","../../admin/src/services/release.ts","../../admin/src/components/ReleaseActionMenu.tsx","../../admin/src/components/ReleaseActionOptions.tsx","../../admin/src/components/CMReleasesContainer.tsx","../../admin/src/index.ts"],"sourcesContent":["import { Permission as StrapiPermission } from '@strapi/helper-plugin';\n\nexport const PERMISSIONS = {\n main: [\n {\n action: 'plugin::content-releases.read',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n create: [\n {\n action: 'plugin::content-releases.create',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n update: [\n {\n action: 'plugin::content-releases.update',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n delete: [\n {\n action: 'plugin::content-releases.delete',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n createAction: [\n {\n action: 'plugin::content-releases.create-action',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n deleteAction: [\n {\n action: 'plugin::content-releases.delete-action',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n publish: [\n {\n action: 'plugin::content-releases.publish',\n subject: null,\n id: '',\n actionParameters: {},\n properties: {},\n conditions: [],\n },\n ],\n} satisfies Record<string, StrapiPermission[]>;\n","export const pluginId = 'content-releases';\n","import { getFetchClient } from '@strapi/helper-plugin';\n\nimport type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';\n\n/* -------------------------------------------------------------------------------------------------\n * Axios data\n * -----------------------------------------------------------------------------------------------*/\nexport interface QueryArguments<TSend> {\n url: string;\n method: 'PUT' | 'GET' | 'POST' | 'DELETE';\n data?: TSend;\n config?: AxiosRequestConfig<TSend>;\n}\n\nconst axiosBaseQuery = async <TData = any, TSend = any>({\n url,\n method,\n data,\n config,\n}: QueryArguments<TSend>) => {\n try {\n const { get, post, del, put } = getFetchClient();\n\n if (method === 'POST') {\n const result = await post<TData, AxiosResponse<TData>, TSend>(url, data, config);\n return { data: result.data };\n }\n\n if (method === 'DELETE') {\n const result = await del<TData, AxiosResponse<TData>, TSend>(url, config);\n return { data: result.data };\n }\n\n if (method === 'PUT') {\n const result = await put<TData, AxiosResponse<TData>, TSend>(url, data, config);\n return { data: result.data };\n }\n\n /**\n * Default is GET.\n */\n const result = await get<TData, AxiosResponse<TData>, TSend>(url, config);\n return { data: result.data };\n } catch (error) {\n const err = error as AxiosError;\n /**\n * Handle error of type AxiosError\n *\n * This format mimics what we want from an AxiosError which is what the\n * rest of the app works with, except this format is \"serializable\" since\n * it goes into the redux store.\n *\n * NOTE – passing the whole response will highlight this \"serializability\" issue.\n */\n return {\n error: {\n status: err.response?.status,\n code: err.code,\n response: {\n data: err.response?.data,\n },\n },\n };\n }\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Axios error\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * This asserts the errors from redux-toolkit-query are\n * axios errors so we can pass them to our utility functions\n * to correctly render error messages.\n */\nconst isAxiosError = (err: unknown): err is AxiosError<{ error: any }> => {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'response' in err &&\n typeof err.response === 'object' &&\n err.response !== null &&\n 'data' in err.response\n );\n};\n\nexport { isAxiosError, axiosBaseQuery };\n","import { createApi } from '@reduxjs/toolkit/query/react';\n\nimport {\n CreateReleaseAction,\n DeleteReleaseAction,\n} from '../../../shared/contracts/release-actions';\nimport { pluginId } from '../pluginId';\n\nimport { axiosBaseQuery } from './axios';\n\nimport type {\n GetReleaseActions,\n UpdateReleaseAction,\n ReleaseActionGroupBy,\n} from '../../../shared/contracts/release-actions';\nimport type {\n CreateRelease,\n DeleteRelease,\n GetContentTypeEntryReleases,\n GetReleases,\n UpdateRelease,\n GetRelease,\n PublishRelease,\n} from '../../../shared/contracts/releases';\n\nexport interface GetReleasesQueryParams {\n page?: number;\n pageSize?: number;\n filters?: {\n releasedAt?: {\n // TODO: this should be a boolean, find a way to avoid strings\n $notNull?: boolean | 'true' | 'false';\n };\n };\n}\n\nexport interface GetReleaseActionsQueryParams {\n page?: number;\n pageSize?: number;\n groupBy?: ReleaseActionGroupBy;\n}\n\ntype GetReleasesTabResponse = GetReleases.Response & {\n meta: {\n activeTab: 'pending' | 'done';\n };\n};\n\nconst releaseApi = createApi({\n reducerPath: pluginId,\n baseQuery: axiosBaseQuery,\n tagTypes: ['Release', 'ReleaseAction'],\n endpoints: (build) => {\n return {\n getReleasesForEntry: build.query<\n GetContentTypeEntryReleases.Response,\n Partial<GetContentTypeEntryReleases.Request['query']>\n >({\n query(params) {\n return {\n url: '/content-releases',\n method: 'GET',\n config: {\n params,\n },\n };\n },\n providesTags: (result) =>\n result\n ? [\n ...result.data.map(({ id }) => ({ type: 'Release' as const, id })),\n { type: 'Release', id: 'LIST' },\n ]\n : [],\n }),\n getReleases: build.query<GetReleasesTabResponse, GetReleasesQueryParams | void>({\n query(\n { page, pageSize, filters } = {\n page: 1,\n pageSize: 16,\n filters: {\n releasedAt: {\n $notNull: false,\n },\n },\n }\n ) {\n return {\n url: '/content-releases',\n method: 'GET',\n config: {\n params: {\n page: page || 1,\n pageSize: pageSize || 16,\n filters: filters || {\n releasedAt: {\n $notNull: false,\n },\n },\n },\n },\n };\n },\n transformResponse(response: GetReleasesTabResponse, meta, arg) {\n const releasedAtValue = arg?.filters?.releasedAt?.$notNull;\n const isActiveDoneTab = releasedAtValue === 'true';\n const newResponse: GetReleasesTabResponse = {\n ...response,\n meta: {\n ...response.meta,\n activeTab: isActiveDoneTab ? 'done' : 'pending',\n },\n };\n\n return newResponse;\n },\n providesTags: (result) =>\n result\n ? [\n ...result.data.map(({ id }) => ({ type: 'Release' as const, id })),\n { type: 'Release', id: 'LIST' },\n ]\n : [{ type: 'Release', id: 'LIST' }],\n }),\n getRelease: build.query<GetRelease.Response, GetRelease.Request['params']>({\n query({ id }) {\n return {\n url: `/content-releases/${id}`,\n method: 'GET',\n };\n },\n providesTags: (result, error, arg) => [{ type: 'Release' as const, id: arg.id }],\n }),\n getReleaseActions: build.query<\n GetReleaseActions.Response,\n GetReleaseActions.Request['params'] & GetReleaseActions.Request['query']\n >({\n query({ releaseId, ...params }) {\n return {\n url: `/content-releases/${releaseId}/actions`,\n method: 'GET',\n config: {\n params,\n },\n };\n },\n providesTags: [{ type: 'ReleaseAction', id: 'LIST' }],\n }),\n createRelease: build.mutation<CreateRelease.Response, CreateRelease.Request['body']>({\n query(data) {\n return {\n url: '/content-releases',\n method: 'POST',\n data,\n };\n },\n invalidatesTags: [{ type: 'Release', id: 'LIST' }],\n }),\n updateRelease: build.mutation<\n void,\n UpdateRelease.Request['params'] & UpdateRelease.Request['body']\n >({\n query({ id, ...data }) {\n return {\n url: `/content-releases/${id}`,\n method: 'PUT',\n data,\n };\n },\n invalidatesTags: (result, error, arg) => [{ type: 'Release', id: arg.id }],\n }),\n createReleaseAction: build.mutation<\n CreateReleaseAction.Response,\n CreateReleaseAction.Request\n >({\n query({ body, params }) {\n return {\n url: `/content-releases/${params.releaseId}/actions`,\n method: 'POST',\n data: body,\n };\n },\n invalidatesTags: [\n { type: 'Release', id: 'LIST' },\n { type: 'ReleaseAction', id: 'LIST' },\n ],\n }),\n updateReleaseAction: build.mutation<\n UpdateReleaseAction.Response,\n UpdateReleaseAction.Request\n >({\n query({ body, params }) {\n return {\n url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,\n method: 'PUT',\n data: body,\n };\n },\n invalidatesTags: () => [{ type: 'ReleaseAction', id: 'LIST' }],\n }),\n deleteReleaseAction: build.mutation<\n DeleteReleaseAction.Response,\n DeleteReleaseAction.Request\n >({\n query({ params }) {\n return {\n url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,\n method: 'DELETE',\n };\n },\n invalidatesTags: [\n { type: 'Release', id: 'LIST' },\n { type: 'ReleaseAction', id: 'LIST' },\n ],\n }),\n publishRelease: build.mutation<PublishRelease.Response, PublishRelease.Request['params']>({\n query({ id }) {\n return {\n url: `/content-releases/${id}/publish`,\n method: 'POST',\n };\n },\n invalidatesTags: (result, error, arg) => [{ type: 'Release', id: arg.id }],\n }),\n deleteRelease: build.mutation<DeleteRelease.Response, DeleteRelease.Request['params']>({\n query({ id }) {\n return {\n url: `/content-releases/${id}`,\n method: 'DELETE',\n };\n },\n invalidatesTags: (result, error, arg) => [{ type: 'Release', id: arg.id }],\n }),\n };\n },\n});\n\nconst {\n useGetReleasesQuery,\n useGetReleasesForEntryQuery,\n useGetReleaseQuery,\n useGetReleaseActionsQuery,\n useCreateReleaseMutation,\n useCreateReleaseActionMutation,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseActionMutation,\n useDeleteReleaseMutation,\n} = releaseApi;\n\nexport {\n useGetReleasesQuery,\n useGetReleasesForEntryQuery,\n useGetReleaseQuery,\n useGetReleaseActionsQuery,\n useCreateReleaseMutation,\n useCreateReleaseActionMutation,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseActionMutation,\n useDeleteReleaseMutation,\n releaseApi,\n};\n","import { Flex, IconButton, Typography } from '@strapi/design-system';\nimport { Menu } from '@strapi/design-system/v2';\nimport { CheckPermissions, useAPIErrorHandler, useNotification } from '@strapi/helper-plugin';\nimport { Cross, More } from '@strapi/icons';\nimport { isAxiosError } from 'axios';\nimport { useIntl } from 'react-intl';\nimport styled from 'styled-components';\n\nimport { DeleteReleaseAction } from '../../../shared/contracts/release-actions';\nimport { PERMISSIONS } from '../constants';\nimport { useDeleteReleaseActionMutation } from '../services/release';\n\nconst StyledMenuItem = styled(Menu.Item)`\n &:hover {\n background: ${({ theme }) => theme.colors.danger100};\n }\n\n svg {\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n }\n\n &:hover {\n svg {\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n }\n }\n`;\n\nconst StyledCross = styled(Cross)`\n padding: ${({ theme }) => theme.spaces[1]};\n`;\n\nconst StyledIconButton = styled(IconButton)`\n /* Setting this style inline with borderColor will not apply the style */\n border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};\n`;\n\ninterface ReleaseActionMenuProps {\n releaseId: DeleteReleaseAction.Request['params']['releaseId'];\n actionId: DeleteReleaseAction.Request['params']['actionId'];\n hasTriggerBorder?: boolean;\n}\n\nexport const ReleaseActionMenu = ({\n releaseId,\n actionId,\n hasTriggerBorder = false,\n}: ReleaseActionMenuProps) => {\n const { formatMessage } = useIntl();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const [deleteReleaseAction] = useDeleteReleaseActionMutation();\n\n const handleDeleteAction = async () => {\n const response = await deleteReleaseAction({\n params: { releaseId, actionId },\n });\n\n if ('data' in response) {\n // Handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.content-manager-edit-view.remove-from-release.notification.success',\n defaultMessage: 'Entry removed from release',\n }),\n });\n\n return;\n }\n\n if ('error' in response) {\n if (isAxiosError(response.error)) {\n // Handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Handle generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n return (\n // A user can access the dropdown if they have permissions to delete a release-action OR update a release\n <CheckPermissions permissions={[...PERMISSIONS.deleteAction, ...PERMISSIONS.update]}>\n <Menu.Root>\n {/* \n TODO Fix in the DS\n - as={IconButton} has TS error: Property 'icon' does not exist on type 'IntrinsicAttributes & TriggerProps & RefAttributes<HTMLButtonElement>'\n - The Icon doesn't actually show unless you hack it with some padding...and it's still a little strange\n */}\n <Menu.Trigger\n as={hasTriggerBorder ? StyledIconButton : IconButton}\n paddingLeft={2}\n paddingRight={2}\n aria-label={formatMessage({\n id: 'content-releases.content-manager-edit-view.release-action-menu',\n defaultMessage: 'Release action options',\n })}\n // @ts-expect-error See above\n icon={<More />}\n />\n {/*\n TODO: Using Menu instead of SimpleMenu mainly because there is no positioning provided from the DS,\n Refactor this once fixed in the DS\n */}\n <Menu.Content top={1} popoverPlacement=\"bottom-end\">\n <CheckPermissions permissions={PERMISSIONS.deleteAction}>\n <StyledMenuItem onSelect={handleDeleteAction}>\n <Flex gap={2}>\n <StyledCross />\n <Typography textColor=\"danger600\" variant=\"omega\">\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.remove-from-release',\n defaultMessage: 'Remove from release',\n })}\n </Typography>\n </Flex>\n </StyledMenuItem>\n </CheckPermissions>\n </Menu.Content>\n </Menu.Root>\n </CheckPermissions>\n );\n};\n","import * as React from 'react';\n\nimport {\n FieldInput,\n FieldLabel,\n VisuallyHidden,\n Field,\n Flex,\n type FieldProps,\n} from '@strapi/design-system';\nimport styled from 'styled-components';\n\ninterface FieldWrapperProps extends FieldProps {\n actionType: 'publish' | 'unpublish';\n}\n\nconst getBorderLeftRadiusValue = (actionType: FieldWrapperProps['actionType']) => {\n return actionType === 'publish' ? 1 : 0;\n};\n\nconst getBorderRightRadiusValue = (actionType: FieldWrapperProps['actionType']) => {\n return actionType === 'publish' ? 0 : 1;\n};\n\nconst FieldWrapper = styled(Field)<FieldWrapperProps>`\n border-top-left-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderLeftRadiusValue(actionType)]};\n border-bottom-left-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderLeftRadiusValue(actionType)]};\n border-top-right-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderRightRadiusValue(actionType)]};\n border-bottom-right-radius: ${({ actionType, theme }) =>\n theme.spaces[getBorderRightRadiusValue(actionType)]};\n\n > label {\n color: inherit;\n padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};\n text-align: center;\n vertical-align: middle;\n text-transform: capitalize;\n }\n\n &:active,\n &[data-checked='true'] {\n color: ${({ theme }) => theme.colors.primary700};\n background-color: ${({ theme }) => theme.colors.primary100};\n border-color: ${({ theme }) => theme.colors.primary700};\n }\n\n &[data-checked='false'] {\n border-left: ${({ actionType }) => actionType === 'unpublish' && 'none'};\n border-right: ${({ actionType }) => actionType === 'publish' && 'none'};\n }\n`;\n\ninterface ActionOptionProps {\n selected: 'publish' | 'unpublish';\n handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n name: string;\n}\n\ninterface OptionProps extends ActionOptionProps {\n actionType: 'publish' | 'unpublish';\n}\n\nconst ActionOption = ({ selected, actionType, handleChange, name }: OptionProps) => {\n return (\n <FieldWrapper\n actionType={actionType}\n background=\"primary0\"\n borderColor=\"neutral200\"\n color={selected === actionType ? 'primary600' : 'neutral600'}\n position=\"relative\"\n cursor=\"pointer\"\n data-checked={selected === actionType}\n >\n <FieldLabel htmlFor={`${name}-${actionType}`}>\n <VisuallyHidden>\n <FieldInput\n type=\"radio\"\n id={`${name}-${actionType}`}\n name={name}\n checked={selected === actionType}\n onChange={handleChange}\n value={actionType}\n />\n </VisuallyHidden>\n {actionType}\n </FieldLabel>\n </FieldWrapper>\n );\n};\n\nexport const ReleaseActionOptions = ({ selected, handleChange, name }: ActionOptionProps) => {\n return (\n <Flex>\n <ActionOption\n actionType=\"publish\"\n selected={selected}\n handleChange={handleChange}\n name={name}\n />\n <ActionOption\n actionType=\"unpublish\"\n selected={selected}\n handleChange={handleChange}\n name={name}\n />\n </Flex>\n );\n};\n","import * as React from 'react';\n\nimport { skipToken } from '@reduxjs/toolkit/query';\nimport {\n Box,\n Button,\n FieldLabel,\n Flex,\n ModalBody,\n ModalHeader,\n ModalLayout,\n SingleSelect,\n SingleSelectOption,\n Typography,\n ModalFooter,\n} from '@strapi/design-system';\nimport { LinkButton } from '@strapi/design-system/v2';\nimport {\n CheckPermissions,\n NoContent,\n useAPIErrorHandler,\n useCMEditViewDataManager,\n useNotification,\n} from '@strapi/helper-plugin';\nimport { Plus } from '@strapi/icons';\nimport { isAxiosError } from 'axios';\nimport { Formik, Form } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useParams, Link as ReactRouterLink } from 'react-router-dom';\nimport * as yup from 'yup';\n\nimport { CreateReleaseAction } from '../../../shared/contracts/release-actions';\nimport { GetContentTypeEntryReleases } from '../../../shared/contracts/releases';\nimport { PERMISSIONS } from '../constants';\nimport { useCreateReleaseActionMutation, useGetReleasesForEntryQuery } from '../services/release';\n\nimport { ReleaseActionMenu } from './ReleaseActionMenu';\nimport { ReleaseActionOptions } from './ReleaseActionOptions';\n\n/* -------------------------------------------------------------------------------------------------\n * AddActionToReleaseModal\n * -----------------------------------------------------------------------------------------------*/\n\nconst RELEASE_ACTION_FORM_SCHEMA = yup.object().shape({\n type: yup.string().oneOf(['publish', 'unpublish']).required(),\n releaseId: yup.string().required(),\n});\n\ninterface FormValues {\n type: CreateReleaseAction.Request['body']['type'];\n releaseId: CreateReleaseAction.Request['params']['releaseId'];\n}\n\nconst INITIAL_VALUES = {\n type: 'publish',\n releaseId: '',\n} satisfies FormValues;\n\ninterface AddActionToReleaseModalProps {\n handleClose: () => void;\n contentTypeUid: GetContentTypeEntryReleases.Request['query']['contentTypeUid'];\n entryId: GetContentTypeEntryReleases.Request['query']['entryId'];\n}\n\nconst NoReleases = () => {\n const { formatMessage } = useIntl();\n return (\n <NoContent\n content={{\n id: 'content-releases.content-manager-edit-view.add-to-release.no-releases-message',\n defaultMessage:\n 'No available releases. Open the list of releases and create a new one from there.',\n }}\n action={\n <LinkButton\n // @ts-expect-error - types are not inferred correctly through the as prop.\n to={{\n pathname: '/plugins/content-releases',\n }}\n as={ReactRouterLink}\n variant=\"secondary\"\n >\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.redirect-button',\n defaultMessage: 'Open the list of releases',\n })}\n </LinkButton>\n }\n />\n );\n};\n\nconst AddActionToReleaseModal = ({\n handleClose,\n contentTypeUid,\n entryId,\n}: AddActionToReleaseModalProps) => {\n const { formatMessage } = useIntl();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const { modifiedData } = useCMEditViewDataManager();\n\n // Get all 'pending' releases that do not have the entry attached\n const response = useGetReleasesForEntryQuery({\n contentTypeUid,\n entryId,\n hasEntryAttached: false,\n });\n\n const releases = response.data?.data;\n const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();\n\n const handleSubmit = async (values: FormValues) => {\n const locale = modifiedData.locale as string | undefined;\n const releaseActionEntry = {\n contentType: contentTypeUid,\n id: entryId,\n locale,\n };\n const response = await createReleaseAction({\n body: { type: values.type, entry: releaseActionEntry },\n params: { releaseId: values.releaseId },\n });\n\n if ('data' in response) {\n // Handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.notification.success',\n defaultMessage: 'Entry added to release',\n }),\n });\n\n handleClose();\n return;\n }\n\n if ('error' in response) {\n if (isAxiosError(response.error)) {\n // Handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Handle generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n return (\n <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release',\n defaultMessage: 'Add to release',\n })}\n </Typography>\n </ModalHeader>\n <Formik\n onSubmit={handleSubmit}\n validationSchema={RELEASE_ACTION_FORM_SCHEMA}\n initialValues={INITIAL_VALUES}\n >\n {({ values, setFieldValue }) => {\n return (\n <Form>\n {releases?.length === 0 ? (\n <NoReleases />\n ) : (\n <ModalBody>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={2}>\n <Box paddingBottom={6}>\n <SingleSelect\n required\n label={formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.select-label',\n defaultMessage: 'Select a release',\n })}\n placeholder={formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.select-placeholder',\n defaultMessage: 'Select',\n })}\n onChange={(value) => setFieldValue('releaseId', value)}\n value={values.releaseId}\n >\n {releases?.map((release) => (\n <SingleSelectOption key={release.id} value={release.id}>\n {release.name}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n </Box>\n <FieldLabel>\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.action-type-label',\n defaultMessage: 'What do you want to do with this entry?',\n })}\n </FieldLabel>\n <ReleaseActionOptions\n selected={values.type}\n handleChange={(e) => setFieldValue('type', e.target.value)}\n name=\"type\"\n />\n </Flex>\n </ModalBody>\n )}\n <ModalFooter\n startActions={\n <Button onClick={handleClose} variant=\"tertiary\" name=\"cancel\">\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.cancel-button',\n defaultMessage: 'Cancel',\n })}\n </Button>\n }\n endActions={\n /**\n * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true\n * for yup.string().required(), even when the value is falsy (including empty string)\n */\n <Button type=\"submit\" disabled={!values.releaseId} loading={isLoading}>\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release.continue-button',\n defaultMessage: 'Continue',\n })}\n </Button>\n }\n />\n </Form>\n );\n }}\n </Formik>\n </ModalLayout>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * CMReleasesContainer\n * -----------------------------------------------------------------------------------------------*/\n\nexport const CMReleasesContainer = () => {\n const [isModalOpen, setIsModalOpen] = React.useState(false);\n const { formatMessage } = useIntl();\n const {\n isCreatingEntry,\n allLayoutData: { contentType },\n } = useCMEditViewDataManager();\n const params = useParams<{ id: string }>();\n\n const canFetch = params?.id != null && contentType?.uid != null;\n const fetchParams = canFetch\n ? {\n contentTypeUid: contentType.uid,\n entryId: params.id,\n hasEntryAttached: true,\n }\n : skipToken;\n // Get all 'pending' releases that have the entry attached\n const response = useGetReleasesForEntryQuery(fetchParams);\n const releases = response.data?.data;\n\n /**\n * If we don't have a contentType.uid or params.id then the data was never fetched\n * TODO: Should we handle this with an error message in the UI or just not show the container?\n */\n if (!canFetch) {\n return null;\n }\n\n /**\n * - Impossible to add entry to release before it exists\n * - Content types without draft and publish cannot add entries to release\n * TODO v5: All contentTypes will have draft and publish enabled\n */\n if (isCreatingEntry || !contentType?.options?.draftAndPublish) {\n return null;\n }\n\n const toggleModal = () => setIsModalOpen((prev) => !prev);\n\n const getReleaseColorVariant = (\n actionType: 'publish' | 'unpublish',\n shade: '100' | '200' | '600'\n ) => {\n if (actionType === 'unpublish') {\n return `secondary${shade}`;\n }\n\n return `success${shade}`;\n };\n\n return (\n <CheckPermissions permissions={PERMISSIONS.main}>\n <Box\n as=\"aside\"\n aria-label={formatMessage({\n id: 'content-releases.plugin.name',\n defaultMessage: 'Releases',\n })}\n background=\"neutral0\"\n borderColor=\"neutral150\"\n hasRadius\n padding={4}\n shadow=\"tableShadow\"\n >\n <Flex direction=\"column\" alignItems=\"stretch\" gap={3}>\n <Typography variant=\"sigma\" textColor=\"neutral600\" textTransform=\"uppercase\">\n {formatMessage({\n id: 'content-releases.plugin.name',\n defaultMessage: 'Releases',\n })}\n </Typography>\n {releases?.map((release) => {\n return (\n <Flex\n key={release.id}\n direction=\"column\"\n alignItems=\"start\"\n borderWidth=\"1px\"\n borderStyle=\"solid\"\n borderColor={getReleaseColorVariant(release.action.type, '200')}\n overflow=\"hidden\"\n hasRadius\n >\n <Box\n paddingTop={3}\n paddingBottom={3}\n paddingLeft={4}\n paddingRight={4}\n background={getReleaseColorVariant(release.action.type, '100')}\n width=\"100%\"\n >\n <Typography\n fontSize={1}\n variant=\"pi\"\n textColor={getReleaseColorVariant(release.action.type, '600')}\n >\n {formatMessage(\n {\n id: 'content-releases.content-manager-edit-view.list-releases.title',\n defaultMessage:\n '{isPublish, select, true {Will be published in} other {Will be unpublished in}}',\n },\n { isPublish: release.action.type === 'publish' }\n )}\n </Typography>\n </Box>\n <Flex padding={4} direction=\"column\" gap={3} width=\"100%\" alignItems=\"flex-start\">\n <Typography fontSize={2} fontWeight=\"bold\" variant=\"omega\" textColor=\"neutral700\">\n {release.name}\n </Typography>\n <ReleaseActionMenu\n releaseId={release.id}\n actionId={release.action.id}\n hasTriggerBorder\n />\n </Flex>\n </Flex>\n );\n })}\n <CheckPermissions permissions={PERMISSIONS.createAction}>\n <Button\n justifyContent=\"center\"\n paddingLeft={4}\n paddingRight={4}\n color=\"neutral700\"\n variant=\"tertiary\"\n startIcon={<Plus />}\n onClick={toggleModal}\n >\n {formatMessage({\n id: 'content-releases.content-manager-edit-view.add-to-release',\n defaultMessage: 'Add to release',\n })}\n </Button>\n </CheckPermissions>\n </Flex>\n {isModalOpen && (\n <AddActionToReleaseModal\n handleClose={toggleModal}\n contentTypeUid={contentType.uid}\n entryId={params.id}\n />\n )}\n </Box>\n </CheckPermissions>\n );\n};\n","import { prefixPluginTranslations } from '@strapi/helper-plugin';\nimport { PaperPlane } from '@strapi/icons';\n\nimport { CMReleasesContainer } from './components/CMReleasesContainer';\nimport { PERMISSIONS } from './constants';\nimport { pluginId } from './pluginId';\nimport { releaseApi } from './services/release';\n\nimport type { Plugin } from '@strapi/types';\n\n// eslint-disable-next-line import/no-default-export\nconst admin: Plugin.Config.AdminInput = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register(app: any) {\n if (\n window.strapi.features.isEnabled('cms-content-releases') &&\n window.strapi.future.isEnabled('contentReleases')\n ) {\n app.addMenuLink({\n to: `/plugins/${pluginId}`,\n icon: PaperPlane,\n intlLabel: {\n id: `${pluginId}.plugin.name`,\n defaultMessage: 'Releases',\n },\n async Component() {\n const { App } = await import('./pages/App');\n return App;\n },\n permissions: PERMISSIONS.main,\n });\n\n /**\n * For some reason every middleware you pass has to a function\n * that returns the actual middleware. It's annoying but no one knows why....\n */\n app.addMiddlewares([() => releaseApi.middleware]);\n\n app.addReducers({\n [releaseApi.reducerPath]: releaseApi.reducer,\n });\n\n // Insert the Releases container in the 'right-links' zone of the Content Manager's edit view\n app.injectContentManagerComponent('editView', 'right-links', {\n name: `${pluginId}-link`,\n Component: CMReleasesContainer,\n });\n }\n },\n async registerTrads({ locales }: { locales: string[] }) {\n const importedTrads = await Promise.all(\n locales.map((locale) => {\n return import(`./translations/${locale}.json`)\n .then(({ default: data }) => {\n return {\n data: prefixPluginTranslations(data, 'content-releases'),\n locale,\n };\n })\n .catch(() => {\n return {\n data: {},\n locale,\n };\n });\n })\n );\n\n return Promise.resolve(importedTrads);\n },\n};\n\n// eslint-disable-next-line import/no-default-export\nexport default admin;\n"],"names":["result","isAxiosError","ReactRouterLink","response"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-7250b0a5.js");
2
+ const index = require("../_chunks/index-PEkKIRyJ.js");
3
3
  require("@strapi/helper-plugin");
4
4
  require("@strapi/icons");
5
5
  require("react/jsx-runtime");
@@ -1,4 +1,4 @@
1
- import { j } from "../_chunks/index-e14e1ea9.mjs";
1
+ import { j } from "../_chunks/index-_Zsj8MUA.mjs";
2
2
  import "@strapi/helper-plugin";
3
3
  import "@strapi/icons";
4
4
  import "react/jsx-runtime";
@@ -69,10 +69,80 @@ const ACTIONS = [
69
69
  pluginName: "content-releases"
70
70
  }
71
71
  ];
72
- const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
72
+ const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
73
+ return strapi2.plugin("content-releases").service(name);
74
+ };
75
+ const { features: features$2 } = require("@strapi/strapi/dist/utils/ee");
73
76
  const register = async ({ strapi: strapi2 }) => {
74
- if (features$1.isEnabled("cms-content-releases") && strapi2.features.future.isEnabled("contentReleases")) {
77
+ if (features$2.isEnabled("cms-content-releases") && strapi2.features.future.isEnabled("contentReleases")) {
75
78
  await strapi2.admin.services.permission.actionProvider.registerMany(ACTIONS);
79
+ const releaseActionService = getService("release-action", { strapi: strapi2 });
80
+ const eventManager = getService("event-manager", { strapi: strapi2 });
81
+ const destroyContentTypeUpdateListener = strapi2.eventHub.on(
82
+ "content-type.update",
83
+ async ({ contentType }) => {
84
+ if (contentType.schema.options.draftAndPublish === false) {
85
+ await releaseActionService.deleteManyForContentType(contentType.uid);
86
+ }
87
+ }
88
+ );
89
+ eventManager.addDestroyListenerCallback(destroyContentTypeUpdateListener);
90
+ const destroyContentTypeDeleteListener = strapi2.eventHub.on(
91
+ "content-type.delete",
92
+ async ({ contentType }) => {
93
+ await releaseActionService.deleteManyForContentType(contentType.uid);
94
+ }
95
+ );
96
+ eventManager.addDestroyListenerCallback(destroyContentTypeDeleteListener);
97
+ }
98
+ };
99
+ const { features: features$1 } = require("@strapi/strapi/dist/utils/ee");
100
+ const bootstrap = async ({ strapi: strapi2 }) => {
101
+ if (features$1.isEnabled("cms-content-releases") && strapi2.features.future.isEnabled("contentReleases")) {
102
+ strapi2.db.lifecycles.subscribe({
103
+ afterDelete(event) {
104
+ const { model, result } = event;
105
+ if (model.kind === "collectionType" && model.options.draftAndPublish) {
106
+ const { id } = result;
107
+ strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
108
+ where: {
109
+ target_type: model.uid,
110
+ target_id: id
111
+ }
112
+ });
113
+ }
114
+ },
115
+ /**
116
+ * deleteMany hook doesn't return the deleted entries ids
117
+ * so we need to fetch them before deleting the entries to save the ids on our state
118
+ */
119
+ async beforeDeleteMany(event) {
120
+ const { model, params } = event;
121
+ if (model.kind === "collectionType" && model.options.draftAndPublish) {
122
+ const { where } = params;
123
+ const entriesToDelete = await strapi2.db.query(model.uid).findMany({ select: ["id"], where });
124
+ event.state.entriesToDelete = entriesToDelete;
125
+ }
126
+ },
127
+ /**
128
+ * We delete the release actions related to deleted entries
129
+ * We make this only after deleteMany is succesfully executed to avoid errors
130
+ */
131
+ async afterDeleteMany(event) {
132
+ const { model, state } = event;
133
+ const entriesToDelete = state.entriesToDelete;
134
+ if (entriesToDelete) {
135
+ await strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
136
+ where: {
137
+ target_type: model.uid,
138
+ target_id: {
139
+ $in: entriesToDelete.map((entry) => entry.id)
140
+ }
141
+ }
142
+ });
143
+ }
144
+ }
145
+ });
76
146
  }
77
147
  };
78
148
  const schema$1 = {
@@ -163,9 +233,15 @@ const contentTypes = {
163
233
  release: release$1,
164
234
  "release-action": releaseAction$1
165
235
  };
166
- const getService = (name, { strapi: strapi2 } = { strapi: global.strapi }) => {
167
- return strapi2.plugin("content-releases").service(name);
168
- };
236
+ const createReleaseActionService = ({ strapi: strapi2 }) => ({
237
+ async deleteManyForContentType(contentTypeUid) {
238
+ return strapi2.db.query(RELEASE_ACTION_MODEL_UID).deleteMany({
239
+ where: {
240
+ target_type: contentTypeUid
241
+ }
242
+ });
243
+ }
244
+ });
169
245
  const getGroupName = (queryValue) => {
170
246
  switch (queryValue) {
171
247
  case "contentType":
@@ -262,19 +338,23 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
262
338
  });
263
339
  },
264
340
  async update(id, releaseData, { user }) {
265
- const updatedRelease = await utils.setCreatorFields({ user, isEdition: true })(releaseData);
266
- const release2 = await strapi2.entityService.update(RELEASE_MODEL_UID, id, {
341
+ const releaseWithCreatorFields = await utils.setCreatorFields({ user, isEdition: true })(releaseData);
342
+ const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, id);
343
+ if (!release2) {
344
+ throw new utils.errors.NotFoundError(`No release found for id ${id}`);
345
+ }
346
+ if (release2.releasedAt) {
347
+ throw new utils.errors.ValidationError("Release already published");
348
+ }
349
+ const updatedRelease = await strapi2.entityService.update(RELEASE_MODEL_UID, id, {
267
350
  /*
268
351
  * The type returned from the entity service: Partial<Input<"plugin::content-releases.release">>
269
352
  * is not compatible with the type we are passing here: UpdateRelease.Request['body']
270
353
  */
271
354
  // @ts-expect-error see above
272
- data: updatedRelease
355
+ data: releaseWithCreatorFields
273
356
  });
274
- if (!release2) {
275
- throw new utils.errors.NotFoundError(`No release found for id ${id}`);
276
- }
277
- return release2;
357
+ return updatedRelease;
278
358
  },
279
359
  async createAction(releaseId, action) {
280
360
  const { validateEntryContentType, validateUniqueEntry } = getService("release-validation", {
@@ -284,6 +364,13 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
284
364
  validateEntryContentType(action.entry.contentType),
285
365
  validateUniqueEntry(releaseId, action)
286
366
  ]);
367
+ const release2 = await strapi2.entityService.findOne(RELEASE_MODEL_UID, releaseId);
368
+ if (!release2) {
369
+ throw new utils.errors.NotFoundError(`No release found for id ${releaseId}`);
370
+ }
371
+ if (release2.releasedAt) {
372
+ throw new utils.errors.ValidationError("Release already published");
373
+ }
287
374
  const { entry, type } = action;
288
375
  return strapi2.entityService.create(RELEASE_ACTION_MODEL_UID, {
289
376
  data: {
@@ -458,13 +545,18 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
458
545
  const updatedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).update({
459
546
  where: {
460
547
  id: actionId,
461
- release: releaseId
548
+ release: {
549
+ id: releaseId,
550
+ releasedAt: {
551
+ $null: true
552
+ }
553
+ }
462
554
  },
463
555
  data: update
464
556
  });
465
557
  if (!updatedAction) {
466
558
  throw new utils.errors.NotFoundError(
467
- `Action with id ${actionId} not found in release with id ${releaseId}`
559
+ `Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
468
560
  );
469
561
  }
470
562
  return updatedAction;
@@ -473,12 +565,17 @@ const createReleaseService = ({ strapi: strapi2 }) => ({
473
565
  const deletedAction = await strapi2.db.query(RELEASE_ACTION_MODEL_UID).delete({
474
566
  where: {
475
567
  id: actionId,
476
- release: releaseId
568
+ release: {
569
+ id: releaseId,
570
+ releasedAt: {
571
+ $null: true
572
+ }
573
+ }
477
574
  }
478
575
  });
479
576
  if (!deletedAction) {
480
577
  throw new utils.errors.NotFoundError(
481
- `Action with id ${actionId} not found in release with id ${releaseId}`
578
+ `Action with id ${actionId} not found in release with id ${releaseId} or it is already published`
482
579
  );
483
580
  }
484
581
  return deletedAction;
@@ -513,7 +610,30 @@ const createReleaseValidationService = ({ strapi: strapi2 }) => ({
513
610
  }
514
611
  }
515
612
  });
516
- const services = { release: createReleaseService, "release-validation": createReleaseValidationService };
613
+ const createEventManagerService = () => {
614
+ const state = {
615
+ destroyListenerCallbacks: []
616
+ };
617
+ return {
618
+ addDestroyListenerCallback(destroyListenerCallback) {
619
+ state.destroyListenerCallbacks.push(destroyListenerCallback);
620
+ },
621
+ destroyAllListeners() {
622
+ if (!state.destroyListenerCallbacks.length) {
623
+ return;
624
+ }
625
+ state.destroyListenerCallbacks.forEach((destroyListenerCallback) => {
626
+ destroyListenerCallback();
627
+ });
628
+ }
629
+ };
630
+ };
631
+ const services = {
632
+ release: createReleaseService,
633
+ "release-action": createReleaseActionService,
634
+ "release-validation": createReleaseValidationService,
635
+ "event-manager": createEventManagerService
636
+ };
517
637
  const RELEASE_SCHEMA = yup__namespace.object().shape({
518
638
  name: yup__namespace.string().trim().required()
519
639
  }).required().noUnknown();
@@ -688,10 +808,8 @@ const releaseActionController = {
688
808
  async delete(ctx) {
689
809
  const actionId = ctx.params.actionId;
690
810
  const releaseId = ctx.params.releaseId;
691
- const deletedReleaseAction = await getService("release", { strapi }).deleteAction(
692
- actionId,
693
- releaseId
694
- );
811
+ const releaseService = getService("release", { strapi });
812
+ const deletedReleaseAction = await releaseService.deleteAction(actionId, releaseId);
695
813
  ctx.body = {
696
814
  data: deletedReleaseAction
697
815
  };
@@ -877,10 +995,16 @@ const getPlugin = () => {
877
995
  if (features.isEnabled("cms-content-releases") && strapi.features.future.isEnabled("contentReleases")) {
878
996
  return {
879
997
  register,
998
+ bootstrap,
880
999
  contentTypes,
881
1000
  services,
882
1001
  controllers,
883
- routes
1002
+ routes,
1003
+ destroy() {
1004
+ if (features.isEnabled("cms-content-releases") && strapi.features.future.isEnabled("contentReleases")) {
1005
+ getService("event-manager").destroyAllListeners();
1006
+ }
1007
+ }
884
1008
  };
885
1009
  }
886
1010
  return {