Skip to content

Commit 3957bc2

Browse files
committed
Variable date range for visitpagecount
1 parent e371fa8 commit 3957bc2

File tree

6 files changed

+98
-39
lines changed

6 files changed

+98
-39
lines changed

LinkDotNet.Blog.Domain/Skill.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ private Skill(string name, string iconUrl, string capability, ProficiencyLevel p
2424

2525
public ProficiencyLevel ProficiencyLevel { get; private set; }
2626

27-
public void SetProficiencyLevel(ProficiencyLevel level)
28-
{
29-
ArgumentNullException.ThrowIfNull(level);
30-
ProficiencyLevel = level;
31-
}
32-
3327
public static Skill Create(string name, string iconUrl, string capability, string proficiencyLevel)
3428
{
3529
if (string.IsNullOrWhiteSpace(name))
@@ -47,4 +41,10 @@ public static Skill Create(string name, string iconUrl, string capability, strin
4741
iconUrl = string.IsNullOrWhiteSpace(iconUrl) ? null : iconUrl;
4842
return new Skill(name.Trim(), iconUrl, capability.Trim(), level);
4943
}
44+
45+
public void SetProficiencyLevel(ProficiencyLevel level)
46+
{
47+
ArgumentNullException.ThrowIfNull(level);
48+
ProficiencyLevel = level;
49+
}
5050
}

LinkDotNet.Blog.IntegrationTests/Web/Pages/Admin/Dashboard/VisitCountPerPageTests.cs

+11-8
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,28 @@ public async Task ShouldShowCounts()
3737
}
3838

