From bd9dacf0566ca542ecab913acbc244f474c6a752 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 1 Jun 2021 23:22:47 +0800 Subject: feat: Add ways to reset timeline or post color. --- .../Timeline.Tests/IntegratedTests/TimelineTest.cs | 12 ++++++++ .../Models/Http/HttpTimelinePatchRequest.cs | 2 +- .../Models/Http/HttpTimelinePostPatchRequest.cs | 2 +- .../Timeline/Models/Validation/ColorValidator.cs | 34 ++++++++++++++++++++++ BackEnd/Timeline/Models/Validation/Validator.cs | 2 +- .../Services/Timeline/TimelinePostService.cs | 20 +++++++++---- .../Timeline/Services/Timeline/TimelineService.cs | 11 +++++-- 7 files changed, 73 insertions(+), 10 deletions(-) (limited to 'BackEnd') diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs index bbfe4ab3..d7832b60 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -438,5 +438,17 @@ namespace Timeline.Tests.IntegratedTests timeline.Postable.Should().Be(false); } } + + [Theory] + [InlineData("")] + [InlineData("default")] + public async Task Patch_Timeline_Color_Default(string value) + { + using var client = await CreateClientAsUser(); + var timeline = await client.TestPatchAsync("timelines/t1", new HttpTimelinePatchRequest { Color = "#111111" }); + timeline.Color.Should().NotBeNull(); + var timeline2 = await client.TestPatchAsync("timelines/t1", new HttpTimelinePatchRequest { Color = value }); + timeline2.Color.Should().BeNull(); + } } } diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs index 9accb6fc..35667af2 100644 --- a/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs @@ -31,7 +31,7 @@ namespace Timeline.Models.Http /// /// New color. Null for not change. /// - [Color] + [Color(PermitDefault = true, PermitEmpty = true)] public string? Color { get; set; } } } diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePostPatchRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePostPatchRequest.cs index 2c6edf66..cb576a74 100644 --- a/BackEnd/Timeline/Models/Http/HttpTimelinePostPatchRequest.cs +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePostPatchRequest.cs @@ -13,7 +13,7 @@ namespace Timeline.Models.Http /// /// Change the color. Null for not change. /// - [Color] + [Color(PermitEmpty = true, PermitDefault = true)] public string? Color { get; set; } } } diff --git a/BackEnd/Timeline/Models/Validation/ColorValidator.cs b/BackEnd/Timeline/Models/Validation/ColorValidator.cs index c5ad833d..4f7accc5 100644 --- a/BackEnd/Timeline/Models/Validation/ColorValidator.cs +++ b/BackEnd/Timeline/Models/Validation/ColorValidator.cs @@ -4,8 +4,22 @@ namespace Timeline.Models.Validation { public class ColorValidator : Validator { + public bool PermitEmpty { get; set; } = false; + public bool PermitDefault { get; set; } = false; + public string DefaultValue { get; set; } = "default"; + protected override (bool, string) DoValidate(string value) { + if (PermitEmpty && value.Length == 0) + { + return (true, GetSuccessMessage()); + } + + if (PermitDefault && value == DefaultValue) + { + return (true, GetSuccessMessage()); + } + if (!value.StartsWith('#')) { return (false, "Color must starts with '#'."); @@ -32,9 +46,29 @@ namespace Timeline.Models.Validation [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public class ColorAttribute : ValidateWithAttribute { + private ColorValidator Validator => (ColorValidator)_validator; + public ColorAttribute() : base(typeof(ColorValidator)) { } + + public bool PermitEmpty + { + get => Validator.PermitEmpty; + set => Validator.PermitEmpty = value; + } + + public bool PermitDefault + { + get => Validator.PermitDefault; + set => Validator.PermitDefault = value; + } + + public string DefaultValue + { + get => Validator.DefaultValue; + set => Validator.DefaultValue = value; + } } } diff --git a/BackEnd/Timeline/Models/Validation/Validator.cs b/BackEnd/Timeline/Models/Validation/Validator.cs index d334960e..0e1f7445 100644 --- a/BackEnd/Timeline/Models/Validation/Validator.cs +++ b/BackEnd/Timeline/Models/Validation/Validator.cs @@ -77,7 +77,7 @@ namespace Timeline.Models.Validation AllowMultiple = false)] public class ValidateWithAttribute : ValidationAttribute { - private readonly IValidator _validator; + protected readonly IValidator _validator; /// /// Create with a given validator. diff --git a/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs index ee1002e0..ae034767 100644 --- a/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs @@ -26,6 +26,7 @@ namespace Timeline.Services.Timeline private readonly IImageService _imageValidator; private readonly IClock _clock; private readonly ColorValidator _colorValidator = new ColorValidator(); + private readonly ColorValidator _colorValidatorAllowEmptyAndDefault = new ColorValidator() { PermitEmpty = true, PermitDefault = true }; public TimelinePostService(ILogger logger, DatabaseContext database, IBasicTimelineService basicTimelineService, IBasicUserService basicUserService, IDataManager dataManager, IImageService imageValidator, IClock clock) { @@ -38,9 +39,9 @@ namespace Timeline.Services.Timeline _clock = clock; } - private void CheckColor(string color, string paramName) + private void CheckColor(string color, string paramName, bool allowEmptyOrDefault) { - if (!_colorValidator.Validate(color, out var message)) + if (!(allowEmptyOrDefault ? _colorValidatorAllowEmptyAndDefault : _colorValidator).Validate(color, out var message)) throw new ArgumentException(string.Format(Resource.ExceptionColorInvalid, message), paramName); } @@ -166,7 +167,7 @@ namespace Timeline.Services.Timeline throw new ArgumentNullException(nameof(request)); if (request.Color is not null) - CheckColor(request.Color, nameof(request)); + CheckColor(request.Color, nameof(request), false); if (request.DataList is null) throw new ArgumentException(Resource.ExceptionDataListNull, nameof(request)); @@ -269,7 +270,7 @@ namespace Timeline.Services.Timeline throw new ArgumentNullException(nameof(request)); if (request.Color is not null) - CheckColor(request.Color, nameof(request)); + CheckColor(request.Color, nameof(request), true); request.Time = request.Time?.MyToUtc(); @@ -287,7 +288,16 @@ namespace Timeline.Services.Timeline entity.Time = request.Time.Value; if (request.Color is not null) - entity.Color = request.Color; + { + if (request.Color.Length == 0 || request.Color == "default") + { + entity.Color = null; + } + else + { + entity.Color = request.Color; + } + } entity.LastUpdated = _clock.GetCurrentTime(); diff --git a/BackEnd/Timeline/Services/Timeline/TimelineService.cs b/BackEnd/Timeline/Services/Timeline/TimelineService.cs index 920fcc74..6f22ff05 100644 --- a/BackEnd/Timeline/Services/Timeline/TimelineService.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelineService.cs @@ -23,7 +23,7 @@ namespace Timeline.Services.Timeline private readonly IClock _clock; private readonly TimelineNameValidator _timelineNameValidator = new TimelineNameValidator(); - private readonly ColorValidator _colorValidator = new ColorValidator(); + private readonly ColorValidator _colorValidator = new ColorValidator() { PermitDefault = true, PermitEmpty = true }; public TimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IBasicUserService userService, IClock clock) : base(loggerFactory, database, userService, clock) @@ -119,7 +119,14 @@ namespace Timeline.Services.Timeline if (newProperties.Color is not null) { changed = true; - entity.Color = newProperties.Color; + if (newProperties.Color.Length == 0 || newProperties.Color == "default") + { + entity.Color = null; + } + else + { + entity.Color = newProperties.Color; + } } if (changed) -- cgit v1.2.3