import { useState, ComponentPropsWithRef } from 'react'; import { Menu, MenuHandler, MenuItem, MenuList, } from '@snowballtools/material-tailwind-react-fork'; import { Deployment, Domain, Environment, Project } from 'gql-client'; import { Button } from 'components/shared/Button'; import { GlobeIcon, HorizontalDotIcon, LinkIcon, RefreshIcon, RocketIcon, UndoIcon, CrossCircleIcon, } from 'components/shared/CustomIcon'; import AssignDomainDialog from './AssignDomainDialog'; import { useGQLClient } from 'context/GQLClientContext'; import { cn } from 'utils/classnames'; import { ChangeStateToProductionDialog } from 'components/projects/Dialog/ChangeStateToProductionDialog'; import { useToast } from 'components/shared/Toast'; interface DeploymentMenuProps extends ComponentPropsWithRef<'div'> { deployment: Deployment; currentDeployment: Deployment; onUpdate: () => Promise; project: Project; prodBranchDomains: Domain[]; } export const DeploymentMenu = ({ deployment, currentDeployment, onUpdate, project, prodBranchDomains, className, ...props }: DeploymentMenuProps) => { const client = useGQLClient(); const { toast, dismiss } = useToast(); const [changeToProduction, setChangeToProduction] = useState(false); const [redeployToProduction, setRedeployToProduction] = useState(false); const [rollbackDeployment, setRollbackDeployment] = useState(false); const [assignDomainDialog, setAssignDomainDialog] = useState(false); const updateDeployment = async () => { const isUpdated = await client.updateDeploymentToProd(deployment.id); if (isUpdated) { await onUpdate(); toast({ id: 'deployment_changed_to_production', title: 'Deployment changed to production', variant: 'success', onDismiss: dismiss, }); } else { toast({ id: 'deployment_not_changed_to_production', title: 'Error changing deployment to production', variant: 'error', onDismiss: dismiss, }); } }; const redeployToProd = async () => { const isRedeployed = await client.redeployToProd(deployment.id); if (isRedeployed) { await onUpdate(); toast({ id: 'redeployed_to_production', title: 'Redeployed to production', variant: 'success', onDismiss: dismiss, }); } else { toast({ id: 'redeployed_to_production_failed', title: 'Error redeploying to production', variant: 'error', onDismiss: dismiss, }); } }; const rollbackDeploymentHandler = async () => { const isRollbacked = await client.rollbackDeployment( project.id, deployment.id, ); if (isRollbacked) { await onUpdate(); toast({ id: 'deployment_rolled_back', title: 'Deployment rolled back', variant: 'success', onDismiss: dismiss, }); } else { toast({ id: 'deployment_rollback_failed', title: 'Error rolling back deployment', variant: 'error', onDismiss: dismiss, }); } }; const deleteDeployment = async () => { const isDeleted = await client.deleteDeployment(deployment.id); if (isDeleted) { await onUpdate(); toast({ id: 'deployment_deleted', title: 'Deployment deleted', variant: 'success', onDismiss: dismiss, }); } else { toast({ id: 'deployment_not_deleted', title: 'Error deleting deployment', variant: 'error', onDismiss: dismiss, }); } }; return ( <>
{/* Dialogs */} setChangeToProduction((preVal) => !preVal)} open={changeToProduction} handleConfirm={async () => { await updateDeployment(); setChangeToProduction((preVal) => !preVal); }} deployment={deployment} domains={prodBranchDomains} /> setRedeployToProduction((preVal) => !preVal)} open={redeployToProduction} confirmButtonTitle="Redeploy" handleConfirm={async () => { await redeployToProd(); setRedeployToProduction((preVal) => !preVal); }} deployment={deployment} domains={deployment.domain ? [deployment.domain] : []} /> {Boolean(currentDeployment) && ( setRollbackDeployment((preVal) => !preVal)} open={rollbackDeployment} confirmButtonTitle="Rollback" handleConfirm={async () => { await rollbackDeploymentHandler(); setRollbackDeployment((preVal) => !preVal); }} deployment={currentDeployment} newDeployment={deployment} domains={currentDeployment.domain ? [currentDeployment.domain] : []} /> )} setAssignDomainDialog(!assignDomainDialog)} /> ); };