Skip to content

Commit 6b57374

Browse files
committed
Add chart visualizations for coding summaries in summary view
- Integrated Chart.js for rendering project and daily coding time summaries. - Added new CSS styles for chart containers and titles. - Replaced previous table displays with bar and line charts for better data visualization. - Implemented pie chart for search results coding time distribution.
1 parent 03ed62b commit 6b57374

1 file changed

Lines changed: 206 additions & 26 deletions

File tree

src/summaryView.ts

Lines changed: 206 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,16 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
124124
<meta charset="UTF-8">
125125
<meta name="viewport" content="width=device-width, initial-scale=1.0">
126126
<title>Coding Time Summary</title>
127+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
127128
<style>
128129
:root {
129130
--background-color: var(--vscode-editor-background);
130131
--text-color: var(--vscode-editor-foreground);
131132
--border-color: var(--vscode-panel-border);
132133
--header-background: var(--vscode-titleBar-activeBackground);
133134
--header-foreground: var(--vscode-titleBar-activeForeground);
135+
--chart-grid-color: var(--vscode-panel-border);
136+
--chart-text-color: var(--vscode-editor-foreground);
134137
}
135138
body {
136139
font-family: var(--vscode-font-family);
@@ -332,6 +335,27 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
332335
font-size: 11px;
333336
color: var(--vscode-foreground);
334337
}
338+
.chart-container {
339+
background: var(--vscode-editor-background);
340+
border: 1px solid var(--vscode-panel-border);
341+
border-radius: 6px;
342+
padding: 20px;
343+
margin-bottom: 30px;
344+
}
345+
.chart-title {
346+
font-size: 16px;
347+
font-weight: 500;
348+
color: var(--vscode-foreground);
349+
margin-bottom: 15px;
350+
}
351+
.chart-wrapper {
352+
position: relative;
353+
height: 300px;
354+
width: 100%;
355+
}
356+
.search-results-chart {
357+
height: 400px;
358+
}
335359
</style>
336360
</head>
337361
<body>
@@ -381,7 +405,26 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
381405
</select>
382406
<button id="search-button">Search</button>
383407
</div>
384-
<div id="content">Loading...</div>
408+
<div id="content">
409+
<div class="chart-container">
410+
<div class="chart-title">Project Summary</div>
411+
<div class="chart-wrapper">
412+
<canvas id="projectChart"></canvas>
413+
</div>
414+
</div>
415+
<div class="chart-container">
416+
<div class="chart-title">Daily Summary (Last 7 Days)</div>
417+
<div class="chart-wrapper">
418+
<canvas id="dailyChart"></canvas>
419+
</div>
420+
</div>
421+
<div class="chart-container search-results-chart" style="display: none;">
422+
<div class="chart-title">Search Results</div>
423+
<div class="chart-wrapper">
424+
<canvas id="searchChart"></canvas>
425+
</div>
426+
</div>
427+
</div>
385428
</div>
386429
<script>
387430
const vscode = acquireVsCodeApi();
@@ -438,25 +481,121 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
438481
function updateContent(data) {
439482
const content = document.getElementById('content');
440483
content.innerHTML = \`
441-
<h2>Project Summary</h2>
442-
<table>
443-
<tr><th>Project</th><th>Coding Time</th></tr>
444-
\${Object.entries(data.projectSummary)
445-
.map(([project, time]) => \`<tr><td>\${project}</td><td>\${formatTime(time)}</td></tr>\`)
446-
.join('')}
447-
</table>
448-
449-
<h2>Daily Summary (Last 7 Days)</h2>
450-
<table>
451-
<tr><th>Date</th><th>Coding Time</th></tr>
452-
\${Object.entries(data.dailySummary)
453-
.sort((a, b) => b[0].localeCompare(a[0]))
454-
.slice(0, 7)
455-
.map(([date, time]) => \`<tr><td>\${date}</td><td>\${formatTime(time)}</td></tr>\`)
456-
.join('')}
457-
</table>
484+
<div class="chart-container">
485+
<div class="chart-title">Project Summary</div>
486+
<div class="chart-wrapper">
487+
<canvas id="projectChart"></canvas>
488+
</div>
489+
</div>
490+
<div class="chart-container">
491+
<div class="chart-title">Daily Summary (Last 7 Days)</div>
492+
<div class="chart-wrapper">
493+
<canvas id="dailyChart"></canvas>
494+
</div>
495+
</div>
458496
\`;
459497
498+
// Create project summary chart
499+
const projectCtx = document.getElementById('projectChart').getContext('2d');
500+
const projectData = Object.entries(data.projectSummary)
501+
.sort((a, b) => b[1] - a[1])
502+
.slice(0, 5); // Show top 5 projects
503+
504+
new Chart(projectCtx, {
505+
type: 'bar',
506+
data: {
507+
labels: projectData.map(([project]) => project),
508+
datasets: [{
509+
label: 'Coding Time (hours)',
510+
data: projectData.map(([_, time]) => time / 60),
511+
backgroundColor: 'rgba(74, 114, 176, 0.7)',
512+
borderColor: 'rgba(74, 114, 176, 1)',
513+
borderWidth: 1
514+
}]
515+
},
516+
options: {
517+
responsive: true,
518+
maintainAspectRatio: false,
519+
scales: {
520+
y: {
521+
beginAtZero: true,
522+
grid: {
523+
color: 'var(--chart-grid-color)'
524+
},
525+
ticks: {
526+
color: 'var(--chart-text-color)'
527+
}
528+
},
529+
x: {
530+
grid: {
531+
color: 'var(--chart-grid-color)'
532+
},
533+
ticks: {
534+
color: 'var(--chart-text-color)'
535+
}
536+
}
537+
},
538+
plugins: {
539+
legend: {
540+
labels: {
541+
color: 'var(--chart-text-color)'
542+
}
543+
}
544+
}
545+
}
546+
});
547+
548+
// Create daily summary chart
549+
const dailyCtx = document.getElementById('dailyChart').getContext('2d');
550+
const dailyData = Object.entries(data.dailySummary)
551+
.sort((a, b) => b[0].localeCompare(a[0]))
552+
.slice(0, 7);
553+
554+
new Chart(dailyCtx, {
555+
type: 'line',
556+
data: {
557+
labels: dailyData.map(([date]) => date),
558+
datasets: [{
559+
label: 'Coding Time (hours)',
560+
data: dailyData.map(([_, time]) => time / 60),
561+
fill: true,
562+
backgroundColor: 'rgba(74, 114, 176, 0.2)',
563+
borderColor: 'rgba(74, 114, 176, 1)',
564+
tension: 0.4
565+
}]
566+
},
567+
options: {
568+
responsive: true,
569+
maintainAspectRatio: false,
570+
scales: {
571+
y: {
572+
beginAtZero: true,
573+
grid: {
574+
color: 'var(--chart-grid-color)'
575+
},
576+
ticks: {
577+
color: 'var(--chart-text-color)'
578+
}
579+
},
580+
x: {
581+
grid: {
582+
color: 'var(--chart-grid-color)'
583+
},
584+
ticks: {
585+
color: 'var(--chart-text-color)'
586+
}
587+
}
588+
},
589+
plugins: {
590+
legend: {
591+
labels: {
592+
color: 'var(--chart-text-color)'
593+
}
594+
}
595+
}
596+
}
597+
});
598+
460599
// Add heatmap creation
461600
createHeatmap(data);
462601
}
@@ -469,18 +608,59 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
469608
}
470609
471610
let totalTime = 0;
472-
const tableRows = entries.map(entry => {
611+
const searchData = entries.reduce((acc, entry) => {
473612
totalTime += entry.timeSpent;
474-
return \`<tr><td>\${entry.date}</td><td>\${entry.project}</td><td>\${formatTime(entry.timeSpent)}</td></tr>\`;
475-
}).join('');
613+
if (!acc[entry.project]) {
614+
acc[entry.project] = 0;
615+
}
616+
acc[entry.project] += entry.timeSpent;
617+
return acc;
618+
}, {});
476619
477620
content.innerHTML = \`
478-
<h2>Search Results: (Coding Time is \${formatTime(totalTime)})</h2>
479-
<table>
480-
<tr><th>Date</th><th>Project</th><th>Coding Time</th></tr>
481-
\${tableRows}
482-
</table>
621+
<div class="chart-container search-results-chart">
622+
<div class="chart-title">Search Results (Total Time: \${formatTime(totalTime)})</div>
623+
<div class="chart-wrapper">
624+
<canvas id="searchChart"></canvas>
625+
</div>
626+
</div>
483627
\`;
628+
629+
// Create search results chart
630+
const searchCtx = document.getElementById('searchChart').getContext('2d');
631+
const searchChartData = Object.entries(searchData)
632+
.sort((a, b) => b[1] - a[1]);
633+
634+
new Chart(searchCtx, {
635+
type: 'pie',
636+
data: {
637+
labels: searchChartData.map(([project]) => project),
638+
datasets: [{
639+
data: searchChartData.map(([_, time]) => time / 60),
640+
backgroundColor: [
641+
'rgba(74, 114, 176, 0.7)',
642+
'rgba(56, 97, 165, 0.7)',
643+
'rgba(37, 75, 145, 0.7)',
644+
'rgba(26, 59, 124, 0.7)',
645+
'rgba(15, 43, 103, 0.7)'
646+
],
647+
borderColor: 'var(--vscode-editor-background)',
648+
borderWidth: 1
649+
}]
650+
},
651+
options: {
652+
responsive: true,
653+
maintainAspectRatio: false,
654+
plugins: {
655+
legend: {
656+
position: 'right',
657+
labels: {
658+
color: 'var(--chart-text-color)'
659+
}
660+
}
661+
}
662+
}
663+
});
484664
}
485665
486666
function formatTime(minutes) {

0 commit comments

Comments
 (0)