Skip to content

Commit f38d48a

Browse files
committed
Move message to property and check for previewimage != fallback (Closes #161)
1 parent f319bf9 commit f38d48a

File tree

4 files changed

+81
-9
lines changed

4 files changed

+81
-9
lines changed

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@using LinkDotNet.Blog.Domain
2+
@using Microsoft.EntityFrameworkCore.Metadata.Internal
23
@inject IJSRuntime JSRuntime
34

45
<h3>@Title</h3>
@@ -7,37 +8,41 @@
78
<div class="new-content">
89
<EditForm Model="@model" OnValidSubmit="OnValidBlogPostCreatedAsync">
910
<DataAnnotationsValidator />
10-
<ValidationSummary />
1111
<div class="mb-3">
1212
<label for="title">Title</label>
13-
<input class="form-control" id="title"
14-
@oninput="args => model.Title = args.Value.ToString()" value="@model.Title"/>
13+
<input class="form-control" id="title"
14+
@oninput="args => model.Title = args.Value.ToString()" value="@model.Title"/>
15+
<ValidationMessage For="() => model.Title"></ValidationMessage>
1516
</div>
1617
<div class="mb-3">
1718
<label for="short">Short Description</label>
1819
<TextAreaWithShortcuts Id="short" Class="form-control" Rows="4"
1920
@bind-Value="@model.ShortDescription"></TextAreaWithShortcuts>
20-
<small for="short" class="form-text text-muted">You can use markdown to style your component</small>
21+
<small for="short" class="form-text text-muted">You can use markdown to style your component</small>
22+
<ValidationMessage For="() => model.ShortDescription"></ValidationMessage>
2123
</div>
2224
<div class="mb-3">
2325
<label for="content">Content</label>
2426
<TextAreaWithShortcuts Id="content" Class="form-control" Rows="10"
2527
@bind-Value="@model.Content"></TextAreaWithShortcuts>
2628
<small for="content" class="form-text text-muted">You can use markdown to style your component. Additional features and keyboard shortcuts are listed <a @onclick="@(() => FeatureDialog.Open())">here</a></small>
2729
<UploadFile OnFileUploaded="SetContentFromFile" id="content-upload"></UploadFile>
28-
<small for="content-upload" class="form-text text-muted">Drag and drop markdown files to upload and
29-
insert them</small>
30+
<small for="content-upload" class="form-text text-muted">Drag and drop markdown files to upload and
31+
insert them</small>
32+
<ValidationMessage For="() => model.Content"></ValidationMessage>
3033
</div>
3134
<div class="mb-3">
3235
<label for="preview">Preview-Url</label>
3336
<InputText class="form-control" id="preview" @bind-Value="model.PreviewImageUrl"/>
3437
<small for="preview" class="form-text text-muted">The primary image which will be used.</small>
38+
<ValidationMessage For="() => model.PreviewImageUrl"></ValidationMessage>
3539
</div>
3640
<div class="mb-3">
3741
<label for="preview">Fallback Preview-Url</label>
3842
<InputText class="form-control" id="fallback-preview" @bind-Value="model.PreviewImageUrlFallback"/>
3943
<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.
40-
<br>For example using a jpg or png as fallback for avif which is not supported in Safari or Edge.</small>
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>
4146
</div>
4247
<div class="form-check">
4348
<InputCheckbox class="form-check-input" id="published" @bind-Value="model.IsPublished" />
@@ -141,4 +146,4 @@
141146
context.PreventNavigation();
142147
}
143148
}
144-
}
149+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public string Tags
9797
}
9898

9999
[MaxLength(256)]
100+
[FallbackUrlValidation]
100101
public string PreviewImageUrlFallback
101102
{
102103
get => previewImageUrlFallback;
@@ -137,4 +138,4 @@ public BlogPost ToBlogPost()
137138
blogPost.Id = id;
138139
return blogPost;
139140
}
140-
}
141+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.ComponentModel.DataAnnotations;
3+
4+
namespace LinkDotNet.Blog.Web.Features.Admin.BlogPostEditor.Components;
5+
6+
[AttributeUsage(AttributeTargets.Property)]
7+
public class FallbackUrlValidationAttribute : ValidationAttribute
8+
{
9+
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
10+
{
11+
var model = validationContext.ObjectInstance as CreateNewModel;
12+
13+
return model.PreviewImageUrl == model.PreviewImageUrlFallback
14+
? new ValidationResult("Preview image url and the fallback preview image url should not be the same.")
15+
: ValidationResult.Success;
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using LinkDotNet.Blog.Web.Features.Admin.BlogPostEditor.Components;
5+
6+
namespace LinkDotNet.Blog.UnitTests.Web.Features.Admin.BlogPostEditor.Components;
7+
8+
public class FallbackUrlValidationAttributeTests
9+
{
10+
[Fact]
11+
public void GivenPreviewImageUrlIsSameAsFallback_WhenValidating_ThenError()
12+
{
13+
const string url = "https://steven-giesel.com";
14+
var model = new CreateNewModel
15+
{
16+
Title = "Title",
17+
ShortDescription = "Desc",
18+
Content = "Content",
19+
PreviewImageUrl = url,
20+
PreviewImageUrlFallback = url,
21+
};
22+
var validationContext = new ValidationContext(model);
23+
var results = new List<ValidationResult>();
24+
25+
var result = Validator.TryValidateObject(model, validationContext, results, true);
26+
27+
result.Should().BeFalse();
28+
results.Count.Should().Be(1);
29+
}
30+
31+
[Fact]
32+
public void GivenPreviewImageUrlIsNotSameAsFallback_WhenValidating_ThenSuccess()
33+
{
34+
var model = new CreateNewModel
35+
{
36+
Title = "Title",
37+
ShortDescription = "Desc",
38+
Content = "Content",
39+
PreviewImageUrl = "https://steven-giesel.com",
40+
PreviewImageUrlFallback = "https://different.url",
41+
};
42+
var validationContext = new ValidationContext(model);
43+
var results = new List<ValidationResult>();
44+
45+
var result = Validator.TryValidateObject(model, validationContext, results, true);
46+
47+
result.Should().BeTrue();
48+
}
49+
}

0 commit comments

Comments
 (0)