git-history-ui 1.0.1 → 1.0.3

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.
Files changed (51) hide show
  1. package/README.md +45 -244
  2. package/dist/backend/server.d.ts.map +1 -1
  3. package/dist/backend/server.js +30 -10
  4. package/dist/backend/server.js.map +1 -1
  5. package/dist/config/paths.d.ts +14 -0
  6. package/dist/config/paths.d.ts.map +1 -0
  7. package/dist/config/paths.js +35 -0
  8. package/dist/config/paths.js.map +1 -0
  9. package/package.json +8 -1
  10. package/public/index.html +0 -1
  11. package/.eslintrc.js +0 -21
  12. package/demo.js +0 -45
  13. package/frontend/.editorconfig +0 -17
  14. package/frontend/.vscode/extensions.json +0 -4
  15. package/frontend/.vscode/launch.json +0 -20
  16. package/frontend/.vscode/tasks.json +0 -42
  17. package/frontend/README.md +0 -59
  18. package/frontend/angular.json +0 -99
  19. package/frontend/package-lock.json +0 -10566
  20. package/frontend/package.json +0 -55
  21. package/frontend/proxy.conf.json +0 -7
  22. package/frontend/public/favicon.ico +0 -0
  23. package/frontend/src/app/app.component.ts +0 -598
  24. package/frontend/src/app/app.config.ts +0 -12
  25. package/frontend/src/app/app.css +0 -0
  26. package/frontend/src/app/app.html +0 -342
  27. package/frontend/src/app/app.routes.ts +0 -3
  28. package/frontend/src/app/app.spec.ts +0 -23
  29. package/frontend/src/app/app.ts +0 -12
  30. package/frontend/src/app/components/color-palette-selector/color-palette-selector.component.ts +0 -137
  31. package/frontend/src/app/components/commit-detail/commit-detail.component.ts +0 -327
  32. package/frontend/src/app/components/commit-graph/commit-graph.component.ts +0 -294
  33. package/frontend/src/app/components/commit-list/commit-list.component.ts +0 -199
  34. package/frontend/src/app/components/diff-viewer/diff-viewer.component.ts +0 -311
  35. package/frontend/src/app/models/color-palette.models.ts +0 -229
  36. package/frontend/src/app/models/git.models.ts +0 -39
  37. package/frontend/src/app/services/git.service.ts +0 -43
  38. package/frontend/src/index.html +0 -13
  39. package/frontend/src/main.ts +0 -6
  40. package/frontend/src/styles.css +0 -397
  41. package/frontend/tsconfig.app.json +0 -15
  42. package/frontend/tsconfig.json +0 -34
  43. package/frontend/tsconfig.spec.json +0 -14
  44. package/jest.config.js +0 -26
  45. package/src/__tests__/gitService.test.ts +0 -533
  46. package/src/__tests__/setup.ts +0 -25
  47. package/src/backend/dev-server.ts +0 -14
  48. package/src/backend/gitService.ts +0 -277
  49. package/src/backend/server.ts +0 -132
  50. package/src/cli.ts +0 -56
  51. package/tsconfig.json +0 -25
