feat: git panel redesign (#535)

* feat(git-panel): add Branches tab, Fetch always visible, inline error banners

- Add dedicated Branches tab (local/remote sections, switch with confirmation, delete branch, create branch)
- Rename History tab to Commits; add change-count badge on Changes tab
- Fetch button always visible when remote exists (not only when both ahead & behind)
- Inline error banner below header for failed push/pull/fetch, with dismiss button
- Server: /api/git/branches now returns localBranches + remoteBranches separately
- Server: add /api/git/delete-branch endpoint (prevents deleting current branch)
- Controller: expose operationError, clearOperationError, deleteBranch, localBranches, remoteBranches
- Constants: add deleteBranch to all ConfirmActionType record maps

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: git log datetime

* feat(git-panel): add staged/unstaged sections and enhanced commit details

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Haile <118998054+blackmammoth@users.noreply.github.com>
This commit is contained in:
Simos Mikelatos
2026-03-13 15:38:53 +01:00
committed by GitHub
parent 1d31c3ec83
commit adb3a06d7e
13 changed files with 732 additions and 172 deletions

View File

@@ -2,8 +2,10 @@ import { useCallback, useState } from 'react';
import { useGitPanelController } from '../hooks/useGitPanelController';
import { useRevertLocalCommit } from '../hooks/useRevertLocalCommit';
import type { ConfirmationRequest, GitPanelProps, GitPanelView } from '../types/types';
import { getChangedFileCount } from '../utils/gitPanelUtils';
import ChangesView from '../view/changes/ChangesView';
import HistoryView from '../view/history/HistoryView';
import BranchesView from '../view/branches/BranchesView';
import GitPanelHeader from '../view/GitPanelHeader';
import GitRepositoryErrorState from '../view/GitRepositoryErrorState';
import GitViewTabs from '../view/GitViewTabs';
@@ -21,6 +23,8 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
isLoading,
currentBranch,
branches,
localBranches,
remoteBranches,
recentCommits,
commitDiffs,
remoteStatus,
@@ -30,9 +34,12 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
isPushing,
isPublishing,
isCreatingInitialCommit,
operationError,
clearOperationError,
refreshAll,
switchBranch,
createBranch,
deleteBranch,
handleFetch,
handlePull,
handlePush,
@@ -56,13 +63,9 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
});
const executeConfirmedAction = useCallback(async () => {
if (!confirmAction) {
return;
}
if (!confirmAction) return;
const actionToExecute = confirmAction;
setConfirmAction(null);
try {
await actionToExecute.onConfirm();
} catch (error) {
@@ -70,6 +73,8 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
}
}, [confirmAction]);
const changeCount = getChangedFileCount(gitStatus);
if (!selectedProject) {
return (
<div className="flex h-full items-center justify-center text-muted-foreground">
@@ -92,6 +97,7 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
isPushing={isPushing}
isPublishing={isPublishing}
isRevertingLocalCommit={isRevertingLocalCommit}
operationError={operationError}
onRefresh={refreshAll}
onRevertLocalCommit={revertLatestLocalCommit}
onSwitchBranch={switchBranch}
@@ -100,6 +106,7 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
onPull={handlePull}
onPush={handlePush}
onPublish={handlePublish}
onClearError={clearOperationError}
onRequestConfirmation={setConfirmAction}
/>
@@ -110,6 +117,7 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
<GitViewTabs
activeView={activeView}
isHidden={hasExpandedFiles}
changeCount={changeCount}
onChange={setActiveView}
/>
@@ -145,6 +153,22 @@ export default function GitPanel({ selectedProject, isMobile = false, onFileOpen
onFetchCommitDiff={fetchCommitDiff}
/>
)}
{activeView === 'branches' && (
<BranchesView
isMobile={isMobile}
isLoading={isLoading}
currentBranch={currentBranch}
localBranches={localBranches}
remoteBranches={remoteBranches}
remoteStatus={remoteStatus}
isCreatingBranch={isCreatingBranch}
onSwitchBranch={switchBranch}
onCreateBranch={createBranch}
onDeleteBranch={deleteBranch}
onRequestConfirmation={setConfirmAction}
/>
)}
</>
)}