Skip to content

Commit bcd881d

Browse files
committed
Allow user to enter schedule date
1 parent 325b9a2 commit bcd881d

File tree

5 files changed

+80
-21
lines changed

5 files changed

+80
-21
lines changed

src/LinkDotNet.Blog.Domain/BlogPost.cs

+4-7
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@ public static BlogPost Create(
4646
throw new InvalidOperationException("Can't schedule publish date if the blog post is already published.");
4747
}
4848

49+
var blogPostUpdateDate = scheduledPublishDate ?? updatedDate ?? DateTime.Now;
50+
4951
var blogPost = new BlogPost
5052
{
5153
Title = title,
5254
ShortDescription = shortDescription,
5355
Content = content,
54-
UpdatedDate = updatedDate ?? DateTime.Now,
56+
UpdatedDate = blogPostUpdateDate,
5557
ScheduledPublishDate = scheduledPublishDate,
5658
PreviewImageUrl = previewImageUrl,
5759
PreviewImageUrlFallback = previewImageUrlFallback,
@@ -64,12 +66,7 @@ public static BlogPost Create(
6466

6567
public void Publish()
6668
{
67-
if (ScheduledPublishDate is not null)
68-
{
69-
UpdatedDate = ScheduledPublishDate.Value;
70-
ScheduledPublishDate = null;
71-
}
72-
69+
ScheduledPublishDate = null;
7370
IsPublished = true;
7471
}
7572

src/LinkDotNet.Blog.Web/Features/Admin/BlogPostEditor/Components/CreateNewBlogPost.razor

+26-12
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,43 @@
3535
<label for="preview">Preview-Url</label>
3636
<InputText class="form-control" id="preview" @bind-Value="model.PreviewImageUrl"/>
3737
<small for="preview" class="form-text text-muted">The primary image which will be used.</small>
38-
<ValidationMessage For="() => model.PreviewImageUrl"></ValidationMessage>
38+
<ValidationMessage For="() => model.PreviewImageUrl"></ValidationMessage>
3939
</div>
4040
<div class="mb-3">
41-
<label for="preview">Fallback Preview-Url</label>
42-
<InputText class="form-control" id="fallback-preview" @bind-Value="model.PreviewImageUrlFallback"/>
43-
<small for="fallback-preview" class="form-text text-muted">Optional: Used as a fallback if the preview image can't be used by the browser.
44-
<br>For example using a jpg or png as fallback for avif which is not supported in Safari or Edge.</small>
45-
<ValidationMessage For="() => model.PreviewImageUrlFallback"></ValidationMessage>
41+
<label for="preview">Fallback Preview-Url</label>
42+
<InputText class="form-control" id="fallback-preview" @bind-Value="model.PreviewImageUrlFallback"/>
43+
<small for="fallback-preview" class="form-text text-muted">Optional: Used as a fallback if the preview image can't be used by the browser.
44+
<br>For example using a jpg or png as fallback for avif which is not supported in Safari or Edge.</small>
45+
<ValidationMessage For="() => model.PreviewImageUrlFallback"></ValidationMessage>
46+
</div>
47+
<div class="mb-3">
48+
<label for="scheduled">Scheduled Publish Date</label>
49+
<InputDate Type="InputDateType.DateTimeLocal"
50+
class="form-control"
51+
id="scheduled"
52+
@bind-Value="model.ScheduledPublishDate"
53+
@bind-Value:after="@(() => model.IsPublished &= !IsScheduled)"/>
54+
<small for="scheduled" class="form-text text-muted">If set the blog post will be published at the given date.
55+
A blog post with a schedule date can't be set to published.</small>
56+
<ValidationMessage For="() => model.ScheduledPublishDate"></ValidationMessage>
4657
</div>
4758
<div class="form-check">
48-
<InputCheckbox class="form-check-input" id="published" @bind-Value="model.IsPublished" />
59+
<InputCheckbox class="form-check-input" id="published" @bind-Value="model.IsPublished"/>
4960
<label class="form-check-label" for="published">Publish</label><br/>
50-
<small for="published" class="form-text text-muted">If this blog post is only draft uncheck the box</small>
61+
<small for="published" class="form-text text-muted">If this blog post is only draft or it will be scheduled, uncheck the box.</small>
62+
<ValidationMessage For="() => model.IsPublished"></ValidationMessage>
5163
</div>
5264
<div class="mb-3">
53-
<label for="tags">Tags</label>
54-
<InputText class="form-control" id="tags" @bind-Value="model.Tags"/>
65+
<label for="tags">Tags</label>
66+
<InputText class="form-control" id="tags" @bind-Value="model.Tags"/>
5567
</div>
56-
@if (BlogPost != null)
68+
@if (BlogPost != null && !IsScheduled)
5769
{
5870
<div class="form-check">
5971
<InputCheckbox class="form-check-input" id="updatedate" @bind-Value="model.ShouldUpdateDate" />
6072
<label class="form-check-label" for="updatedate">Update Publish Date?</label><br/>
6173
<small for="updatedate" class="form-text text-muted">If set the publish date is set to now,
62-
otherwise its original date</small>
74+
otherwise its original date.</small>
6375
</div>
6476
}
6577
<button class="btn btn-primary" type="submit" disabled="@(!canSubmit)">Submit</button>
@@ -101,6 +113,8 @@
101113

102114
private bool canSubmit = true;
103115

116+
private bool IsScheduled => model.ScheduledPublishDate.HasValue;
117+
104118
protected override void OnParametersSet()
105119
{
106120
if (BlogPost == null)

src/LinkDotNet.Blog.Web/Features/Admin/BlogPostEditor/Components/PublishedWithScheduledDateValidationAttribute.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public sealed class PublishedWithScheduledDateValidationAttribute : ValidationAt
99
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
1010
{
1111
return validationContext.ObjectInstance is CreateNewModel { IsPublished: true, ScheduledPublishDate: { } }
12-
? new ValidationResult("Cannot have a scheduled publish date when the post is already published.")
12+
? new ValidationResult("Cannot publish the post right away and schedule it for later.")
1313
: ValidationResult.Success;
1414
}
1515
}

tests/LinkDotNet.Blog.UnitTests/Domain/BlogPostTests.cs

+10
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,14 @@ public void ShouldUpdateScheduledPublishDate()
101101

102102
blogPost.ScheduledPublishDate.Should().Be(new DateTime(2023, 3, 24));
103103
}
104+
105+
[Fact]
106+
public void GivenScheduledPublishDate_WhenCreating_ThenUpdateDateIsScheduledPublishDate()
107+
{
108+
var date = new DateTime(2023, 3, 24);
109+
110+
var bp = BlogPost.Create("1", "2", "3", "4", false, scheduledPublishDate: date);
111+
112+
bp.UpdatedDate.Should().Be(date);
113+
}
104114
}