@@ -1,327 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { Commit, DiffFile } from '../../models/git.models';
4
-
5
- @Component({
6
- selector: 'app-commit-detail',
7
- standalone: true,
8
- imports: [CommonModule],
9
- template: `
10
- <div class="modal-overlay" (click)="onClose()">
11
- <div class="modal-container" [class.dark]="isDarkMode" (click)="$event.stopPropagation()">
12
- <div class="modal-header">
13
- <h3 class="modal-title">Commit Details</h3>
14
- <button (click)="onClose()" class="close-button">
15
- <svg class="close-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
16
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
17
- </svg>
18
- </button>
19
- </div>
20
-
21
- <div class="modal-content" *ngIf="commit">
22
- <div class="commit-details">
23
- <div class="commit-header">
24
- <div class="commit-meta">
25
- <span class="commit-hash">{{ commit.hash }}</span>
26
- <span class="commit-author">by {{ commit.author }}</span>
27
- <span class="commit-date">{{ formatDate(commit.date) }}</span>
28
- </div>
29
- <h3 class="commit-message">{{ commit.message }}</h3>
30
- </div>
31
-
32
- <div class="commit-sections">
33
- <div class="section">
34
- <h4 class="section-title">Files Changed</h4>
35
- <div class="file-list">
36
- <div *ngFor="let diffFile of diffFiles" class="file-item">
37
- <span class="file-name">{{ diffFile.file }}</span>
38
- <button class="btn btn-primary" (click)="onFileClick(diffFile.file)">
39
- View Diff
40
- </button>
41
- </div>
42
- </div>
43
- </div>
44
-
45
- <div class="section" *ngIf="diffFiles.length > 0">
46
- <h4 class="section-title">Diff Summary</h4>
47
- <div class="diff-summary">
48
- <div *ngFor="let file of diffFiles" class="diff-item">
49
- <div class="diff-file-name">{{ file.file }}</div>
50
- <div class="diff-stats">
51
- +{{ file.additions }} -{{ file.deletions }}
52
- </div>
53
- </div>
54
- </div>
55
- </div>
56
- </div>
57
- </div>
58
- </div>
59
- </div>
60
- </div>
61
- `,
62
- styles: [`
63
- .modal-overlay {
64
- position: fixed;
65
- inset: 0;
66
- background-color: rgba(0, 0, 0, 0.5);
67
- z-index: 50;
68
- display: flex;
69
- align-items: center;
70
- justify-content: center;
71
- min-height: 100vh;
72
- padding: 1rem;
73
- }
74
-
75
- .modal-container {
76
- background-color: white;
77
- border-radius: 0.5rem;
78
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
79
- max-width: 64rem;
80
- width: 100%;
81
- max-height: 100vh;
82
- overflow-y: auto;
83
- transition: background-color 0.2s ease, color 0.2s ease;
84
- }
85
-
86
- .modal-header {
87
- display: flex;
88
- justify-content: space-between;
89
- align-items: center;
90
- padding: 1.5rem;
91
- border-bottom: 1px solid #e5e7eb;
92
- transition: border-bottom-color 0.2s ease;
93
- }
94
-
95
- .modal-title {
96
- font-size: 1.125rem;
97
- font-weight: 600;
98
- color: #111827;
99
- transition: color 0.2s ease;
100
- }
101
-
102
- /* Force dark mode styles with higher specificity */
103
- .modal-container.dark .modal-title,
104
- .dark .modal-container .modal-title,
105
- .dark .modal-title,
106
- .dark .modal-header .modal-title,
107
- .modal-container.dark .modal-header .modal-title {
108
- color: #e0e0e0 !important;
109
- }
110
-
111
- .close-button {
112
- color: #6b7280;
113
- background: none;
114
- border: none;
115
- cursor: pointer;
116
- padding: 0.5rem;
117
- }
118
-
119
- .close-button:hover {
120
- color: #374151;
121
- }
122
-
123
- .close-icon {
124
- width: 1.5rem;
125
- height: 1.5rem;
126
- }
127
-
128
- .modal-content {
129
- padding: 1.5rem;
130
- }
131
-
132
- .commit-header {
133
- border-bottom: 1px solid #e5e7eb;
134
- padding-bottom: 1rem;
135
- margin-bottom: 1rem;
136
- transition: border-bottom-color 0.2s ease;
137
- }
138
-
139
- .commit-meta {
140
- display: flex;
141
- align-items: center;
142
- gap: 0.5rem;
143
- margin-bottom: 0.5rem;
144
- }
145
-
146
- .commit-hash {
147
- font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
148
- font-size: 0.875rem;
149
- color: #6b7280;
150
- transition: color 0.2s ease;
151
- }
152
-
153
- .commit-author {
154
- font-size: 0.875rem;
155
- color: #374151;
156
- transition: color 0.2s ease;
157
- }
158
-
159
- .commit-date {
160
- font-size: 0.875rem;
161
- color: #6b7280;
162
- transition: color 0.2s ease;
163
- }
164
-
165
- .commit-message {
166
- font-size: 1.25rem;
167
- font-weight: 600;
168
- color: #111827;
169
- transition: color 0.2s ease;
170
- }
171
-
172
- .commit-sections {
173
- display: grid;
174
- grid-template-columns: 1fr 1fr;
175
- gap: 1.5rem;
176
- }
177
-
178
- .section-title {
179
- font-size: 1.125rem;
180
- font-weight: 500;
181
- color: #111827;
182
- margin-bottom: 0.75rem;
183
- transition: color 0.2s ease;
184
- }
185
-
186
- .file-list, .diff-summary {
187
- display: flex;
188
- flex-direction: column;
189
- gap: 0.5rem;
190
- }
191
-
192
- .file-item, .diff-item {
193
- display: flex;
194
- justify-content: space-between;
195
- align-items: center;
196
- padding: 0.5rem;
197
- background-color: #f9fafb;
198
- border-radius: 0.25rem;
199
- transition: background-color 0.2s ease;
200
- }
201
-
202
- .file-name, .diff-file-name {
203
- font-size: 0.875rem;
204
- color: #374151;
205
- transition: color 0.2s ease;
206
- }
207
-
208
- .diff-stats {
209
- font-size: 0.75rem;
210
- color: #6b7280;
211
- transition: color 0.2s ease;
212
- }
213
-
214
- /* Dark mode styles */
215
- .dark .modal-container {
216
- background-color: #2d2d2d !important;
217
- color: #e0e0e0 !important;
218
- }
219
-
220
- .dark .modal-header {
221
- border-color: #404040 !important;
222
- }
223
-
224
- .dark .modal-title {
225
- color: #e0e0e0 !important;
226
- }
227
-
228
- .dark .close-button {
229
- color: #9ca3af !important;
230
- }
231
-
232
- .dark .close-button:hover {
233
- color: #d1d5db !important;
234
- }
235
-
236
- .dark .commit-header {
237
- border-color: #404040 !important;
238
- }
239
-
240
- .dark .commit-hash {
241
- color: #9ca3af !important;
242
- }
243
-
244
- .dark .commit-author {
245
- color: #d1d5db !important;
246
- }
247
-
248
- .dark .commit-date {
249
- color: #9ca3af !important;
250
- }
251
-
252
- .dark .commit-message {
253
- color: #e0e0e0 !important;
254
- }
255
-
256
- .dark .section-title {
257
- color: #e0e0e0 !important;
258
- }
259
-
260
- .dark .file-item,
261
- .dark .diff-item {
262
- background-color: #404040 !important;
263
- }
264
-
265
- .dark .file-name,
266
- .dark .diff-file-name {
267
- color: #d1d5db !important;
268
- }
269
-
270
- .dark .diff-stats {
271
- color: #9ca3af !important;
272
- }
273
-
274
- @media (max-width: 768px) {
275
- .commit-sections {
276
- grid-template-columns: 1fr;
277
- }
278
- }
279
- `]
280
- })
281
- export class CommitDetailComponent implements OnInit {
282
- @Input() commit: Commit | null = null;
283
- @Input() diffFiles: DiffFile[] = [];
284
- @Output() close = new EventEmitter<void>();
285
- @Output() fileClick = new EventEmitter<string>();
286
-
287
- isDarkMode = false;
288
-
289
- ngOnInit() {
290
- this.checkDarkMode();
291
- this.setupDarkModeObserver();
292
- }
293
-
294
- private checkDarkMode() {
295
- this.isDarkMode = document.documentElement.classList.contains('dark');
296
- }
297
-
298
- private setupDarkModeObserver() {
299
- // Observe changes to the document element's class list
300
- const observer = new MutationObserver((mutations) => {
301
- mutations.forEach((mutation) => {
302
- if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
303
- this.checkDarkMode();
304
- }
305
- });
306
- });
307
-
308
- // Start observing the document element for class changes
309
- observer.observe(document.documentElement, {
310
- attributes: true,
311
- attributeFilter: ['class']
312
- });
313
- }
314
-
315
- onClose() {
316
- this.close.emit();
317
- }
318
-
319
- onFileClick(file: string) {
320
- this.fileClick.emit(file);
321
- }
322
-
323
- formatDate(dateString: string): string {
324
- const date = new Date(dateString);
325
- return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
326
- }
327
- }
@@ -1,294 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, ElementRef, ViewChild, AfterViewInit, OnChanges, SimpleChanges, OnDestroy } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import * as d3 from 'd3';
4
- import { Commit, CommitNode } from '../../models/git.models';
5
- import { ColorPalette } from '../../models/color-palette.models';
6
-
7
- @Component({
8
- selector: 'app-commit-graph',
9
- standalone: true,
10
- imports: [CommonModule],
11
- template: `
12
- <div class="graph-container">
13
- <svg #commitGraph width="100%" height="600"></svg>
14
- </div>
15
- `,
16
- styles: [`
17
- .graph-container {
18
- background-color: white;
19
- border-radius: 0.5rem;
20
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
21
- padding: 1.5rem;
22
- transition: background-color 0.2s ease;
23
- }
24
-
25
- /* Dark mode styles */
26
- .dark .graph-container {
27
- background-color: #2d2d2d;
28
- }
29
-
30
- /* SVG dark mode support */
31
- .dark svg {
32
- background-color: transparent;
33
- }
34
- `]
35
- })
36
- export class CommitGraphComponent implements AfterViewInit, OnChanges, OnDestroy {
37
- @ViewChild('commitGraph', { static: true }) svgElement!: ElementRef;
38
- @Input() commits: Commit[] = [];
39
- @Input() colorPalette?: ColorPalette;
40
- @Output() commitClick = new EventEmitter<Commit>();
41
-
42
- private svg: any;
43
- private g: any;
44
- private observer: MutationObserver | null = null;
45
-
46
- ngAfterViewInit() {
47
- this.initializeGraph();
48
- this.setupDarkModeObserver();
49
- }
50
-
51
- ngOnChanges(changes: SimpleChanges) {
52
- if (changes['commits'] && this.svg) {
53
- this.renderGraph();
54
- }
55
- }
56
-
57
- ngOnDestroy() {
58
- if (this.observer) {
59
- this.observer.disconnect();
60
- }
61
- }
62
-
63
- private initializeGraph() {
64
- this.svg = d3.select(this.svgElement.nativeElement);
65
- this.g = this.svg.append('g');
66
- this.renderGraph();
67
- }
68
-
69
- private renderGraph() {
70
- if (!this.commits.length) return;
71
-
72
- this.g.selectAll('*').remove();
73
-
74
- const width = this.svgElement.nativeElement.getBoundingClientRect().width;
75
- const height = 600;
76
- const margin = { top: 20, right: 20, bottom: 20, left: 20 };
77
-
78
- // Get colors based on dark mode
79
- const colors = this.getGraphColors();
80
-
81
- // Create a more realistic git graph structure
82
- const { nodes, links, branches } = this.createGitGraphStructure();
83
-
84
- // Create force simulation for better layout
85
- const simulation = d3.forceSimulation(nodes)
86
- .force('link', d3.forceLink(links).id((d: any) => d.id).distance(100))
87
- .force('charge', d3.forceManyBody().strength(-300))
88
- .force('center', d3.forceCenter(width / 2, height / 2))
89
- .force('collision', d3.forceCollide().radius(30));
90
-
91
- // Create branch lines (different colors for different branches)
92
- const branchGroups = this.g.selectAll('.branch-group')
93
- .data(branches)
94
- .enter().append('g')
95
- .attr('class', 'branch-group');
96
-
97
- branchGroups.selectAll('.branch-line')
98
- .data((d: any) => d.links)
99
- .enter().append('line')
100
- .attr('class', 'branch-line')
101
- .attr('stroke', (d: any, i: number) => this.getBranchColor(d.branch, colors))
102
- .attr('stroke-width', 3)
103
- .attr('opacity', 0.7);
104
-
105
- // Create links between commits
106
- this.g.selectAll('.link')
107
- .data(links)
108
- .enter().append('line')
109
- .attr('class', 'link')
110
- .attr('stroke', colors.link)
111
- .attr('stroke-width', 2)
112
- .attr('opacity', 0.5);
113
-
114
- // Create commit nodes
115
- const node = this.g.selectAll('.commit-node')
116
- .data(nodes)
117
- .enter().append('g')
118
- .attr('class', 'commit-node')
119
- .style('cursor', 'pointer');
120
-
121
- // Add circles for nodes
122
- node.append('circle')
123
- .attr('r', 10)
124
- .attr('fill', (d: any) => this.getNodeColor(d, colors))
125
- .attr('stroke', colors.nodeStroke)
126
- .attr('stroke-width', 2);
127
-
128
- // Add commit hash text
129
- node.append('text')
130
- .attr('text-anchor', 'middle')
131
- .attr('dy', 25)
132
- .attr('fill', colors.text)
133
- .attr('class', 'text-xs')
134
- .text((d: any) => d.commit.hash.substring(0, 6));
135
-
136
- // Add commit message on hover
137
- node.append('title')
138
- .text((d: any) => `${d.commit.message}\n${d.commit.author}\n${this.formatDate(d.commit.date)}`);
139
-
140
- // Add click handlers
141
- node.on('click', (event: any, d: any) => {
142
- this.commitClick.emit(d.commit);
143
- });
144
-
145
- // Update positions on simulation tick
146
- simulation.on('tick', () => {
147
- // Update branch lines
148
- branchGroups.selectAll('.branch-line')
149
- .attr('x1', (d: any) => d.source.x)
150
- .attr('y1', (d: any) => d.source.y)
151
- .attr('x2', (d: any) => d.target.x)
152
- .attr('y2', (d: any) => d.target.y);
153
-
154
- // Update links
155
- this.g.selectAll('.link')
156
- .attr('x1', (d: any) => d.source.x)
157
- .attr('y1', (d: any) => d.source.y)
158
- .attr('x2', (d: any) => d.target.x)
159
- .attr('y2', (d: any) => d.target.y);
160
-
161
- // Update nodes
162
- node.attr('transform', (d: any) => `translate(${d.x},${d.y})`);
163
- });
164
- }
165
-
166
- private getGraphColors() {
167
- const isDarkMode = document.documentElement.classList.contains('dark');
168
- console.log('Graph colors - Dark mode:', isDarkMode);
169
-
170
- if (this.colorPalette) {
171
- return {
172
- link: this.colorPalette.colors.link,
173
- nodeFill: this.colorPalette.colors.nodeFill,
174
- nodeStroke: this.colorPalette.colors.nodeStroke,
175
- text: this.colorPalette.colors.graphText
176
- };
177
- }
178
-
179
- // Fallback to default colors
180
- if (isDarkMode) {
181
- return {
182
- link: '#4b5563', // gray-600 for dark mode
183
- nodeFill: '#3b82f6', // blue-500 (same for both modes)
184
- nodeStroke: '#1e40af', // blue-700 (same for both modes)
185
- text: '#9ca3af' // gray-400 for dark mode
186
- };
187
- } else {
188
- return {
189
- link: '#cbd5e0', // gray-300 for light mode
190
- nodeFill: '#3b82f6', // blue-500 (same for both modes)
191
- nodeStroke: '#1e40af', // blue-700 (same for both modes)
192
- text: '#6b7280' // gray-500 for light mode
193
- };
194
- }
195
- }
196
-
197
- private setupDarkModeObserver() {
198
- // Observe changes to the document element's class list
199
- this.observer = new MutationObserver((mutations) => {
200
- mutations.forEach((mutation) => {
201
- if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
202
- // Re-render graph when dark mode changes
203
- if (this.svg) {
204
- this.renderGraph();
205
- }
206
- }
207
- });
208
- });
209
-
210
- // Start observing the document element for class changes
211
- this.observer.observe(document.documentElement, {
212
- attributes: true,
213
- attributeFilter: ['class']
214
- });
215
- }
216
-
217
- private createGitGraphStructure() {
218
- const nodes = this.commits.map((commit, i) => ({
219
- id: commit.hash,
220
- commit: commit,
221
- branch: commit.branches[0] || 'main',
222
- index: i,
223
- isMerge: commit.parents && commit.parents.length > 1,
224
- isBranch: commit.branches.length > 0
225
- }));
226
-
227
- const links = [];
228
- const branches: any[] = [];
229
- const branchColors = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4'];
230
-
231
- // Create links between commits
232
- for (let i = 1; i < nodes.length; i++) {
233
- const current = nodes[i];
234
- const previous = nodes[i - 1];
235
-
236
- links.push({
237
- source: previous.id,
238
- target: current.id,
239
- branch: current.branch
240
- });
241
- }
242
-
243
- // Group commits by branch
244
- const branchGroups = new Map();
245
- nodes.forEach(node => {
246
- const branch = node.branch;
247
- if (!branchGroups.has(branch)) {
248
- branchGroups.set(branch, []);
249
- }
250
- branchGroups.get(branch).push(node);
251
- });
252
-
253
- // Create branch structures
254
- branchGroups.forEach((branchNodes, branchName) => {
255
- const branchLinks = [];
256
- for (let i = 1; i < branchNodes.length; i++) {
257
- branchLinks.push({
258
- source: branchNodes[i - 1],
259
- target: branchNodes[i],
260
- branch: branchName
261
- });
262
- }
263
-
264
- branches.push({
265
- name: branchName,
266
- links: branchLinks,
267
- color: branchColors[branches.length % branchColors.length]
268
- });
269
- });
270
-
271
- return { nodes, links, branches };
272
- }
273
-
274
- private getBranchColor(branchName: string, colors: any): string {
275
- const branchColors = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4'];
276
- const branchIndex = branchName.charCodeAt(0) % branchColors.length;
277
- return branchColors[branchIndex];
278
- }
279
-
280
- private getNodeColor(node: any, colors: any): string {
281
- if (node.isMerge) {
282
- return '#8b5cf6'; // Purple for merge commits
283
- } else if (node.isBranch) {
284
- return '#10b981'; // Green for branch commits
285
- } else {
286
- return colors.nodeFill;
287
- }
288
- }
289
-
290
- private formatDate(dateString: string): string {
291
- const date = new Date(dateString);
292
- return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
293
- }
294
- }