Skip to content

Commit bcafd63

Browse files
Merge pull request #5 from IowaComputerGurus/feature/storage-by-day
Add storage by day chart
2 parents d24a2b9 + c29bee6 commit bcafd63

File tree

7 files changed

+142
-54
lines changed

7 files changed

+142
-54
lines changed

.github/workflows/ci-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Ensure .NET Installed
2424
uses: actions/setup-dotnet@v1
2525
with:
26-
dotnet-version: 5.0.x
26+
dotnet-version: 6.0.x
2727

2828
- name: Install GitVersion
2929
run: dotnet tool install --global GitVersion.Tool

.github/workflows/release-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Ensure .NET Installed
2222
uses: actions/setup-dotnet@v1
2323
with:
24-
dotnet-version: 5.0.x
24+
dotnet-version: 6.0.x
2525

2626
- name: Install GitVersion
2727
run: dotnet tool install --global GitVersion.Tool

Source/GitHubCostVisualizer.Web/GitHubCostVisualizer.Web.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
4-
<TargetFramework>net5.0</TargetFramework>
4+
<TargetFramework>net6.0</TargetFramework>
55
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
66
</PropertyGroup>
77

Source/GitHubCostVisualizer.Web/Models/UsageReportViewModel.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,27 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Text.Json.Serialization;
34

45

56
namespace GitHubCostVisualizer.Web.Models
67
{
8+
public class DailyStorageData
9+
{
10+
[JsonPropertyName("labels")]
11+
public List<string> Labels { get; set; }
12+
[JsonPropertyName("datasets")]
13+
public List<DailyStorageDataSet> DataSets { get; set; }
14+
}
15+
16+
public class DailyStorageDataSet
17+
{
18+
[JsonPropertyName("label")]
19+
public string Label { get; set; }
20+
[JsonPropertyName("data")]
21+
public List<decimal> Data { get; set; }
22+
}
23+
24+
725
public class UsageReportViewModel
826
{
927
public DateTime StartDate { get; set; }
@@ -15,5 +33,6 @@ public class UsageReportViewModel
1533
public List<KeyValuePair<DateTime, decimal>> DailyStorageSummary { get; set; }
1634
public List<KeyValuePair<string, decimal>> AverageDailyStorageByRepo { get; set; }
1735

36+
public DailyStorageData DailyStorageByRepo { get; set; }
1837
}
1938
}

Source/GitHubCostVisualizer.Web/Processor/GithubUsageProcessor.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,50 @@ group x by x.Date
3636
into grp
3737
select new KeyValuePair<DateTime, decimal>(grp.Key, grp.Sum(i => i.Quantity)))
3838
.ToList();
39+
40+
model.DailyStorageByRepo = GenerateStorageByDays(entries);
41+
3942
if (model.DailyStorageSummary.Count > 0)
4043
{
4144
model.AverageDailyStorage =
4245
model.DailyStorageSummary.Sum(i => i.Value) / model.DailyStorageSummary.Count;
4346

4447
var totalDays = model.DailyStorageSummary.Count();
4548
model.AverageDailyStorageByRepo = (from x in entries.Where(i => i.Product == Constants.GitHubProducts.SharedStorage)
46-
group x by x.Repository
49+
group x by x.Repository
4750
into grp
48-
select new KeyValuePair<string, decimal>(grp.Key, grp.Sum(i => i.Quantity) / grp.Count())).ToList();
51+
select new KeyValuePair<string, decimal>(grp.Key, grp.Sum(i => i.Quantity) / grp.Count())).ToList();
4952
}
5053

5154
return model;
5255
}
56+
57+
private DailyStorageData GenerateStorageByDays(List<GithubUsageEntry> entries)
58+
{
59+
var storage = entries.Where(e => e.Product == Constants.GitHubProducts.SharedStorage).ToList();
60+
var startDate = storage.Min(r => r.Date);
61+
var endDate = storage.Max(r => r.Date);
62+
63+
var repos = storage.Select(r => r.Repository).Distinct().OrderBy(r => r);
64+
var dayList = Enumerable.Range(0, 1 + endDate.Subtract(startDate).Days).Select(o => startDate.AddDays(o)).ToList();
65+
66+
var q = from r in repos
67+
from d in dayList
68+
join s in storage on new { r, d } equals new { r = s.Repository, d = s.Date } into byDay
69+
from bd in byDay.DefaultIfEmpty()
70+
select new { Repo = r, Date = d, Quantity = bd?.Quantity ?? 0 };
71+
72+
var results = q.GroupBy(k => k.Repo)
73+
.OrderBy(g => g.Key)
74+
.Select(g => new DailyStorageDataSet { Label = g.Key, Data = g.OrderBy(r => r.Date).Select(r => r.Quantity).ToList() });
75+
//.Select(r=>new KeyValuePair<DateTime, decimal>(r.Date, r.Quantity)).ToArray());
76+
//results.Dump();
77+
78+
return new DailyStorageData
79+
{
80+
Labels = dayList.Select(d=>d.ToShortDateString()).ToList(),
81+
DataSets = results.ToList()
82+
};
83+
}
5384
}
5485
}