tests/LinkDotNet.Blog.UnitTests/Web/Features/Admin/BlogPostEditor/Components/CreateNewBlogPostTests.cs

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.Linq;
3+
using AngleSharp.Html.Dom;
4+
using AngleSharpWrappers;
35
using LinkDotNet.Blog.Domain;
46
using LinkDotNet.Blog.TestUtilities;
57
using LinkDotNet.Blog.Web.Features.Admin.BlogPostEditor.Components;
@@ -207,4 +209,40 @@ public void ShouldNotBlogNavigationOnInitialLoad()
207209
fakeNavigationManager.History.Count.Should().Be(1);
208210
fakeNavigationManager.History.Single().State.Should().Be(NavigationState.Succeeded);
209211
}
210-
}
212+
213+
[Fact]
214+
public void GivenBlogPostWithSchedule_ShouldSetSchedule()
215+
{
216+
BlogPost blogPost = null;
217+
var cut = RenderComponent<CreateNewBlogPost>(
218+
p => p.Add(c => c.OnBlogPostCreated, bp => blogPost = bp));
219+
cut.Find("#title").Input("My Title");
220+
cut.Find("#short").Input("My short Description");
221+
cut.Find("#content").Input("My content");
222+
cut.Find("#preview").Change("My preview url");
223+
cut.Find("#published").Change(false);
224+
cut.Find("#scheduled").Change("01/01/2099 00:00");
225+
226+
cut.Find("form").Submit();
227+
228+
blogPost.ScheduledPublishDate.Should().Be(new DateTime(2099, 01, 01));
229+
}
230+
231+
[Fact]
232+
public void GivenBlogPost_WhenEnteringScheduledDate_ThenIsPublishedSetToFalse()
233+
{
234+
BlogPost blogPost = null;
235+
var cut = RenderComponent<CreateNewBlogPost>(
236+
p => p.Add(c => c.OnBlogPostCreated, bp => blogPost = bp));
237+
cut.Find("#title").Input("My Title");
238+
cut.Find("#short").Input("My short Description");
239+
cut.Find("#content").Input("My content");
240+
cut.Find("#preview").Change("My preview url");
241+
cut.Find("#published").Change(true);
242+
243+
cut.Find("#scheduled").Change("01/01/2099 00:00");
244+
245+
var element = cut.Find("#published").Unwrap() as IHtmlInputElement;
246+
element.IsChecked.Should().BeFalse();
247+
}
248+
}

0 commit comments

Comments
 (0)