Mayank2027 commited on
Commit
fb24fd4
·
verified ·
1 Parent(s): 6c7f017

Create frontend/src/components/GitPanel.tsx

Browse files
Files changed (1) hide show
  1. frontend/src/components/GitPanel.tsx +148 -0
frontend/src/components/GitPanel.tsx ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import axios from 'axios';
3
+ import { FaCodeBranch, FaHistory, FaPen, FaFileAlt } from 'react-icons/fa';
4
+ import ReactMarkdown from 'react-markdown';
5
+
6
+ const GitPanel: React.FC<{ projectPath: string }> = ({ projectPath }) => {
7
+ const [branches, setBranches] = useState<string[]>([]);
8
+ const [logs, setLogs] = useState<any[]>([]);
9
+ const [commitMsg, setCommitMsg] = useState('');
10
+ const [generating, setGenerating] = useState(false);
11
+ const [prSummary, setPrSummary] = useState('');
12
+
13
+ const fetchData = async () => {
14
+ try {
15
+ const [branchesRes, logsRes] = await Promise.all([
16
+ axios.post('/api/git', { action: 'branch', project_path: projectPath }),
17
+ axios.post('/api/git', { action: 'log', project_path: projectPath })
18
+ ]);
19
+ setBranches(branchesRes.data.branches || []);
20
+ setLogs(logsRes.data.log || []);
21
+ } catch (e) {}
22
+ };
23
+
24
+ useEffect(() => { fetchData(); }, []);
25
+
26
+ const generateCommitMessage = async () => {
27
+ setGenerating(true);
28
+ try {
29
+ const diffRes = await axios.post('/api/git', { action: 'diff', project_path: projectPath });
30
+ const diff = diffRes.data.diff || '';
31
+ const resp = await fetch('/api/chat', {
32
+ method: 'POST',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ body: JSON.stringify({
35
+ model: 'groq-llama-3.1-8b-instant',
36
+ messages: [{ role: 'user', content: `Generate a concise git commit message for the following diff:\n${diff}` }],
37
+ project_path: projectPath,
38
+ }),
39
+ });
40
+ const reader = resp.body?.getReader();
41
+ let msg = '';
42
+ while (reader) {
43
+ const { done, value } = await reader.read();
44
+ if (done) break;
45
+ const text = new TextDecoder().decode(value);
46
+ const lines = text.split('\n').filter(l => l.startsWith('data: ')).map(l => l.slice(6));
47
+ for (const line of lines) {
48
+ if (line === '[DONE]') break;
49
+ try {
50
+ const { token } = JSON.parse(line);
51
+ msg += token;
52
+ } catch (e) {}
53
+ }
54
+ }
55
+ setCommitMsg(msg.replace(/ERROR:.*/, '').trim());
56
+ } catch (e) {}
57
+ setGenerating(false);
58
+ };
59
+
60
+ const generatePRSummary = async () => {
61
+ try {
62
+ const diffRes = await axios.post('/api/git', { action: 'diff', project_path: projectPath });
63
+ const diff = diffRes.data.diff || '';
64
+ const resp = await fetch('/api/chat', {
65
+ method: 'POST',
66
+ headers: { 'Content-Type': 'application/json' },
67
+ body: JSON.stringify({
68
+ model: 'groq-llama-3.3-70b-versatile',
69
+ messages: [{ role: 'user', content: `Review the following diff and provide a PR summary with suggestions:\n${diff}` }],
70
+ project_path: projectPath,
71
+ }),
72
+ });
73
+ const reader = resp.body?.getReader();
74
+ let summary = '';
75
+ while (reader) {
76
+ const { done, value } = await reader.read();
77
+ if (done) break;
78
+ const text = new TextDecoder().decode(value);
79
+ const lines = text.split('\n').filter(l => l.startsWith('data: ')).map(l => l.slice(6));
80
+ for (const line of lines) {
81
+ if (line === '[DONE]') break;
82
+ try {
83
+ const { token } = JSON.parse(line);
84
+ summary += token;
85
+ } catch (e) {}
86
+ }
87
+ }
88
+ setPrSummary(summary);
89
+ } catch (e) {}
90
+ };
91
+
92
+ const commit = async () => {
93
+ await axios.post('/api/git', { action: 'commit', project_path: projectPath, args: { message: commitMsg } });
94
+ fetchData();
95
+ setCommitMsg('');
96
+ };
97
+
98
+ return (
99
+ <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-primary)', padding: 12, overflowY: 'auto' }}>
100
+ <div style={{ fontWeight: 600, marginBottom: 8 }}><FaCodeBranch /> Git</div>
101
+
102
+ <div style={{ marginBottom: 12 }}>
103
+ <div style={{ fontSize: 12, color: 'var(--text-secondary)', marginBottom: 4 }}>Branches</div>
104
+ {branches.map(b => (
105
+ <div key={b} style={{ padding: '2px 8px', background: 'var(--bg-tertiary)', borderRadius: 4, marginBottom: 2, fontSize: 13 }}>{b}</div>
106
+ ))}
107
+ </div>
108
+
109
+ <div style={{ marginBottom: 12 }}>
110
+ <div style={{ fontSize: 12, color: 'var(--text-secondary)', marginBottom: 4 }}>Recent Commits</div>
111
+ {logs.map((log, i) => (
112
+ <div key={i} style={{ borderBottom: '1px solid var(--border)', padding: '4px 0', fontSize: 12 }}>
113
+ <span style={{ color: 'var(--accent)' }}>{log.hash?.substring(0,7)} </span>
114
+ {log.message}
115
+ </div>
116
+ ))}
117
+ </div>
118
+
119
+ <div style={{ marginBottom: 12 }}>
120
+ <textarea
121
+ style={{ width: '100%', height: 40, background: 'var(--bg-tertiary)', color: 'var(--text-primary)', border: '1px solid var(--border)', borderRadius: 4, padding: 4, fontSize: 12 }}
122
+ placeholder="Commit message..."
123
+ value={commitMsg}
124
+ onChange={e => setCommitMsg(e.target.value)}
125
+ />
126
+ <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
127
+ <button onClick={generateCommitMessage} disabled={generating} style={{ background: 'var(--accent)', color: 'white', padding: '4px 8px', borderRadius: 4, fontSize: 12, display: 'flex', alignItems: 'center', gap: 4 }}>
128
+ <FaPen /> {generating ? '...' : 'AI Message'}
129
+ </button>
130
+ <button onClick={commit} style={{ background: 'var(--success)', color: 'white', padding: '4px 8px', borderRadius: 4, fontSize: 12 }}>Commit</button>
131
+ </div>
132
+ </div>
133
+
134
+ <div style={{ marginBottom: 12 }}>
135
+ <button onClick={generatePRSummary} style={{ background: 'var(--accent)', color: 'white', padding: '4px 12px', borderRadius: 4, fontSize: 12, display: 'flex', alignItems: 'center', gap: 4 }}>
136
+ <FaFileAlt /> Generate PR Summary
137
+ </button>
138
+ {prSummary && (
139
+ <div style={{ marginTop: 8, padding: 8, background: 'var(--bg-secondary)', borderRadius: 4 }}>
140
+ <ReactMarkdown>{prSummary}</ReactMarkdown>
141
+ </div>
142
+ )}
143
+ </div>
144
+ </div>
145
+ );
146
+ };
147
+
148
+ export default GitPanel;