From 2bbe7f63b0051301a60f1d09577e0d7b98ae884d Mon Sep 17 00:00:00 2001 From: Blomios Date: Fri, 14 Aug 2026 09:33:05 +0200 Subject: [PATCH] =?UTF-8?q?feat(ui):=20colonne=20tags=20de=20versions=20?= =?UTF-8?q?=C3=A0=20gauche=20du=20graph=20Git=20=E2=80=94=20#193?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/features/git/GitGraphView.tsx | 39 ++++++++++++++----- .../src/features/git/gitGraphView.test.tsx | 31 ++++++++++++++- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/frontend/src/features/git/GitGraphView.tsx b/frontend/src/features/git/GitGraphView.tsx index 8074197d..1096438d 100644 --- a/frontend/src/features/git/GitGraphView.tsx +++ b/frontend/src/features/git/GitGraphView.tsx @@ -69,6 +69,8 @@ const LANE_W = 16; const ROW_H = 36; /** Radius of the commit dot. */ const DOT_R = 4.5; +/** Stable version tag column, kept outside the DAG lanes. */ +const TAGS_COL_W = 112; /** Horizontal centre of a lane. */ const laneX = (lane: number) => lane * LANE_W + LANE_W / 2; @@ -283,6 +285,8 @@ export function GitGraphView({ projectId }: GitGraphViewProps) { )} {vm.rows.map((row) => { const isSelected = row.commit.hash === selectedHash; + const tagRefs = row.commit.refs.filter(isTag); + const branchRefs = row.commit.refs.filter((ref) => !isTag(ref)); return (
+ {/* Version tags live in their own stable column, left of the DAG. */} +
+ {tagRefs.map((ref) => ( + + {ref} + + ))} +
+ {/* SVG lanes + node */} - {/* Ref badges */} - {row.commit.refs.length > 0 && ( -
- {row.commit.refs.map((ref) => ( + {/* Branch refs stay beside the graph in the existing refs zone. */} + {branchRefs.length > 0 && ( +
+ {branchRefs.map((ref) => ( {ref} diff --git a/frontend/src/features/git/gitGraphView.test.tsx b/frontend/src/features/git/gitGraphView.test.tsx index e2c5efe9..44390c91 100644 --- a/frontend/src/features/git/gitGraphView.test.tsx +++ b/frontend/src/features/git/gitGraphView.test.tsx @@ -10,7 +10,7 @@ * - Clicking close hides the detail panel. */ -import { describe, it, expect } from "vitest"; +import { describe, it, expect, vi } from "vitest"; import { render, screen, waitFor, fireEvent } from "@testing-library/react"; import { MockGitGateway } from "@/adapters/mock"; @@ -22,7 +22,7 @@ import { GitGraphView } from "./GitGraphView"; // Helpers // --------------------------------------------------------------------------- -function renderView(git: MockGitGateway = new MockGitGateway()) { +function renderView(git: unknown = new MockGitGateway()) { const gateways = { git } as unknown as Gateways; return render( @@ -71,6 +71,10 @@ describe("GitGraphView", () => { expect(tagBadge).toBeTruthy(); // Tag badge should have the warning colour class expect(tagBadge.className).toMatch(/warning/); + const tagCell = screen.getByTestId("git-tags-cell-aaaaaaaa"); + expect(tagCell.textContent).toContain("tag: v1.0"); + expect(tagCell.style.width).toBe("112px"); + expect(tagBadge.className).toMatch(/truncate/); }); it("shows 'feature' branch badge", async () => { @@ -82,6 +86,29 @@ describe("GitGraphView", () => { expect(featureBadge.className).toMatch(/primary/); }); + it("keeps tags in the left tag column and branches in the refs zone", async () => { + renderView({ + graph: vi.fn(async () => [ + { + hash: "1111111111111111111111111111111111111111", + summary: "Release build", + parents: [], + refs: ["main", "tag: v2026.08.14-long-release-name"], + author: "Alice", + timestamp: 1_717_200_000, + }, + ]), + }); + await waitForCommits(); + + const tagCell = screen.getByTestId("git-tags-cell-11111111"); + const branchCell = screen.getByTestId("git-branch-refs-cell-11111111"); + expect(tagCell.textContent).toContain("tag: v2026.08.14-long-release-name"); + expect(tagCell.textContent).not.toContain("main"); + expect(branchCell.textContent).toContain("main"); + expect(branchCell.textContent).not.toContain("tag: v2026.08.14-long-release-name"); + }); + it("clicking a commit row opens the detail panel", async () => { renderView(); await waitForCommits();