agentgui 1.0.67 → 1.0.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prd +214 -0
- package/.prd-browser +607 -0
- package/CLAUDE.md +1532 -125
- package/browser-test-harness.js +371 -0
- package/browser-test.js +409 -0
- package/execute-tests.js +164 -0
- package/lib/claude-runner.js +41 -12
- package/lib/database-service.ts +252 -0
- package/lib/sync-service.ts +275 -0
- package/lib/types.ts +168 -0
- package/package.json +1 -1
- package/readme.md +586 -0
- package/run-e2e-test.sh +88 -0
- package/server.js +274 -8
- package/static/index.html +487 -180
- package/static/js/client.js +558 -0
- package/static/js/event-filter.js +311 -0
- package/static/js/event-processor.js +454 -0
- package/static/js/streaming-renderer.js +813 -0
- package/static/js/syntax-highlighter.js +271 -0
- package/static/js/ui-components.js +433 -0
- package/static/js/websocket-manager.js +482 -0
- package/static/templates/INDEX.html +465 -0
- package/static/templates/README.md +190 -0
- package/static/templates/agent-capabilities.html +56 -0
- package/static/templates/agent-metadata-panel.html +44 -0
- package/static/templates/agent-status-badge.html +30 -0
- package/static/templates/code-annotation-panel.html +155 -0
- package/static/templates/code-suggestion-panel.html +184 -0
- package/static/templates/command-header.html +77 -0
- package/static/templates/command-output-scrollable.html +118 -0
- package/static/templates/elapsed-time.html +54 -0
- package/static/templates/error-alert.html +106 -0
- package/static/templates/error-history-timeline.html +160 -0
- package/static/templates/error-recovery-options.html +109 -0
- package/static/templates/error-stack-trace.html +95 -0
- package/static/templates/error-summary.html +80 -0
- package/static/templates/event-counter.html +48 -0
- package/static/templates/execution-actions.html +97 -0
- package/static/templates/execution-progress-bar.html +80 -0
- package/static/templates/execution-stepper.html +120 -0
- package/static/templates/file-breadcrumb.html +118 -0
- package/static/templates/file-diff-viewer.html +121 -0
- package/static/templates/file-metadata.html +133 -0
- package/static/templates/file-read-panel.html +66 -0
- package/static/templates/file-write-panel.html +120 -0
- package/static/templates/git-branch-remote.html +107 -0
- package/static/templates/git-diff-list.html +101 -0
- package/static/templates/git-log-visualization.html +153 -0
- package/static/templates/git-status-panel.html +115 -0
- package/static/templates/quality-metrics-display.html +170 -0
- package/static/templates/terminal-output-panel.html +87 -0
- package/static/templates/test-results-display.html +144 -0
- package/test-browser.js +457 -0
- package/test-runner.js +182 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!-- File Read Operation Display -->
|
|
2
|
+
<div class="file-read-panel card" role="region" aria-label="File read operation: {{ filePath }}">
|
|
3
|
+
<div class="card-header flex items-start justify-between gap-3 mb-3 pb-3 border-b">
|
|
4
|
+
<div class="flex items-center gap-2 flex-1 min-w-0">
|
|
5
|
+
<svg class="w-4 h-4 text-primary flex-shrink-0" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
6
|
+
<path d="M5.5 13a3 3 0 01.369-1.618l1.83-1.83a3 3 0 015.604 0l.83 1.83A3 3 0 0113.5 13H11V9.413l1.293 1.293a1 1 0 001.414-1.414l-3-3a1 1 0 00-1.414 0l-3 3a1 1 0 001.414 1.414L9 9.414V13H5.5z"/>
|
|
7
|
+
</svg>
|
|
8
|
+
<div class="flex-1 min-w-0">
|
|
9
|
+
<h4 class="font-semibold text-sm truncate">{{ fileName }}</h4>
|
|
10
|
+
<p class="text-xs text-secondary truncate" title="{{ filePath }}">{{ filePath }}</p>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="flex items-center gap-2 flex-shrink-0">
|
|
15
|
+
<span class="badge badge-sm">Read</span>
|
|
16
|
+
<span class="badge badge-sm" aria-label="File size: {{ fileSize }}">{{ fileSizeFormatted }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<!-- File Metadata -->
|
|
21
|
+
<div class="text-xs text-secondary mb-3 pb-3 border-b space-y-1">
|
|
22
|
+
<p><span class="font-mono">{{ fileEncoding }}</span> • {{ lastModified }}</p>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- Code Block with Syntax Highlighting -->
|
|
26
|
+
<pre class="code-block" role="region" aria-label="File content"><code class="language-{{ languageClass }}" data-line-count="{{ lineCount }}">{{ fileContent }}</code></pre>
|
|
27
|
+
|
|
28
|
+
<!-- Action Buttons -->
|
|
29
|
+
<div class="flex gap-2 mt-3 pt-3 border-t">
|
|
30
|
+
<button class="btn btn-sm btn-tertiary" data-action="copy" aria-label="Copy file content">
|
|
31
|
+
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
32
|
+
<path d="M7 3a1 1 0 000 2h6a1 1 0 000-2H7zM4 7a1 1 0 011-1h10a1 1 0 011 1v10a2 2 0 01-2 2H6a2 2 0 01-2-2V7z"/>
|
|
33
|
+
</svg>
|
|
34
|
+
Copy
|
|
35
|
+
</button>
|
|
36
|
+
<button class="btn btn-sm btn-tertiary" data-action="download" aria-label="Download file">
|
|
37
|
+
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
38
|
+
<path d="M2 6a2 2 0 012-2h12a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6zm14 1a1 1 0 11-2 0 1 1 0 012 0z"/>
|
|
39
|
+
</svg>
|
|
40
|
+
Download
|
|
41
|
+
</button>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<style scoped>
|
|
46
|
+
.file-read-panel {
|
|
47
|
+
padding: 16px;
|
|
48
|
+
background: var(--color-bg-primary);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.code-block {
|
|
52
|
+
background-color: var(--color-bg-code);
|
|
53
|
+
border: 1px solid var(--color-border);
|
|
54
|
+
border-radius: 4px;
|
|
55
|
+
padding: 12px;
|
|
56
|
+
overflow-x: auto;
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
line-height: 1.5;
|
|
59
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.btn-sm {
|
|
63
|
+
padding: 4px 8px;
|
|
64
|
+
font-size: 11px;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<!-- File Write Operation Display with Before/After Comparison -->
|
|
2
|
+
<div class="file-write-panel card" role="region" aria-label="File write operation: {{ filePath }}">
|
|
3
|
+
<div class="card-header flex items-start justify-between gap-3 mb-3 pb-3 border-b">
|
|
4
|
+
<div class="flex items-center gap-2 flex-1 min-w-0">
|
|
5
|
+
<svg class="w-4 h-4 text-primary flex-shrink-0" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
6
|
+
<path d="M11 3a1 1 0 10-2 0v1a1 1 0 102 0V3zM15.657 5.757a1 1 0 00-1.414-1.414l-.707.707a1 1 0 001.414 1.414l.707-.707zM18 10a1 1 0 01-1 1h-1a1 1 0 110-2h1a1 1 0 011 1zM15.657 14.243a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414l.707.707zM11 17a1 1 0 102 0v-1a1 1 0 10-2 0v1zM5.757 15.657a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414l-.707.707zM2 10a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.757 4.343a1 1 0 00-1.414 1.414l.707.707a1 1 0 001.414-1.414l-.707-.707z"/>
|
|
7
|
+
</svg>
|
|
8
|
+
<div class="flex-1 min-w-0">
|
|
9
|
+
<h4 class="font-semibold text-sm truncate">{{ fileName }}</h4>
|
|
10
|
+
<p class="text-xs text-secondary truncate" title="{{ filePath }}">{{ filePath }}</p>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="flex items-center gap-2 flex-shrink-0">
|
|
15
|
+
<span class="badge badge-sm bg-yellow-100 text-yellow-800">Modified</span>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<!-- Tabs: Before/After/Diff -->
|
|
20
|
+
<div class="tabs mb-3" role="tablist">
|
|
21
|
+
<button class="tab-button active" data-tab="before" role="tab" aria-selected="true" aria-controls="before-panel">
|
|
22
|
+
Before
|
|
23
|
+
</button>
|
|
24
|
+
<button class="tab-button" data-tab="after" role="tab" aria-selected="false" aria-controls="after-panel">
|
|
25
|
+
After
|
|
26
|
+
</button>
|
|
27
|
+
<button class="tab-button" data-tab="diff" role="tab" aria-selected="false" aria-controls="diff-panel">
|
|
28
|
+
Diff
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<!-- Before Panel -->
|
|
33
|
+
<div id="before-panel" class="tab-panel active" role="tabpanel" aria-labelledby="before-tab">
|
|
34
|
+
<pre class="code-block"><code class="language-{{ languageClass }}">{{ contentBefore }}</code></pre>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<!-- After Panel -->
|
|
38
|
+
<div id="after-panel" class="tab-panel hidden" role="tabpanel" aria-labelledby="after-tab">
|
|
39
|
+
<pre class="code-block"><code class="language-{{ languageClass }}">{{ contentAfter }}</code></pre>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- Diff Panel -->
|
|
43
|
+
<div id="diff-panel" class="tab-panel hidden" role="tabpanel" aria-labelledby="diff-tab">
|
|
44
|
+
<pre class="code-block diff-block"><code>{{ diffContent }}</code></pre>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<!-- Action Buttons -->
|
|
48
|
+
<div class="flex gap-2 mt-3 pt-3 border-t">
|
|
49
|
+
<button class="btn btn-sm btn-tertiary" data-action="copy-before" aria-label="Copy original content">
|
|
50
|
+
Copy Before
|
|
51
|
+
</button>
|
|
52
|
+
<button class="btn btn-sm btn-tertiary" data-action="copy-after" aria-label="Copy new content">
|
|
53
|
+
Copy After
|
|
54
|
+
</button>
|
|
55
|
+
<button class="btn btn-sm btn-tertiary" data-action="download-diff" aria-label="Download diff">
|
|
56
|
+
Download Diff
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<style scoped>
|
|
62
|
+
.file-write-panel {
|
|
63
|
+
padding: 16px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.tabs {
|
|
67
|
+
display: flex;
|
|
68
|
+
gap: 8px;
|
|
69
|
+
border-bottom: 1px solid var(--color-border);
|
|
70
|
+
margin-bottom: 16px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.tab-button {
|
|
74
|
+
padding: 8px 12px;
|
|
75
|
+
background: none;
|
|
76
|
+
border: none;
|
|
77
|
+
color: var(--color-text-secondary);
|
|
78
|
+
font-size: 13px;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
border-bottom: 2px solid transparent;
|
|
81
|
+
transition: all 0.2s;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.tab-button.active {
|
|
85
|
+
color: var(--color-primary);
|
|
86
|
+
border-bottom-color: var(--color-primary);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.tab-panel {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.tab-panel.active {
|
|
94
|
+
display: block;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.code-block {
|
|
98
|
+
background-color: var(--color-bg-code);
|
|
99
|
+
border: 1px solid var(--color-border);
|
|
100
|
+
border-radius: 4px;
|
|
101
|
+
padding: 12px;
|
|
102
|
+
overflow-x: auto;
|
|
103
|
+
font-size: 12px;
|
|
104
|
+
line-height: 1.5;
|
|
105
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.diff-block {
|
|
109
|
+
background-color: var(--color-bg-diff);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.btn-sm {
|
|
113
|
+
padding: 4px 8px;
|
|
114
|
+
font-size: 11px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.hidden {
|
|
118
|
+
display: none;
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<!-- Git Branch and Remote Display -->
|
|
2
|
+
<div class="git-branch-remote card" role="region" aria-label="Git branch and remote information">
|
|
3
|
+
<!-- Current Branch -->
|
|
4
|
+
<div class="mb-3 pb-3 border-b">
|
|
5
|
+
<h5 class="font-semibold text-sm mb-2">Current Branch</h5>
|
|
6
|
+
<div class="flex items-center gap-2">
|
|
7
|
+
<svg class="w-4 h-4 text-primary" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
8
|
+
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
<div>
|
|
11
|
+
<p class="font-mono font-semibold">{{ currentBranch }}</p>
|
|
12
|
+
<p class="text-xs text-secondary">{{ branchDescription }}</p>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<!-- Remote Branches -->
|
|
18
|
+
<div class="mb-3 pb-3 border-b">
|
|
19
|
+
<h5 class="font-semibold text-sm mb-2">Remotes</h5>
|
|
20
|
+
<div class="space-y-2">
|
|
21
|
+
{{ for remote in remotes }}
|
|
22
|
+
<div class="flex items-center justify-between text-sm">
|
|
23
|
+
<div class="flex items-center gap-2">
|
|
24
|
+
<span class="badge badge-sm">{{ remote.name }}</span>
|
|
25
|
+
<code class="font-mono text-xs">{{ remote.url }}</code>
|
|
26
|
+
</div>
|
|
27
|
+
<span class="text-secondary text-xs">{{ remote.status }}</span>
|
|
28
|
+
</div>
|
|
29
|
+
{{ end }}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<!-- Tracking Status -->
|
|
34
|
+
<div class="mb-3 pb-3 border-b">
|
|
35
|
+
<h5 class="font-semibold text-sm mb-2">Tracking Status</h5>
|
|
36
|
+
<div class="grid grid-cols-2 gap-3 text-sm">
|
|
37
|
+
<div class="flex items-center gap-2">
|
|
38
|
+
<svg class="w-4 h-4 text-green-600" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
39
|
+
<path fill-rule="evenodd" d="M12 2a1 1 0 011 1v6.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 111.414-1.414L11 9.586V3a1 1 0 011-1z"/>
|
|
40
|
+
</svg>
|
|
41
|
+
<span><span class="font-semibold">{{ aheadCount }}</span> ahead</span>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="flex items-center gap-2">
|
|
44
|
+
<svg class="w-4 h-4 text-red-600" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
45
|
+
<path fill-rule="evenodd" d="M8 18a1 1 0 001-1v-6.586l1.293 1.293a1 1 0 001.414-1.414l-3-3a1 1 0 00-1.414 0l-3 3a1 1 0 101.414 1.414L7 10.414V17a1 1 0 001 1z"/>
|
|
46
|
+
</svg>
|
|
47
|
+
<span><span class="font-semibold">{{ behindCount }}</span> behind</span>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- Quick Actions -->
|
|
53
|
+
<div class="flex gap-2">
|
|
54
|
+
<button class="btn btn-sm" data-action="checkout-branch" aria-label="Switch branch">
|
|
55
|
+
Checkout
|
|
56
|
+
</button>
|
|
57
|
+
<button class="btn btn-sm" data-action="merge" aria-label="Merge branch">
|
|
58
|
+
Merge
|
|
59
|
+
</button>
|
|
60
|
+
<button class="btn btn-sm" data-action="rebase" aria-label="Rebase branch">
|
|
61
|
+
Rebase
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<style scoped>
|
|
67
|
+
.git-branch-remote {
|
|
68
|
+
padding: 16px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.badge {
|
|
72
|
+
background-color: var(--color-primary);
|
|
73
|
+
color: white;
|
|
74
|
+
padding: 2px 6px;
|
|
75
|
+
border-radius: 3px;
|
|
76
|
+
font-size: 10px;
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.badge-sm {
|
|
81
|
+
padding: 2px 6px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.font-mono {
|
|
85
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.btn {
|
|
89
|
+
padding: 6px 10px;
|
|
90
|
+
background-color: var(--color-primary);
|
|
91
|
+
color: white;
|
|
92
|
+
border: none;
|
|
93
|
+
border-radius: 3px;
|
|
94
|
+
font-size: 12px;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
transition: all 0.2s;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.btn:hover {
|
|
100
|
+
background-color: var(--color-primary-dark);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.btn-sm {
|
|
104
|
+
padding: 4px 8px;
|
|
105
|
+
font-size: 11px;
|
|
106
|
+
}
|
|
107
|
+
</style>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<!-- Git Diff List for Multiple Files -->
|
|
2
|
+
<div class="git-diff-list card" role="region" aria-label="Git diffs for changed files">
|
|
3
|
+
<div class="card-header border-b pb-3 mb-3">
|
|
4
|
+
<h4 class="font-semibold">{{ fileCount }} Files Changed</h4>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<!-- Diff Items -->
|
|
8
|
+
<div class="diff-items space-y-3">
|
|
9
|
+
{{ for file in diffs }}
|
|
10
|
+
<details class="diff-item">
|
|
11
|
+
<summary class="cursor-pointer font-medium py-2 px-3 bg-secondary hover:bg-hover-bg rounded flex items-center justify-between">
|
|
12
|
+
<div class="flex items-center gap-2 flex-1 min-w-0">
|
|
13
|
+
<svg class="w-4 h-4 chevron" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
|
14
|
+
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"/>
|
|
15
|
+
</svg>
|
|
16
|
+
<span class="truncate">{{ file.name }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="flex gap-1 flex-shrink-0">
|
|
19
|
+
<span class="text-green-600 text-xs">+{{ file.additions }}</span>
|
|
20
|
+
<span class="text-red-600 text-xs">-{{ file.deletions }}</span>
|
|
21
|
+
</div>
|
|
22
|
+
</summary>
|
|
23
|
+
|
|
24
|
+
<!-- Diff Content -->
|
|
25
|
+
<div class="diff-content p-3 mt-2 bg-code rounded text-xs">
|
|
26
|
+
<pre><code class="language-diff">{{ file.diff }}</code></pre>
|
|
27
|
+
</div>
|
|
28
|
+
</details>
|
|
29
|
+
{{ end }}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<style scoped>
|
|
34
|
+
.git-diff-list {
|
|
35
|
+
padding: 16px;
|
|
36
|
+
max-height: 600px;
|
|
37
|
+
overflow-y: auto;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.diff-item {
|
|
41
|
+
border: 1px solid var(--color-border);
|
|
42
|
+
border-radius: 4px;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.diff-item[open] summary {
|
|
47
|
+
background-color: var(--color-bg-hover);
|
|
48
|
+
border-bottom: 1px solid var(--color-border);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
summary {
|
|
52
|
+
list-style: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
summary::-webkit-details-marker {
|
|
56
|
+
display: none;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.chevron {
|
|
60
|
+
transition: transform 0.2s;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
details[open] .chevron {
|
|
65
|
+
transform: rotate(180deg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.diff-content {
|
|
69
|
+
background-color: var(--color-bg-code);
|
|
70
|
+
border: 1px solid var(--color-border);
|
|
71
|
+
border-radius: 3px;
|
|
72
|
+
max-height: 300px;
|
|
73
|
+
overflow: auto;
|
|
74
|
+
margin-top: 8px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.diff-content pre {
|
|
78
|
+
margin: 0;
|
|
79
|
+
padding: 0;
|
|
80
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
81
|
+
line-height: 1.5;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Diff syntax highlighting */
|
|
85
|
+
.diff-content code {
|
|
86
|
+
color: var(--color-text-terminal);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.diff-added {
|
|
90
|
+
color: #10b981;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.diff-removed {
|
|
94
|
+
color: #ef4444;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.diff-header {
|
|
98
|
+
color: #3b82f6;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<!-- Git Log Visualization Timeline -->
|
|
2
|
+
<div class="git-log-visualization card" role="region" aria-label="Git commit history">
|
|
3
|
+
<div class="card-header border-b pb-3 mb-3">
|
|
4
|
+
<h4 class="font-semibold">{{ commitCount }} Recent Commits</h4>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<!-- Timeline -->
|
|
8
|
+
<div class="commit-timeline" role="list">
|
|
9
|
+
{{ for commit in commits }}
|
|
10
|
+
<div class="commit-item" role="listitem">
|
|
11
|
+
<!-- Timeline Connector -->
|
|
12
|
+
<div class="commit-connector" aria-hidden="true"></div>
|
|
13
|
+
|
|
14
|
+
<!-- Commit Dot -->
|
|
15
|
+
<div class="commit-dot" aria-hidden="true">
|
|
16
|
+
<div class="dot-inner"></div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<!-- Commit Card -->
|
|
20
|
+
<div class="commit-card">
|
|
21
|
+
<div class="flex items-start justify-between gap-2">
|
|
22
|
+
<div class="flex-1">
|
|
23
|
+
<h5 class="font-semibold text-sm">{{ commit.message }}</h5>
|
|
24
|
+
<p class="text-xs text-secondary">by {{ commit.author }}</p>
|
|
25
|
+
</div>
|
|
26
|
+
<code class="font-mono text-xs bg-code px-2 py-1 rounded">
|
|
27
|
+
{{ commit.hash }}
|
|
28
|
+
</code>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<!-- Commit Details -->
|
|
32
|
+
<div class="text-xs mt-2 space-y-1">
|
|
33
|
+
<p class="text-secondary" title="{{ commit.timestampFull }}">
|
|
34
|
+
{{ commit.timestamp }}
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
<!-- Changed Files -->
|
|
38
|
+
{{ if commit.files }}
|
|
39
|
+
<div class="mt-2">
|
|
40
|
+
<span class="text-secondary">{{ commit.filesCount }} files</span>
|
|
41
|
+
<span class="text-green-600">+{{ commit.additions }}</span>
|
|
42
|
+
<span class="text-red-600">-{{ commit.deletions }}</span>
|
|
43
|
+
</div>
|
|
44
|
+
{{ end }}
|
|
45
|
+
|
|
46
|
+
<!-- Tags -->
|
|
47
|
+
{{ if commit.tags }}
|
|
48
|
+
<div class="flex gap-1 flex-wrap mt-2">
|
|
49
|
+
{{ for tag in commit.tags }}
|
|
50
|
+
<span class="badge badge-tag">{{ tag }}</span>
|
|
51
|
+
{{ end }}
|
|
52
|
+
</div>
|
|
53
|
+
{{ end }}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
{{ end }}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<style scoped>
|
|
62
|
+
.git-log-visualization {
|
|
63
|
+
padding: 16px;
|
|
64
|
+
max-height: 600px;
|
|
65
|
+
overflow-y: auto;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.commit-timeline {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
gap: 0;
|
|
72
|
+
list-style: none;
|
|
73
|
+
margin: 0;
|
|
74
|
+
padding: 0;
|
|
75
|
+
position: relative;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.commit-timeline::before {
|
|
79
|
+
content: '';
|
|
80
|
+
position: absolute;
|
|
81
|
+
left: 19px;
|
|
82
|
+
top: 12px;
|
|
83
|
+
bottom: 0;
|
|
84
|
+
width: 2px;
|
|
85
|
+
background: linear-gradient(to bottom, var(--color-primary), transparent);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.commit-item {
|
|
89
|
+
position: relative;
|
|
90
|
+
display: flex;
|
|
91
|
+
gap: 12px;
|
|
92
|
+
padding-bottom: 16px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.commit-item:last-child {
|
|
96
|
+
padding-bottom: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.commit-dot {
|
|
100
|
+
position: relative;
|
|
101
|
+
width: 40px;
|
|
102
|
+
height: 40px;
|
|
103
|
+
border-radius: 50%;
|
|
104
|
+
background-color: var(--color-bg-secondary);
|
|
105
|
+
border: 2px solid var(--color-primary);
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
flex-shrink: 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.dot-inner {
|
|
113
|
+
width: 8px;
|
|
114
|
+
height: 8px;
|
|
115
|
+
border-radius: 50%;
|
|
116
|
+
background-color: var(--color-primary);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.commit-card {
|
|
120
|
+
flex: 1;
|
|
121
|
+
background-color: var(--color-bg-secondary);
|
|
122
|
+
border: 1px solid var(--color-border);
|
|
123
|
+
border-radius: 4px;
|
|
124
|
+
padding: 10px;
|
|
125
|
+
margin-top: 2px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.commit-card:hover {
|
|
129
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.font-mono {
|
|
133
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.bg-code {
|
|
137
|
+
background-color: var(--color-bg-code);
|
|
138
|
+
border-radius: 2px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.badge {
|
|
142
|
+
background-color: var(--color-primary);
|
|
143
|
+
color: white;
|
|
144
|
+
padding: 2px 6px;
|
|
145
|
+
border-radius: 3px;
|
|
146
|
+
font-size: 10px;
|
|
147
|
+
font-weight: 600;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.badge-tag {
|
|
151
|
+
background-color: var(--color-secondary);
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<!-- Git Status Panel -->
|
|
2
|
+
<div class="git-status-panel card" role="region" aria-label="Git repository status">
|
|
3
|
+
<div class="card-header flex items-center justify-between mb-3 pb-3 border-b">
|
|
4
|
+
<div>
|
|
5
|
+
<h4 class="font-semibold">{{ repoName }}</h4>
|
|
6
|
+
<p class="text-xs text-secondary">{{ currentBranch }} @ {{ commitHash }}</p>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="badge" data-status="{{ repoStatus }}">
|
|
9
|
+
{{ repoStatusLabel }}
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<!-- File Changes Summary -->
|
|
14
|
+
<div class="changes-summary grid grid-cols-3 gap-2 mb-3 pb-3 border-b">
|
|
15
|
+
<div class="text-center">
|
|
16
|
+
<p class="text-2xl font-bold text-green-600">{{ modifiedCount }}</p>
|
|
17
|
+
<p class="text-xs text-secondary">Modified</p>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="text-center border-l border-r pl-2 pr-2">
|
|
20
|
+
<p class="text-2xl font-bold text-blue-600">{{ addedCount }}</p>
|
|
21
|
+
<p class="text-xs text-secondary">Added</p>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="text-center">
|
|
24
|
+
<p class="text-2xl font-bold text-red-600">{{ deletedCount }}</p>
|
|
25
|
+
<p class="text-xs text-secondary">Deleted</p>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<!-- File List -->
|
|
30
|
+
<div class="file-list space-y-1">
|
|
31
|
+
<div class="text-xs font-semibold text-secondary mb-2">Changed Files</div>
|
|
32
|
+
{{ for file in changedFiles }}
|
|
33
|
+
<div class="file-item flex items-center gap-2 text-sm py-1">
|
|
34
|
+
<span class="status-icon" data-status="{{ file.status }}" aria-hidden="true">
|
|
35
|
+
{{ if file.status == 'modified' }}M{{ else if file.status == 'added' }}A{{ else if file.status == 'deleted' }}D{{ end }}
|
|
36
|
+
</span>
|
|
37
|
+
<span class="file-path flex-1 truncate" title="{{ file.path }}">{{ file.path }}</span>
|
|
38
|
+
</div>
|
|
39
|
+
{{ end }}
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- Actions -->
|
|
43
|
+
<div class="flex gap-2 mt-3 pt-3 border-t">
|
|
44
|
+
<button class="btn btn-sm" data-action="commit" aria-label="Open commit dialog">
|
|
45
|
+
Commit
|
|
46
|
+
</button>
|
|
47
|
+
<button class="btn btn-sm" data-action="push" aria-label="Push changes">
|
|
48
|
+
Push
|
|
49
|
+
</button>
|
|
50
|
+
<button class="btn btn-sm" data-action="pull" aria-label="Pull changes">
|
|
51
|
+
Pull
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<style scoped>
|
|
57
|
+
.git-status-panel {
|
|
58
|
+
padding: 16px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.status-icon {
|
|
62
|
+
display: inline-block;
|
|
63
|
+
width: 20px;
|
|
64
|
+
text-align: center;
|
|
65
|
+
font-size: 11px;
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
padding: 2px 4px;
|
|
68
|
+
border-radius: 3px;
|
|
69
|
+
flex-shrink: 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.status-icon[data-status="modified"] {
|
|
73
|
+
color: #16a34a;
|
|
74
|
+
background-color: #dcfce7;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.status-icon[data-status="added"] {
|
|
78
|
+
color: #2563eb;
|
|
79
|
+
background-color: #dbeafe;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.status-icon[data-status="deleted"] {
|
|
83
|
+
color: #dc2626;
|
|
84
|
+
background-color: #fee2e2;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.file-item:hover {
|
|
88
|
+
background-color: var(--color-bg-hover);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.file-path {
|
|
92
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
93
|
+
font-size: 12px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.btn {
|
|
97
|
+
padding: 6px 10px;
|
|
98
|
+
background-color: var(--color-primary);
|
|
99
|
+
color: white;
|
|
100
|
+
border: none;
|
|
101
|
+
border-radius: 3px;
|
|
102
|
+
font-size: 12px;
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
transition: all 0.2s;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.btn:hover {
|
|
108
|
+
background-color: var(--color-primary-dark);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.btn-sm {
|
|
112
|
+
padding: 4px 8px;
|
|
113
|
+
font-size: 11px;
|
|
114
|
+
}
|
|
115
|
+
</style>
|