3939
[Fact]
40-
public async Task ShouldFilterStartDate()
40+
public async Task ShouldFilterByDate()
4141
{
4242
var blogPost1 = new BlogPostBuilder().WithTitle("1").WithLikes(2).Build();
4343
var blogPost2 = new BlogPostBuilder().WithTitle("2").WithLikes(2).Build();
4444
await Repository.StoreAsync(blogPost1);
4545
await Repository.StoreAsync(blogPost2);
46-
var urlClicked1New = new UserRecord
47-
{ UrlClicked = $"blogPost/{blogPost1.Id}", DateTimeUtcClicked = DateTime.UtcNow };
48-
var urlClicked1Old = new UserRecord
46+
var clicked1 = new UserRecord
47+
{ UrlClicked = $"blogPost/{blogPost1.Id}", DateTimeUtcClicked = new DateTime(2020, 1, 1) };
48+
var clicked2 = new UserRecord
4949
{ UrlClicked = $"blogPost/{blogPost1.Id}", DateTimeUtcClicked = DateTime.MinValue };
50-
var urlClicked2 = new UserRecord
50+
var clicked3 = new UserRecord
5151
{ UrlClicked = $"blogPost/{blogPost2.Id}", DateTimeUtcClicked = DateTime.MinValue };
52-
await DbContext.UserRecords.AddRangeAsync(new[] { urlClicked1New, urlClicked1Old, urlClicked2 });
52+
var clicked4 = new UserRecord
53+
{ UrlClicked = $"blogPost/{blogPost1.Id}", DateTimeUtcClicked = new DateTime(2021, 1, 1) };
54+
await DbContext.UserRecords.AddRangeAsync(new[] { clicked1, clicked2, clicked3, clicked4 });
5355
await DbContext.SaveChangesAsync();
5456
using var ctx = new TestContext();
5557
ctx.Services.AddScoped(_ => DbContext);
5658
var cut = ctx.RenderComponent<VisitCountPerPage>();
5759

58-
cut.FindComponent<DateRangeSelector>().Find("select").Change(DateTime.UtcNow.Date);
60+
cut.FindComponent<DateRangeSelector>().Find("#startDate").Change(new DateTime(2019, 1, 1));
61+
cut.FindComponent<DateRangeSelector>().Find("#endDate").Change(new DateTime(2020, 12, 31));
5962

6063
cut.WaitForState(() => cut.FindAll("td").Any());
6164
var elements = cut.FindAll("td").ToList();
@@ -81,4 +84,4 @@ private async Task SaveBlogPostArticleClicked(string blogPostId, int count)
8184

8285
await DbContext.SaveChangesAsync();
8386
}
84-
}
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using Bunit;
3+
using FluentAssertions;
4+
using LinkDotNet.Blog.Web.Shared.Admin.Dashboard;
5+
using Xunit;
6+
7+
namespace LinkDotNet.Blog.UnitTests.Web.Shared.Admin.Dashboard;
8+
9+
public class DateRangeSelectorTests : TestContext
10+
{
11+
[Fact]
12+
public void ShouldSetBeginDateWhenSet()
13+
{
14+
Filter filter = null;
15+
var cut = RenderComponent<DateRangeSelector>(p => p.Add(s => s.FilterChanged, f =>
16+
{
17+
filter = f;
18+
}));
19+
20+
cut.Find("#startDate").Change(new DateTime(2020, 1, 1));
21+
22+
filter.Should().NotBeNull();
23+
filter.StartDate.Should().Be(new DateTime(2020, 1, 1));
24+
filter.EndDate.Should().BeNull();
25+
}
26+
27+
[Fact]
28+
public void ShouldSetEndDateWhenSet()
29+
{
30+
Filter filter = null;
31+
var cut = RenderComponent<DateRangeSelector>(p => p.Add(s => s.FilterChanged, f =>
32+
{
33+
filter = f;
34+
}));
35+
36+
cut.Find("#endDate").Change(new DateTime(2020, 1, 1));
37+
38+
filter.Should().NotBeNull();
39+
filter.EndDate.Should().Be(new DateTime(2020, 1, 1));
40+
filter.StartDate.Should().BeNull();
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
1-
<div class="col-lg-1 col-md-2 col-sm-3 col-4">
2-
<p>Since: </p>
3-
</div>
4-
<div class="col-lg-2 col-md-4 col-sm-6 col-8">
5-
<select @onchange="RaiseDateTimeSpanChanged">
6-
@foreach (var (title, time) in options)
7-
{
8-
<option value="@time">@title</option>
9-
}
10-
</select>
1+
<div class="row mb-3">
2+
<div class="col-2">
3+
<label for="startDate">Since</label>
4+
<input type="date" class="form-control" id="startDate" @onchange="StartDateChanged"/>
5+
</div>
6+
<div class="col-2">
7+
<label for="endDate">To</label>
8+
<input type="date" class="form-control" id="endDate" @onchange="EndDateChanged"/>
9+
</div>
1110
</div>
1211
@code {
1312
[Parameter]
14-
public EventCallback<DateTime> DateTimeSpanChanged { get; set; }
13+
public EventCallback<Filter> FilterChanged { get; set; }
14+
15+
private Filter filter = new();
1516

16-
private readonly Dictionary<string, DateTime> options = new()
17+
private async Task ApplyFilters()
1718
{
18-
{ "Beginning of time", DateTime.MinValue },
19-
{ "Last 90 Days", DateTime.UtcNow.AddDays(-90) },
20-
{ "Last 30 Days", DateTime.UtcNow.AddDays(-30) },
21-
{ "Last 7 Days", DateTime.UtcNow.AddDays(-7) },
22-
{ "Since Today", DateTime.UtcNow.Date },
23-
};
19+
await FilterChanged.InvokeAsync(filter);
20+
}
2421

25-
private async Task RaiseDateTimeSpanChanged(ChangeEventArgs args)
22+
private async Task StartDateChanged(ChangeEventArgs args)
2623
{
27-
await DateTimeSpanChanged.InvokeAsync(DateTime.Parse(args.Value!.ToString()));
24+
filter.StartDate = args.Value is string dateTime ? DateTime.Parse(dateTime) : null;
25+
await ApplyFilters();
2826
}
2927

28+
private async Task EndDateChanged(ChangeEventArgs args)
29+
{
30+
filter.EndDate = args.Value is string dateTime ? DateTime.Parse(dateTime) : null;
31+
await ApplyFilters();
32+
}
3033
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace LinkDotNet.Blog.Web.Shared.Admin.Dashboard;
4+
5+
public sealed class Filter
6+
{
7+
public DateTime? StartDate { get; set; }
8+
9+
public DateTime? EndDate { get; set; }
10+
}

LinkDotNet.Blog.Web/Shared/Admin/Dashboard/VisitCountPerPage.razor

+6-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<div class="card-header">Blog Post Visit Counts</div>
1010
<div class="card-body">
1111
<div class="row">
12-
<DateRangeSelector DateTimeSpanChanged="RefreshVisitCount"></DateRangeSelector>
12+
<DateRangeSelector FilterChanged="RefreshVisitCount"></DateRangeSelector>
1313
<table class="table table-striped table-hover">
1414
<tbody>
1515
<tr>
@@ -40,7 +40,7 @@
4040

4141
@code {
4242

43-
private DateTime startDate = DateTime.MinValue;
43+
private Filter filter = new();
4444
private IList<VisitCountPageData> visitData;
4545

4646
protected override async Task OnInitializedAsync()
@@ -51,7 +51,8 @@
5151
private async Task LoadBlogPostInformationAsync()
5252
{
5353
visitData = await (from ur in blogDbContext.UserRecords
54-
where ur.DateTimeUtcClicked >= startDate
54+
where (!filter.StartDate.HasValue || ur.DateTimeUtcClicked >= filter.StartDate)
55+
&& (!filter.EndDate.HasValue || ur.DateTimeUtcClicked <= filter.EndDate)
5556
join bp in blogDbContext.BlogPosts
5657
on ur.UrlClicked.Replace("blogPost/", string.Empty) equals bp.Id
5758
group new { ur, bp } by new { ur.UrlClicked }
@@ -66,9 +67,9 @@
6667
}).ToListAsync();
6768
}
6869

69-
private async Task RefreshVisitCount(DateTime newBeginning)
70+
private async Task RefreshVisitCount(Filter newBeginning)
7071
{
71-
startDate = newBeginning;
72+
filter = newBeginning;
7273
visitData = null;
7374
await LoadBlogPostInformationAsync();
7475
}

0 commit comments

Comments
 (0)