diff --git a/backend/app/routers/git_mgr.py b/backend/app/routers/git_mgr.py index c7f50ad..6c421eb 100644 --- a/backend/app/routers/git_mgr.py +++ b/backend/app/routers/git_mgr.py @@ -185,9 +185,13 @@ def git_status(): @router.get("/log") -def git_log(): +def git_log(diagram_id: Optional[int] = None): repo_root = _repo_root() - r = _run("log", "--pretty=format:%H|%h|%s|%an|%ai", "-30", cwd=repo_root) + cmd = ["log", "--pretty=format:%H|%h|%s|%an|%ai", "--follow", "-50"] + if diagram_id is not None: + # Filter to commits that touched this diagram's file (glob by id prefix) + cmd += ["--", f"diagrams/{diagram_id:04d}_*.json"] + r = _run(*cmd, cwd=repo_root) if r.returncode != 0: return [] entries = [] diff --git a/frontend/css/main.css b/frontend/css/main.css index 84df00e..7c58792 100644 --- a/frontend/css/main.css +++ b/frontend/css/main.css @@ -326,6 +326,14 @@ button:active { background: #1a1a3a; } .git-hash { font-family: monospace; color: #6688cc; font-size: 11px; } .git-msg { color: #bbc; font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .git-date { color: #445; font-size: 10px; text-align: right; } +.git-scope-btn { + font-size: 10px; padding: 2px 8px; + background: #111122; border: 1px solid #2a2a44; color: #445566; cursor: pointer; +} +.git-scope-btn:first-of-type { border-radius: 3px 0 0 3px; } +.git-scope-btn:last-of-type { border-radius: 0 3px 3px 0; border-left: none; } +.git-scope-btn.active { background: #1a2840; border-color: #334466; color: #88aadd; } +.git-scope-btn:disabled { opacity: 0.35; cursor: default; } .git-restore-btn { font-size: 10px; padding: 2px 6px; background: #1a2840; border: 1px solid #334466; border-radius: 3px; diff --git a/frontend/index.html b/frontend/index.html index b0ec60c..2d25f91 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -449,8 +449,14 @@
- -
+
+ +
+ + +
+
+
diff --git a/frontend/js/api.js b/frontend/js/api.js index 3bb63c2..d4af115 100644 --- a/frontend/js/api.js +++ b/frontend/js/api.js @@ -62,7 +62,7 @@ const api = { }, git: { status: () => apiFetch("/git/status"), - log: () => apiFetch("/git/log"), + log: (diagram_id) => apiFetch(diagram_id != null ? `/git/log?diagram_id=${diagram_id}` : "/git/log"), commit: (message, diagram_id) => apiFetch("/git/commit", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message, diagram_id: diagram_id ?? null }) }), push: () => apiFetch("/git/push", { method: "POST" }), history: (hash) => apiFetch(`/git/history/${hash}`), diff --git a/frontend/js/app.js b/frontend/js/app.js index 25247a9..a206e17 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -2024,8 +2024,26 @@ class WiringApp { commitBtn._gitBound = true; commitBtn.addEventListener("click", () => this._gitCommit()); document.getElementById("btn-git-push").addEventListener("click", () => this._gitPush()); + + // History scope toggle + const btnDiagram = document.getElementById("btn-git-log-diagram"); + const btnAll = document.getElementById("btn-git-log-all"); + btnDiagram.addEventListener("click", () => { + btnDiagram.classList.add("active"); btnAll.classList.remove("active"); + this._gitLoadLog(); + }); + btnAll.addEventListener("click", () => { + btnAll.classList.add("active"); btnDiagram.classList.remove("active"); + this._gitLoadLog(); + }); } + // Default scope: "this diagram" if one is open, else "all" + const hasDiagram = !!this.diagramId; + document.getElementById("btn-git-log-diagram").classList.toggle("active", hasDiagram); + document.getElementById("btn-git-log-all").classList.toggle("active", !hasDiagram); + document.getElementById("btn-git-log-diagram").disabled = !hasDiagram; + await this._gitRefresh(); } @@ -2051,9 +2069,13 @@ class WiringApp { async _gitLoadLog() { const list = document.getElementById("git-log-list"); if (!list) return; + const diagramScope = document.getElementById("btn-git-log-diagram")?.classList.contains("active"); + const diagramId = diagramScope && this.diagramId ? this.diagramId : null; + const title = document.getElementById("git-log-title"); + if (title) title.textContent = diagramId ? "History — this diagram" : "History — all commits"; list.innerHTML = '
Loading…
'; try { - const entries = await api.git.log(); + const entries = await api.git.log(diagramId); if (!entries.length) { list.innerHTML = '
No commits yet
'; return;