Skip to content

Commit bf668c3

Browse files
authored
Merge pull request #13 from twentyTwo/develop
Enhance Summary View
2 parents a901895 + a07ee76 commit bf668c3

2 files changed

Lines changed: 218 additions & 27 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "simple-coding-time-tracker",
33
"displayName": "Simple Coding Time Tracker",
44
"description": "Track and visualize your coding time across projects",
5-
"version": "0.3.1",
5+
"version": "0.3.2",
66
"publisher": "noorashuvo",
77
"license": "MIT",
88
"icon": "icon-sctt.png",

src/summaryView.ts

Lines changed: 217 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -597,10 +597,16 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
597597
</div>
598598
</div>
599599
<div class="chart-container">
600-
<div class="chart-title">Daily Summary (Last 7 Days)</div>
600+
<div class="chart-title">Daily Summary (Last 30 Days)</div>
601601
<div class="chart-wrapper">
602602
<canvas id="dailyChart"></canvas>
603603
</div>
604+
<div class="chart-container search-results-chart">
605+
<div class="chart-title">Project Distribution</div>
606+
<div class="chart-wrapper">
607+
<canvas id="searchChart"></canvas>
608+
</div>
609+
</div>
604610
</div>
605611
\`;
606612
@@ -644,11 +650,11 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
644650
}
645651
});
646652
647-
// Daily summary chart
653+
// Daily summary chart - showing last 30 days
648654
const dailyCtx = document.getElementById('dailyChart').getContext('2d');
649655
const dailyData = Object.entries(data.dailySummary)
650656
.sort((a, b) => new Date(a[0]).getTime() - new Date(b[0]).getTime())
651-
.slice(-7);
657+
.slice(-30); // Show last 30 days instead of 7
652658
653659
new Chart(dailyCtx, {
654660
type: 'line',
@@ -702,6 +708,71 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
702708
}
703709
}
704710
});
711+
712+
// Initialize the search chart with all data
713+
const searchCtx = document.getElementById('searchChart').getContext('2d');
714+
const allProjectData = Object.entries(data.projectSummary)
715+
.sort((a, b) => b[1] - a[1]);
716+
717+
new Chart(searchCtx, {
718+
type: 'pie',
719+
data: {
720+
labels: allProjectData.map(([project]) => project),
721+
datasets: [{
722+
data: allProjectData.map(([_, minutes]) => ({
723+
value: minutes,
724+
hours: Math.floor(minutes / 60),
725+
mins: Math.round(minutes % 60)
726+
})),
727+
backgroundColor: [
728+
'rgba(255, 99, 132, 0.7)', // Red
729+
'rgba(54, 162, 235, 0.7)', // Blue
730+
'rgba(255, 206, 86, 0.7)', // Yellow
731+
'rgba(75, 192, 192, 0.7)', // Teal
732+
'rgba(153, 102, 255, 0.7)', // Purple
733+
'rgba(255, 159, 64, 0.7)', // Orange
734+
'rgba(199, 199, 199, 0.7)', // Gray
735+
'rgba(83, 102, 255, 0.7)', // Indigo
736+
'rgba(40, 167, 69, 0.7)', // Green
737+
'rgba(220, 53, 69, 0.7)' // Dark Red
738+
],
739+
borderColor: chartColors.background,
740+
borderWidth: 1
741+
}]
742+
},
743+
options: {
744+
responsive: true,
745+
maintainAspectRatio: false,
746+
plugins: {
747+
legend: {
748+
position: 'right',
749+
labels: {
750+
color: chartColors.text,
751+
font: {
752+
size: 12,
753+
weight: '500'
754+
},
755+
padding: 20,
756+
usePointStyle: true
757+
}
758+
},
759+
tooltip: {
760+
backgroundColor: isDarkTheme ? 'rgba(0, 0, 0, 0.8)' : 'rgba(255, 255, 255, 0.8)',
761+
titleColor: chartColors.text,
762+
bodyColor: chartColors.text,
763+
borderColor: chartColors.grid,
764+
borderWidth: 1,
765+
padding: 12,
766+
callbacks: {
767+
label: function(context) {
768+
const data = context.raw;
769+
return \`\${context.label}: \${data.hours} hour\${data.hours !== 1 ? 's' : ''} and \${data.mins} minute\${data.mins !== 1 ? 's' : ''}\`;
770+
}
771+
}
772+
}
773+
}
774+
}
775+
});
705776
}
706777
707778
function displaySearchResult(entries) {
@@ -710,31 +781,151 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
710781
content.innerHTML = '<p>No results found.</p>';
711782
return;
712783
}
713-
784+
785+
// Calculate data for all charts
714786
let totalTime = 0;
715-
const searchData = entries.reduce((acc, entry) => {
787+
const projectData = {};
788+
const dailyData = {};
789+
790+
// Process entries for both project and daily summaries
791+
entries.forEach(entry => {
716792
totalTime += entry.timeSpent;
717-
if (!acc[entry.project]) {
718-
acc[entry.project] = 0;
793+
794+
// Update project data
795+
if (!projectData[entry.project]) {
796+
projectData[entry.project] = 0;
719797
}
720-
acc[entry.project] += entry.timeSpent;
721-
return acc;
722-
}, {});
723-
798+
projectData[entry.project] += entry.timeSpent;
799+
800+
// Update daily data
801+
if (!dailyData[entry.date]) {
802+
dailyData[entry.date] = 0;
803+
}
804+
dailyData[entry.date] += entry.timeSpent;
805+
});
806+
807+
// Update the content with all three charts
724808
content.innerHTML = \`
725-
<div class="chart-container search-results-chart">
726-
<div class="chart-title">Search Results (Total Time: \${formatTime(totalTime)})</div>
809+
<div class="chart-container">
810+
<div class="chart-title">Project Summary (Filtered)</div>
811+
<div class="chart-wrapper">
812+
<canvas id="projectChart"></canvas>
813+
</div>
814+
</div>
815+
<div class="chart-container">
816+
<div class="chart-title">Daily Summary (Filtered)</div>
817+
<div class="chart-wrapper">
818+
<canvas id="dailyChart"></canvas>
819+
</div>
820+
</div>
821+
<div class="chart-container">
822+
<div class="chart-title">Project Distribution (Total Time: \${formatTime(totalTime)})</div>
727823
<div class="chart-wrapper">
728824
<canvas id="searchChart"></canvas>
729825
</div>
730826
</div>
731827
\`;
732-
733-
// Create search results chart
828+
829+
// Create Project Summary Bar Chart
830+
const projectCtx = document.getElementById('projectChart').getContext('2d');
831+
const projectChartData = Object.entries(projectData)
832+
.sort((a, b) => b[1] - a[1])
833+
.slice(0, 5);
834+
835+
new Chart(projectCtx, {
836+
type: 'bar',
837+
data: {
838+
labels: projectChartData.map(([project]) => project),
839+
datasets: [{
840+
label: 'Coding Time',
841+
data: projectChartData.map(([_, time]) => time/60),
842+
backgroundColor: chartColors.chartBlues,
843+
borderColor: chartColors.grid,
844+
borderWidth: 1
845+
}]
846+
},
847+
options: {
848+
...commonChartConfig,
849+
indexAxis: 'y',
850+
plugins: {
851+
...commonChartConfig.plugins,
852+
tooltip: {
853+
...commonChartConfig.plugins.tooltip,
854+
callbacks: {
855+
label: function(context) {
856+
const hours = Math.floor(context.raw);
857+
const mins = Math.round((context.raw % 1) * 60);
858+
return \`\${context.label}: \${hours} hour\${hours !== 1 ? 's' : ''} and \${mins} minute\${mins !== 1 ? 's' : ''}\`;
859+
}
860+
}
861+
}
862+
}
863+
}
864+
});
865+
866+
// Create Daily Summary Line Chart
867+
const dailyCtx = document.getElementById('dailyChart').getContext('2d');
868+
const dailyChartData = Object.entries(dailyData)
869+
.sort((a, b) => new Date(a[0]).getTime() - new Date(b[0]).getTime());
870+
871+
new Chart(dailyCtx, {
872+
type: 'line',
873+
data: {
874+
labels: dailyChartData.map(([date]) => {
875+
const d = new Date(date);
876+
return d.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });
877+
}),
878+
datasets: [{
879+
label: 'Coding Time',
880+
data: dailyChartData.map(([_, time]) => time / 60),
881+
fill: true,
882+
backgroundColor: \`\${chartColors.accent}33\`,
883+
borderColor: chartColors.accent,
884+
borderWidth: 2,
885+
tension: 0.4,
886+
pointBackgroundColor: chartColors.accent,
887+
pointBorderColor: chartColors.background,
888+
pointBorderWidth: 2,
889+
pointRadius: 4,
890+
pointHoverRadius: 6
891+
}]
892+
},
893+
options: {
894+
...commonChartConfig,
895+
scales: {
896+
...commonChartConfig.scales,
897+
y: {
898+
...commonChartConfig.scales.y,
899+
ticks: {
900+
...commonChartConfig.scales.y.ticks,
901+
callback: function(value) {
902+
return \`\${value}h\`;
903+
}
904+
}
905+
}
906+
},
907+
plugins: {
908+
...commonChartConfig.plugins,
909+
tooltip: {
910+
...commonChartConfig.plugins.tooltip,
911+
callbacks: {
912+
label: function(context) {
913+
const hours = Math.floor(context.raw);
914+
const mins = Math.round((context.raw % 1) * 60);
915+
const date = new Date(context.label);
916+
return \`\${date.toLocaleDateString('en-US', { weekday: 'long' })}: \${hours} hour\${hours !== 1 ? 's' : ''} and \${mins} minute\${mins !== 1 ? 's' : ''}\`;
917+
}
918+
}
919+
}
920+
}
921+
}
922+
});
923+
924+
// Create Project Distribution Pie Chart
734925
const searchCtx = document.getElementById('searchChart').getContext('2d');
735-
const searchChartData = Object.entries(searchData)
926+
const searchChartData = Object.entries(projectData)
736927
.sort((a, b) => b[1] - a[1]);
737-
928+
738929
new Chart(searchCtx, {
739930
type: 'pie',
740931
data: {
@@ -747,15 +938,15 @@ export class SummaryViewProvider implements vscode.WebviewViewProvider {
747938
})),
748939
backgroundColor: [
749940
'rgba(255, 99, 132, 0.7)', // Red
750-
'rgba(54, 162, 235, 0.7)', // Blue
751-
'rgba(255, 206, 86, 0.7)', // Yellow
752-
'rgba(75, 192, 192, 0.7)', // Teal
753-
'rgba(153, 102, 255, 0.7)', // Purple
754-
'rgba(255, 159, 64, 0.7)', // Orange
755-
'rgba(199, 199, 199, 0.7)', // Gray
756-
'rgba(83, 102, 255, 0.7)', // Indigo
757-
'rgba(40, 167, 69, 0.7)', // Green
758-
'rgba(220, 53, 69, 0.7)' // Dark Red
941+
'rgba(54, 162, 235, 0.7)', // Blue
942+
'rgba(255, 206, 86, 0.7)', // Yellow
943+
'rgba(75, 192, 192, 0.7)', // Teal
944+
'rgba(153, 102, 255, 0.7)', // Purple
945+
'rgba(255, 159, 64, 0.7)', // Orange
946+
'rgba(199, 199, 199, 0.7)', // Gray
947+
'rgba(83, 102, 255, 0.7)', // Indigo
948+
'rgba(40, 167, 69, 0.7)', // Green
949+
'rgba(220, 53, 69, 0.7)' // Dark Red
759950
],
760951
borderColor: chartColors.background,
761952
borderWidth: 1

0 commit comments

Comments
 (0)