Source/GitHubCostVisualizer.Web/Views/Home/_StorageDetail.cshtml

Lines changed: 87 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
@model UsageReportViewModel
1+
@using System.Text.Json
2+
@model UsageReportViewModel
23

34

45
<div class="card">
@@ -25,6 +26,15 @@
2526
aria-selected="False">
2627
Chart
2728
</a>
29+
<a class="nav-item nav-link"
30+
id="nav-tab-storage-repository-daily-chart-tab"
31+
data-toggle="tab"
32+
href="#nav-tab-storage-repository-daily-chart"
33+
role="tab"
34+
aria-controls="nav-tab-storage-repository-chart"
35+
aria-selected="False">
36+
Chart By Day
37+
</a>
2838
</div>
2939
</nav>
3040
<div class="tab-content">
@@ -50,33 +60,86 @@
5060
<div class="tab-pane fade" id="nav-tab-storage-repository-chart" role="tabpanel" aria-labelledby="nav-tab-storage-repository-chart-tab">
5161
<canvas id="action-storage-by-repository-chart" width="300" height="250"></canvas>
5262
<script>
53-
var actionStorageChartContext = $('#action-storage-by-repository-chart');
54-
var actionStorageChart = new Chart(actionStorageChartContext,
55-
{
56-
type: 'pie',
57-
data: {
58-
datasets: [
59-
{
60-
data: [@Html.Raw(string.Join(", ", Model.AverageDailyStorageByRepo.Select(s => s.Value)))],
61-
backgroundColor: getColors(@Model.AverageDailyStorageByRepo.Count, 'primary', 'dark', 'secondary', 'light')
62-
}
63-
],
64-
labels: [@Html.Raw(String.Join(", ", Model.AverageDailyStorageByRepo.Select(m => $"'{m.Key}'")))]
63+
var actionStorageChartContext = $('#action-storage-by-repository-chart');
64+
var actionStorageChart = new Chart(actionStorageChartContext,
65+
{
66+
type: 'pie',
67+
data: {
68+
datasets: [
69+
{
70+
data: [@Html.Raw(string.Join(", ", Model.AverageDailyStorageByRepo.Select(s => s.Value)))],
71+
backgroundColor: getColors(@Model.AverageDailyStorageByRepo.Count, 'primary', 'dark', 'secondary', 'light')
72+
}
73+
],
74+
labels: [@Html.Raw(String.Join(", ", Model.AverageDailyStorageByRepo.Select(m => $"'{m.Key}'")))]
75+
},
76+
options: {
77+
tooltips: {
78+
enabled: true,
79+
callbacks: {
80+
label: function(tooltipItem, data) {
81+
var label = data.labels[tooltipItem.index];
82+
var val = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
83+
return label + ':' + val + ' (' + (100 * val / @Html.Raw(Model.AverageDailyStorageByRepo.Sum(d => d.Value))).toFixed(2) + '%)';
84+
}
85+
}
86+
87+
}
88+
}
89+
});
90+
</script>
91+
</div>
92+
<div class="tab-pane fade" id="nav-tab-storage-repository-daily-chart" role="tabpanel" aria-labelledby="nav-tab-storage-repository-daily-chart-tab">
93+
<canvas id="action-storage-by-repository-daily-chart" width="300" height="250"></canvas>
94+
<script>
95+
var allData = @Html.Raw(JsonSerializer.Serialize(Model.DailyStorageByRepo));
96+
var colors = getColors(allData.datasets.length, 'primary', 'dark', 'secondary', 'light');
97+
98+
var ds = allData.datasets.map(function(e, i) {
99+
return {
100+
fill: false,
101+
label: e.label,
102+
data: e.data,
103+
borderColor: colors[i]
104+
}
105+
});
106+
allData.datasets = ds;
107+
var actionStorageByDayChartContext = $('#action-storage-by-repository-daily-chart');
108+
var actionStorageByDayChart = new Chart(actionStorageByDayChartContext,
109+
{
110+
type: 'line',
111+
data: allData,
112+
113+
options: {
114+
scales: {
115+
x: {
116+
type: "time",
117+
display: true,
118+
time: { unit: "day" }
65119
},
66-
options: {
67-
tooltips: {
68-
enabled: true,
69-
callbacks: {
70-
label: function(tooltipItem, data) {
71-
var label = data.labels[tooltipItem.index];
72-
var val = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
73-
return label + ':' + val + ' (' + (100 * val / @Html.Raw(Model.AverageDailyStorageByRepo.Sum(d => d.Value))).toFixed(2) + '%)';
74-
}
120+
y: {
121+
title: { display: true, text: "Storage"},
122+
ticks: {
123+
callback: function(val, index) {
124+
console.log(val, index);
125+
return val + "GB";
75126
}
76-
77127
}
78128
}
79-
});
129+
},
130+
tooltips: {
131+
enabled: true,
132+
callbacks: {
133+
label: function(tooltipItem, data) {
134+
var label = data.datasets[tooltipItem.datasetIndex].label;
135+
var val = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
136+
return label + ':' + val + "GB";
137+
}
138+
}
139+
140+
}
141+
}
142+
});
80143
</script>
81144
</div>
82145
</div>

Source/Source.sln

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)