diff --git a/apps/studio/components/interfaces/BranchManagement/BranchManagement.tsx b/apps/studio/components/interfaces/BranchManagement/BranchManagement.tsx index 7d41b6f1505..968c50fc2a3 100644 --- a/apps/studio/components/interfaces/BranchManagement/BranchManagement.tsx +++ b/apps/studio/components/interfaces/BranchManagement/BranchManagement.tsx @@ -27,13 +27,8 @@ import { Button } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' import { BranchLoader, BranchManagementSection, BranchRow, MergeRequestRow } from './BranchPanels' -import { CreateBranchModal } from './CreateBranchModal' -import { - BranchingEmptyState, - PreviewBranchesEmptyState, - PullRequestsEmptyState, -} from './EmptyStates' -import Overview from './Overview' +import { PreviewBranchesEmptyState, PullRequestsEmptyState } from './EmptyStates' +import { Overview } from './Overview' type Tab = 'overview' | 'prs' | 'branches' diff --git a/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx b/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx index e4739dfad27..f8befcce523 100644 --- a/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx +++ b/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx @@ -36,6 +36,7 @@ import { } from 'ui' import { sanitizeRoute } from './ProjectDropdown' import { useFlag } from 'hooks/ui/useFlag' +import { useAppStateSnapshot } from 'state/app-state' const BranchLink = ({ branch, @@ -80,11 +81,11 @@ export const BranchDropdown = () => { const gitlessBranching = useFlag('gitlessBranching') const projectDetails = useSelectedProject() const snap = useAppStateSnapshot() + const [open, setOpen] = useState(false) + const [showDeployRequestModal, setShowDeployRequestModal] = useState(false) const projectRef = projectDetails?.parent_project_ref || ref - const [open, setOpen] = useState(false) - const [showDeployRequestModal, setShowDeployRequestModal] = useState(false) const { data: branches, isLoading, @@ -116,8 +117,6 @@ export const BranchDropdown = () => { const BRANCHING_GITHUB_DISCUSSION_LINK = 'https://github.com/orgs/supabase/discussions/18937' - const [open, setOpen] = useState(false) - const MenuContent = ({ branchList, showSearch, @@ -162,23 +161,26 @@ export const BranchDropdown = () => {

Create branch

