Branch deletion error should link to the blocking PR (SZ-130)
rk@tigase.net opened 3 days ago

Summary

When a branch deletion is blocked because the branch has an associated pull request, the error toast shows a plain text message with no way to navigate to the blocking PR. The user must manually find the PR to close or merge it.

Severity

UX Enhancement

Milestone

1.11.0

Parent

SZ-126 — Branch/project deletion blocked by PR foreign key constraint

Estimated Fix Time

1.5 hours

Expected Behavior

When branch deletion is blocked by an open PR, the error should include a navigable link to the blocking PR:

"Cannot delete branch — it has an open pull request. View PR →"

Clicking "View PR →" navigates directly to the blocking PR.

Actual Behavior

Plain text toast: "Cannot delete branch — it has an associated pull request. Close or merge the PR first." No link, no navigation path.

  • rk@tigase.net commented 3 days ago

    Fix

    Backend — BranchServiceImpl.deleteBranch()

    Instead of throwing IllegalStateException with a plain string, throw a custom exception that carries the PR reference:

    final var prs = pullRequestRepository.findBySource_Id(id);
    if (!prs.isEmpty()) {
        final var pr = prs.get(0);
        throw new BranchHasPullRequestException(
                pr.getId(), pr.getPrKey()
        );
    }
    

    Backend — new BranchHasPullRequestException

    public class BranchHasPullRequestException extends RuntimeException {
        private final Long prId;
        private final String prKey;
        // constructor, getters
    }
    

    Backend — GlobalExceptionHandler

    Add handler that returns structured JSON on 409:

    @ExceptionHandler(BranchHasPullRequestException.class)
    public ResponseEntity<Map<String, Object>> handleBranchHasPr(
            BranchHasPullRequestException ex) {
        return ResponseEntity.status(HttpStatus.CONFLICT).body(Map.of(
                "message", "Cannot delete branch — it has an associated pull request.",
                "prKey", ex.getPrKey(),
                "prId", ex.getPrId()
        ));
    }
    

    Frontend — branches.ts case 409

    Parse structured response and include PR link in error:

    case 409: {
        const data = err.response?.data;
        const prKey = data?.prKey;
        const prId = data?.prId;
        const error = new Error(data?.message || "Cannot delete branch.");
        (error as any).prId = prId;
        (error as any).prKey = prKey;
        throw error;
    }
    

    Frontend — BranchesPage.tsx delete handler

    Render toast with navigation link when prId is present:

    } catch (err: unknown) {
        const e = err as any;
        if (e.prId) {
            toast.error(
                <span>
                    Cannot delete branch —
                    <a href={`/app/projects/${projectId}/pullrequests/${e.prId}`}>
                        View {e.prKey} →
                    </a>
                </span>
            );
        } else {
            toast.error(e.message || "Failed to delete branch");
        }
    }
    

    Files Changed

    • backend/.../exception/BranchHasPullRequestException.java (new)
    • backend/.../exception/handlers/GlobalExceptionHandler.java
    • backend/.../service/impl/BranchServiceImpl.java
    • frontend/src/api/branches.ts
    • frontend/src/pages/projects/BranchesPage.tsx
issue 1 of 1
Type
Usuability
Priority
Normal
Assignee
Version
1.10.0
Sprints
n/a
Customer
n/a
Issue Votes (0)
Watchers (3)
Reference
SZ-130
Please wait...
Page is in error, reload to recover