diff --git a/frontend/common/services/useReleasePipelines.ts b/frontend/common/services/useReleasePipelines.ts index c77e6143f167..24c9989c5466 100644 --- a/frontend/common/services/useReleasePipelines.ts +++ b/frontend/common/services/useReleasePipelines.ts @@ -89,6 +89,16 @@ export const releasePipelinesService = service url: `projects/${query.projectId}/release-pipelines/${query.pipelineId}/remove-feature/`, }), }), + unpublishReleasePipeline: builder.mutation< + Res['releasePipeline'], + Req['publishReleasePipeline'] + >({ + invalidatesTags: [{ id: 'LIST', type: 'ReleasePipelines' }], + query: (query: Req['publishReleasePipeline']) => ({ + method: 'POST', + url: `projects/${query.projectId}/release-pipelines/${query.pipelineId}/unpublish-pipeline/`, + }), + }), updateReleasePipeline: builder.mutation< Res['releasePipeline'], Req['updateReleasePipeline'] @@ -164,6 +174,7 @@ export const { useGetReleasePipelinesQuery, usePublishReleasePipelineMutation, useRemoveFeatureMutation, + useUnpublishReleasePipelineMutation, useUpdateReleasePipelineMutation, // END OF EXPORTS } = releasePipelinesService diff --git a/frontend/web/components/pages/ReleasePipelinesPage.tsx b/frontend/web/components/pages/ReleasePipelinesPage.tsx index 5902c77186e3..0f71365ffd17 100644 --- a/frontend/web/components/pages/ReleasePipelinesPage.tsx +++ b/frontend/web/components/pages/ReleasePipelinesPage.tsx @@ -1,22 +1,19 @@ import PageTitle from 'components/PageTitle' import { useGetReleasePipelinesQuery } from 'common/services/useReleasePipelines' import { Button } from 'components/base/forms/Button' -import { useHistory, useRouteMatch } from 'react-router-dom' +import { useHistory } from 'react-router-dom' import ConfigProvider from 'common/providers/ConfigProvider' import ReleasePipelinesList from 'components/release-pipelines/ReleasePipelinesList' import { useState } from 'react' import PlanBasedAccess from 'components/PlanBasedAccess' - -interface RouteParams { - projectId: string -} +import { useRouteContext } from 'components/providers/RouteContext' const ReleasePipelinesPage = () => { const history = useHistory() - const match = useRouteMatch() + + const { projectId } = useRouteContext() const [page, setPage] = useState(1) const pageSize = 10 - const { projectId } = match.params const { data, isLoading } = useGetReleasePipelinesQuery({ page, page_size: pageSize, @@ -48,7 +45,7 @@ const ReleasePipelinesPage = () => { { + const [ + publishReleasePipeline, + { + error: publishReleasePipelineError, + isError: isPublishingError, + isLoading: isPublishing, + isSuccess: isPublishingSuccess, + }, + ] = usePublishReleasePipelineMutation() + + const [ + unpublishReleasePipeline, + { + error: unpublishReleasePipelineError, + isError: isUnpublishingError, + isLoading: isUnpublishing, + isSuccess: isUnpublishingSuccess, + }, + ] = useUnpublishReleasePipelineMutation() + + useEffect(() => { + if (isPublishingSuccess) { + closeModal2() + toast('Release pipeline published successfully') + return + } + + if (isPublishingError) { + toast('Error publishing release pipeline', 'danger') + return + } + }, [isPublishingSuccess, isPublishingError, publishReleasePipelineError]) + + useEffect(() => { + if (isUnpublishingSuccess) { + closeModal2() + toast('Release pipeline unpublished successfully') + return + } + + if (isUnpublishingError) { + toast('Error unpublishing release pipeline', 'danger') + return + } + }, [ + isUnpublishingSuccess, + isUnpublishingError, + unpublishReleasePipelineError, + ]) + + const handleConfirm = () => { + if (isPublished) { + unpublishReleasePipeline({ + pipelineId, + projectId, + }) + + return + } + + publishReleasePipeline({ + pipelineId, + projectId, + }) + } + + const isLoading = isPublishing || isUnpublishing + + return ( +
+

+ Are you sure you want to{' '} + {isPublished ? 'unpublish' : 'publish'} this release + pipeline? +

+
+ + +
+
+ ) +} + +export type { ChangeReleasePipelineStatusModalProps } +export default ChangeReleasePipelineStatusModal diff --git a/frontend/web/components/release-pipelines/ReleasePipelinesList.tsx b/frontend/web/components/release-pipelines/ReleasePipelinesList.tsx index ea8fd525c7c2..a060876a2d91 100644 --- a/frontend/web/components/release-pipelines/ReleasePipelinesList.tsx +++ b/frontend/web/components/release-pipelines/ReleasePipelinesList.tsx @@ -1,7 +1,4 @@ -import { - useDeleteReleasePipelineMutation, - usePublishReleasePipelineMutation, -} from 'common/services/useReleasePipelines' +import { useDeleteReleasePipelineMutation } from 'common/services/useReleasePipelines' import { PagedResponse, ReleasePipeline } from 'common/types/responses' import { useHistory } from 'react-router-dom' import Button from 'components/base/forms/Button' @@ -10,8 +7,9 @@ import DropdownMenu from 'components/base/DropdownMenu' import PanelSearch from 'components/PanelSearch' import Tag from 'components/tags/Tag' import { useEffect } from 'react' +import ChangeReleasePipelineStatusModal from './ChangeReleasePipelineStatusModal' -const NoReleasePipelines = ({ projectId }: { projectId: string }) => { +const NoReleasePipelines = ({ projectId }: { projectId: number }) => { const history = useHistory() return ( @@ -50,7 +48,7 @@ const NoReleasePipelines = ({ projectId }: { projectId: string }) => { type ReleasePipelinesListProps = { data: PagedResponse | undefined isLoading: boolean - projectId: string + projectId: number page: number pageSize: number onPageChange: (page: number) => void @@ -74,30 +72,8 @@ const ReleasePipelinesList = ({ isSuccess: isDeletingSuccess, }, ] = useDeleteReleasePipelineMutation() - const [ - publishReleasePipeline, - { - error: publishReleasePipelineError, - isError: isPublishingError, - isLoading: isPublishing, - isSuccess: isPublishingSuccess, - }, - ] = usePublishReleasePipelineMutation() - const pipelinesList = data?.results - - useEffect(() => { - if (isPublishingSuccess) { - return toast('Release pipeline published successfully') - } - if (isPublishingError) { - return toast( - publishReleasePipelineError?.data?.detail ?? - 'Something went wrong while publishing the release pipeline', - 'danger', - ) - } - }, [isPublishingSuccess, isPublishingError, publishReleasePipelineError]) + const pipelinesList = data?.results useEffect(() => { if (isDeletingSuccess) { @@ -113,6 +89,21 @@ const ReleasePipelinesList = ({ } }, [isDeletingSuccess, isDeletingError, deleteReleasePipelineError]) + const openChangeReleasePipelineStatusModal = ( + projectId: number, + pipelineId: number, + isPublished: boolean, + ) => { + openModal2( + isPublished ? 'Unpublish Release Pipeline' : 'Publish Release Pipeline', + , + ) + } + if (isLoading) { return (
@@ -150,6 +141,14 @@ const ReleasePipelinesList = ({ stages_count, }: ReleasePipeline) => { const isPublished = !!published_at + const canUnpublish = isPublished && !features?.length + + const getTooltip = (action: string) => { + if (isPublished) { + return `Cannot ${action} a published release pipeline` + } + return undefined + } return ( @@ -182,43 +181,44 @@ const ReleasePipelinesList = ({ { history.push( `/project/${projectId}/release-pipelines/${id}/edit`, ) }, - tooltip: published_at - ? 'Cannot edit a published release pipeline' - : undefined, + tooltip: getTooltip('edit'), + }, + { + disabled: isPublished && !canUnpublish, + icon: isPublished + ? 'minus-circle' + : ('checkmark-circle' as IconName), + label: isPublished ? 'Unpublish' : 'Publish', + onClick: () => + openChangeReleasePipelineStatusModal( + projectId, + id, + isPublished, + ), + tooltip: + isPublished && !canUnpublish + ? 'Cannot unpublish a release pipeline with in-flight features' + : undefined, }, - ...(!isPublished - ? [ - { - disabled: isPublishing, - icon: 'checkmark-circle' as IconName, - label: 'Publish Release Pipeline', - onClick: () => { - publishReleasePipeline({ - pipelineId: id, - projectId: Number(projectId), - }) - }, - }, - ] - : []), { - disabled: isDeleting, + disabled: isDeleting || isPublished, icon: 'trash-2', - label: 'Remove Release Pipeline', + label: 'Remove', onClick: () => { deleteReleasePipeline({ pipelineId: id, projectId: Number(projectId), }) }, + tooltip: getTooltip('remove'), }, ]} />