- {gitlessBranching && isBranch && selectedBranch && !selectedBranch.is_default && ( - <> - { - setOpen(false) - setShowDeployRequestModal(true) - }} - onClick={() => setOpen(false)} - > -
- - Create deploy request -
-
- - )} + {gitlessBranching && + isBranchingEnabled && + selectedBranch && + !selectedBranch.is_default && ( + <> + { + setOpen(false) + setShowDeployRequestModal(true) + }} + onClick={() => setOpen(false)} + > +
+ + Create deploy request +
+
+ + )} { diff --git a/apps/studio/data/merge-requests/merge-request-create-mutation.ts b/apps/studio/data/merge-requests/merge-request-create-mutation.ts index e383a1aa5c3..168ea47e4be 100644 --- a/apps/studio/data/merge-requests/merge-request-create-mutation.ts +++ b/apps/studio/data/merge-requests/merge-request-create-mutation.ts @@ -27,7 +27,7 @@ export async function createMergeRequest({ id: `mr-${Date.now()}`, project_ref: projectRef, base: '6b3b94fe-f9f9-4c12-8796-ff67db250757', - head: '7902c891-5286-4366-a44d-007b39e0782d', + head: '3b13fe5b-a529-4bc4-a0c8-a333f83f03e9', title, description, merge_requested_by: 'current-user-id', diff --git a/apps/studio/data/merge-requests/merge-request-delete-mutation.ts b/apps/studio/data/merge-requests/merge-request-delete-mutation.ts new file mode 100644 index 00000000000..803285ec991 --- /dev/null +++ b/apps/studio/data/merge-requests/merge-request-delete-mutation.ts @@ -0,0 +1,61 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import { toast } from 'sonner' +import { handleError, del } from 'data/fetchers' +import type { ResponseError } from 'types' +import { mergeRequestKeys } from './keys' + +export type MergeRequestDeleteVariables = { + id: string + projectRef: string +} + +export async function deleteMergeRequest({ + id, + projectRef, +}: MergeRequestDeleteVariables): Promise { + // Mock data for development + return new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 500) + }) + + // Real API call (commented out for now) + // const { error } = await del('/v1/merge-requests/{merge_request_id}', { + // params: { + // path: { merge_request_id: id }, + // }, + // }) + + // if (error) handleError(error) +} + +export const useMergeRequestDeleteMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + return useMutation( + (vars) => deleteMergeRequest(vars), + { + async onSuccess(data, variables, context) { + const { projectRef } = variables + await queryClient.invalidateQueries(mergeRequestKeys.list(projectRef)) + await queryClient.invalidateQueries(mergeRequestKeys.detail(projectRef, variables.id)) + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + toast.error(`Failed to delete merge request: ${data.message}`) + } else { + onError(data, variables, context) + } + }, + ...options, + } + ) +} diff --git a/apps/studio/data/merge-requests/merge-request-query.ts b/apps/studio/data/merge-requests/merge-request-query.ts index acfe7297f48..d94a9bfa5d7 100644 --- a/apps/studio/data/merge-requests/merge-request-query.ts +++ b/apps/studio/data/merge-requests/merge-request-query.ts @@ -22,14 +22,12 @@ export async function getMergeRequest( id: id, project_ref: 'mock-project-ref', base: '6b3b94fe-f9f9-4c12-8796-ff67db250757', - head: '7902c891-5286-4366-a44d-007b39e0782d', + head: '3b13fe5b-a529-4bc4-a0c8-a333f83f03e9', title: 'Deploy feature-auth to production', description: 'This deploy request includes new authentication features, improved error handling, and several bug fixes. The changes have been thoroughly tested in the staging environment.', merge_requested_by: 'user-123', - merge_approved_by: null, merge_requested_at: '2024-01-15T10:30:00Z', - merge_approved_at: null, created_at: '2024-01-15T10:30:00Z', updated_at: '2024-01-15T10:30:00Z', }) diff --git a/apps/studio/data/merge-requests/merge-request-update-mutation.ts b/apps/studio/data/merge-requests/merge-request-update-mutation.ts index bbbddf82d37..4139e4c7ee8 100644 --- a/apps/studio/data/merge-requests/merge-request-update-mutation.ts +++ b/apps/studio/data/merge-requests/merge-request-update-mutation.ts @@ -22,7 +22,7 @@ export async function updateMergeRequest({ id: id, project_ref: 'mock-project-ref', base: '6b3b94fe-f9f9-4c12-8796-ff67db250757', - head: '7902c891-5286-4366-a44d-007b39e0782d', + head: '3b13fe5b-a529-4bc4-a0c8-a333f83f03e9', title: 'Deploy feature-auth to production', description: 'This deploy request includes new authentication features, improved error handling, and several bug fixes.', diff --git a/apps/studio/data/merge-requests/merge-requests-query.ts b/apps/studio/data/merge-requests/merge-requests-query.ts index 35d95613053..b49561caeb2 100644 --- a/apps/studio/data/merge-requests/merge-requests-query.ts +++ b/apps/studio/data/merge-requests/merge-requests-query.ts @@ -15,9 +15,7 @@ export type MergeRequest = { title: string description?: string merge_requested_by: string | null - merge_approved_by: string | null merge_requested_at: string | null - merge_approved_at: string | null created_at: string updated_at: string } @@ -36,13 +34,11 @@ export async function getMergeRequests( id: 'mr-1', project_ref: projectRef, base: '6b3b94fe-f9f9-4c12-8796-ff67db250757', - head: '7902c891-5286-4366-a44d-007b39e0782d', + head: '3b13fe5b-a529-4bc4-a0c8-a333f83f03e9', title: 'Deploy feature-auth to production', description: 'This PR includes new authentication features and bug fixes.', merge_requested_by: 'user-123', - merge_approved_by: null, merge_requested_at: '2024-01-15T10:30:00Z', - merge_approved_at: null, created_at: '2024-01-15T10:30:00Z', updated_at: '2024-01-15T10:30:00Z', }, @@ -50,13 +46,11 @@ export async function getMergeRequests( id: 'mr-2', project_ref: projectRef, base: '6b3b94fe-f9f9-4c12-8796-ff67db250757', - head: '7902c891-5286-4366-a44d-007b39e0782d', + head: '3b13fe5b-a529-4bc4-a0c8-a333f83f03e9', title: 'Deploy hotfix-db-migration to production', description: 'Critical database schema updates for user table.', merge_requested_by: 'user-456', - merge_approved_by: 'user-789', merge_requested_at: '2024-01-14T14:20:00Z', - merge_approved_at: '2024-01-14T15:45:00Z', created_at: '2024-01-14T14:20:00Z', updated_at: '2024-01-14T15:45:00Z', }, diff --git a/apps/studio/pages/project/[ref]/merge-requests/[id].tsx b/apps/studio/pages/project/[ref]/merge-requests/[id].tsx index 8abb11835ef..e9348507c3c 100644 --- a/apps/studio/pages/project/[ref]/merge-requests/[id].tsx +++ b/apps/studio/pages/project/[ref]/merge-requests/[id].tsx @@ -12,7 +12,7 @@ import { useBranchesQuery } from 'data/branches/branches-query' import { useBranchMergeMutation } from 'data/branches/branch-merge-mutation' import { useBranchPushMutation } from 'data/branches/branch-push-mutation' import { useMergeRequestQuery } from 'data/merge-requests/merge-request-query' -import { useMergeRequestUpdateMutation } from 'data/merge-requests/merge-request-update-mutation' +import { useMergeRequestDeleteMutation } from 'data/merge-requests/merge-request-delete-mutation' import { useBranchMergeDiff } from 'hooks/branches/useBranchMergeDiff' import { useWorkflowManagement } from 'hooks/branches/useWorkflowManagement' import DatabaseDiffPanel from 'components/interfaces/BranchManagement/DatabaseDiffPanel' @@ -31,6 +31,7 @@ import { AlertTriangle, CheckCircle, Clock, + Trash, } from 'lucide-react' import Link from 'next/link' import { ButtonTooltip } from 'components/ui/ButtonTooltip' @@ -49,7 +50,6 @@ const MergeRequestPage: NextPageWithLayout = () => { const [isSubmitting, setIsSubmitting] = useState(false) const [workflowFinalStatus, setWorkflowFinalStatus] = useState(null) - const isBranch = project?.parent_project_ref !== undefined const parentProjectRef = project?.parent_project_ref || project?.ref const parentProject = useProjectByRef(parentProjectRef) @@ -124,8 +124,7 @@ const MergeRequestPage: NextPageWithLayout = () => { onWorkflowComplete: (status) => { setWorkflowFinalStatus(status) refetchDiff() - edgeFunctionsDiff.refetchCurrentBranchFunctions() - edgeFunctionsDiff.refetchMainBranchFunctions() + edgeFunctionsDiff.clearDiffsOptimistically() }, }) @@ -136,8 +135,7 @@ const MergeRequestPage: NextPageWithLayout = () => { onWorkflowComplete: (status) => { setWorkflowFinalStatus(status) refetchDiff() - edgeFunctionsDiff.refetchCurrentBranchFunctions() - edgeFunctionsDiff.refetchMainBranchFunctions() + edgeFunctionsDiff.clearDiffsOptimistically() }, }) @@ -186,18 +184,11 @@ const MergeRequestPage: NextPageWithLayout = () => { const { mutate: mergeBranch, isLoading: isMerging } = useBranchMergeMutation({ onSuccess: (data) => { setIsSubmitting(false) - if (data.hadChanges) { - if (data.migrationCreated) { - toast.success('Migration created and branch merge initiated!') - } else { - toast.success('Branch merge initiated!') - } - // Add workflow run ID to URL for persistence - if (data.workflowRunId) { - addWorkflowRun(data.workflowRunId) - } + if (data.workflowRunId) { + toast.success('Branch merge initiated!') + addWorkflowRun(data.workflowRunId) } else { - toast.info('No changes to merge - branch merged successfully!') + toast.info('No changes to merge') } }, onError: (error) => { @@ -206,15 +197,15 @@ const MergeRequestPage: NextPageWithLayout = () => { }, }) - const { mutate: updateMergeRequest, isLoading: isUpdatingMergeRequest } = - useMergeRequestUpdateMutation({ + const { mutate: deleteMergeRequest, isLoading: isDeletingMergeRequest } = + useMergeRequestDeleteMutation({ onSuccess: () => { - toast.success('Merge request approved!') - // Proceed with actual merge - handleMerge() + toast.success('Merge request deleted!') + // Navigate back to merge requests list + router.push(`/project/${parentProjectRef}/branches?tab=prs`) }, - onError: (error) => { - toast.error(`Failed to approve merge request: ${error.message}`) + onError: (error: any) => { + toast.error(`Failed to delete merge request: ${error.message}`) }, }) @@ -237,13 +228,11 @@ const MergeRequestPage: NextPageWithLayout = () => { }) } - const handleApproveMerge = () => { + const handleDeleteMergeRequest = () => { if (!mergeRequest?.id || !parentProjectRef) return - // TODO: Get current user ID - updateMergeRequest({ + deleteMergeRequest({ id: mergeRequest.id, projectRef: parentProjectRef, - merge_approved_by: 'current-user-id', // This should be replaced with actual user ID }) } @@ -355,25 +344,11 @@ const MergeRequestPage: NextPageWithLayout = () => { ) } - const isMergeDisabled = - !combinedHasChanges || - isCombinedDiffLoading || - isBranchOutOfDateOverall || - !mergeRequest.merge_approved_by + const isMergeDisabled = !combinedHasChanges || isCombinedDiffLoading || isBranchOutOfDateOverall - // Update primary actions - separate approve and merge actions + // Update primary actions - just merge action const primaryActions = (
- {!mergeRequest.merge_approved_by && ( - - )} {isMergeDisabled ? ( {
) - const pageTitle = () => ( -
- {mergeRequest?.title || `${mergeRequest?.head} → ${mergeRequest?.base}`} -
- ) + const pageTitle = () => mergeRequest?.title || `${mergeRequest?.head} → ${mergeRequest?.base}` const pageSubtitle = () => { if (!mergeRequest?.merge_requested_at) return 'Merge request information unavailable' const requestedTime = dayjs(mergeRequest.merge_requested_at).fromNow() - const approvalStatus = mergeRequest.merge_approved_by ? 'Approved' : 'Open' return (
- {approvalStatus} + Open {mergeRequest.merge_requested_by} requested to merge { } overrideAction={ hasCurrentWorkflowFailed ? ( +
+ + +
+ ) : currentWorkflowRun?.status === 'FUNCTIONS_DEPLOYED' ? ( ) : undefined }