From 8d0cc1791b67604a3fe151b884c606e1120691e3 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Wed, 14 Dec 2022 21:46:13 +0100 Subject: [PATCH 01/33] Add bonus points handling --- .../Settings/EditPointRuleModal.razor | 3 +++ .../Settings/EditResultConfigModal.razor | 27 ++++++++----------- .../ViewModels/PointRuleViewModel.cs | 17 ++++++++++++ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor b/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor index 0bb033c7..67887308 100644 --- a/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor +++ b/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor @@ -67,6 +67,9 @@ default: break; } + + + diff --git a/src/iRLeagueManager.Web/Components/Settings/EditResultConfigModal.razor b/src/iRLeagueManager.Web/Components/Settings/EditResultConfigModal.razor index 3f5026aa..dab4267a 100644 --- a/src/iRLeagueManager.Web/Components/Settings/EditResultConfigModal.razor +++ b/src/iRLeagueManager.Web/Components/Settings/EditResultConfigModal.razor @@ -84,24 +84,19 @@ Session Scorings -
-
-
- Session Scorings -
- @foreach(var scoring in @Bind(vm, x => x.Scorings).Where(x => x.IsCombinedResult == false)) - { -
-
- - -
- +
+ @foreach(var scoring in @Bind(vm, x => x.Scorings).Where(x => x.IsCombinedResult == false)) + { +
+
+ +
- } -
- +
+ } +
+
diff --git a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs index 04bb8302..0a1cd545 100644 --- a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs @@ -38,6 +38,23 @@ public PointRuleType RuleType public IDictionary BonusPoints { get => model.BonusPoints; set => SetP(model.BonusPoints, value => model.BonusPoints = value, value); } public ICollection PointsSortOptions { get => model.PointsSortOptions; set => SetP(model.PointsSortOptions, value => model.PointsSortOptions = value, value); } public ICollection FinalSortOptions { get => model.FinalSortOptions; set => SetP(model.FinalSortOptions, value => model.FinalSortOptions = value, value); } + public string BonusPointsString + { + get => string.Join(';', BonusPoints.Select(x => string.Join(':', x.Key, x.Value))); + set + { + var points = new Dictionary(); + var bonus = value.Split(';'); + foreach (var pair in bonus) + { + var parts = pair.Split(':'); + var key = parts[0]; + var keyValue = parts.Length <= 1 ? 0 : int.TryParse(parts[1], out int res) ? res : 0; + points.Add(key, keyValue); + } + BonusPoints = points; + } + } public enum PointRuleType { From 12010074f6e2cd8570019704bb6d98a00818a66c Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Wed, 14 Dec 2022 22:02:59 +0100 Subject: [PATCH 02/33] Add sort options --- .../Components/Settings/EditSortOptionsModal.razor | 4 +++- src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs | 8 ++++++++ .../ViewModels/SortOptionsViewModel.cs | 2 ++ src/iRLeagueManager.Web/iRLeagueManager.Web.csproj | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/Settings/EditSortOptionsModal.razor b/src/iRLeagueManager.Web/Components/Settings/EditSortOptionsModal.razor index b51f18df..a2e72fdb 100644 --- a/src/iRLeagueManager.Web/Components/Settings/EditSortOptionsModal.razor +++ b/src/iRLeagueManager.Web/Components/Settings/EditSortOptionsModal.razor @@ -120,7 +120,9 @@ SortValue.RacePts => "Race Points", SortValue.PenPts => "Penalty Points", SortValue.BonusPts => "Bonus Points", - SortValue.TotalPts => "TotalPoints", + SortValue.TotalPts => "Total Points", + SortValue.TotalPtsNoBonus => "Total Points w/o Bonus", + SortValue.TotalPtsNoPenalty => "Total Points w/o Penalty", SortValue.Intvl => "Intervall", SortValue.ComplLaps => "Completed Laps", SortValue.LeadLaps => "Lead Laps", diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs index 306f11b3..f77d296e 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs @@ -70,6 +70,10 @@ public SortDirection SortDirection SortOptions.QualLapDesc => (SortValue.QualLap, SortDirection.Descending), SortOptions.FinPosAsc => (SortValue.FinalPos, SortDirection.Ascending), SortOptions.FinPosDesc => (SortValue.FinalPos, SortDirection.Descending), + SortOptions.TotalPtsWoBonusAsc => (SortValue.TotalPtsNoBonus, SortDirection.Ascending), + SortOptions.TotalPtsWoBonusDesc => (SortValue.TotalPtsNoBonus, SortDirection.Descending), + SortOptions.TotalPtsWoPenaltyAsc => (SortValue.TotalPtsNoPenalty, SortDirection.Ascending), + SortOptions.TotalPtsWoPenaltyDesc => (SortValue.TotalPtsNoPenalty, SortDirection.Descending), _ => (SortValue.TotalPts, SortDirection.Descending), }; } @@ -106,6 +110,10 @@ private SortOptions GetSortOptions(SortValue sortValue, SortDirection direction) (SortValue.QualLap, SortDirection.Descending) => SortOptions.QualLapDesc, (SortValue.FinalPos, SortDirection.Ascending) => SortOptions.FinPosAsc, (SortValue.FinalPos, SortDirection.Descending) => SortOptions.FinPosDesc, + (SortValue.TotalPtsNoBonus, SortDirection.Ascending) => SortOptions.TotalPtsWoBonusAsc, + (SortValue.TotalPtsNoBonus, SortDirection.Descending) => SortOptions.TotalPtsWoBonusDesc, + (SortValue.TotalPtsNoPenalty, SortDirection.Ascending) => SortOptions.TotalPtsWoPenaltyAsc, + (SortValue.TotalPtsNoPenalty, SortDirection.Descending) => SortOptions.TotalPtsWoPenaltyDesc, _ => SortOptions.TotalPtsDesc, }; } diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs index 3b7dff58..466a92a7 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs @@ -53,6 +53,8 @@ public enum SortValue PenPts, BonusPts, TotalPts, + TotalPtsNoBonus, + TotalPtsNoPenalty, Intvl, ComplLaps, LeadLaps, diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index f7c2ca8d..d4588443 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -21,7 +21,7 @@ - + From 7eb792e5cde921fe1a1eeb017a5b0d3f3afd51f3 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Wed, 14 Dec 2022 22:21:56 +0100 Subject: [PATCH 03/33] Fix warnings --- .../Components/Settings/SearchUserModal.razor | 2 +- src/iRLeagueManager.Web/Components/ValueChange.razor | 2 -- src/iRLeagueManager.Web/Pages/Seasons.razor | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor b/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor index a6389b0a..4124e050 100644 --- a/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor +++ b/src/iRLeagueManager.Web/Components/Settings/SearchUserModal.razor @@ -49,7 +49,7 @@ .Search() .Post(model); var result = await request; - if (result.Success) + if (result.Success && result.Content is not null) { return result.Content; } diff --git a/src/iRLeagueManager.Web/Components/ValueChange.razor b/src/iRLeagueManager.Web/Components/ValueChange.razor index 4f05ae08..b7b2a74a 100644 --- a/src/iRLeagueManager.Web/Components/ValueChange.razor +++ b/src/iRLeagueManager.Web/Components/ValueChange.razor @@ -7,8 +7,6 @@ public double Value { get; set; } [Parameter] public double Change { get; set; } - [Parameter] - public string Width { get; set; } private static string ChangeClass(double change) { diff --git a/src/iRLeagueManager.Web/Pages/Seasons.razor b/src/iRLeagueManager.Web/Pages/Seasons.razor index 8f0451df..0b0a5c67 100644 --- a/src/iRLeagueManager.Web/Pages/Seasons.razor +++ b/src/iRLeagueManager.Web/Pages/Seasons.razor @@ -39,7 +39,7 @@ return; } var result = await apiService.CurrentLeague.Seasons().Get(); - if (result.Success) + if (result.Success && result.Content is not null) { var seasons = result.Content; navigationManager.NavigateTo($"./{LeagueName}/Seasons/{seasons.Last().SeasonId}"); From 7c0a4bce12ce14101b062206e4d1085c5cff6911 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 15 Dec 2022 07:41:22 +0100 Subject: [PATCH 04/33] Improve UI behaviour - remove edit functions when season finished - fix vertical scrolling on settings page --- src/iRLeagueManager.Web/App.razor | 3 ++ .../Components/DisplaySchedule.razor | 18 ++++++--- .../Components/Reviews/ReviewCard.razor | 8 ++-- src/iRLeagueManager.Web/Pages/Results.razor | 7 ++-- src/iRLeagueManager.Web/Pages/Reviews.razor | 12 +++++- src/iRLeagueManager.Web/Pages/Schedules.razor | 5 ++- .../Pages/Settings/Settings.razor | 2 +- src/iRLeagueManager.Web/Shared/NavMenu.razor | 37 ++++++++++--------- src/iRLeagueManager.Web/appsettings.json | 4 +- 9 files changed, 60 insertions(+), 36 deletions(-) diff --git a/src/iRLeagueManager.Web/App.razor b/src/iRLeagueManager.Web/App.razor index c47561f9..a973e60a 100644 --- a/src/iRLeagueManager.Web/App.razor +++ b/src/iRLeagueManager.Web/App.razor @@ -2,9 +2,11 @@ @using iRLeagueManager.Web.ViewModels @inject EventListViewModel EventList @inject LeagueApiService ApiService +@inject SharedStateService SharedState + @@ -28,3 +30,4 @@ + diff --git a/src/iRLeagueManager.Web/Components/DisplaySchedule.razor b/src/iRLeagueManager.Web/Components/DisplaySchedule.razor index ded1fbcf..175779ef 100644 --- a/src/iRLeagueManager.Web/Components/DisplaySchedule.razor +++ b/src/iRLeagueManager.Web/Components/DisplaySchedule.razor @@ -78,17 +78,23 @@ } } - + @if (ReadOnly == false) + { + + } } -
- -
+ @if (ReadOnly == false) + { +
+ +
+ }
diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor index 6ea36558..e619a8f6 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor @@ -20,7 +20,7 @@ @Bind(Review, x => x.Comments).Where(x => x.Votes.Any()).Count()
- @if (EditClick.HasDelegate) + @if (EditClick.HasDelegate && ReadOnly == false) { @@ -148,6 +148,8 @@ public EventCallback DeleteClick { get; set; } [Parameter] public bool IsSteward { get; set; } = false; + [Parameter] + public bool ReadOnly { get; set; } = false; private ElementReference ReviewText { get; set; } diff --git a/src/iRLeagueManager.Web/Pages/Results.razor b/src/iRLeagueManager.Web/Pages/Results.razor index 91d51026..d8f5accb 100644 --- a/src/iRLeagueManager.Web/Pages/Results.razor +++ b/src/iRLeagueManager.Web/Pages/Results.razor @@ -11,7 +11,6 @@ @using iRLeagueManager.Web.Components.Results @using iRLeagueManager.Web.ViewModels @inherits LeagueComponentBase -@inject SharedStateService sharedState @inject ResultsPageViewModel vm
@@ -37,7 +36,7 @@ - @if (vm.SelectedEvent?.HasResult == true && sharedState.SeasonFinished == false) + @if (vm.SelectedEvent?.HasResult == true && SharedState.SeasonFinished == false) { @@ -74,6 +73,8 @@ @code { private const string resultTabParam = "resultTab"; + [CascadingParameter] + public SharedStateService SharedState { get; set; } = default!; [CascadingParameter] public IModalService ModalService { get; set; } = default!; diff --git a/src/iRLeagueManager.Web/Pages/Reviews.razor b/src/iRLeagueManager.Web/Pages/Reviews.razor index eefce309..20641632 100644 --- a/src/iRLeagueManager.Web/Pages/Reviews.razor +++ b/src/iRLeagueManager.Web/Pages/Reviews.razor @@ -26,9 +26,13 @@ Review=review EditClick=@(async () => await OnEditClick(review)) DeleteClick=@(async () => await OnDeleteClick(review)) - IsSteward=true/> + IsSteward=true + ReadOnly=ReadOnly/> + } + @if (ReadOnly == false) + { + } - @foreach(var review in OrderReviews(@Bind(ReviewsVm, x => x.Reviews))) @@ -41,9 +45,13 @@
@code { + [CascadingParameter] + public SharedStateService SharedState { get; set; } = default!; [CascadingParameter] public IModalService ModalService { get; set; } = default!; + private bool ReadOnly => SharedState.SeasonFinished; + protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); diff --git a/src/iRLeagueManager.Web/Pages/Schedules.razor b/src/iRLeagueManager.Web/Pages/Schedules.razor index 9070c13d..2f0c67c3 100644 --- a/src/iRLeagueManager.Web/Pages/Schedules.razor +++ b/src/iRLeagueManager.Web/Pages/Schedules.razor @@ -19,7 +19,7 @@
@foreach(var schedule in @Bind(vm, x => x.Schedules)) { - + }
@@ -35,6 +35,9 @@
@code { + [CascadingParameter] + public SharedStateService SharedState { get; set; } = default!; + protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); diff --git a/src/iRLeagueManager.Web/Pages/Settings/Settings.razor b/src/iRLeagueManager.Web/Pages/Settings/Settings.razor index 78d95a0f..4a92f5f5 100644 --- a/src/iRLeagueManager.Web/Pages/Settings/Settings.razor +++ b/src/iRLeagueManager.Web/Pages/Settings/Settings.razor @@ -11,7 +11,7 @@

Settings

-
+
- @if (EditClick.HasDelegate && ReadOnly == false) + @if (OnEditClick.HasDelegate && ReadOnly == false) { -
@@ -121,10 +121,18 @@ @foreach (var comment in @Bind(Review, x => x.Comments)) {
  • - await InvokeAsync(StateHasChanged))/> + InvokeAsync(StateHasChanged)) + OnDeleteClick=@(() => DeleteCommentClick(comment))/>
  • } + @if (ReadOnly == false && UserHasCommented(Review) == false) + { + + } } @@ -138,18 +146,22 @@ public IEnumerable EventMembers { get; set; } = default!; [CascadingParameter] public IModalService ModalService { get; set; } = default!; + [CascadingParameter] + public Task AuthenticationTask { get; set; } = default!; [Parameter(CaptureUnmatchedValues=true)] public IReadOnlyDictionary? AdditionalAttributes { get; set; } [Parameter, EditorRequired] public ReviewViewModel Review { get; set; } = default!; [Parameter] - public EventCallback EditClick { get; set; } + public EventCallback OnEditClick { get; set; } [Parameter] - public EventCallback DeleteClick { get; set; } + public EventCallback OnDeleteClick { get; set; } [Parameter] public bool IsSteward { get; set; } = false; [Parameter] public bool ReadOnly { get; set; } = false; + [Parameter] + public string UserId { get; set; } = string.Empty; private ElementReference ReviewText { get; set; } @@ -172,6 +184,12 @@ await Review.DeleteAsync(); } + private bool UserHasCommented(ReviewViewModel review) + { + var hasCommented = Review.Comments.Any(x => x.AuthorUserId == UserId); + return hasCommented; + } + private async Task EditResultClick() { var parameters = new ModalParameters() @@ -189,4 +207,31 @@ Review.SetModel(reviewModel); } } + + private async Task AddCommentClick() + { + var parameters = new ModalParameters() + .Add(nameof(EditCommentModal.Model), new ReviewCommentModel()) + .Add(nameof(EditReviewResultModal.InvolvedMembers), Review.InvolvedMembers) + .Add(nameof(EditCommentModal.OnSubmit), new Func>((comment, cancellationToken) => + Review.AddComment(comment.GetModel(), cancellationToken))); + var options = new ModalOptions() + { + DisableBackgroundCancel = false + }; + await ModalService.Show("Add Comment", parameters, options).Result; + await InvokeAsync(StateHasChanged); + } + + private async Task DeleteCommentClick(ReviewCommentViewModel comment) + { + var parameters = new ModalParameters() + .Add(nameof(ConfirmModal.Text), "Are you sure you want to delete this comment?") + .Add(nameof(ConfirmModal.ButtonTypes), ButtonTypes.YesNo); + var confirm = await ModalService.Show("Delete Comment", parameters).Result; + if (confirm.Confirmed) + { + await Review.RemoveComment(comment); + } + } } diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor index 40072e31..04656cc7 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor @@ -3,25 +3,33 @@ @using iRLeagueApiCore.Common.Models.Reviews @using iRLeagueManager.Web.ViewModels -
    -
    @Bind(Comment, x => x.AuthorName)
    -
    - @Bind(Comment, x=> x.Text) -
    +
    - @foreach(var vote in @Bind(Comment, x => x.Votes)) - { - var member = @Bind(vote, x => x.MemberAtFault); - @Bind(vote, x => x.VoteCategoryText)@(member != null ? $": {member.FirstName} {member.LastName}" : string.Empty) - } +
    @Bind(Comment, x => x.AuthorName)
    +
    + @Bind(Comment, x=> x.Text) +
    +
    + @foreach(var vote in @Bind(Comment, x => x.Votes)) + { + var member = @Bind(vote, x => x.MemberAtFault); + @Bind(vote, x => x.VoteCategoryText)@(member != null ? $": {member.FirstName} {member.LastName}" : string.Empty) + } +
    @if (UserCanEdit) { -
    - -
    + }
    +@if (UserCanEdit) +{ +
    + +
    +} @code { [CascadingParameter] @@ -33,27 +41,21 @@ [CascadingParameter] private Task AuthenticationStateTask { get; set; } = default!; [Parameter] - public EventCallback OnStateHasChanged { get; set; } = default!; + public EventCallback OnStateHasChanged { get; set; } + [Parameter] + public EventCallback OnDeleteClick { get; set; } private bool UserCanEdit; //[Parameter] //public EventCallback EditClick { get; set; } - protected override void OnParametersSet() + protected override async Task OnParametersSetAsync() { - _ = Comment ?? throw new InvalidOperationException($"Parameter {nameof(Comment)} must have a value"); + _ = Comment ?? throw BlazorParameterNullException.New(this, Comment); _ = AuthenticationStateTask ?? throw BlazorParameterNullException.New(this, AuthenticationStateTask); - base.OnParametersSet(); - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender == false) - { - return; - } UserCanEdit = await GetUserCanEdit(); + base.OnParametersSet(); } private async Task GetUserCanEdit() @@ -82,7 +84,8 @@ .Add(nameof(EditCommentModal.Model), Comment.CopyModel()) .Add(nameof(EditCommentModal.InvolvedMembers), InvolvedMembers) .Add(nameof(EditCommentModal.OnSubmit), - new Func>(async (comment, cancellationToken) => await comment.SaveChangesAsync(cancellationToken))); + new Func>((comment, cancellationToken) => + comment.SaveChangesAsync(cancellationToken))); var result = await ModalService.Show("Edit Comment", parameters).Result; if (result.Confirmed && result.Data is ReviewCommentModel comment) { diff --git a/src/iRLeagueManager.Web/Pages/Reviews.razor b/src/iRLeagueManager.Web/Pages/Reviews.razor index 20641632..90efe34a 100644 --- a/src/iRLeagueManager.Web/Pages/Reviews.razor +++ b/src/iRLeagueManager.Web/Pages/Reviews.razor @@ -24,10 +24,11 @@ { await OnEditClick(review)) - DeleteClick=@(async () => await OnDeleteClick(review)) + OnEditClick=@(async () => await OnEditClick(review)) + OnDeleteClick=@(async () => await OnDeleteClick(review)) IsSteward=true - ReadOnly=ReadOnly/> + ReadOnly=@ReadOnly + UserId=@UserId/> } @if (ReadOnly == false) { @@ -49,9 +50,19 @@ public SharedStateService SharedState { get; set; } = default!; [CascadingParameter] public IModalService ModalService { get; set; } = default!; + [CascadingParameter] + private Task AuthTask { get; set; } = default!; + + private string UserId { get; set; } = string.Empty; private bool ReadOnly => SharedState.SeasonFinished; + protected override async Task OnParametersSetAsync() + { + _ = AuthTask ?? throw BlazorParameterNullException.New(this, AuthTask); + await SetCurrentUserId(); + } + protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); @@ -66,6 +77,12 @@ } } + private async Task SetCurrentUserId() + { + var state = await AuthTask; + UserId = state.User.GetUserId() ?? string.Empty; + } + private async Task OnEditClick(ReviewViewModel review) { var parameters = new ModalParameters() diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs index f96ad46d..b06edd36 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs @@ -1,97 +1,90 @@ using iRLeagueApiCore.Common.Models.Reviews; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using System.Collections.ObjectModel; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ReviewCommentViewModel : LeagueViewModelBase { - public class ReviewCommentViewModel : LeagueViewModelBase + public ReviewCommentViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService, new()) { - public ReviewCommentViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService, new()) - { - } - public ReviewCommentViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ReviewCommentModel model) : - base(loggerFactory, apiService, model) - { - } + } + public ReviewCommentViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ReviewCommentModel model) : + base(loggerFactory, apiService, model) + { + } - public long CommentId => model.CommentId; - public long ReviewId => model.ReviewId; - public DateTime Date => model.Date.GetValueOrDefault(); - public string AuthorName => model.AuthorName; - public string AuthorUserId => model.AuthorUserId; - public DateTime CreatedOn => model.CreatedOn.GetValueOrDefault(); - public DateTime LastModifiedOn => model.LastModifiedOn.GetValueOrDefault(); + public long CommentId => model.CommentId; + public long ReviewId => model.ReviewId; + public DateTime Date => model.Date.GetValueOrDefault(); + public string AuthorName => model.AuthorName; + public string AuthorUserId => model.AuthorUserId; + public DateTime CreatedOn => model.CreatedOn.GetValueOrDefault(); + public DateTime LastModifiedOn => model.LastModifiedOn.GetValueOrDefault(); - public string Text { get => model.Text; set => SetP(model.Text, value => model.Text = value, value); } - - private ObservableCollection votes = new(); - public ObservableCollection Votes { get => votes; set => Set(ref votes, value); } + public string Text { get => model.Text; set => SetP(model.Text, value => model.Text = value, value); } - public void AddVote(VoteViewModel vote) - { - votes.Add(vote); - model.Votes.Add(vote.GetModel()); - } + private ObservableCollection votes = new(); + public ObservableCollection Votes { get => votes; set => Set(ref votes, value); } - public void AddVote(VoteModel vote) - { - model.Votes.Add(vote); - votes.Add(new VoteViewModel(LoggerFactory, ApiService, vote)); - } + public void AddVote(VoteViewModel vote) + { + votes.Add(vote); + model.Votes.Add(vote.GetModel()); + } + + public void AddVote(VoteModel vote) + { + model.Votes.Add(vote); + votes.Add(new VoteViewModel(LoggerFactory, ApiService, vote)); + } + + public void RemoveVote(VoteViewModel vote) + { + votes.Remove(vote); + model.Votes.Remove(vote.GetModel()); + } - public void RemoveVote(VoteViewModel vote) + private void RefreshVoteList() + { + if (model.Votes == null) { - votes.Remove(vote); - model.Votes.Remove(vote.GetModel()); + return; } + Votes = new ObservableCollection(model.Votes.Select(x => new VoteViewModel(LoggerFactory, ApiService, x))); + } - private void RefreshVoteList() + public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - if (model.Votes == null) - { - return; - } - Votes = new ObservableCollection(model.Votes.Select(x => new VoteViewModel(LoggerFactory, ApiService, x))); + return LeagueNullResult(); } - public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + try { - if (model == null) - { - return true; - } - if (ApiService.CurrentLeague == null) + Loading = true; + var request = ApiService.CurrentLeague.ReviewComments() + .WithId(CommentId) + .Put(model); + var result = await request; + if (result.Success == false || result.Content is null) { - return false; - } - - try - { - Loading = true; - var request = ApiService.CurrentLeague.ReviewComments() - .WithId(CommentId) - .Put(model); - var result = await request; - if (result.Success == false || result.Content is null) - { - result.EnsureSuccess(); - return false; - } - SetModel(result.Content); - return true; - } - finally - { - Loading = false; + return result.ToStatusResult(); } + SetModel(result.Content); + return result.ToStatusResult(); } - - public override void SetModel(ReviewCommentModel model) + finally { - base.SetModel(model); - RefreshVoteList(); + Loading = false; } } -} \ No newline at end of file + + public override void SetModel(ReviewCommentModel model) + { + base.SetModel(model); + RefreshVoteList(); + } +} diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs index 365261a2..8b63c7de 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs @@ -124,26 +124,25 @@ public void RemoveMemberSelection(IEnumerable selection) /// /// /// - public async Task AddComment(PostReviewCommentModel postComment) + public async Task AddComment(PostReviewCommentModel postComment, CancellationToken cancellationToken) { // Get the endpoint var reviewEndpoint = GetReviewEndpoint(); if (reviewEndpoint == null) { - return false; + return LeagueNullResult(); } // Upload comment var result = await reviewEndpoint.ReviewComments().Post(postComment); - if (result.Success == false) + if (result.Success && result.Content is not null) { - return false; + // Update comment list + model.ReviewComments = model.ReviewComments.Concat(new[] { result.Content }); + RefreshCommentList(); } - // Update comment list - RefreshCommentList(); - - return true; + return result.ToStatusResult(); } /// @@ -151,18 +150,25 @@ public async Task AddComment(PostReviewCommentModel postComment) /// /// /// - public async Task RemoveComment(long commentId) + public async Task RemoveComment(ReviewCommentViewModel comment, CancellationToken cancellationToken = default) { - var commentEndpoint = ApiService.CurrentLeague? + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + var commentEndpoint = ApiService.CurrentLeague .ReviewComments() - .WithId(commentId); - if (commentEndpoint == null) + .WithId(comment.CommentId); + + var result = await commentEndpoint.Delete(cancellationToken); + if (result.Success) { - return false; + model.ReviewComments = model.ReviewComments.Except(new[] { comment.GetModel() }); + RefreshCommentList(); } - var result = await commentEndpoint.Delete(); - return result.Success; + return result.ToStatusResult(); } /// diff --git a/src/iRLeagueManager.Web/appsettings.json b/src/iRLeagueManager.Web/appsettings.json index bed1c144..79e31d96 100644 --- a/src/iRLeagueManager.Web/appsettings.json +++ b/src/iRLeagueManager.Web/appsettings.json @@ -9,8 +9,8 @@ } }, "AllowedHosts": "*", - //"APIServer": "http://localhost:5000", - "APIServer": "https://irleaguemanager.net/irleagueapi/", + "APIServer": "http://localhost:5000", + //"APIServer": "https://irleaguemanager.net/irleagueapi/", "DefaultUser": "testuser", "DefaultPassword": "TestPass123!" } From d0da471952de183f5435f1dee100ffa613bca850 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 15 Dec 2022 17:48:48 +0100 Subject: [PATCH 06/33] Fix vote selection not working on comment add --- src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor | 2 +- src/iRLeagueManager.Web/Program.cs | 6 ------ src/iRLeagueManager.Web/iRLeagueManager.Web.csproj | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor index 3a8e5fdb..1ba17026 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor @@ -211,7 +211,7 @@ private async Task AddCommentClick() { var parameters = new ModalParameters() - .Add(nameof(EditCommentModal.Model), new ReviewCommentModel()) + .Add(nameof(EditCommentModal.Model), new ReviewCommentModel() { Votes = new List() }) .Add(nameof(EditReviewResultModal.InvolvedMembers), Review.InvolvedMembers) .Add(nameof(EditCommentModal.OnSubmit), new Func>((comment, cancellationToken) => Review.AddComment(comment.GetModel(), cancellationToken))); diff --git a/src/iRLeagueManager.Web/Program.cs b/src/iRLeagueManager.Web/Program.cs index e7424b6c..dc828a6f 100644 --- a/src/iRLeagueManager.Web/Program.cs +++ b/src/iRLeagueManager.Web/Program.cs @@ -6,15 +6,9 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Server.Data; using iRLeagueManager.Web.Shared; -using iRLeagueManager.Web.ViewModels; -using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Server; -using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI; -using Microsoft.EntityFrameworkCore; using System.Text.Json; using System.Text.Json.Serialization; diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index d4588443..3a2364ed 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -2,7 +2,7 @@ net6.0 - 0.4.0 + 0.4.1-dev.1 enable enable aspnet-iRLeagueManager.Web-2B05F9DC-55A3-49D1-BD64-31507000EDF3 From 76c321bc066c465750947f6ae56a6c487a4707b9 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 16 Dec 2022 08:15:16 +0100 Subject: [PATCH 07/33] disable menu closing on season select --- src/iRLeagueManager.Web/Shared/NavMenu.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iRLeagueManager.Web/Shared/NavMenu.razor b/src/iRLeagueManager.Web/Shared/NavMenu.razor index 70cd35df..b099cd4e 100644 --- a/src/iRLeagueManager.Web/Shared/NavMenu.razor +++ b/src/iRLeagueManager.Web/Shared/NavMenu.razor @@ -22,7 +22,7 @@
    diff --git a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs index 978cbf6e..dd527a7e 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs @@ -24,6 +24,7 @@ public ScoringViewModel(ILoggerFactory loggerFactory, LeagueApiService apiServic public bool UseResultSetTeam { get => model.UseResultSetTeam; set => SetP(model.UseResultSetTeam, value => model.UseResultSetTeam = value, value); } public bool UpdateTeamOnRecalculation { get => model.UpdateTeamOnRecalculation; set => SetP(model.UpdateTeamOnRecalculation, value => model.UpdateTeamOnRecalculation = value, value); } public int MaxResultsPerGroup { get => model.MaxResultsPerGroup; set => SetP(model.MaxResultsPerGroup, value => model.MaxResultsPerGroup = value, value); } + public bool CalcPoints { get => !model.UseSourcePoints; set => SetP(model.UseSourcePoints, value => model.UseSourcePoints = value, !value); } private PointRuleViewModel pointRule; public PointRuleViewModel PointRule { get => pointRule; set => Set(ref pointRule, value); } diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index 3a2364ed..f37ca0c3 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -21,7 +21,7 @@ - + From 6bd09d03bf2280382a049e190ffe4471c1db487b Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 23 Dec 2022 12:06:59 +0100 Subject: [PATCH 09/33] implement password reset from webpage --- .../Components/DisplaySchedule.razor | 2 +- .../Components/Results/DisplayResult.razor | 2 +- .../Settings/EditPointRuleModal.razor | 2 +- .../Components/Settings/EditScoring.razor | 2 +- .../Standings/DisplayStanding.razor | 2 +- src/iRLeagueManager.Web/Pages/Leagues.razor | 2 +- .../Pages/Member/Login.razor | 51 +++++----- .../Pages/Member/PasswordReset.razor | 99 +++++++++++++++++++ .../Pages/Member/RequestPasswordReset.razor | 97 ++++++++++++++++++ src/iRLeagueManager.Web/Pages/Results.razor | 4 +- src/iRLeagueManager.Web/Pages/Reviews.razor | 6 +- src/iRLeagueManager.Web/Pages/Schedules.razor | 6 +- src/iRLeagueManager.Web/Pages/Seasons.razor | 2 +- src/iRLeagueManager.Web/Pages/Standings.razor | 4 +- .../iRLeagueManager.Web.csproj | 2 +- 15 files changed, 241 insertions(+), 42 deletions(-) create mode 100644 src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor create mode 100644 src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor diff --git a/src/iRLeagueManager.Web/Components/DisplaySchedule.razor b/src/iRLeagueManager.Web/Components/DisplaySchedule.razor index 635b95f9..04e7ad70 100644 --- a/src/iRLeagueManager.Web/Components/DisplaySchedule.razor +++ b/src/iRLeagueManager.Web/Components/DisplaySchedule.razor @@ -31,7 +31,7 @@
    @Bind(Schedule, x => x.Name)
    } -
    +
    diff --git a/src/iRLeagueManager.Web/Components/Results/DisplayResult.razor b/src/iRLeagueManager.Web/Components/Results/DisplayResult.razor index fbe5439b..0364d3b9 100644 --- a/src/iRLeagueManager.Web/Components/Results/DisplayResult.razor +++ b/src/iRLeagueManager.Web/Components/Results/DisplayResult.razor @@ -14,7 +14,7 @@ var displayStartPos = resultRows.Any(x => x.StartPosition != 0); var displayQualyLap = resultRows.Any(x => x.QualifyingTime > TimeSpan.FromSeconds(1)); } -
    +
    diff --git a/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor b/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor index 67887308..e6f053bd 100644 --- a/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor +++ b/src/iRLeagueManager.Web/Components/Settings/EditPointRuleModal.razor @@ -23,7 +23,7 @@ break; case @PointRuleViewModel.PointRuleType.PointList:
    -
    +
    @{var pointsPerPlace = @Bind(PointRule, x => x.PointsPerPlace);}
    diff --git a/src/iRLeagueManager.Web/Components/Settings/EditScoring.razor b/src/iRLeagueManager.Web/Components/Settings/EditScoring.razor index 30d4f4ef..28e3ea72 100644 --- a/src/iRLeagueManager.Web/Components/Settings/EditScoring.razor +++ b/src/iRLeagueManager.Web/Components/Settings/EditScoring.razor @@ -24,7 +24,7 @@ } @if (@Bind(pointRule, x => x.PointsPerPlace).Count() > 0) { -
    +
    diff --git a/src/iRLeagueManager.Web/Components/Standings/DisplayStanding.razor b/src/iRLeagueManager.Web/Components/Standings/DisplayStanding.razor index e07ea3ad..e480f2b0 100644 --- a/src/iRLeagueManager.Web/Components/Standings/DisplayStanding.razor +++ b/src/iRLeagueManager.Web/Components/Standings/DisplayStanding.razor @@ -4,7 +4,7 @@
    @Standing.Name
    -
    +
    @{ var showDriver = HasDriver(Standing.StandingRows) && Standing.IsTeamStanding == false; diff --git a/src/iRLeagueManager.Web/Pages/Leagues.razor b/src/iRLeagueManager.Web/Pages/Leagues.razor index 71b92ae5..ee22cd1c 100644 --- a/src/iRLeagueManager.Web/Pages/Leagues.razor +++ b/src/iRLeagueManager.Web/Pages/Leagues.razor @@ -13,7 +13,7 @@

    Leagues

    -
    +
    diff --git a/src/iRLeagueManager.Web/Pages/Member/Login.razor b/src/iRLeagueManager.Web/Pages/Member/Login.razor index f00fcb7a..b6e26af9 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Login.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Login.razor @@ -9,30 +9,33 @@ @inject NavigationManager NavigationManager @attribute [AllowAnonymous] -
    -

    Login

    -
    - - - -
    - - - -
    -
    - - - -
    - -
    +
    +
    +

    Login

    +
    + + + +
    + + + +
    +
    + + + +
    + +
    + Forgot password +
    diff --git a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor new file mode 100644 index 00000000..fc87d4a7 --- /dev/null +++ b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor @@ -0,0 +1,99 @@ +@page "/member/{UserId}/SetPassword/{ResetToken}" +@using System.ComponentModel.DataAnnotations +@using Microsoft.AspNetCore.WebUtilities +@using System.Text +@inject NavigationManager NavigationManager +@inject LeagueApiService ApiService +@attribute [AllowAnonymous] + +
    + @if (Success) + { +

    + Your password was successfully set.
    You can now try to login again. +

    + } + else + { +
    +

    Set new Password

    +
    + + + +
    + + + +
    +
    + + + +
    + + +
    +
    +
    + } +
    + +@code { + [Parameter] + public string UserId { get; set; } = string.Empty; + [Parameter] + public string ResetToken { get; set; } = string.Empty; + + private bool Loading { get; set; } + + private bool Success { get; set; } + + private StatusResultValidator ResultValidator { get; set; } = default!; + + public record SetPassword + { + [Required] + public string? NewPassword { get; set; } + [Required] + [Compare(nameof(NewPassword), ErrorMessage = "Confirmed password is not the same")] + public string? ConfirmPassword { get; set; } + } + + private SetPassword model { get; } = new(); + + protected override void OnParametersSet() + { + _ = UserId ?? throw BlazorParameterNullException.New(this, UserId); + _ = ResetToken ?? throw BlazorParameterNullException.New(this, ResetToken); + } + + private async Task OnValidSubmit() + { + try + { + Loading = true; + var token = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(ResetToken)); + var requestUrl = $"Authenticate/SetPassword/{UserId}"; + var request = ApiService.Client.CustomEndpoint(requestUrl) + .Post(new { PasswordToken = token, NewPassword = model.NewPassword}); + var result = await request; + if (result.Success == false) + { + ResultValidator.ValidateResult(result.ToStatusResult()); + return; + } + Success = true; + } + finally + { + Loading = false; + } + } +} diff --git a/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor b/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor new file mode 100644 index 00000000..0781e5cb --- /dev/null +++ b/src/iRLeagueManager.Web/Pages/Member/RequestPasswordReset.razor @@ -0,0 +1,97 @@ +@page "/member/PasswordReset" +@using System.ComponentModel.DataAnnotations +@using Microsoft.AspNetCore.WebUtilities +@using System.Text +@inject NavigationManager NavigationManager +@inject LeagueApiService ApiService +@attribute [AllowAnonymous] + +
    + @if (Success) + { +

    Password reset requested. An email with a link to set a new password has been send to your email address.

    +

    If you do not receive the mail immediately please wait a few minutes and check your spam folders.

    + } + else + { +
    +

    Request Password Reset

    +
    + + + +
    + + + +
    +
    + + + +
    + + +
    +
    +
    + } +
    + +@code { + private bool Loading { get; set; } + + private StatusResultValidator ResultValidator { get; set; } = default!; + + private bool Success { get; set; } + + public record ResetPassword + { + [Required] + public string UserName { get; set; } = string.Empty; + [Required, EmailAddress] + public string Email { get; set; } = string.Empty; + + public string LinkUriTemplate { get; set; } = string.Empty; + } + + private ResetPassword model { get; } = new(); + + private async Task OnValidSubmit() + { + try + { + Loading = true; + model.LinkUriTemplate = GenerateLinkUrlTemplate(); + var requestUrl = $"Authenticate/ResetPassword"; + var request = ApiService.Client.CustomEndpoint(requestUrl) + .Post(model); + var result = await request; + if (result.Success == false) + { + ResultValidator.ValidateResult(result.ToStatusResult()); + return; + } + Success = true; + } + catch(Exception ex) + { + ResultValidator.ErrorMessage = ex.Message; + } + finally + { + Loading = false; + } + } + + private string GenerateLinkUrlTemplate() + { + return $"{NavigationManager.BaseUri}member/{{userId}}/SetPassword/{{token}}"; + } +} diff --git a/src/iRLeagueManager.Web/Pages/Results.razor b/src/iRLeagueManager.Web/Pages/Results.razor index d8f5accb..cab774b6 100644 --- a/src/iRLeagueManager.Web/Pages/Results.razor +++ b/src/iRLeagueManager.Web/Pages/Results.razor @@ -13,7 +13,7 @@ @inherits LeagueComponentBase @inject ResultsPageViewModel vm -
    +
    x.Loading)>

    Results

    @@ -55,7 +55,7 @@ { @foreach(var result in @Bind(vm.SelectedEventResult!, x => x.SessionResults).OrderByDescending(x => x.SessionNr)) { - + } } diff --git a/src/iRLeagueManager.Web/Pages/Reviews.razor b/src/iRLeagueManager.Web/Pages/Reviews.razor index 90efe34a..dab6fc31 100644 --- a/src/iRLeagueManager.Web/Pages/Reviews.razor +++ b/src/iRLeagueManager.Web/Pages/Reviews.razor @@ -11,7 +11,7 @@ @inherits LeagueComponentBase @inject ReviewsPageViewModel ReviewsVm -
    +
    x.Loading))>

    Reviews

    @@ -22,7 +22,7 @@ @foreach(var review in OrderReviews(@Bind(ReviewsVm, x => x.Reviews))) { - await OnEditClick(review)) OnDeleteClick=@(async () => await OnDeleteClick(review)) @@ -38,7 +38,7 @@ @foreach(var review in OrderReviews(@Bind(ReviewsVm, x => x.Reviews))) { - + } diff --git a/src/iRLeagueManager.Web/Pages/Schedules.razor b/src/iRLeagueManager.Web/Pages/Schedules.razor index 2f0c67c3..a35aaf18 100644 --- a/src/iRLeagueManager.Web/Pages/Schedules.razor +++ b/src/iRLeagueManager.Web/Pages/Schedules.razor @@ -9,7 +9,7 @@ @inject SchedulesPageViewModel vm @inject JsonSerializerOptions jsonOptions -
    +
    x.Loading)>

    Schedules

    @@ -19,7 +19,7 @@
    @foreach(var schedule in @Bind(vm, x => x.Schedules)) { - + }
    @@ -27,7 +27,7 @@
    @foreach(var schedule in @Bind(vm, x => x.Schedules)) { - + }
    diff --git a/src/iRLeagueManager.Web/Pages/Seasons.razor b/src/iRLeagueManager.Web/Pages/Seasons.razor index 0b0a5c67..dd83401a 100644 --- a/src/iRLeagueManager.Web/Pages/Seasons.razor +++ b/src/iRLeagueManager.Web/Pages/Seasons.razor @@ -13,7 +13,7 @@

    Seasons

    -
    +

    @sharedState.SeasonName

    diff --git a/src/iRLeagueManager.Web/Pages/Standings.razor b/src/iRLeagueManager.Web/Pages/Standings.razor index 4040ed40..09ad1de0 100644 --- a/src/iRLeagueManager.Web/Pages/Standings.razor +++ b/src/iRLeagueManager.Web/Pages/Standings.razor @@ -14,7 +14,7 @@ @inherits LeagueComponentBase @inject StandingsPageViewModel vm -
    +
    x.Loading)>

    Standings

    @@ -36,7 +36,7 @@ @if (@Bind(vm, x => x.SelectedStanding) != null) { - x.SelectedStanding)/> + x.SelectedStanding)/> }
    diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index f37ca0c3..368c63be 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -20,7 +20,7 @@ - + From 5fcd016568ec4a465de9f70f114f2081c01b3140 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 23 Dec 2022 12:16:23 +0100 Subject: [PATCH 10/33] Fix links --- src/iRLeagueManager.Web/Pages/Leagues.razor | 9 ++++----- src/iRLeagueManager.Web/Pages/Member/Login.razor | 2 +- src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor | 2 +- src/iRLeagueManager.Web/Pages/Seasons.razor | 8 ++++---- src/iRLeagueManager.Web/appsettings.json | 4 ++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/iRLeagueManager.Web/Pages/Leagues.razor b/src/iRLeagueManager.Web/Pages/Leagues.razor index ee22cd1c..8a807393 100644 --- a/src/iRLeagueManager.Web/Pages/Leagues.razor +++ b/src/iRLeagueManager.Web/Pages/Leagues.razor @@ -8,12 +8,11 @@ @inject LeaguesViewModel vm @inject ILeagueApiClient apiClient - - x.Loading)> -

    Leagues

    -
    -
    + x.Loading)> +

    Leagues

    +
    +
    diff --git a/src/iRLeagueManager.Web/Pages/Member/Login.razor b/src/iRLeagueManager.Web/Pages/Member/Login.razor index b6e26af9..4ce9f843 100644 --- a/src/iRLeagueManager.Web/Pages/Member/Login.razor +++ b/src/iRLeagueManager.Web/Pages/Member/Login.razor @@ -34,7 +34,7 @@ Login - Forgot password + Forgot password diff --git a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor index fc87d4a7..39178a59 100644 --- a/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor +++ b/src/iRLeagueManager.Web/Pages/Member/PasswordReset.razor @@ -10,7 +10,7 @@ @if (Success) {

    - Your password was successfully set.
    You can now try to login again. + Your password was successfully set.
    You can now try to login again.

    } else diff --git a/src/iRLeagueManager.Web/Pages/Seasons.razor b/src/iRLeagueManager.Web/Pages/Seasons.razor index dd83401a..82bbe43c 100644 --- a/src/iRLeagueManager.Web/Pages/Seasons.razor +++ b/src/iRLeagueManager.Web/Pages/Seasons.razor @@ -9,11 +9,11 @@ @inject SharedStateService sharedState @*@inject AuthenticationStateProvider authStateProvider*@ - x.Loading)> -

    Seasons

    -
    -
    + x.Loading)> +

    Seasons

    +
    +

    @sharedState.SeasonName

    diff --git a/src/iRLeagueManager.Web/appsettings.json b/src/iRLeagueManager.Web/appsettings.json index 79e31d96..bed1c144 100644 --- a/src/iRLeagueManager.Web/appsettings.json +++ b/src/iRLeagueManager.Web/appsettings.json @@ -9,8 +9,8 @@ } }, "AllowedHosts": "*", - "APIServer": "http://localhost:5000", - //"APIServer": "https://irleaguemanager.net/irleagueapi/", + //"APIServer": "http://localhost:5000", + "APIServer": "https://irleaguemanager.net/irleagueapi/", "DefaultUser": "testuser", "DefaultPassword": "TestPass123!" } From f098dc67b1508133a652f90fcb056e65d326026d Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 23 Dec 2022 19:04:57 +0100 Subject: [PATCH 11/33] code cleanup using profile --- src/iRLeagueManager.Web/Data/AsyncTokenStore.cs | 10 +--------- .../Data/AuthenticatedHttpClientFactory.cs | 4 +--- .../Data/LeagueApiClientFactory.cs | 10 +++------- src/iRLeagueManager.Web/Data/LeagueApiService.cs | 1 - .../Data/SamePropertyEqualityComparer.cs | 8 +++----- src/iRLeagueManager.Web/Data/SharedStateService.cs | 2 -- src/iRLeagueManager.Web/Data/StatusResult.cs | 7 +++---- .../Exceptions/BlazorParameterNullException.cs | 2 +- .../Extensions/LeagueApiClientExtensions.cs | 1 - .../Shared/LeagueComponentBase.cs | 4 ++-- .../Shared/StatusResultValidator.cs | 2 +- .../ViewModels/EventListViewModel.cs | 3 +-- .../ViewModels/EventResultViewModel.cs | 4 +--- .../ViewModels/LeagueUserViewModel.cs | 5 ++--- .../ViewModels/LeagueUsersViewModel.cs | 7 ++----- .../ViewModels/LeagueViewModel.cs | 6 +++--- .../ViewModels/LeagueViewModelBase.cs | 12 +++++------- .../ViewModels/LeaguesViewModel.cs | 2 +- .../ViewModels/PointRuleViewModel.cs | 2 +- .../ViewModels/ResultConfigSettingsViewModel.cs | 3 +-- .../ViewModels/ResultConfigViewModel.cs | 12 ++++++------ .../ViewModels/ResultFiltersViewModel.cs | 2 +- .../ViewModels/ResultsPageViewModel.cs | 2 +- .../ViewModels/ReviewViewModel.cs | 11 +++++------ .../ViewModels/ReviewsPageViewModel.cs | 5 ++--- .../ViewModels/ScheduleViewModel.cs | 6 ++---- .../ViewModels/SchedulesPageViewModel.cs | 4 +--- .../ViewModels/ScoringViewModel.cs | 7 ++----- .../ViewModels/SeasonViewModel.cs | 2 +- .../ViewModels/SeasonsViewModel.cs | 7 +------ .../ViewModels/SessionResultViewModel.cs | 4 ++-- .../ViewModels/SessionViewModel.cs | 6 +++--- .../ViewModels/SortOptionViewModel.cs | 3 +-- .../ViewModels/SortOptionsViewModel.cs | 2 +- .../ViewModels/StandingConfigurationViewModel.cs | 2 +- .../ViewModels/StandingsPageViewModel.cs | 1 - src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs | 2 +- 37 files changed, 63 insertions(+), 110 deletions(-) diff --git a/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs b/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs index 5eee7094..0daa89d6 100644 --- a/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs +++ b/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs @@ -1,14 +1,6 @@ using iRLeagueApiCore.Client.Http; -using System.Threading.Tasks; -using Blazored.LocalStorage; -using Microsoft.Extensions.Logging; -using System; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Components.Server; -using System.Security.Claims; -using System.IdentityModel.Tokens.Jwt; using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage; +using System.IdentityModel.Tokens.Jwt; namespace iRLeagueManager.Web.Data { diff --git a/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs b/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs index 3e0426ed..84df0394 100644 --- a/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs +++ b/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs @@ -1,6 +1,4 @@ -using System.Net.Http; - -namespace iRLeagueManager.Web.Server.Data +namespace iRLeagueManager.Web.Server.Data { public class AuthenticatedHttpClientFactory : IHttpClientFactory { diff --git a/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs b/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs index 141ee924..54c3d647 100644 --- a/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs +++ b/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs @@ -1,9 +1,5 @@ -using iRLeagueApiCore.Client; -using Microsoft.Extensions.Logging; -using System; -using System.Net.Http; -using Blazored.LocalStorage; -using System.Threading.Tasks; +using Blazored.LocalStorage; +using iRLeagueApiCore.Client; using iRLeagueApiCore.Client.Http; using System.Text.Json; @@ -20,7 +16,7 @@ public class LeagueApiClientFactory private readonly string baseAddress; - public LeagueApiClientFactory(IConfiguration configuration, ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory, + public LeagueApiClientFactory(IConfiguration configuration, ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory, ILocalStorageService localStorage, ITokenStore tokenStore, JsonSerializerOptions jsonOptions) { baseAddress = configuration["APIServer"]; diff --git a/src/iRLeagueManager.Web/Data/LeagueApiService.cs b/src/iRLeagueManager.Web/Data/LeagueApiService.cs index ae3fdee9..ddf216f3 100644 --- a/src/iRLeagueManager.Web/Data/LeagueApiService.cs +++ b/src/iRLeagueManager.Web/Data/LeagueApiService.cs @@ -2,7 +2,6 @@ using iRLeagueApiCore.Client.Endpoints.Leagues; using iRLeagueApiCore.Client.Endpoints.Seasons; using iRLeagueApiCore.Common.Models; -using System.Collections.ObjectModel; using System.Text.Json; namespace iRLeagueManager.Web.Data; diff --git a/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs b/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs index 17ed707e..94ee961f 100644 --- a/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs +++ b/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs @@ -1,7 +1,5 @@ -using iRLeagueApiCore.Common.Models; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; -using System.Reflection; namespace iRLeagueManager.Web.Data { @@ -9,8 +7,8 @@ public class SamePropertyEqualityComparer : IEqualityComparer>? x, Expression>? y) { - var xMemberExpression = x?.Body as MemberExpression - ?? (x?.Body as UnaryExpression)?.Operand as MemberExpression; + var xMemberExpression = x?.Body as MemberExpression + ?? (x?.Body as UnaryExpression)?.Operand as MemberExpression; var yMemberExpression = y?.Body as MemberExpression ?? (y?.Body as UnaryExpression)?.Operand as MemberExpression; if (xMemberExpression == null || yMemberExpression == null) diff --git a/src/iRLeagueManager.Web/Data/SharedStateService.cs b/src/iRLeagueManager.Web/Data/SharedStateService.cs index cc0d37b1..510084aa 100644 --- a/src/iRLeagueManager.Web/Data/SharedStateService.cs +++ b/src/iRLeagueManager.Web/Data/SharedStateService.cs @@ -1,6 +1,4 @@ using iRLeagueApiCore.Common.Models; -using System.Collections.ObjectModel; -using System.ComponentModel; using System.Runtime.CompilerServices; namespace iRLeagueManager.Web.Data; diff --git a/src/iRLeagueManager.Web/Data/StatusResult.cs b/src/iRLeagueManager.Web/Data/StatusResult.cs index ada8cdd8..f62f289d 100644 --- a/src/iRLeagueManager.Web/Data/StatusResult.cs +++ b/src/iRLeagueManager.Web/Data/StatusResult.cs @@ -1,9 +1,8 @@ using iRLeagueApiCore.Common.Responses; -using System.Linq; namespace iRLeagueManager.Web.Data { - public class StatusResult + public class StatusResult { public StatusResult(bool success, string status) { @@ -11,13 +10,13 @@ public StatusResult(bool success, string status) Status = status; } - public StatusResult(bool success, string status, string message) : + public StatusResult(bool success, string status, string message) : this(success, status) { Message = message; } - public StatusResult(bool success, string status, string message, IEnumerable errors) : + public StatusResult(bool success, string status, string message, IEnumerable errors) : this(success, status, message) { Message = message; diff --git a/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs b/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs index 0dbc28ff..9904c849 100644 --- a/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs +++ b/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs @@ -15,7 +15,7 @@ public static BlazorParameterNullException New : InvalidOperationException { - public BlazorParameterNullException() : + public BlazorParameterNullException() : base($"Usage of {typeof(TComponent)} requires a Parameter of type {typeof(TParameter)} but value was 'null'") { } diff --git a/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs b/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs index d5565681..a6d2751c 100644 --- a/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs +++ b/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs @@ -1,7 +1,6 @@ using iRLeagueApiCore.Client.Results; using iRLeagueManager.Web.Data; using Microsoft.AspNetCore.Components; -using System; using System.Collections.Specialized; using System.Runtime.Serialization; using System.Web; diff --git a/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs b/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs index d5ac359e..4428955a 100644 --- a/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs +++ b/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs @@ -103,7 +103,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) return; } SeasonId = ApiService.CurrentSeason.Id; - + HasRendered = true; await LoadEventList(ApiService.CurrentSeason.Id); if (EventId != null) @@ -143,7 +143,7 @@ protected override void Dispose(bool disposing) private void OnEventListPropertyChanged(object? sender, PropertyChangedEventArgs e) { - switch(e.PropertyName) + switch (e.PropertyName) { case nameof(EventList.Selected): _ = OnEventChangedAsync(EventList.Selected); diff --git a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs index 4c6ac324..b24e7e8d 100644 --- a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs +++ b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs @@ -54,7 +54,7 @@ public void ValidateResult(StatusResult result) private void DisplayErrorMessage(StatusResult result) { - foreach(var error in result.Errors) + foreach (var error in result.Errors) { if (error is Exception) { diff --git a/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs index ebaf7d1d..ec0ccc09 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs @@ -1,11 +1,10 @@ using iRLeagueManager.Web.Data; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { public class EventListViewModel : LeagueViewModelBase { - public EventListViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public EventListViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { } diff --git a/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs index 2de66a50..fefb210f 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs @@ -1,7 +1,5 @@ using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; -using System.Collections.ObjectModel; -using System.Linq.Expressions; namespace iRLeagueManager.Web.ViewModels { @@ -9,7 +7,7 @@ public class EventResultViewModel : LeagueViewModelBase { private EventResultModel model; - public EventResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public EventResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new EventResultModel()) { } diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs index ee5963bf..7bf85168 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs @@ -2,13 +2,12 @@ using iRLeagueApiCore.Common.Models.Users; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using System.Collections.Generic; namespace iRLeagueManager.Web.ViewModels { public class LeagueUserViewModel : LeagueViewModelBase { - public LeagueUserViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueUserModel model) : + public LeagueUserViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueUserModel model) : base(loggerFactory, apiService, model) { } @@ -16,7 +15,7 @@ public LeagueUserViewModel(ILoggerFactory loggerFactory, LeagueApiService apiSer public string UserId => model.UserId; public string UserName { get => model.UserName; set => SetP(model.UserName, value => model.UserName = value, value); } public string FirstName { get => model.Firstname; set => SetP(model.Firstname, value => model.Firstname = value, value); } - public string LastName { get => model.Lastname; set => SetP(model.Lastname, value => model.Lastname = value,value); } + public string LastName { get => model.Lastname; set => SetP(model.Lastname, value => model.Lastname = value, value); } public IEnumerable Roles => model.LeagueRoles.Select(x => LeagueRoles.GetRoleValue(x)); diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs index f0584757..1d2af3a6 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs @@ -1,15 +1,12 @@ -using iRLeagueApiCore.Client.Results; -using iRLeagueApiCore.Common.Models.Users; +using iRLeagueApiCore.Common.Models.Users; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using Microsoft.AspNetCore.Mvc; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { public class LeagueUsersViewModel : LeagueViewModelBase { - public LeagueUsersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public LeagueUsersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { } diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs index c50969c8..2cc17da7 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs @@ -1,6 +1,6 @@ using iRLeagueApiCore.Common.Models; -using iRLeagueManager.Web.Extensions; using iRLeagueManager.Web.Data; +using iRLeagueManager.Web.Extensions; namespace iRLeagueManager.Web.ViewModels; @@ -11,7 +11,7 @@ public LeagueViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService { } - public LeagueViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueModel model) : + public LeagueViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueModel model) : base(loggerFactory, apiService, model) { seasons = new ObservableCollection(); @@ -74,7 +74,7 @@ public async Task LoadCurrent(CancellationToken cancellationToken } finally { - Loading = false; + Loading = false; } } diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs b/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs index 83c98a6a..0f42bfc9 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs @@ -1,8 +1,6 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Shared; using MvvmBlazor.ViewModel; -using System.Linq.Expressions; -using System.Reflection; using System.Runtime.CompilerServices; using System.Text.Json; @@ -23,8 +21,8 @@ public LeagueViewModelBase(ILoggerFactory loggerFactory, LeagueApiService apiSer protected CancellationTokenSource Cts { get; } = new(); private bool loading; - public bool Loading - { + public bool Loading + { get => loading; protected set => Set(ref loading, value); } @@ -85,10 +83,10 @@ protected bool SetP(TProperty get, Action set, TProperty v // return false; //} - protected static StatusResult LeagueNullResult() => + protected static StatusResult LeagueNullResult() => StatusResult.FailedResult("League Null", $"{nameof(LeagueApiService)}.{nameof(LeagueApiService.CurrentLeague)} was null", Array.Empty()); - protected static StatusResult SeasonNullResult() => + protected static StatusResult SeasonNullResult() => StatusResult.FailedResult("Season Null", $"{nameof(LeagueApiService)}.{nameof(LeagueApiService.CurrentSeason)} was null", Array.Empty()); } @@ -96,7 +94,7 @@ public class LeagueViewModelBase : LeagueViewModelBase private string _status; public string Status { get => _status; set => Set(ref _status, value); } - public LeaguesViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public LeaguesViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { _status = string.Empty; diff --git a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs index 0a1cd545..a303dcae 100644 --- a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs @@ -11,7 +11,7 @@ public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiServ { } - public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, PointRuleModel model) : + public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, PointRuleModel model) : base(loggerFactory, apiService, model) { } diff --git a/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs index 63d8a3b2..ee08bf75 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs @@ -1,13 +1,12 @@ using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { public class ResultConfigSettingsViewModel : LeagueViewModelBase { - public ResultConfigSettingsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public ResultConfigSettingsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { resultConfigs = new ObservableCollection(); diff --git a/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs index edfd6eca..76accfa9 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs @@ -28,14 +28,14 @@ public ResultConfigViewModel(ILoggerFactory loggerFactory, LeagueApiService apiS public ResultKind ResultKind { get => model.ResultKind; set => SetP(model.ResultKind, value => model.ResultKind = value, value); } public int ResultsPerTeam { get => model.ResultsPerTeam; set => SetP(model.ResultsPerTeam, value => model.ResultsPerTeam = value, value); } public ResultConfigInfoModel? SourceResultConfig { get => model.SourceResultConfig; set => SetP(model.SourceResultConfig, value => model.SourceResultConfig = value, value); } - public long SourceResultConfigId - { + public long SourceResultConfigId + { get => SourceResultConfig?.ResultConfigId ?? 0; set => SetP(SourceResultConfig, value => SourceResultConfig = value, GetConfigInfoModel(AvailableResultConfigs.FirstOrDefault(x => x.ResultConfigId == value))); } - public bool CalculateCombinedResult - { - get => Scorings.Any(x => x.IsCombinedResult); + public bool CalculateCombinedResult + { + get => Scorings.Any(x => x.IsCombinedResult); set { if (value && CalculateCombinedResult == false) @@ -163,7 +163,7 @@ public void RemoveScoring(ScoringViewModel scoring) private void UpdateScoringIndex() { - foreach(var (scoring, index) in model.Scorings.Where(x => x.IsCombinedResult == false).Select((x, i) => (x, i))) + foreach (var (scoring, index) in model.Scorings.Where(x => x.IsCombinedResult == false).Select((x, i) => (x, i))) { scoring.Index = index; } diff --git a/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs index 2a146497..6d659934 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.ViewModels; public class ResultFiltersViewModel : LeagueViewModelBase { - public ResultFiltersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public ResultFiltersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { filters = new(); diff --git a/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs index 1d996435..d84e5078 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs @@ -171,7 +171,7 @@ public async Task DeleteEventResults(CancellationToken cancellatio { await LoadFromEventAsync(SelectedEvent.EventId); } - return result.ToStatusResult(); + return result.ToStatusResult(); } finally { diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs index 8b63c7de..c9e47113 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs @@ -3,13 +3,12 @@ using iRLeagueApiCore.Common.Models.Reviews; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { public class ReviewViewModel : LeagueViewModelBase { - public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService, new()) { } @@ -20,7 +19,7 @@ public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService public long ReviewId => model.ReviewId; public long EventId => model.EventId; - public string SessionName => model.SessionName; + public string SessionName => model.SessionName; public int SessionNr => model.SessionNr; public long SeasonId => model.SeasonId; public string AuthorName => model.AuthorName; @@ -186,14 +185,14 @@ public async Task RemoveComment(ReviewCommentViewModel comment, Ca private void UpdateModelMemberList() { - foreach(var member in InvolvedMembers) + foreach (var member in InvolvedMembers) { if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) { model.InvolvedMembers.Add(member); } } - foreach(var member in model.InvolvedMembers.ToArray()) + foreach (var member in model.InvolvedMembers.ToArray()) { if (InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) { @@ -301,7 +300,7 @@ private void RefreshVoteList() private IEnumerable GetCountedVotes() { List countedVotes = new(); - foreach(var vote in Comments.SelectMany(x => x.Votes)) + foreach (var vote in Comments.SelectMany(x => x.Votes)) { CountedVote? countedVote = countedVotes .FirstOrDefault(x => CompareVotes(vote, x.Vote)); diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs index bba06245..746e5c90 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs @@ -1,13 +1,12 @@ using iRLeagueApiCore.Common.Models.Members; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { public class ReviewsPageViewModel : LeagueViewModelBase { - public ReviewsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public ReviewsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { } @@ -51,7 +50,7 @@ public async Task LoadFromEventAsync(long eventId, CancellationToken cancellatio var reviewModels = result.Content; Reviews = new(reviewModels.Select(x => new ReviewViewModel(LoggerFactory, ApiService, x))); - + var membersEndpoint = eventEndpoint .Members(); var membersResult = await membersEndpoint.Get(cancellationToken); diff --git a/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs index 22b87c2e..a780563f 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs @@ -1,8 +1,6 @@ using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using MvvmBlazor.ViewModel; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { @@ -10,12 +8,12 @@ public class ScheduleViewModel : LeagueViewModelBase { private ScheduleModel model; - public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new ScheduleModel()) { } - public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScheduleModel model) : + public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScheduleModel model) : base(loggerFactory, apiService) { events = new ObservableCollection(); diff --git a/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs index 60ea83a9..f5ea486f 100644 --- a/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs @@ -1,12 +1,10 @@ using iRLeagueManager.Web.Data; -using MvvmBlazor.ViewModel; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels; public class SchedulesPageViewModel : LeagueViewModelBase { - public SchedulesPageViewModel(ILoggerFactory loggerFactory, ILogger logger, LeagueApiService apiService) + public SchedulesPageViewModel(ILoggerFactory loggerFactory, ILogger logger, LeagueApiService apiService) : base(loggerFactory, apiService) { schedules = new ObservableCollection(); diff --git a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs index dd527a7e..ef744d6b 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs @@ -1,15 +1,12 @@ -using iRLeagueApiCore.Common.Enums; -using iRLeagueApiCore.Common.Models; +using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; -using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations; -using System.Runtime.CompilerServices; namespace iRLeagueManager.Web.ViewModels { public class ScoringViewModel : LeagueViewModelBase { - public ScoringViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScoringModel model) : + public ScoringViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScoringModel model) : base(loggerFactory, apiService, model) { pointRule ??= new(loggerFactory, apiService); diff --git a/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs index 1dea38d2..299ea567 100644 --- a/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs @@ -12,7 +12,7 @@ public SeasonViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService } public SeasonViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, SeasonModel model) : - base (loggerFactory, apiService, model) + base(loggerFactory, apiService, model) { } diff --git a/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs index 64ff0e7d..d570a8a5 100644 --- a/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs @@ -1,10 +1,5 @@ -using iRLeagueApiCore.Client; -using iRLeagueManager.Web.Data; +using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using iRLeagueManager.Web.ViewModels; -using Microsoft.AspNetCore.Components; -using MvvmBlazor.ViewModel; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels; diff --git a/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs index e299753a..9a4d8444 100644 --- a/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs @@ -8,7 +8,7 @@ public class SessionResultViewModel : LeagueViewModelBase> OrderByPropertySelector } } public bool OrderDescending { get; private set; } - + public IEnumerable ResultRows { get diff --git a/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs index 7fc5a608..9105ca26 100644 --- a/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs @@ -8,7 +8,7 @@ public class SessionViewModel : LeagueViewModelBase { private SessionModel model; - public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) { model = new SessionModel(); @@ -22,9 +22,9 @@ public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiServic public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } public long SessionId { get => model.SessionId; set => SetP(model.SessionId, value => model.SessionId = value, value); } - public int SessionNr { get => model.SessionNr; set => SetP(model.SessionNr, value => model.SessionNr = value, value); } + public int SessionNr { get => model.SessionNr; set => SetP(model.SessionNr, value => model.SessionNr = value, value); } public SessionType SessionType { get => model.SessionType; set => SetP(model.SessionType, value => model.SessionType = value, value); } - public DateTime Duration + public DateTime Duration { get => DateTime.MinValue.Add(model.Duration); set => SetP(model.Duration, value => model.Duration = value, value.TimeOfDay); diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs index f77d296e..79c106da 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs @@ -1,5 +1,4 @@ using iRLeagueApiCore.Common.Enums; -using iRLeagueManager.Web.Data; namespace iRLeagueManager.Web.ViewModels { @@ -24,7 +23,7 @@ public SortValue SortValue } } } - + private SortDirection sortDirection; public SortDirection SortDirection { diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs index 466a92a7..31bdc641 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.ViewModels { public class SortOptionsViewModel : LeagueViewModelBase> { - public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new List()) { } diff --git a/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs b/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs index c98fbf00..b18d40da 100644 --- a/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs @@ -6,7 +6,7 @@ namespace iRLeagueManager.Web.ViewModels; public class StandingConfigurationViewModel : LeagueViewModelBase { - public StandingConfigurationViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, StandingConfigModel model) : + public StandingConfigurationViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, StandingConfigModel model) : base(loggerFactory, apiService, model) { } diff --git a/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs index 7e221e05..312a8e54 100644 --- a/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs @@ -1,7 +1,6 @@ using iRLeagueApiCore.Common.Models.Standings; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -using System.Collections.ObjectModel; namespace iRLeagueManager.Web.ViewModels { diff --git a/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs b/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs index 7306ed17..8844f8f9 100644 --- a/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs @@ -6,7 +6,7 @@ namespace iRLeagueManager.Web.ViewModels { public class VoteViewModel : LeagueViewModelBase { - public VoteViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, VoteModel model) : + public VoteViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, VoteModel model) : base(loggerFactory, apiService, model) { } From 5b3312b0a9385d990d90d225a890982d092cd4b6 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 23 Dec 2022 19:05:50 +0100 Subject: [PATCH 12/33] use file scoped namespaces --- .../Components/ButtonTypes.cs | 13 +- .../Components/ConfirmResult.cs | 15 +- .../Data/ApplicationDbContext.cs | 13 +- .../Data/AsyncTokenStore.cs | 149 +++-- .../Data/AuthenticatedHttpClientFactory.cs | 13 +- src/iRLeagueManager.Web/Data/CountedVote.cs | 17 +- .../Data/LeagueApiClientFactory.cs | 55 +- .../Data/SamePropertyEqualityComparer.cs | 35 +- src/iRLeagueManager.Web/Data/StatusResult.cs | 91 ++- .../Data/TrackListService.cs | 41 +- .../BlazorParameterNullException.cs | 37 +- .../Extensions/EnumerableExtensions.cs | 23 +- .../Extensions/LeagueApiClientExtensions.cs | 99 ++- .../Extensions/StringExtensions.cs | 15 +- .../Extensions/TimeSpanExtensions.cs | 19 +- src/iRLeagueManager.Web/Pages/Error.cshtml.cs | 33 +- src/iRLeagueManager.Web/Services.cs | 61 +- src/iRLeagueManager.Web/Shared/IModalBody.cs | 9 +- src/iRLeagueManager.Web/Shared/IModelState.cs | 15 +- .../Shared/JwtAuthenticationStateProvicer.cs | 73 ++- .../Shared/LeagueComponentBase.cs | 241 ++++--- .../Shared/LoginRedirect.cs | 43 +- src/iRLeagueManager.Web/Shared/RouteView.cs | 35 +- .../Shared/StatusResultValidator.cs | 133 ++-- .../ViewModels/EventListViewModel.cs | 121 ++-- .../ViewModels/EventResultViewModel.cs | 43 +- .../ViewModels/LeagueUserViewModel.cs | 117 ++-- .../ViewModels/LeagueUsersViewModel.cs | 109 ++-- .../ViewModels/LeagueViewModelBase.cs | 189 +++--- .../ViewModels/LeaguesViewModel.cs | 63 +- .../ViewModels/PointRuleViewModel.cs | 129 ++-- .../ResultConfigSettingsViewModel.cs | 133 ++-- .../ViewModels/ResultConfigViewModel.cs | 283 +++++---- .../ViewModels/ReviewViewModel.cs | 599 +++++++++--------- .../ViewModels/ReviewsPageViewModel.cs | 93 ++- .../ViewModels/ScheduleViewModel.cs | 207 +++--- .../ViewModels/ScoringViewModel.cs | 53 +- .../ViewModels/SessionResultViewModel.cs | 69 +- .../ViewModels/SessionViewModel.cs | 65 +- .../ViewModels/SortOptionViewModel.cs | 215 ++++--- .../ViewModels/SortOptionsViewModel.cs | 109 ++-- .../ViewModels/StandingsPageViewModel.cs | 121 ++-- .../ViewModels/VoteViewModel.cs | 53 +- 43 files changed, 2003 insertions(+), 2046 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/ButtonTypes.cs b/src/iRLeagueManager.Web/Components/ButtonTypes.cs index d607d3e8..78e2a391 100644 --- a/src/iRLeagueManager.Web/Components/ButtonTypes.cs +++ b/src/iRLeagueManager.Web/Components/ButtonTypes.cs @@ -1,9 +1,8 @@ -namespace iRLeagueManager.Web.Components +namespace iRLeagueManager.Web.Components; + +public enum ButtonTypes { - public enum ButtonTypes - { - Ok, - OkCancel, - YesNo, - } + Ok, + OkCancel, + YesNo, } diff --git a/src/iRLeagueManager.Web/Components/ConfirmResult.cs b/src/iRLeagueManager.Web/Components/ConfirmResult.cs index f2f386e3..0d868668 100644 --- a/src/iRLeagueManager.Web/Components/ConfirmResult.cs +++ b/src/iRLeagueManager.Web/Components/ConfirmResult.cs @@ -1,10 +1,9 @@ -namespace iRLeagueManager.Web.Components +namespace iRLeagueManager.Web.Components; + +public enum ConfirmResult { - public enum ConfirmResult - { - Ok, - Yes, - No, - Cancel - } + Ok, + Yes, + No, + Cancel } diff --git a/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs b/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs index 28973635..ffb964a3 100644 --- a/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs +++ b/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs @@ -1,13 +1,12 @@ using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -namespace iRLeagueManager.Web.Data +namespace iRLeagueManager.Web.Data; + +public class ApplicationDbContext : IdentityDbContext { - public class ApplicationDbContext : IdentityDbContext + public ApplicationDbContext(DbContextOptions options) + : base(options) { - public ApplicationDbContext(DbContextOptions options) - : base(options) - { - } } -} \ No newline at end of file +} diff --git a/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs b/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs index 0daa89d6..6b52a566 100644 --- a/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs +++ b/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs @@ -2,104 +2,103 @@ using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage; using System.IdentityModel.Tokens.Jwt; -namespace iRLeagueManager.Web.Data +namespace iRLeagueManager.Web.Data; + +public class AsyncTokenStore : ITokenStore { - public class AsyncTokenStore : ITokenStore - { - private readonly ILogger logger; - private readonly ProtectedLocalStorage localStore; + private readonly ILogger logger; + private readonly ProtectedLocalStorage localStore; + + private const string tokenKey = "LeagueApiToken"; + + private string inMemoryToken = string.Empty; - private const string tokenKey = "LeagueApiToken"; + public event EventHandler? TokenChanged; - private string inMemoryToken = string.Empty; + public bool IsLoggedIn { get; private set; } + public DateTime Expiration { get; private set; } - public event EventHandler? TokenChanged; + public AsyncTokenStore(ILogger logger, ProtectedLocalStorage localStorage) + { + this.logger = logger; + this.localStore = localStorage; + } - public bool IsLoggedIn { get; private set; } - public DateTime Expiration { get; private set; } + public async Task ClearTokenAsync() + { + var tokenValue = inMemoryToken; - public AsyncTokenStore(ILogger logger, ProtectedLocalStorage localStorage) + logger.LogDebug("Clear token in local browser store"); + IsLoggedIn = false; + inMemoryToken = string.Empty; + await localStore.DeleteAsync(tokenKey); + await Task.FromResult(true); + if (inMemoryToken != tokenValue) { - this.logger = logger; - this.localStore = localStorage; + TokenChanged?.Invoke(this, EventArgs.Empty); } + } - public async Task ClearTokenAsync() + public async Task GetTokenAsync() + { + if (string.IsNullOrEmpty(inMemoryToken) == false) { - var tokenValue = inMemoryToken; - - logger.LogDebug("Clear token in local browser store"); - IsLoggedIn = false; - inMemoryToken = string.Empty; - await localStore.DeleteAsync(tokenKey); - await Task.FromResult(true); - if (inMemoryToken != tokenValue) - { - TokenChanged?.Invoke(this, EventArgs.Empty); - } + return inMemoryToken; } - public async Task GetTokenAsync() + logger.LogDebug("Reading token from local browser store"); + try { - if (string.IsNullOrEmpty(inMemoryToken) == false) - { - return inMemoryToken; - } - - logger.LogDebug("Reading token from local browser store"); - try + //if (contextAccessor.HttpContext?.Session.IsAvailable == true) + //{ + // string token = contextAccessor.HttpContext?.Session.GetString(tokenKey) ?? string.Empty; + // return await Task.FromResult(token); + //} + var token = await localStore.GetAsync(tokenKey); + if (token.Success) { - //if (contextAccessor.HttpContext?.Session.IsAvailable == true) - //{ - // string token = contextAccessor.HttpContext?.Session.GetString(tokenKey) ?? string.Empty; - // return await Task.FromResult(token); - //} - var token = await localStore.GetAsync(tokenKey); - if (token.Success) + if (IsLoggedIn == false) { - if (IsLoggedIn == false) + // set expiration date + var handler = new JwtSecurityTokenHandler(); + var jsonToken = handler.ReadJwtToken(token.Value); + if (jsonToken.Claims.Any(x => x.Type == "exp")) { - // set expiration date - var handler = new JwtSecurityTokenHandler(); - var jsonToken = handler.ReadJwtToken(token.Value); - if (jsonToken.Claims.Any(x => x.Type == "exp")) - { - var expSeconds = Convert.ToInt64(jsonToken.Claims.First(x => x.Type == "exp").Value); - Expiration = new DateTime(1970, 1, 1).AddSeconds(expSeconds); - } + var expSeconds = Convert.ToInt64(jsonToken.Claims.First(x => x.Type == "exp").Value); + Expiration = new DateTime(1970, 1, 1).AddSeconds(expSeconds); } + } - // check if token is still valid - if (Expiration < DateTime.UtcNow.AddMinutes(5)) - { - await ClearTokenAsync(); - logger.LogInformation("Token read from token store has expired"); - return string.Empty; - } - IsLoggedIn = true; - return inMemoryToken = token.Value ?? string.Empty; + // check if token is still valid + if (Expiration < DateTime.UtcNow.AddMinutes(5)) + { + await ClearTokenAsync(); + logger.LogInformation("Token read from token store has expired"); + return string.Empty; } - IsLoggedIn = false; - return string.Empty; - } - catch (Exception ex) - { - logger.LogError("Could not read from local browser session: {Exception}", ex); - return string.Empty; + IsLoggedIn = true; + return inMemoryToken = token.Value ?? string.Empty; } + IsLoggedIn = false; + return string.Empty; } - - public async Task SetTokenAsync(string token) + catch (Exception ex) { - var oldToken = inMemoryToken; - logger.LogDebug("Set token to local browser session: {Token}", token); - await localStore.SetAsync(tokenKey, token); - inMemoryToken = token; + logger.LogError("Could not read from local browser session: {Exception}", ex); + return string.Empty; + } + } - if (inMemoryToken != oldToken) - { - TokenChanged?.Invoke(this, EventArgs.Empty); - } + public async Task SetTokenAsync(string token) + { + var oldToken = inMemoryToken; + logger.LogDebug("Set token to local browser session: {Token}", token); + await localStore.SetAsync(tokenKey, token); + inMemoryToken = token; + + if (inMemoryToken != oldToken) + { + TokenChanged?.Invoke(this, EventArgs.Empty); } } } diff --git a/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs b/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs index 84df0394..4461a2c8 100644 --- a/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs +++ b/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs @@ -1,13 +1,12 @@ -namespace iRLeagueManager.Web.Server.Data +namespace iRLeagueManager.Web.Server.Data; + +public class AuthenticatedHttpClientFactory : IHttpClientFactory { - public class AuthenticatedHttpClientFactory : IHttpClientFactory - { - public HttpClient CreateClient(string name) - { - return new HttpClient(); + public HttpClient CreateClient(string name) + { + return new HttpClient(); - } } } diff --git a/src/iRLeagueManager.Web/Data/CountedVote.cs b/src/iRLeagueManager.Web/Data/CountedVote.cs index 726013d7..e53f6bf3 100644 --- a/src/iRLeagueManager.Web/Data/CountedVote.cs +++ b/src/iRLeagueManager.Web/Data/CountedVote.cs @@ -1,15 +1,14 @@ using iRLeagueManager.Web.ViewModels; -namespace iRLeagueManager.Web.Data +namespace iRLeagueManager.Web.Data; + +public class CountedVote { - public class CountedVote - { - public int Count { get; set; } - public VoteViewModel Vote { get; set; } + public int Count { get; set; } + public VoteViewModel Vote { get; set; } - public CountedVote(VoteViewModel vote) - { - Vote = vote; - } + public CountedVote(VoteViewModel vote) + { + Vote = vote; } } diff --git a/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs b/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs index 54c3d647..547320a8 100644 --- a/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs +++ b/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs @@ -3,38 +3,37 @@ using iRLeagueApiCore.Client.Http; using System.Text.Json; -namespace iRLeagueManager.Web.Server.Data +namespace iRLeagueManager.Web.Server.Data; + +public class LeagueApiClientFactory { - public class LeagueApiClientFactory - { - private readonly ILoggerFactory loggerFactory; - private readonly ILogger logger; - private readonly IHttpClientFactory httpClientFactory; - private readonly ILocalStorageService localStorage; - private readonly ITokenStore tokenStore; - private readonly JsonSerializerOptions jsonOptions; + private readonly ILoggerFactory loggerFactory; + private readonly ILogger logger; + private readonly IHttpClientFactory httpClientFactory; + private readonly ILocalStorageService localStorage; + private readonly ITokenStore tokenStore; + private readonly JsonSerializerOptions jsonOptions; - private readonly string baseAddress; + private readonly string baseAddress; - public LeagueApiClientFactory(IConfiguration configuration, ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory, - ILocalStorageService localStorage, ITokenStore tokenStore, JsonSerializerOptions jsonOptions) - { - baseAddress = configuration["APIServer"]; - this.loggerFactory = loggerFactory; - logger = loggerFactory.CreateLogger(); - this.httpClientFactory = httpClientFactory; - this.localStorage = localStorage; - this.tokenStore = tokenStore; - this.jsonOptions = jsonOptions; - } + public LeagueApiClientFactory(IConfiguration configuration, ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory, + ILocalStorageService localStorage, ITokenStore tokenStore, JsonSerializerOptions jsonOptions) + { + baseAddress = configuration["APIServer"]; + this.loggerFactory = loggerFactory; + logger = loggerFactory.CreateLogger(); + this.httpClientFactory = httpClientFactory; + this.localStorage = localStorage; + this.tokenStore = tokenStore; + this.jsonOptions = jsonOptions; + } - public ILeagueApiClient CreateClient() - { - var httpClient = httpClientFactory.CreateClient(); - httpClient.BaseAddress = new Uri(baseAddress); - var client = new LeagueApiClient(loggerFactory.CreateLogger(), httpClient, tokenStore, jsonOptions); + public ILeagueApiClient CreateClient() + { + var httpClient = httpClientFactory.CreateClient(); + httpClient.BaseAddress = new Uri(baseAddress); + var client = new LeagueApiClient(loggerFactory.CreateLogger(), httpClient, tokenStore, jsonOptions); - return client; - } + return client; } } diff --git a/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs b/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs index 94ee961f..c40c1f33 100644 --- a/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs +++ b/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs @@ -1,28 +1,27 @@ using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; -namespace iRLeagueManager.Web.Data +namespace iRLeagueManager.Web.Data; + +public class SamePropertyEqualityComparer : IEqualityComparer>> { - public class SamePropertyEqualityComparer : IEqualityComparer>> + public bool Equals(Expression>? x, Expression>? y) { - public bool Equals(Expression>? x, Expression>? y) + var xMemberExpression = x?.Body as MemberExpression + ?? (x?.Body as UnaryExpression)?.Operand as MemberExpression; + var yMemberExpression = y?.Body as MemberExpression + ?? (y?.Body as UnaryExpression)?.Operand as MemberExpression; + if (xMemberExpression == null || yMemberExpression == null) { - var xMemberExpression = x?.Body as MemberExpression - ?? (x?.Body as UnaryExpression)?.Operand as MemberExpression; - var yMemberExpression = y?.Body as MemberExpression - ?? (y?.Body as UnaryExpression)?.Operand as MemberExpression; - if (xMemberExpression == null || yMemberExpression == null) - { - return false; - } - return xMemberExpression.Member == yMemberExpression.Member; + return false; } + return xMemberExpression.Member == yMemberExpression.Member; + } - public int GetHashCode([DisallowNull] Expression> obj) - { - var memberExpression = obj.Body as MemberExpression; - //var memberName = memberExpression.Member.Name; - return memberExpression?.Member.GetHashCode() ?? 0; - } + public int GetHashCode([DisallowNull] Expression> obj) + { + var memberExpression = obj.Body as MemberExpression; + //var memberName = memberExpression.Member.Name; + return memberExpression?.Member.GetHashCode() ?? 0; } } diff --git a/src/iRLeagueManager.Web/Data/StatusResult.cs b/src/iRLeagueManager.Web/Data/StatusResult.cs index f62f289d..30fab4bf 100644 --- a/src/iRLeagueManager.Web/Data/StatusResult.cs +++ b/src/iRLeagueManager.Web/Data/StatusResult.cs @@ -1,52 +1,51 @@ using iRLeagueApiCore.Common.Responses; -namespace iRLeagueManager.Web.Data +namespace iRLeagueManager.Web.Data; + +public class StatusResult { - public class StatusResult + public StatusResult(bool success, string status) + { + IsSuccess = success; + Status = status; + } + + public StatusResult(bool success, string status, string message) : + this(success, status) + { + Message = message; + } + + public StatusResult(bool success, string status, string message, IEnumerable errors) : + this(success, status, message) + { + Message = message; + Errors = errors; + } + + public bool IsSuccess { get; } + public string Status { get; } = string.Empty; + public string Message { get; } = string.Empty; + public IEnumerable Errors { get; } = Array.Empty(); + public IEnumerable ValidationErrors => Errors.OfType(); + + public const string Success = "Success"; + public const string BadRequest = "Bad request"; + public const string Unauthorized = "Unauthorized"; + public const string ServerError = "Internal server Error"; + + public static StatusResult SuccessResult() + { + return new StatusResult(true, "Success"); + } + + public static StatusResult SuccessResult(string message) + { + return new StatusResult(true, "Success", message); + } + + public static StatusResult FailedResult(string status, string message, IEnumerable errors) { - public StatusResult(bool success, string status) - { - IsSuccess = success; - Status = status; - } - - public StatusResult(bool success, string status, string message) : - this(success, status) - { - Message = message; - } - - public StatusResult(bool success, string status, string message, IEnumerable errors) : - this(success, status, message) - { - Message = message; - Errors = errors; - } - - public bool IsSuccess { get; } - public string Status { get; } = string.Empty; - public string Message { get; } = string.Empty; - public IEnumerable Errors { get; } = Array.Empty(); - public IEnumerable ValidationErrors => Errors.OfType(); - - public const string Success = "Success"; - public const string BadRequest = "Bad request"; - public const string Unauthorized = "Unauthorized"; - public const string ServerError = "Internal server Error"; - - public static StatusResult SuccessResult() - { - return new StatusResult(true, "Success"); - } - - public static StatusResult SuccessResult(string message) - { - return new StatusResult(true, "Success", message); - } - - public static StatusResult FailedResult(string status, string message, IEnumerable errors) - { - return new StatusResult(false, status, message, errors); - } + return new StatusResult(false, status, message, errors); } } diff --git a/src/iRLeagueManager.Web/Data/TrackListService.cs b/src/iRLeagueManager.Web/Data/TrackListService.cs index 1dee88ef..18ec0d73 100644 --- a/src/iRLeagueManager.Web/Data/TrackListService.cs +++ b/src/iRLeagueManager.Web/Data/TrackListService.cs @@ -1,33 +1,32 @@ using iRLeagueApiCore.Common.Models.Tracks; -namespace iRLeagueManager.Web.Data +namespace iRLeagueManager.Web.Data; + +public class TrackListService { - public class TrackListService - { - private readonly LeagueApiService apiService; - private readonly TimeSpan updateInterval = TimeSpan.FromHours(1); + private readonly LeagueApiService apiService; + private readonly TimeSpan updateInterval = TimeSpan.FromHours(1); - private DateTime lastUpdate = DateTime.MinValue; - private IList cachedTrackList = Array.Empty(); + private DateTime lastUpdate = DateTime.MinValue; + private IList cachedTrackList = Array.Empty(); - public TrackListService(LeagueApiService apiService) - { - this.apiService = apiService; - } + public TrackListService(LeagueApiService apiService) + { + this.apiService = apiService; + } - public async Task> GetTracks() + public async Task> GetTracks() + { + if (lastUpdate < (DateTime.UtcNow - updateInterval)) { - if (lastUpdate < (DateTime.UtcNow - updateInterval)) + var request = apiService.Client.Tracks().Get(); + var result = await request; + if (result.Success && result.Content is not null) { - var request = apiService.Client.Tracks().Get(); - var result = await request; - if (result.Success && result.Content is not null) - { - lastUpdate = DateTime.UtcNow; - cachedTrackList = result.Content.ToList(); - } + lastUpdate = DateTime.UtcNow; + cachedTrackList = result.Content.ToList(); } - return cachedTrackList; } + return cachedTrackList; } } diff --git a/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs b/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs index 9904c849..185b403a 100644 --- a/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs +++ b/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs @@ -1,28 +1,27 @@ -namespace iRLeagueManager.Web.Exceptions +namespace iRLeagueManager.Web.Exceptions; + +public static class BlazorParameterNullException { - public static class BlazorParameterNullException + public static BlazorParameterNullException New(TComponent component, TParameter parameter) { - public static BlazorParameterNullException New(TComponent component, TParameter parameter) - { - return new BlazorParameterNullException(); - } + return new BlazorParameterNullException(); + } - public static BlazorParameterNullException New(TComponent component, TParameter parameter, string parameterName) - { - return new BlazorParameterNullException(parameterName); - } + public static BlazorParameterNullException New(TComponent component, TParameter parameter, string parameterName) + { + return new BlazorParameterNullException(parameterName); } +} - public class BlazorParameterNullException : InvalidOperationException +public class BlazorParameterNullException : InvalidOperationException +{ + public BlazorParameterNullException() : + base($"Usage of {typeof(TComponent)} requires a Parameter of type {typeof(TParameter)} but value was 'null'") { - public BlazorParameterNullException() : - base($"Usage of {typeof(TComponent)} requires a Parameter of type {typeof(TParameter)} but value was 'null'") - { - } + } - public BlazorParameterNullException(string parameterName) : - base($"Usage of {typeof(TComponent)} requires a Parameter of type {typeof(TParameter)} with name {parameterName} but value was 'null'") - { - } + public BlazorParameterNullException(string parameterName) : + base($"Usage of {typeof(TComponent)} requires a Parameter of type {typeof(TParameter)} with name {parameterName} but value was 'null'") + { } } diff --git a/src/iRLeagueManager.Web/Extensions/EnumerableExtensions.cs b/src/iRLeagueManager.Web/Extensions/EnumerableExtensions.cs index ad259148..7409003c 100644 --- a/src/iRLeagueManager.Web/Extensions/EnumerableExtensions.cs +++ b/src/iRLeagueManager.Web/Extensions/EnumerableExtensions.cs @@ -1,19 +1,18 @@ -namespace iRLeagueManager.Web.Extensions +namespace iRLeagueManager.Web.Extensions; + +public static class EnumerableExtensions { - public static class EnumerableExtensions + public static IEnumerable NotNull(this IEnumerable enumerable) where T : notnull { - public static IEnumerable NotNull(this IEnumerable enumerable) where T : notnull - { - return enumerable.Where(x => x is not null).OfType(); - } + return enumerable.Where(x => x is not null).OfType(); + } - public static T? MinOrDefault(this IEnumerable enumerable) + public static T? MinOrDefault(this IEnumerable enumerable) + { + if (enumerable.Any() == false) { - if (enumerable.Any() == false) - { - return default; - } - return enumerable.Min(); + return default; } + return enumerable.Min(); } } diff --git a/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs b/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs index a6d2751c..d0227ac6 100644 --- a/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs +++ b/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs @@ -5,76 +5,75 @@ using System.Runtime.Serialization; using System.Web; -namespace iRLeagueManager.Web.Extensions +namespace iRLeagueManager.Web.Extensions; + +public static class LeagueApiClientExtensions { - public static class LeagueApiClientExtensions + public static T? EnsureSuccess(this ClientActionResult clientActionResult) { - public static T? EnsureSuccess(this ClientActionResult clientActionResult) + if (clientActionResult.Success == true) { - if (clientActionResult.Success == true) - { - return clientActionResult.Content; - } - if (clientActionResult.HttpStatusCode == System.Net.HttpStatusCode.NotFound) - { - return default(T); - } - throw new ActionResultException(clientActionResult); + return clientActionResult.Content; } - - public static StatusResult ToStatusResult(this ClientActionResult clientActionResult) + if (clientActionResult.HttpStatusCode == System.Net.HttpStatusCode.NotFound) { - if (clientActionResult.Success) - { - return StatusResult.SuccessResult(clientActionResult.Message); - } - return StatusResult.FailedResult(clientActionResult.Status, clientActionResult.Message, clientActionResult.Errors); + return default(T); } + throw new ActionResultException(clientActionResult); } - public static class ExtensionMethods + public static StatusResult ToStatusResult(this ClientActionResult clientActionResult) { - public static NameValueCollection QueryString(this NavigationManager navigationManager) - { - return HttpUtility.ParseQueryString(new Uri(navigationManager.Uri).Query); - } - - public static string QueryString(this NavigationManager navigationManager, string key) + if (clientActionResult.Success) { - return navigationManager.QueryString()[key] ?? string.Empty; + return StatusResult.SuccessResult(clientActionResult.Message); } + return StatusResult.FailedResult(clientActionResult.Status, clientActionResult.Message, clientActionResult.Errors); + } +} - public static T? QueryParameter(this NavigationManager navigationManager, string key) - { - var paramString = navigationManager.QueryString()[key]; - if (string.IsNullOrEmpty(paramString)) - { - return default(T); - } - return (T)Convert.ChangeType(paramString, typeof(T)); - } +public static class ExtensionMethods +{ + public static NameValueCollection QueryString(this NavigationManager navigationManager) + { + return HttpUtility.ParseQueryString(new Uri(navigationManager.Uri).Query); } - public class ActionResultException : InvalidOperationException + public static string QueryString(this NavigationManager navigationManager, string key) { - public ClientActionResult ActionResult; + return navigationManager.QueryString()[key] ?? string.Empty; + } - public ActionResultException(ClientActionResult actionResult) : this(actionResult, $"Action result did not indicate success: {actionResult.Status} -> {actionResult.Message} -- from Request: {actionResult.RequestUrl}") + public static T? QueryParameter(this NavigationManager navigationManager, string key) + { + var paramString = navigationManager.QueryString()[key]; + if (string.IsNullOrEmpty(paramString)) { + return default(T); } + return (T)Convert.ChangeType(paramString, typeof(T)); + } +} - public ActionResultException(ClientActionResult actionResult, string message) : this(actionResult, message, default) - { - } +public class ActionResultException : InvalidOperationException +{ + public ClientActionResult ActionResult; - public ActionResultException(ClientActionResult actionResult, string message, Exception? innerException) : base(message, innerException) - { - ActionResult = actionResult; - } + public ActionResultException(ClientActionResult actionResult) : this(actionResult, $"Action result did not indicate success: {actionResult.Status} -> {actionResult.Message} -- from Request: {actionResult.RequestUrl}") + { + } - protected ActionResultException(ClientActionResult actionResult, SerializationInfo info, StreamingContext context) : base(info, context) - { - ActionResult = actionResult; - } + public ActionResultException(ClientActionResult actionResult, string message) : this(actionResult, message, default) + { + } + + public ActionResultException(ClientActionResult actionResult, string message, Exception? innerException) : base(message, innerException) + { + ActionResult = actionResult; + } + + protected ActionResultException(ClientActionResult actionResult, SerializationInfo info, StreamingContext context) : base(info, context) + { + ActionResult = actionResult; } } diff --git a/src/iRLeagueManager.Web/Extensions/StringExtensions.cs b/src/iRLeagueManager.Web/Extensions/StringExtensions.cs index 85761969..58eb35ab 100644 --- a/src/iRLeagueManager.Web/Extensions/StringExtensions.cs +++ b/src/iRLeagueManager.Web/Extensions/StringExtensions.cs @@ -1,16 +1,15 @@ using System.Text.RegularExpressions; -namespace iRLeagueManager.Web.Extensions +namespace iRLeagueManager.Web.Extensions; + +public static class StringExtensions { - public static class StringExtensions + public static string PadNumbers(this string input, int n = 10) { - public static string PadNumbers(this string input, int n = 10) + if (string.IsNullOrEmpty(input)) { - if (string.IsNullOrEmpty(input)) - { - return input; - } - return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(n, '0')); + return input; } + return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(n, '0')); } } diff --git a/src/iRLeagueManager.Web/Extensions/TimeSpanExtensions.cs b/src/iRLeagueManager.Web/Extensions/TimeSpanExtensions.cs index 954b3342..077a7b04 100644 --- a/src/iRLeagueManager.Web/Extensions/TimeSpanExtensions.cs +++ b/src/iRLeagueManager.Web/Extensions/TimeSpanExtensions.cs @@ -1,15 +1,14 @@ -namespace iRLeagueManager.Web.Extensions +namespace iRLeagueManager.Web.Extensions; + +public static class TimeSpanExtensions { - public static class TimeSpanExtensions + public static DateTime AsDateTime(this TimeSpan timeSpan) { - public static DateTime AsDateTime(this TimeSpan timeSpan) - { - return new DateTime(timeSpan.Ticks); - } + return new DateTime(timeSpan.Ticks); + } - public static string LapTimeString(this TimeSpan timeSpan) - { - return timeSpan.AsDateTime().ToString(@"m:ss.fff"); - } + public static string LapTimeString(this TimeSpan timeSpan) + { + return timeSpan.AsDateTime().ToString(@"m:ss.fff"); } } diff --git a/src/iRLeagueManager.Web/Pages/Error.cshtml.cs b/src/iRLeagueManager.Web/Pages/Error.cshtml.cs index 47f6b1db..03c21583 100644 --- a/src/iRLeagueManager.Web/Pages/Error.cshtml.cs +++ b/src/iRLeagueManager.Web/Pages/Error.cshtml.cs @@ -2,26 +2,25 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using System.Diagnostics; -namespace iRLeagueManager.Web.Pages +namespace iRLeagueManager.Web.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +[IgnoreAntiforgeryToken] +public class ErrorModel : PageModel { - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - [IgnoreAntiforgeryToken] - public class ErrorModel : PageModel - { - public string? RequestId { get; set; } + public string? RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - private readonly ILogger _logger; + private readonly ILogger _logger; - public ErrorModel(ILogger logger) - { - _logger = logger; - } + public ErrorModel(ILogger logger) + { + _logger = logger; + } - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; } -} \ No newline at end of file +} diff --git a/src/iRLeagueManager.Web/Services.cs b/src/iRLeagueManager.Web/Services.cs index dca08516..6cc3a9b4 100644 --- a/src/iRLeagueManager.Web/Services.cs +++ b/src/iRLeagueManager.Web/Services.cs @@ -2,39 +2,38 @@ using iRLeagueManager.Web.ViewModels; using Microsoft.Extensions.DependencyInjection.Extensions; -namespace iRLeagueManager.Web +namespace iRLeagueManager.Web; + +public static class Services { - public static class Services + public static IServiceCollection AddTrackList(this IServiceCollection services) { - public static IServiceCollection AddTrackList(this IServiceCollection services) - { - services.TryAddScoped(); - return services; - } + services.TryAddScoped(); + return services; + } - public static IServiceCollection AddViewModels(this IServiceCollection services) - { - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddTransient(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - return services; - } + public static IServiceCollection AddViewModels(this IServiceCollection services) + { + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddTransient(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + return services; } } diff --git a/src/iRLeagueManager.Web/Shared/IModalBody.cs b/src/iRLeagueManager.Web/Shared/IModalBody.cs index 6a6f6095..7f9a882d 100644 --- a/src/iRLeagueManager.Web/Shared/IModalBody.cs +++ b/src/iRLeagueManager.Web/Shared/IModalBody.cs @@ -1,7 +1,6 @@ -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public interface IModalBody { - public interface IModalBody - { - public Task CanSubmit(); - } + public Task CanSubmit(); } diff --git a/src/iRLeagueManager.Web/Shared/IModelState.cs b/src/iRLeagueManager.Web/Shared/IModelState.cs index 2f489709..b22731e0 100644 --- a/src/iRLeagueManager.Web/Shared/IModelState.cs +++ b/src/iRLeagueManager.Web/Shared/IModelState.cs @@ -1,11 +1,10 @@ using System.ComponentModel; -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public interface IModelState : INotifyPropertyChanged { - public interface IModelState : INotifyPropertyChanged - { - public bool Loading { get; } - public bool Saving { get; } - public bool HasChanged { get; } - } -} \ No newline at end of file + public bool Loading { get; } + public bool Saving { get; } + public bool HasChanged { get; } +} diff --git a/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs b/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs index 0b7c957f..1901820c 100644 --- a/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs +++ b/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs @@ -3,56 +3,55 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public class JwtAuthenticationStateProvicer : AuthenticationStateProvider, IDisposable { - public class JwtAuthenticationStateProvicer : AuthenticationStateProvider, IDisposable - { - private readonly JwtSecurityTokenHandler tokenHandler = new(); - private readonly IAsyncTokenProvider tokenStore; - private string lastToken = string.Empty; + private readonly JwtSecurityTokenHandler tokenHandler = new(); + private readonly IAsyncTokenProvider tokenStore; + private string lastToken = string.Empty; - public JwtAuthenticationStateProvicer(IAsyncTokenProvider tokenStore) - { - this.tokenStore = tokenStore; - tokenStore.TokenChanged += TokenStore_TokenChanged; - } + public JwtAuthenticationStateProvicer(IAsyncTokenProvider tokenStore) + { + this.tokenStore = tokenStore; + tokenStore.TokenChanged += TokenStore_TokenChanged; + } - private void TokenStore_TokenChanged(object? sender, EventArgs e) - { - NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); - } + private void TokenStore_TokenChanged(object? sender, EventArgs e) + { + NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); + } - private async Task GetTokenUser() + private async Task GetTokenUser() + { + var token = await tokenStore.GetTokenAsync(); + if (string.IsNullOrEmpty(token)) { - var token = await tokenStore.GetTokenAsync(); - if (string.IsNullOrEmpty(token)) - { - return GetAnonymous(); - } - var jwtSecurityToken = tokenHandler.ReadJwtToken(token); - var identity = new ClaimsIdentity(jwtSecurityToken.Claims, "bearer"); - return new ClaimsPrincipal(identity); + return GetAnonymous(); } + var jwtSecurityToken = tokenHandler.ReadJwtToken(token); + var identity = new ClaimsIdentity(jwtSecurityToken.Claims, "bearer"); + return new ClaimsPrincipal(identity); + } - private static ClaimsPrincipal GetAnonymous() + private static ClaimsPrincipal GetAnonymous() + { + return new ClaimsPrincipal(new ClaimsIdentity(new[] { - return new ClaimsPrincipal(new ClaimsIdentity(new[] - { new Claim(ClaimTypes.Sid, "0"), new Claim(ClaimTypes.Name, "Anonymous"), new Claim(ClaimTypes.Role, "Anonymous") }, null)); - } + } - public override async Task GetAuthenticationStateAsync() - { - var user = await GetTokenUser(); - return new AuthenticationState(user); - } + public override async Task GetAuthenticationStateAsync() + { + var user = await GetTokenUser(); + return new AuthenticationState(user); + } - void IDisposable.Dispose() - { - tokenStore.TokenChanged -= TokenStore_TokenChanged; - } + void IDisposable.Dispose() + { + tokenStore.TokenChanged -= TokenStore_TokenChanged; } } diff --git a/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs b/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs index 4428955a..e36604ab 100644 --- a/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs +++ b/src/iRLeagueManager.Web/Shared/LeagueComponentBase.cs @@ -6,162 +6,161 @@ using MvvmBlazor.Components; using System.ComponentModel; -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public abstract partial class LeagueComponentBase : MvvmComponentBase { - public abstract partial class LeagueComponentBase : MvvmComponentBase - { - [Inject] - public SharedStateService Shared { get; set; } = default!; - [Inject] - public LeagueApiService ApiService { get; set; } = default!; - [Inject] - public NavigationManager NavigationManager { get; set; } = default!; + [Inject] + public SharedStateService Shared { get; set; } = default!; + [Inject] + public LeagueApiService ApiService { get; set; } = default!; + [Inject] + public NavigationManager NavigationManager { get; set; } = default!; - private EventListViewModel eventList = default!; + private EventListViewModel eventList = default!; - [CascadingParameter] - public EventListViewModel EventList + [CascadingParameter] + public EventListViewModel EventList + { + get => eventList; + set { - get => eventList; - set + if (eventList != null) + { + eventList.PropertyChanged -= OnEventListPropertyChanged; + } + eventList = value; + if (eventList != null) { - if (eventList != null) - { - eventList.PropertyChanged -= OnEventListPropertyChanged; - } - eventList = value; - if (eventList != null) - { - eventList.PropertyChanged += OnEventListPropertyChanged; - } + eventList.PropertyChanged += OnEventListPropertyChanged; } } - [Parameter] - public string? LeagueName { get; set; } - [Parameter] - public long? SeasonId { get; set; } - [Parameter] - public long? EventId { get; set; } + } + [Parameter] + public string? LeagueName { get; set; } + [Parameter] + public long? SeasonId { get; set; } + [Parameter] + public long? EventId { get; set; } + + protected bool ParametersSet { get; set; } = false; + protected bool HasRendered { get; set; } = false; - protected bool ParametersSet { get; set; } = false; - protected bool HasRendered { get; set; } = false; + protected virtual void SharedStateChanged(object? sender, EventArgs e) + { + InvokeAsync(StateHasChanged); + } - protected virtual void SharedStateChanged(object? sender, EventArgs e) + protected virtual void RedirectUrl() + { + } + + protected override void OnParametersSet() + { + if (SeasonId == null && EventId == null && Shared.SeasonId != 0) { - InvokeAsync(StateHasChanged); + SeasonId = Shared.SeasonId; } + ParametersSet = true; + } - protected virtual void RedirectUrl() + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + if (firstRender == false || ParametersSet == false) { + return; } - protected override void OnParametersSet() + if (LeagueName == null) { - if (SeasonId == null && EventId == null && Shared.SeasonId != 0) - { - SeasonId = Shared.SeasonId; - } - ParametersSet = true; + return; } + await ApiService.SetCurrentLeagueAsync(LeagueName); - protected override async Task OnAfterRenderAsync(bool firstRender) + if (ApiService.CurrentLeague == null) { - await base.OnAfterRenderAsync(firstRender); - if (firstRender == false || ParametersSet == false) - { - return; - } - - if (LeagueName == null) - { - return; - } - await ApiService.SetCurrentLeagueAsync(LeagueName); - - if (ApiService.CurrentLeague == null) - { - return; - } - if (EventId != null) - { - await ApiService.SetCurrentSeasonByEventId(LeagueName, EventId.Value); - } - if (ApiService.CurrentSeason == null && SeasonId != null) - { - await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, SeasonId.Value); - } - if (ApiService.CurrentSeason == null) - { - var lastSeason = Shared.SeasonList.LastOrDefault(); - if (lastSeason != null) - { - await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, lastSeason.SeasonId); - } - } - if (ApiService.CurrentSeason == null) - { - return; - } - SeasonId = ApiService.CurrentSeason.Id; - - HasRendered = true; - await LoadEventList(ApiService.CurrentSeason.Id); - if (EventId != null) - { - EventList.Selected = EventList.EventList.FirstOrDefault(x => x.EventId == EventId); - return; - } - if (EventList.Selected == null) + return; + } + if (EventId != null) + { + await ApiService.SetCurrentSeasonByEventId(LeagueName, EventId.Value); + } + if (ApiService.CurrentSeason == null && SeasonId != null) + { + await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, SeasonId.Value); + } + if (ApiService.CurrentSeason == null) + { + var lastSeason = Shared.SeasonList.LastOrDefault(); + if (lastSeason != null) { - EventList.Selected = EventList.EventList.LastOrDefault(x => x.HasResult); - EventId = EventList.Selected?.EventId; + await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, lastSeason.SeasonId); } } - - protected async Task LoadEventList(long seasonId) + if (ApiService.CurrentSeason == null) { - await EventList.LoadEventListAsync(seasonId); + return; } + SeasonId = ApiService.CurrentSeason.Id; - protected virtual async Task OnEventChangedAsync(EventViewModel? @event) + HasRendered = true; + await LoadEventList(ApiService.CurrentSeason.Id); + if (EventId != null) { - await Task.CompletedTask; + EventList.Selected = EventList.EventList.FirstOrDefault(x => x.EventId == EventId); + return; } - - protected override void OnInitialized() + if (EventList.Selected == null) { - Shared.StateChanged += SharedStateChanged; - base.OnInitialized(); + EventList.Selected = EventList.EventList.LastOrDefault(x => x.HasResult); + EventId = EventList.Selected?.EventId; } + } - protected override void Dispose(bool disposing) - { - Shared.StateChanged -= SharedStateChanged; - EventList.PropertyChanged -= OnEventListPropertyChanged; - base.Dispose(disposing); - } + protected async Task LoadEventList(long seasonId) + { + await EventList.LoadEventListAsync(seasonId); + } - private void OnEventListPropertyChanged(object? sender, PropertyChangedEventArgs e) + protected virtual async Task OnEventChangedAsync(EventViewModel? @event) + { + await Task.CompletedTask; + } + + protected override void OnInitialized() + { + Shared.StateChanged += SharedStateChanged; + base.OnInitialized(); + } + + protected override void Dispose(bool disposing) + { + Shared.StateChanged -= SharedStateChanged; + EventList.PropertyChanged -= OnEventListPropertyChanged; + base.Dispose(disposing); + } + + private void OnEventListPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) { - switch (e.PropertyName) - { - case nameof(EventList.Selected): - _ = OnEventChangedAsync(EventList.Selected); - break; - } + case nameof(EventList.Selected): + _ = OnEventChangedAsync(EventList.Selected); + break; } + } - protected string GetRoleString(params string[] roleNames) + protected string GetRoleString(params string[] roleNames) + { + IEnumerable roles = new[] { "Admin" }; + if (LeagueName != null) { - IEnumerable roles = new[] { "Admin" }; - if (LeagueName != null) - { - var leagueRoleNames = roleNames - .Select(x => LeagueRoles.GetLeagueRoleName(LeagueName, x)) - .NotNull(); - roles = roles.Concat(leagueRoleNames); - } - return string.Join(',', roles); + var leagueRoleNames = roleNames + .Select(x => LeagueRoles.GetLeagueRoleName(LeagueName, x)) + .NotNull(); + roles = roles.Concat(leagueRoleNames); } + return string.Join(',', roles); } } diff --git a/src/iRLeagueManager.Web/Shared/LoginRedirect.cs b/src/iRLeagueManager.Web/Shared/LoginRedirect.cs index ed4d6d7b..0d028a90 100644 --- a/src/iRLeagueManager.Web/Shared/LoginRedirect.cs +++ b/src/iRLeagueManager.Web/Shared/LoginRedirect.cs @@ -2,32 +2,31 @@ using Microsoft.AspNetCore.Components.Authorization; using System.Net; -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public class LoginRedirect : ComponentBase { - public class LoginRedirect : ComponentBase - { - [CascadingParameter] - public Task AuthStateTask { get; set; } = default!; - [Inject] - public NavigationManager NavigationManager { get; set; } = default!; + [CascadingParameter] + public Task AuthStateTask { get; set; } = default!; + [Inject] + public NavigationManager NavigationManager { get; set; } = default!; - protected override async Task OnAfterRenderAsync(bool firstRender) + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender == false) { - if (firstRender == false) - { - return; - } - var loadState = await AuthStateTask; - - if (loadState?.User.Identity?.IsAuthenticated == true) - { - // redirect to original page - NavigationManager.NavigateTo(NavigationManager.Uri); - } + return; + } + var loadState = await AuthStateTask; - // redirect to login page - var returnUrl = WebUtility.UrlEncode(new Uri(NavigationManager.Uri).PathAndQuery); - NavigationManager.NavigateTo($"member/login?returnUrl={returnUrl}"); + if (loadState?.User.Identity?.IsAuthenticated == true) + { + // redirect to original page + NavigationManager.NavigateTo(NavigationManager.Uri); } + + // redirect to login page + var returnUrl = WebUtility.UrlEncode(new Uri(NavigationManager.Uri).PathAndQuery); + NavigationManager.NavigateTo($"member/login?returnUrl={returnUrl}"); } } diff --git a/src/iRLeagueManager.Web/Shared/RouteView.cs b/src/iRLeagueManager.Web/Shared/RouteView.cs index 3d84d363..a5763034 100644 --- a/src/iRLeagueManager.Web/Shared/RouteView.cs +++ b/src/iRLeagueManager.Web/Shared/RouteView.cs @@ -4,27 +4,26 @@ using Microsoft.AspNetCore.Components.Rendering; using System.Net; -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public class AppRouteView : RouteView { - public class AppRouteView : RouteView - { - [Inject] - public NavigationManager NavigationManager { get; set; } = default!; - [Inject] - public ILeagueApiClient ApiClient { get; set; } = default!; + [Inject] + public NavigationManager NavigationManager { get; set; } = default!; + [Inject] + public ILeagueApiClient ApiClient { get; set; } = default!; - protected override void Render(RenderTreeBuilder builder) + protected override void Render(RenderTreeBuilder builder) + { + var authorize = Attribute.GetCustomAttribute(RouteData.PageType, typeof(AuthorizeAttribute)) != null; + if (authorize && ApiClient.IsLoggedIn == false) + { + var returnUrl = WebUtility.UrlEncode(new Uri(NavigationManager.Uri).PathAndQuery); + NavigationManager.NavigateTo($"member/login?returnUrl={returnUrl}"); + } + else { - var authorize = Attribute.GetCustomAttribute(RouteData.PageType, typeof(AuthorizeAttribute)) != null; - if (authorize && ApiClient.IsLoggedIn == false) - { - var returnUrl = WebUtility.UrlEncode(new Uri(NavigationManager.Uri).PathAndQuery); - NavigationManager.NavigateTo($"member/login?returnUrl={returnUrl}"); - } - else - { - base.Render(builder); - } + base.Render(builder); } } } diff --git a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs index b24e7e8d..a3d152bd 100644 --- a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs +++ b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs @@ -2,95 +2,94 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; -namespace iRLeagueManager.Web.Shared +namespace iRLeagueManager.Web.Shared; + +public class StatusResultValidator : ComponentBase { - public class StatusResultValidator : ComponentBase - { - private ValidationMessageStore messageStore = default!; - [CascadingParameter] - private EditContext CurrentEditContext { get; set; } = default!; + private ValidationMessageStore messageStore = default!; + [CascadingParameter] + private EditContext CurrentEditContext { get; set; } = default!; - public string ErrorMessage { get; set; } = string.Empty; + public string ErrorMessage { get; set; } = string.Empty; - protected override void OnInitialized() - { - _ = CurrentEditContext ?? throw new InvalidOperationException($"Usage of {nameof(StatusResultValidator)} requires an {nameof(EditContext)} as cascading parameter"); - messageStore = new ValidationMessageStore(CurrentEditContext); - CurrentEditContext.OnValidationRequested += (sender, args) => ClearErrors(); - } + protected override void OnInitialized() + { + _ = CurrentEditContext ?? throw new InvalidOperationException($"Usage of {nameof(StatusResultValidator)} requires an {nameof(EditContext)} as cascading parameter"); + messageStore = new ValidationMessageStore(CurrentEditContext); + CurrentEditContext.OnValidationRequested += (sender, args) => ClearErrors(); + } + + private void ClearErrors() + { + messageStore.Clear(); + ErrorMessage = string.Empty; + } - private void ClearErrors() + public void ValidateResult(StatusResult result) + { + if (result.IsSuccess) { messageStore.Clear(); ErrorMessage = string.Empty; + return; } - public void ValidateResult(StatusResult result) - { - if (result.IsSuccess) - { - messageStore.Clear(); - ErrorMessage = string.Empty; - return; - } - - switch (result.Status) - { - case StatusResult.Unauthorized: - AddUnauthorizedValidationMessages(); - break; - case StatusResult.BadRequest: - AddBadRequestValidationMessages(result); - break; - case StatusResult.ServerError: - DisplayErrorMessage(result); - break; - default: - DisplayErrorMessage(result); - break; - } + switch (result.Status) + { + case StatusResult.Unauthorized: + AddUnauthorizedValidationMessages(); + break; + case StatusResult.BadRequest: + AddBadRequestValidationMessages(result); + break; + case StatusResult.ServerError: + DisplayErrorMessage(result); + break; + default: + DisplayErrorMessage(result); + break; } + } - private void DisplayErrorMessage(StatusResult result) + private void DisplayErrorMessage(StatusResult result) + { + foreach (var error in result.Errors) { - foreach (var error in result.Errors) + if (error is Exception) { - if (error is Exception) - { - ErrorMessage += $"\nError: {error.GetType()}"; - continue; - } - ErrorMessage += $"\nError: {error}"; + ErrorMessage += $"\nError: {error.GetType()}"; + continue; } + ErrorMessage += $"\nError: {error}"; } + } - private void AddUnauthorizedValidationMessages() - { - var usernameField = CurrentEditContext.Field("Username"); - var passwordField = CurrentEditContext.Field("Password"); - messageStore.Add(usernameField, ""); - messageStore.Add(passwordField, "Incorrect Username or Password"); - } + private void AddUnauthorizedValidationMessages() + { + var usernameField = CurrentEditContext.Field("Username"); + var passwordField = CurrentEditContext.Field("Password"); + messageStore.Add(usernameField, ""); + messageStore.Add(passwordField, "Incorrect Username or Password"); + } - private void AddBadRequestValidationMessages(StatusResult result) + private void AddBadRequestValidationMessages(StatusResult result) + { + var validationErrors = result.ValidationErrors; + foreach (var validationError in validationErrors) { - var validationErrors = result.ValidationErrors; - foreach (var validationError in validationErrors) - { - var fieldName = GetModelFieldName(validationError.Property); - var identifier = CurrentEditContext.Field(fieldName); - messageStore.Add(identifier, validationError.Error); - } + var fieldName = GetModelFieldName(validationError.Property); + var identifier = CurrentEditContext.Field(fieldName); + messageStore.Add(identifier, validationError.Error); } + } - private static string GetModelFieldName(string requestFieldName) + private static string GetModelFieldName(string requestFieldName) + { + if (requestFieldName.StartsWith("Model.")) { - if (requestFieldName.StartsWith("Model.")) - { - return requestFieldName.Substring("Model.".Length); - } - return requestFieldName; + return requestFieldName.Substring("Model.".Length); } + return requestFieldName; } } diff --git a/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs index ec0ccc09..e4c79b6e 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs @@ -1,87 +1,86 @@ using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class EventListViewModel : LeagueViewModelBase { - public class EventListViewModel : LeagueViewModelBase + public EventListViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) { - public EventListViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) - { - } + } - public long? LoadedSeasonId { get; set; } + public long? LoadedSeasonId { get; set; } - private ObservableCollection eventList = new(); - public ObservableCollection EventList { get => eventList; set => Set(ref eventList, value); } + private ObservableCollection eventList = new(); + public ObservableCollection EventList { get => eventList; set => Set(ref eventList, value); } - private EventViewModel? selected; - public EventViewModel? Selected { get => selected; set => Set(ref selected, value); } + private EventViewModel? selected; + public EventViewModel? Selected { get => selected; set => Set(ref selected, value); } - public async Task LoadEventListAsync(long seasonId) + public async Task LoadEventListAsync(long seasonId) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) + return; + } + + try + { + Loading = true; + await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, seasonId); + LoadedSeasonId = seasonId; + if (ApiService.CurrentSeason == null) { + LoadedSeasonId = null; + EventList.Clear(); return; } - try + var sessionsEndpoint = ApiService.CurrentSeason.Events(); + var result = await sessionsEndpoint.Get(); + if (result.Success == false || result.Content is null) { - Loading = true; - await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, seasonId); - LoadedSeasonId = seasonId; - if (ApiService.CurrentSeason == null) - { - LoadedSeasonId = null; - EventList.Clear(); - return; - } - - var sessionsEndpoint = ApiService.CurrentSeason.Events(); - var result = await sessionsEndpoint.Get(); - if (result.Success == false || result.Content is null) - { - EventList.Clear(); - return; - } - - var sessions = result.Content; - EventList = new ObservableCollection(sessions.Select(x => new EventViewModel(LoggerFactory, ApiService, x))); - if (Selected != null) - { - Selected = EventList.FirstOrDefault(x => x.EventId == Selected.EventId); - } + EventList.Clear(); + return; } - finally + + var sessions = result.Content; + EventList = new ObservableCollection(sessions.Select(x => new EventViewModel(LoggerFactory, ApiService, x))); + if (Selected != null) { - Loading = false; + Selected = EventList.FirstOrDefault(x => x.EventId == Selected.EventId); } } + finally + { + Loading = false; + } + } - public async Task LoadEventListFromEventAsync(long eventId, CancellationToken cancellationToken = default) + public async Task LoadEventListFromEventAsync(long eventId, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return; - } + return; + } - try - { - Loading = true; - var result = await ApiService.CurrentLeague - .Events() - .WithId(eventId) - .Get(cancellationToken); - if (result.Success == false || result.Content is null) - { - return; - } - var @event = result.Content; - await LoadEventListAsync(@event.SeasonId); - } - finally + try + { + Loading = true; + var result = await ApiService.CurrentLeague + .Events() + .WithId(eventId) + .Get(cancellationToken); + if (result.Success == false || result.Content is null) { - Loading = false; + return; } + var @event = result.Content; + await LoadEventListAsync(@event.SeasonId); + } + finally + { + Loading = false; } } } diff --git a/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs index fefb210f..fe99f21f 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs @@ -1,30 +1,29 @@ using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class EventResultViewModel : LeagueViewModelBase { - public class EventResultViewModel : LeagueViewModelBase - { - private EventResultModel model; + private EventResultModel model; - public EventResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - this(loggerFactory, apiService, new EventResultModel()) - { - } + public EventResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + this(loggerFactory, apiService, new EventResultModel()) + { + } - public EventResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, EventResultModel model) : - base(loggerFactory, apiService) - { - this.model = model; - sessionResults = new ObservableCollection(model.SessionResults.Select(x => new SessionResultViewModel(loggerFactory, ApiService, x))); - } + public EventResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, EventResultModel model) : + base(loggerFactory, apiService) + { + this.model = model; + sessionResults = new ObservableCollection(model.SessionResults.Select(x => new SessionResultViewModel(loggerFactory, ApiService, x))); + } - public long ResultId => model.ResultId; - public long SeasonId => model.SeasonId; - public long EventId => model.EventId; - public string Name => model.DisplayName; + public long ResultId => model.ResultId; + public long SeasonId => model.SeasonId; + public long EventId => model.EventId; + public string Name => model.DisplayName; - private ObservableCollection sessionResults; - public ObservableCollection SessionResults { get => sessionResults; set => Set(ref sessionResults, value); } - } -} \ No newline at end of file + private ObservableCollection sessionResults; + public ObservableCollection SessionResults { get => sessionResults; set => Set(ref sessionResults, value); } +} diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs index 7bf85168..52640c15 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs @@ -3,80 +3,79 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class LeagueUserViewModel : LeagueViewModelBase { - public class LeagueUserViewModel : LeagueViewModelBase + public LeagueUserViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueUserModel model) : + base(loggerFactory, apiService, model) { - public LeagueUserViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueUserModel model) : - base(loggerFactory, apiService, model) - { - } + } - public string UserId => model.UserId; - public string UserName { get => model.UserName; set => SetP(model.UserName, value => model.UserName = value, value); } - public string FirstName { get => model.Firstname; set => SetP(model.Firstname, value => model.Firstname = value, value); } - public string LastName { get => model.Lastname; set => SetP(model.Lastname, value => model.Lastname = value, value); } + public string UserId => model.UserId; + public string UserName { get => model.UserName; set => SetP(model.UserName, value => model.UserName = value, value); } + public string FirstName { get => model.Firstname; set => SetP(model.Firstname, value => model.Firstname = value, value); } + public string LastName { get => model.Lastname; set => SetP(model.Lastname, value => model.Lastname = value, value); } - public IEnumerable Roles => model.LeagueRoles.Select(x => LeagueRoles.GetRoleValue(x)); + public IEnumerable Roles => model.LeagueRoles.Select(x => LeagueRoles.GetRoleValue(x)); - public bool HasRole(LeagueRoleValue role) - { - return LeagueRoles.CheckRole(role, Roles); - } + public bool HasRole(LeagueRoleValue role) + { + return LeagueRoles.CheckRole(role, Roles); + } - public bool IsImplicitRole(LeagueRoleValue role) - { - var implicitOfRoles = LeagueRoles.ImplicitRoleOf(role); - return implicitOfRoles.Any(x => LeagueRoles.CheckRole(x, Roles)); - } + public bool IsImplicitRole(LeagueRoleValue role) + { + var implicitOfRoles = LeagueRoles.ImplicitRoleOf(role); + return implicitOfRoles.Any(x => LeagueRoles.CheckRole(x, Roles)); + } - public async Task AddRoleAsync(LeagueRoleValue role) + public async Task AddRoleAsync(LeagueRoleValue role) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } - - var addRoleModel = new RoleModel() { RoleName = role.ToString() }; - var request = ApiService.CurrentLeague - .Users() - .WithId(model.UserId) - .AddRole() - .Post(addRoleModel); - var result = await request; - if (result.Success && result.Content is not null) - { - SetModel(result.Content); - } - - return result.ToStatusResult(); + return LeagueNullResult(); } - public async Task RemoveRoleAsync(LeagueRoleValue role) + var addRoleModel = new RoleModel() { RoleName = role.ToString() }; + var request = ApiService.CurrentLeague + .Users() + .WithId(model.UserId) + .AddRole() + .Post(addRoleModel); + var result = await request; + if (result.Success && result.Content is not null) { - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } + SetModel(result.Content); + } - var addRoleModel = new RoleModel() { RoleName = role.ToString() }; - var request = ApiService.CurrentLeague - .Users() - .WithId(model.UserId) - .RemoveRole() - .Post(addRoleModel); - var result = await request; - if (result.Success && result.Content is not null) - { - SetModel(result.Content); - } + return result.ToStatusResult(); + } - return result.ToStatusResult(); + public async Task RemoveRoleAsync(LeagueRoleValue role) + { + if (ApiService.CurrentLeague == null) + { + return LeagueNullResult(); } - public override void SetModel(LeagueUserModel model) + var addRoleModel = new RoleModel() { RoleName = role.ToString() }; + var request = ApiService.CurrentLeague + .Users() + .WithId(model.UserId) + .RemoveRole() + .Post(addRoleModel); + var result = await request; + if (result.Success && result.Content is not null) { - base.SetModel(model); + SetModel(result.Content); } + + return result.ToStatusResult(); + } + + public override void SetModel(LeagueUserModel model) + { + base.SetModel(model); } -} \ No newline at end of file +} diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs index 1d2af3a6..2ad703c8 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs @@ -2,79 +2,78 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class LeagueUsersViewModel : LeagueViewModelBase { - public class LeagueUsersViewModel : LeagueViewModelBase + public LeagueUsersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) + { + } + + private ObservableCollection leagueUsers = new(); + public ObservableCollection LeagueUsers { get => leagueUsers; set => Set(ref leagueUsers, value); } + + public async Task LoadAsync() { - public LeagueUsersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) + if (ApiService.CurrentLeague == null) { + return LeagueNullResult(); } - private ObservableCollection leagueUsers = new(); - public ObservableCollection LeagueUsers { get => leagueUsers; set => Set(ref leagueUsers, value); } - - public async Task LoadAsync() + try { - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } + Loading = true; + var getUsersEndpoint = ApiService.CurrentLeague.Users().Get(); + var result = await getUsersEndpoint; - try + if (result.Success == false || result.Content is null) { - Loading = true; - var getUsersEndpoint = ApiService.CurrentLeague.Users().Get(); - var result = await getUsersEndpoint; - - if (result.Success == false || result.Content is null) - { - return result.ToStatusResult(); - } - - var users = result.Content; - LeagueUsers = new ObservableCollection( - users.Select(x => new LeagueUserViewModel(LoggerFactory, ApiService, x))); return result.ToStatusResult(); } - finally - { - Loading = false; - } + + var users = result.Content; + LeagueUsers = new ObservableCollection( + users.Select(x => new LeagueUserViewModel(LoggerFactory, ApiService, x))); + return result.ToStatusResult(); + } + finally + { + Loading = false; } + } - public async Task AddUser(UserModel user) + public async Task AddUser(UserModel user) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } + return LeagueNullResult(); + } - if (LeagueUsers.Any(x => x.UserId == user.UserId)) - { - return StatusResult.SuccessResult(); - } + if (LeagueUsers.Any(x => x.UserId == user.UserId)) + { + return StatusResult.SuccessResult(); + } - try - { - Loading = true; + try + { + Loading = true; - var request = ApiService.CurrentLeague - .Users() - .WithId(user.UserId) - .AddRole() - .Post(new() { RoleName = "Member" }); - var result = await request; - if (result.Success) - { - return await LoadAsync(); - } - return StatusResult.SuccessResult(); - } - finally + var request = ApiService.CurrentLeague + .Users() + .WithId(user.UserId) + .AddRole() + .Post(new() { RoleName = "Member" }); + var result = await request; + if (result.Success) { - Loading = false; + return await LoadAsync(); } + return StatusResult.SuccessResult(); + } + finally + { + Loading = false; } } } diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs b/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs index 0f42bfc9..aba7ea1b 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueViewModelBase.cs @@ -4,116 +4,115 @@ using System.Runtime.CompilerServices; using System.Text.Json; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class LeagueViewModelBase : ViewModelBase, IModelState { - public class LeagueViewModelBase : ViewModelBase, IModelState + public LeagueViewModelBase(ILoggerFactory loggerFactory, LeagueApiService apiService) { - public LeagueViewModelBase(ILoggerFactory loggerFactory, LeagueApiService apiService) - { - LoggerFactory = loggerFactory; - Logger = loggerFactory.CreateLogger(); - this.ApiService = apiService; - } + LoggerFactory = loggerFactory; + Logger = loggerFactory.CreateLogger(); + this.ApiService = apiService; + } - protected ILoggerFactory LoggerFactory { get; } - protected ILogger Logger { get; } - protected LeagueApiService ApiService { get; } - protected CancellationTokenSource Cts { get; } = new(); + protected ILoggerFactory LoggerFactory { get; } + protected ILogger Logger { get; } + protected LeagueApiService ApiService { get; } + protected CancellationTokenSource Cts { get; } = new(); - private bool loading; - public bool Loading - { - get => loading; - protected set => Set(ref loading, value); - } + private bool loading; + public bool Loading + { + get => loading; + protected set => Set(ref loading, value); + } - private bool saving; - public bool Saving - { - get => saving; - protected set => Set(ref saving, value); - } + private bool saving; + public bool Saving + { + get => saving; + protected set => Set(ref saving, value); + } - private bool hasChanged = false; + private bool hasChanged = false; - public bool HasChanged - { - get => hasChanged; - protected set => Set(ref hasChanged, value); - } + public bool HasChanged + { + get => hasChanged; + protected set => Set(ref hasChanged, value); + } - /// - /// Set a value on a model property and call OnPropertyChanged() if value changed - /// - /// - /// current value of property - /// action to update property value - /// new value to set - /// Name of the property for OnPropertyChanged() - /// - protected bool SetP(TProperty get, Action set, TProperty value, [CallerMemberName] string? propertyName = null) + /// + /// Set a value on a model property and call OnPropertyChanged() if value changed + /// + /// + /// current value of property + /// action to update property value + /// new value to set + /// Name of the property for OnPropertyChanged() + /// + protected bool SetP(TProperty get, Action set, TProperty value, [CallerMemberName] string? propertyName = null) + { + if (!EqualityComparer.Default.Equals(get, value)) { - if (!EqualityComparer.Default.Equals(get, value)) - { - set.Invoke(value); - HasChanged = true; - OnPropertyChanged(propertyName); - return true; - } - return false; + set.Invoke(value); + HasChanged = true; + OnPropertyChanged(propertyName); + return true; } - - //protected bool Set(TModel model, Expression> property, TProperty value, [CallerMemberName] string ? propertyName = null) - //{ - // ArgumentNullException.ThrowIfNull(model); - // ArgumentNullException.ThrowIfNull(property); - - // var propertyValue = property.Compile().Invoke(model); - // if (!EqualityComparer.Default.Equals(propertyValue, value)) - // { - // var propertyExpression = property.Body as MemberExpression - // ?? throw new ArgumentException("Argument must be a member Expression", nameof(property)); - // var propertyInfo = propertyExpression.Member as PropertyInfo - // ?? throw new ArgumentException("Expression must target a Property", nameof(property)); - // propertyInfo.SetValue(model, value); - // HasChanged = true; - // OnPropertyChanged(propertyName); - // return true; - // } - // return false; - //} - - protected static StatusResult LeagueNullResult() => - StatusResult.FailedResult("League Null", $"{nameof(LeagueApiService)}.{nameof(LeagueApiService.CurrentLeague)} was null", Array.Empty()); - - protected static StatusResult SeasonNullResult() => - StatusResult.FailedResult("Season Null", $"{nameof(LeagueApiService)}.{nameof(LeagueApiService.CurrentSeason)} was null", Array.Empty()); + return false; } - public class LeagueViewModelBase : LeagueViewModelBase - { - protected TModel model = default!; + //protected bool Set(TModel model, Expression> property, TProperty value, [CallerMemberName] string ? propertyName = null) + //{ + // ArgumentNullException.ThrowIfNull(model); + // ArgumentNullException.ThrowIfNull(property); + + // var propertyValue = property.Compile().Invoke(model); + // if (!EqualityComparer.Default.Equals(propertyValue, value)) + // { + // var propertyExpression = property.Body as MemberExpression + // ?? throw new ArgumentException("Argument must be a member Expression", nameof(property)); + // var propertyInfo = propertyExpression.Member as PropertyInfo + // ?? throw new ArgumentException("Expression must target a Property", nameof(property)); + // propertyInfo.SetValue(model, value); + // HasChanged = true; + // OnPropertyChanged(propertyName); + // return true; + // } + // return false; + //} + + protected static StatusResult LeagueNullResult() => + StatusResult.FailedResult("League Null", $"{nameof(LeagueApiService)}.{nameof(LeagueApiService.CurrentLeague)} was null", Array.Empty()); + + protected static StatusResult SeasonNullResult() => + StatusResult.FailedResult("Season Null", $"{nameof(LeagueApiService)}.{nameof(LeagueApiService.CurrentSeason)} was null", Array.Empty()); +} - public LeagueViewModelBase(ILoggerFactory loggerFactory, LeagueApiService apiService, TModel model) : - base(loggerFactory, apiService) - { - SetModel(model); - } +public class LeagueViewModelBase : LeagueViewModelBase +{ + protected TModel model = default!; - public virtual TModel GetModel() - { - return model; - } + public LeagueViewModelBase(ILoggerFactory loggerFactory, LeagueApiService apiService, TModel model) : + base(loggerFactory, apiService) + { + SetModel(model); + } - public virtual void SetModel(TModel model) - { - this.model = model; - } + public virtual TModel GetModel() + { + return model; + } - public virtual TModel CopyModel() - { - return JsonSerializer.Deserialize(JsonSerializer.Serialize(model)) - ?? throw new InvalidOperationException("Could not copy model"); - } + public virtual void SetModel(TModel model) + { + this.model = model; + } + + public virtual TModel CopyModel() + { + return JsonSerializer.Deserialize(JsonSerializer.Serialize(model)) + ?? throw new InvalidOperationException("Could not copy model"); } } diff --git a/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs index 3b5edac6..bc880a10 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs @@ -1,45 +1,44 @@ using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class LeaguesViewModel : LeagueViewModelBase { - public class LeaguesViewModel : LeagueViewModelBase - { - private string _status; - public string Status { get => _status; set => Set(ref _status, value); } + private string _status; + public string Status { get => _status; set => Set(ref _status, value); } - public LeaguesViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) - { - _status = string.Empty; - leagues = new ObservableCollection(); - } + public LeaguesViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) + { + _status = string.Empty; + leagues = new ObservableCollection(); + } - private ObservableCollection leagues; - public ObservableCollection Leagues { get => leagues; set => Set(ref leagues, value); } + private ObservableCollection leagues; + public ObservableCollection Leagues { get => leagues; set => Set(ref leagues, value); } - //public override void OnInitialized() - //{ - // apiClient = RootServiceProvider.GetRequiredService(); - //} + //public override void OnInitialized() + //{ + // apiClient = RootServiceProvider.GetRequiredService(); + //} - //public override async Task OnAfterRenderAsync(bool firstRender) - public override async Task OnAfterRenderAsync(bool firstRender) + //public override async Task OnAfterRenderAsync(bool firstRender) + public override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) { - if (firstRender) + Loading = true; + Status = string.Empty; + var result = await ApiService.Client.Leagues().Get(); + Status = result.Status; + if (result.Success && result.Content is not null) { - Loading = true; - Status = string.Empty; - var result = await ApiService.Client.Leagues().Get(); - Status = result.Status; - if (result.Success && result.Content is not null) - { - var leagueModels = result.Content; - Leagues = new ObservableCollection( - leagueModels.Select(x => new LeagueViewModel(LoggerFactory, ApiService, x)) - ); - } - Loading = false; + var leagueModels = result.Content; + Leagues = new ObservableCollection( + leagueModels.Select(x => new LeagueViewModel(LoggerFactory, ApiService, x)) + ); } + Loading = false; } } } diff --git a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs index a303dcae..74f6b3be 100644 --- a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs @@ -2,92 +2,91 @@ using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class PointRuleViewModel : LeagueViewModelBase { - public class PointRuleViewModel : LeagueViewModelBase + public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + this(loggerFactory, apiService, new()) { - public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - this(loggerFactory, apiService, new()) - { - } + } - public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, PointRuleModel model) : - base(loggerFactory, apiService, model) - { - } + public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, PointRuleModel model) : + base(loggerFactory, apiService, model) + { + } - public long LeagueId => model.LeagueId; - public long PointRuleId => model.PointRuleId; + public long LeagueId => model.LeagueId; + public long PointRuleId => model.PointRuleId; - private PointRuleType ruleType; - public PointRuleType RuleType + private PointRuleType ruleType; + public PointRuleType RuleType + { + get => ruleType; + set { - get => ruleType; - set + if (Set(ref ruleType, value)) { - if (Set(ref ruleType, value)) - { - RuleTypeChanged(value); - } + RuleTypeChanged(value); } } + } - public int MaxPoints { get => model.MaxPoints; set => SetP(model.MaxPoints, value => model.MaxPoints = value, value); } - public int PointDropOff { get => model.PointDropOff; set => SetP(model.PointDropOff, value => model.PointDropOff = value, value); } - public IList PointsPerPlace { get => model.PointsPerPlace; set => SetP(model.PointsPerPlace, value => model.PointsPerPlace = value, value); } - public IDictionary BonusPoints { get => model.BonusPoints; set => SetP(model.BonusPoints, value => model.BonusPoints = value, value); } - public ICollection PointsSortOptions { get => model.PointsSortOptions; set => SetP(model.PointsSortOptions, value => model.PointsSortOptions = value, value); } - public ICollection FinalSortOptions { get => model.FinalSortOptions; set => SetP(model.FinalSortOptions, value => model.FinalSortOptions = value, value); } - public string BonusPointsString + public int MaxPoints { get => model.MaxPoints; set => SetP(model.MaxPoints, value => model.MaxPoints = value, value); } + public int PointDropOff { get => model.PointDropOff; set => SetP(model.PointDropOff, value => model.PointDropOff = value, value); } + public IList PointsPerPlace { get => model.PointsPerPlace; set => SetP(model.PointsPerPlace, value => model.PointsPerPlace = value, value); } + public IDictionary BonusPoints { get => model.BonusPoints; set => SetP(model.BonusPoints, value => model.BonusPoints = value, value); } + public ICollection PointsSortOptions { get => model.PointsSortOptions; set => SetP(model.PointsSortOptions, value => model.PointsSortOptions = value, value); } + public ICollection FinalSortOptions { get => model.FinalSortOptions; set => SetP(model.FinalSortOptions, value => model.FinalSortOptions = value, value); } + public string BonusPointsString + { + get => string.Join(';', BonusPoints.Select(x => string.Join(':', x.Key, x.Value))); + set { - get => string.Join(';', BonusPoints.Select(x => string.Join(':', x.Key, x.Value))); - set + var points = new Dictionary(); + var bonus = value.Split(';'); + foreach (var pair in bonus) { - var points = new Dictionary(); - var bonus = value.Split(';'); - foreach (var pair in bonus) - { - var parts = pair.Split(':'); - var key = parts[0]; - var keyValue = parts.Length <= 1 ? 0 : int.TryParse(parts[1], out int res) ? res : 0; - points.Add(key, keyValue); - } - BonusPoints = points; + var parts = pair.Split(':'); + var key = parts[0]; + var keyValue = parts.Length <= 1 ? 0 : int.TryParse(parts[1], out int res) ? res : 0; + points.Add(key, keyValue); } + BonusPoints = points; } + } - public enum PointRuleType - { - MaxPoints = 0, - PointList = 1, - Formula = 2, - } + public enum PointRuleType + { + MaxPoints = 0, + PointList = 1, + Formula = 2, + } - public override void SetModel(PointRuleModel model) - { - base.SetModel(model); - RuleType = InferRuleType(model); - OnPropertyChanged(); - } + public override void SetModel(PointRuleModel model) + { + base.SetModel(model); + RuleType = InferRuleType(model); + OnPropertyChanged(); + } - private void RuleTypeChanged(PointRuleType ruleType) + private void RuleTypeChanged(PointRuleType ruleType) + { + switch (ruleType) { - switch (ruleType) - { - case PointRuleType.MaxPoints: - break; - default: - break; - } + case PointRuleType.MaxPoints: + break; + default: + break; } + } - private static PointRuleType InferRuleType(PointRuleModel model) + private static PointRuleType InferRuleType(PointRuleModel model) + { + if (model.MaxPoints != 0) { - if (model.MaxPoints != 0) - { - return PointRuleType.MaxPoints; - } - return PointRuleType.PointList; + return PointRuleType.MaxPoints; } + return PointRuleType.PointList; } } diff --git a/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs index ee08bf75..ef11ca6c 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs @@ -2,94 +2,93 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ResultConfigSettingsViewModel : LeagueViewModelBase { - public class ResultConfigSettingsViewModel : LeagueViewModelBase + public ResultConfigSettingsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) { - public ResultConfigSettingsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) - { - resultConfigs = new ObservableCollection(); - } + resultConfigs = new ObservableCollection(); + } - private ObservableCollection resultConfigs; - public ObservableCollection ResultsConfigs { get => resultConfigs; set => Set(ref resultConfigs, value); } + private ObservableCollection resultConfigs; + public ObservableCollection ResultsConfigs { get => resultConfigs; set => Set(ref resultConfigs, value); } - private ResultConfigViewModel? selected; - public ResultConfigViewModel? Selected { get => selected; set => Set(ref selected, value); } + private ResultConfigViewModel? selected; + public ResultConfigViewModel? Selected { get => selected; set => Set(ref selected, value); } - public async Task LoadFromLeagueAsync() + public async Task LoadFromLeagueAsync() + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return; - } - - var resultConfigsEndpoint = ApiService.CurrentLeague.ResultConfigs(); - var resultConfigsResult = await resultConfigsEndpoint.Get(); - if (resultConfigsResult.Success == false || resultConfigsResult.Content is null) - { - return; - } - - ResultsConfigs = new ObservableCollection( - resultConfigsResult.Content.Select(x => new ResultConfigViewModel(LoggerFactory, ApiService, x))); + return; } - public async Task AddConfiguration() + var resultConfigsEndpoint = ApiService.CurrentLeague.ResultConfigs(); + var resultConfigsResult = await resultConfigsEndpoint.Get(); + if (resultConfigsResult.Success == false || resultConfigsResult.Content is null) { - if (ApiService.CurrentLeague is null) - { - return LeagueNullResult(); - } - - try - { - Loading = true; - ResultConfigModel newConfig = new() { Name = "New Config", DisplayName = "New Config" }; - var request = ApiService.CurrentLeague.ResultConfigs() - .Post(newConfig); - var result = await request; + return; + } - if (result.Success == true && result.Content is not null) - { - ResultsConfigs.Add(new ResultConfigViewModel(LoggerFactory, ApiService, result.Content)); - } + ResultsConfigs = new ObservableCollection( + resultConfigsResult.Content.Select(x => new ResultConfigViewModel(LoggerFactory, ApiService, x))); + } - return result.ToStatusResult(); - } - finally - { - Loading = false; - } + public async Task AddConfiguration() + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); } - public async Task DeleteConfiguration(ResultConfigViewModel config) + try { - if (ApiService.CurrentLeague is null) + Loading = true; + ResultConfigModel newConfig = new() { Name = "New Config", DisplayName = "New Config" }; + var request = ApiService.CurrentLeague.ResultConfigs() + .Post(newConfig); + var result = await request; + + if (result.Success == true && result.Content is not null) { - return LeagueNullResult(); + ResultsConfigs.Add(new ResultConfigViewModel(LoggerFactory, ApiService, result.Content)); } - try - { - Loading = true; - var request = ApiService.CurrentLeague.ResultConfigs() - .WithId(config.ResultConfigId) - .Delete(); - var result = await request; + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } - if (result.Success) - { - ResultsConfigs.Remove(config); - } + public async Task DeleteConfiguration(ResultConfigViewModel config) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } - return result.ToStatusResult(); - } - finally + try + { + Loading = true; + var request = ApiService.CurrentLeague.ResultConfigs() + .WithId(config.ResultConfigId) + .Delete(); + var result = await request; + + if (result.Success) { - Loading = false; + ResultsConfigs.Remove(config); } + + return result.ToStatusResult(); + } + finally + { + Loading = false; } } } diff --git a/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs index 76accfa9..b21bff7c 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs @@ -3,191 +3,190 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ResultConfigViewModel : LeagueViewModelBase { - public class ResultConfigViewModel : LeagueViewModelBase + public ResultConfigViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) + : this(loggerFactory, apiService, new()) { - public ResultConfigViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) - : this(loggerFactory, apiService, new()) - { - } + } - public ResultConfigViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ResultConfigModel model) - : base(loggerFactory, apiService, model) - { - scorings = new(); - filtersForPoints = new(); - filtersForResult = new(); - availableResultConfigs = new(); - } + public ResultConfigViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ResultConfigModel model) + : base(loggerFactory, apiService, model) + { + scorings = new(); + filtersForPoints = new(); + filtersForResult = new(); + availableResultConfigs = new(); + } - public long LeagueId => model.LeagueId; - public long ResultConfigId => model.ResultConfigId; - public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } - public string DisplayName { get => model.DisplayName; set => SetP(model.DisplayName, value => model.DisplayName = value, value); } - public ResultKind ResultKind { get => model.ResultKind; set => SetP(model.ResultKind, value => model.ResultKind = value, value); } - public int ResultsPerTeam { get => model.ResultsPerTeam; set => SetP(model.ResultsPerTeam, value => model.ResultsPerTeam = value, value); } - public ResultConfigInfoModel? SourceResultConfig { get => model.SourceResultConfig; set => SetP(model.SourceResultConfig, value => model.SourceResultConfig = value, value); } - public long SourceResultConfigId - { - get => SourceResultConfig?.ResultConfigId ?? 0; - set => SetP(SourceResultConfig, value => SourceResultConfig = value, GetConfigInfoModel(AvailableResultConfigs.FirstOrDefault(x => x.ResultConfigId == value))); - } - public bool CalculateCombinedResult + public long LeagueId => model.LeagueId; + public long ResultConfigId => model.ResultConfigId; + public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } + public string DisplayName { get => model.DisplayName; set => SetP(model.DisplayName, value => model.DisplayName = value, value); } + public ResultKind ResultKind { get => model.ResultKind; set => SetP(model.ResultKind, value => model.ResultKind = value, value); } + public int ResultsPerTeam { get => model.ResultsPerTeam; set => SetP(model.ResultsPerTeam, value => model.ResultsPerTeam = value, value); } + public ResultConfigInfoModel? SourceResultConfig { get => model.SourceResultConfig; set => SetP(model.SourceResultConfig, value => model.SourceResultConfig = value, value); } + public long SourceResultConfigId + { + get => SourceResultConfig?.ResultConfigId ?? 0; + set => SetP(SourceResultConfig, value => SourceResultConfig = value, GetConfigInfoModel(AvailableResultConfigs.FirstOrDefault(x => x.ResultConfigId == value))); + } + public bool CalculateCombinedResult + { + get => Scorings.Any(x => x.IsCombinedResult); + set { - get => Scorings.Any(x => x.IsCombinedResult); - set + if (value && CalculateCombinedResult == false) { - if (value && CalculateCombinedResult == false) - { - var combined = AddScoring(); - combined.Name = "Combined"; - combined.ShowResults = true; - combined.IsCombinedResult = true; - return; - } - if (value == false && CalculateCombinedResult) + var combined = AddScoring(); + combined.Name = "Combined"; + combined.ShowResults = true; + combined.IsCombinedResult = true; + return; + } + if (value == false && CalculateCombinedResult) + { + var removeScoring = Scorings.FirstOrDefault(x => x.IsCombinedResult); + if (removeScoring != null) { - var removeScoring = Scorings.FirstOrDefault(x => x.IsCombinedResult); - if (removeScoring != null) - { - RemoveScoring(removeScoring); - } + RemoveScoring(removeScoring); } } } + } - private StandingConfigurationViewModel? standingConfig; - public StandingConfigurationViewModel? StandingConfig { get => standingConfig; set => Set(ref standingConfig, value); } - public bool CalculateStandings + private StandingConfigurationViewModel? standingConfig; + public StandingConfigurationViewModel? StandingConfig { get => standingConfig; set => Set(ref standingConfig, value); } + public bool CalculateStandings + { + get => StandingConfig is not null; + set { - get => StandingConfig is not null; - set + if (value && model.StandingConfig is null) { - if (value && model.StandingConfig is null) - { - model.StandingConfig = new StandingConfigModel(); - StandingConfig = new(LoggerFactory, ApiService, model.StandingConfig); - } - if (value == false && model.StandingConfig is not null) - { - model.StandingConfig = null; - StandingConfig = null; - } + model.StandingConfig = new StandingConfigModel(); + StandingConfig = new(LoggerFactory, ApiService, model.StandingConfig); + } + if (value == false && model.StandingConfig is not null) + { + model.StandingConfig = null; + StandingConfig = null; } } + } + + private ObservableCollection scorings; + public ObservableCollection Scorings { get => scorings; set => SetP(scorings, value => scorings = value, value); } - private ObservableCollection scorings; - public ObservableCollection Scorings { get => scorings; set => SetP(scorings, value => scorings = value, value); } + private ObservableCollection filtersForPoints; + public ObservableCollection FiltersForPoints { get => filtersForPoints; set => Set(ref filtersForPoints, value); } - private ObservableCollection filtersForPoints; - public ObservableCollection FiltersForPoints { get => filtersForPoints; set => Set(ref filtersForPoints, value); } + private ObservableCollection filtersForResult; + public ObservableCollection FiltersForResult { get => filtersForResult; set => Set(ref filtersForResult, value); } - private ObservableCollection filtersForResult; - public ObservableCollection FiltersForResult { get => filtersForResult; set => Set(ref filtersForResult, value); } + private ObservableCollection availableResultConfigs; + public ObservableCollection AvailableResultConfigs { get => availableResultConfigs; set => Set(ref availableResultConfigs, value); } - private ObservableCollection availableResultConfigs; - public ObservableCollection AvailableResultConfigs { get => availableResultConfigs; set => Set(ref availableResultConfigs, value); } + public override void SetModel(ResultConfigModel model) + { + base.SetModel(model); + Scorings = new(model.Scorings.Select(scoringModel => new ScoringViewModel(LoggerFactory, ApiService, scoringModel))); + FiltersForPoints = new(model.FiltersForPoints.Select(filter => new ResultFilterViewModel(LoggerFactory, ApiService, filter))); + FiltersForResult = new(model.FiltersForResult.Select(filter => new ResultFilterViewModel(LoggerFactory, ApiService, filter))); + StandingConfig = model.StandingConfig is not null ? new StandingConfigurationViewModel(LoggerFactory, ApiService, model.StandingConfig) : null; + } - public override void SetModel(ResultConfigModel model) + public async Task LoadAvailableResultConfigs(CancellationToken cancellationToken) + { + if (ApiService.CurrentLeague is null) { - base.SetModel(model); - Scorings = new(model.Scorings.Select(scoringModel => new ScoringViewModel(LoggerFactory, ApiService, scoringModel))); - FiltersForPoints = new(model.FiltersForPoints.Select(filter => new ResultFilterViewModel(LoggerFactory, ApiService, filter))); - FiltersForResult = new(model.FiltersForResult.Select(filter => new ResultFilterViewModel(LoggerFactory, ApiService, filter))); - StandingConfig = model.StandingConfig is not null ? new StandingConfigurationViewModel(LoggerFactory, ApiService, model.StandingConfig) : null; + return LeagueNullResult(); } - public async Task LoadAvailableResultConfigs(CancellationToken cancellationToken) + var request = ApiService.CurrentLeague.ResultConfigs() + .Get(cancellationToken); + var result = await request; + if (result.Success && result.Content is IEnumerable configs) { - if (ApiService.CurrentLeague is null) - { - return LeagueNullResult(); - } + AvailableResultConfigs = new(configs); + } + + return result.ToStatusResult(); + } + public async Task SaveChangesAsync(CancellationToken cancellationToken) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = true; var request = ApiService.CurrentLeague.ResultConfigs() - .Get(cancellationToken); + .WithId(ResultConfigId) + .Put(model, cancellationToken); var result = await request; - if (result.Success && result.Content is IEnumerable configs) + + if (result.Success && result.Content is not null) { - AvailableResultConfigs = new(configs); + SetModel(result.Content); } return result.ToStatusResult(); } - - public async Task SaveChangesAsync(CancellationToken cancellationToken) + finally { - if (ApiService.CurrentLeague is null) - { - return LeagueNullResult(); - } - - try - { - Loading = true; - var request = ApiService.CurrentLeague.ResultConfigs() - .WithId(ResultConfigId) - .Put(model, cancellationToken); - var result = await request; + Loading = false; + } + } - if (result.Success && result.Content is not null) - { - SetModel(result.Content); - } + public ScoringViewModel AddScoring() + { + var scoring = new ScoringModel() { Name = "New Scoring" }; + model.Scorings.Add(scoring); + var newScoring = new ScoringViewModel(LoggerFactory, ApiService, scoring); + Scorings.Add(newScoring); + UpdateScoringIndex(); + return newScoring; + } - return result.ToStatusResult(); - } - finally - { - Loading = false; - } - } + public void RemoveScoring(ScoringViewModel scoring) + { + Scorings.Remove(scoring); + model.Scorings.Remove(scoring.GetModel()); + UpdateScoringIndex(); + } - public ScoringViewModel AddScoring() + private void UpdateScoringIndex() + { + foreach (var (scoring, index) in model.Scorings.Where(x => x.IsCombinedResult == false).Select((x, i) => (x, i))) { - var scoring = new ScoringModel() { Name = "New Scoring" }; - model.Scorings.Add(scoring); - var newScoring = new ScoringViewModel(LoggerFactory, ApiService, scoring); - Scorings.Add(newScoring); - UpdateScoringIndex(); - return newScoring; + scoring.Index = index; } - - public void RemoveScoring(ScoringViewModel scoring) + var combinedScoring = model.Scorings.FirstOrDefault(x => x.IsCombinedResult); + if (combinedScoring != null) { - Scorings.Remove(scoring); - model.Scorings.Remove(scoring.GetModel()); - UpdateScoringIndex(); + combinedScoring.Index = 999; } + } - private void UpdateScoringIndex() + public ResultConfigInfoModel? GetConfigInfoModel(ResultConfigModel? model) + { + if (model == null) { - foreach (var (scoring, index) in model.Scorings.Where(x => x.IsCombinedResult == false).Select((x, i) => (x, i))) - { - scoring.Index = index; - } - var combinedScoring = model.Scorings.FirstOrDefault(x => x.IsCombinedResult); - if (combinedScoring != null) - { - combinedScoring.Index = 999; - } + return null; } - public ResultConfigInfoModel? GetConfigInfoModel(ResultConfigModel? model) + return new() { - if (model == null) - { - return null; - } - - return new() - { - Name = model.Name, - DisplayName = model.DisplayName, - LeagueId = model.LeagueId, - ResultConfigId = model.ResultConfigId, - }; - } + Name = model.Name, + DisplayName = model.DisplayName, + LeagueId = model.LeagueId, + ResultConfigId = model.ResultConfigId, + }; } -} \ No newline at end of file +} diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs index c9e47113..42f1c49b 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs @@ -4,392 +4,391 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ReviewViewModel : LeagueViewModelBase { - public class ReviewViewModel : LeagueViewModelBase + public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService, new()) { - public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService, new()) - { - } - public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ReviewModel model) : - base(loggerFactory, apiService, model) - { - } + } + public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ReviewModel model) : + base(loggerFactory, apiService, model) + { + } - public long ReviewId => model.ReviewId; - public long EventId => model.EventId; - public string SessionName => model.SessionName; - public int SessionNr => model.SessionNr; - public long SeasonId => model.SeasonId; - public string AuthorName => model.AuthorName; - public string AuthorUserId => model.AuthorUserId; - public DateTime CreatedOn => model.CreatedOn.GetValueOrDefault(); - public DateTime LastModifiedOn => model.LastModifiedOn.GetValueOrDefault(); - - private long? sessionId; - public long? SessionId { get => sessionId; set => Set(ref sessionId, value); } - public string IncidentKind { get => model.IncidentKind; set => SetP(model.IncidentKind, value => model.IncidentKind = value, value); } - public string FullDescription { get => model.FullDescription; set => SetP(model.FullDescription, value => model.FullDescription = value, value); } - public string OnLap { get => model.OnLap; set => SetP(model.OnLap, value => model.OnLap = value, value); } - public string Corner { get => model.Corner; set => SetP(model.Corner, value => model.Corner = value, value); } - public TimeSpan TimeStamp { get => model.TimeStamp; set => SetP(model.TimeStamp, value => model.TimeStamp = value, value); } - public string IncidentNr { get => model.IncidentNr; set => SetP(model.IncidentNr, value => model.IncidentNr = value, value); } - public string ResultText { get => model.ResultText; set => SetP(model.ResultText, value => model.ResultText = value, value); } - - private IList involvedMembers = new List(); - public IList InvolvedMembers { get => involvedMembers; set => Set(ref involvedMembers, value); } - - private ObservableCollection comments = new(); - public ObservableCollection Comments { get => comments; set => Set(ref comments, value); } - - private ObservableCollection votes = new(); - public ObservableCollection Votes { get => votes; set => Set(ref votes, value); } - - public IEnumerable CountedVotes => GetCountedVotes(); - - public void AddVote(VoteViewModel vote) - { - votes.Add(vote); - model.VoteResults.Add(vote.GetModel()); - } + public long ReviewId => model.ReviewId; + public long EventId => model.EventId; + public string SessionName => model.SessionName; + public int SessionNr => model.SessionNr; + public long SeasonId => model.SeasonId; + public string AuthorName => model.AuthorName; + public string AuthorUserId => model.AuthorUserId; + public DateTime CreatedOn => model.CreatedOn.GetValueOrDefault(); + public DateTime LastModifiedOn => model.LastModifiedOn.GetValueOrDefault(); + + private long? sessionId; + public long? SessionId { get => sessionId; set => Set(ref sessionId, value); } + public string IncidentKind { get => model.IncidentKind; set => SetP(model.IncidentKind, value => model.IncidentKind = value, value); } + public string FullDescription { get => model.FullDescription; set => SetP(model.FullDescription, value => model.FullDescription = value, value); } + public string OnLap { get => model.OnLap; set => SetP(model.OnLap, value => model.OnLap = value, value); } + public string Corner { get => model.Corner; set => SetP(model.Corner, value => model.Corner = value, value); } + public TimeSpan TimeStamp { get => model.TimeStamp; set => SetP(model.TimeStamp, value => model.TimeStamp = value, value); } + public string IncidentNr { get => model.IncidentNr; set => SetP(model.IncidentNr, value => model.IncidentNr = value, value); } + public string ResultText { get => model.ResultText; set => SetP(model.ResultText, value => model.ResultText = value, value); } + + private IList involvedMembers = new List(); + public IList InvolvedMembers { get => involvedMembers; set => Set(ref involvedMembers, value); } + + private ObservableCollection comments = new(); + public ObservableCollection Comments { get => comments; set => Set(ref comments, value); } + + private ObservableCollection votes = new(); + public ObservableCollection Votes { get => votes; set => Set(ref votes, value); } + + public IEnumerable CountedVotes => GetCountedVotes(); + + public void AddVote(VoteViewModel vote) + { + votes.Add(vote); + model.VoteResults.Add(vote.GetModel()); + } - public void AddVote(VoteModel vote) - { - model.VoteResults.Add(vote); - votes.Add(new(LoggerFactory, ApiService, vote)); - } + public void AddVote(VoteModel vote) + { + model.VoteResults.Add(vote); + votes.Add(new(LoggerFactory, ApiService, vote)); + } - public void RemoveVote(VoteViewModel vote) - { - votes.Remove(vote); - model.VoteResults.Remove(vote.GetModel()); - } + public void RemoveVote(VoteViewModel vote) + { + votes.Remove(vote); + model.VoteResults.Remove(vote.GetModel()); + } - /// - /// Add one or more members to the selection"/> - /// - /// - public void AddMemberSelection(IEnumerable selection) + /// + /// Add one or more members to the selection"/> + /// + /// + public void AddMemberSelection(IEnumerable selection) + { + foreach (var member in selection) { - foreach (var member in selection) + if (model.InvolvedMembers.Contains(member)) { - if (model.InvolvedMembers.Contains(member)) - { - continue; - } - if (member.MemberId == 0) - { - continue; - } - if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId)) - { - continue; - } - model.InvolvedMembers.Add(member); + continue; } - RefreshMemberList(); - } - - /// - /// Remove one or more members from the selection"/> - /// - /// - public void RemoveMemberSelection(IEnumerable selection) - { - foreach (var member in selection) + if (member.MemberId == 0) { - if (model.InvolvedMembers.Contains(member)) - { - model.InvolvedMembers.Remove(member); - continue; - } - if (member.MemberId == 0) - { - continue; - } - var involvedMember = model.InvolvedMembers.FirstOrDefault(x => x.MemberId == member.MemberId); - if (involvedMember != null) - { - model.InvolvedMembers.Remove(involvedMember); - continue; - } + continue; + } + if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId)) + { + continue; } - RefreshMemberList(); + model.InvolvedMembers.Add(member); } + RefreshMemberList(); + } - /// - /// Add a comment to the review - /// - /// - /// - public async Task AddComment(PostReviewCommentModel postComment, CancellationToken cancellationToken) + /// + /// Remove one or more members from the selection"/> + /// + /// + public void RemoveMemberSelection(IEnumerable selection) + { + foreach (var member in selection) { - // Get the endpoint - var reviewEndpoint = GetReviewEndpoint(); - if (reviewEndpoint == null) + if (model.InvolvedMembers.Contains(member)) { - return LeagueNullResult(); + model.InvolvedMembers.Remove(member); + continue; } - - // Upload comment - var result = await reviewEndpoint.ReviewComments().Post(postComment); - if (result.Success && result.Content is not null) + if (member.MemberId == 0) + { + continue; + } + var involvedMember = model.InvolvedMembers.FirstOrDefault(x => x.MemberId == member.MemberId); + if (involvedMember != null) { - // Update comment list - model.ReviewComments = model.ReviewComments.Concat(new[] { result.Content }); - RefreshCommentList(); + model.InvolvedMembers.Remove(involvedMember); + continue; } + } + RefreshMemberList(); + } - return result.ToStatusResult(); + /// + /// Add a comment to the review + /// + /// + /// + public async Task AddComment(PostReviewCommentModel postComment, CancellationToken cancellationToken) + { + // Get the endpoint + var reviewEndpoint = GetReviewEndpoint(); + if (reviewEndpoint == null) + { + return LeagueNullResult(); } - /// - /// Delete a comment - /// - /// - /// - public async Task RemoveComment(ReviewCommentViewModel comment, CancellationToken cancellationToken = default) + // Upload comment + var result = await reviewEndpoint.ReviewComments().Post(postComment); + if (result.Success && result.Content is not null) { - if (ApiService.CurrentLeague is null) - { - return LeagueNullResult(); - } + // Update comment list + model.ReviewComments = model.ReviewComments.Concat(new[] { result.Content }); + RefreshCommentList(); + } - var commentEndpoint = ApiService.CurrentLeague - .ReviewComments() - .WithId(comment.CommentId); + return result.ToStatusResult(); + } - var result = await commentEndpoint.Delete(cancellationToken); - if (result.Success) - { - model.ReviewComments = model.ReviewComments.Except(new[] { comment.GetModel() }); - RefreshCommentList(); - } + /// + /// Delete a comment + /// + /// + /// + public async Task RemoveComment(ReviewCommentViewModel comment, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } - return result.ToStatusResult(); + var commentEndpoint = ApiService.CurrentLeague + .ReviewComments() + .WithId(comment.CommentId); + + var result = await commentEndpoint.Delete(cancellationToken); + if (result.Success) + { + model.ReviewComments = model.ReviewComments.Except(new[] { comment.GetModel() }); + RefreshCommentList(); } - /// - /// Get endpoint for this review by the current value - /// - /// - private IReviewByIdEndpoint? GetReviewEndpoint() + return result.ToStatusResult(); + } + + /// + /// Get endpoint for this review by the current value + /// + /// + private IReviewByIdEndpoint? GetReviewEndpoint() + { + if (ReviewId == 0) { - if (ReviewId == 0) - { - return null; - } - return ApiService.CurrentLeague?.Reviews().WithId(ReviewId); + return null; } + return ApiService.CurrentLeague?.Reviews().WithId(ReviewId); + } - private void UpdateModelMemberList() + private void UpdateModelMemberList() + { + foreach (var member in InvolvedMembers) { - foreach (var member in InvolvedMembers) + if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) { - if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) - { - model.InvolvedMembers.Add(member); - } + model.InvolvedMembers.Add(member); } - foreach (var member in model.InvolvedMembers.ToArray()) + } + foreach (var member in model.InvolvedMembers.ToArray()) + { + if (InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) { - if (InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) - { - model.InvolvedMembers.Remove(member); - } + model.InvolvedMembers.Remove(member); } } + } - private void RefreshMemberList() + private void RefreshMemberList() + { + // Add comments from to list that are not already in there + foreach (var member in model.InvolvedMembers) { - // Add comments from to list that are not already in there - foreach (var member in model.InvolvedMembers) + if (InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) { - if (InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) - { - InvolvedMembers.Add(member); - } + InvolvedMembers.Add(member); } - // Remove comments that are no longer in the model - foreach (var member in InvolvedMembers.ToArray()) + } + // Remove comments that are no longer in the model + foreach (var member in InvolvedMembers.ToArray()) + { + if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) { - if (model.InvolvedMembers.Any(x => x.MemberId == member.MemberId) == false) - { - InvolvedMembers.Remove(member); - } + InvolvedMembers.Remove(member); } } + } - /// - /// Refresh comment list with the current comment models - /// - private void RefreshCommentList() + /// + /// Refresh comment list with the current comment models + /// + private void RefreshCommentList() + { + // Add comments from to list that are not already in there + foreach (var comment in model.ReviewComments) { - // Add comments from to list that are not already in there - foreach (var comment in model.ReviewComments) + if (Comments.Any(x => x.GetModel() == comment) == false) { - if (Comments.Any(x => x.GetModel() == comment) == false) - { - Comments.Add(new ReviewCommentViewModel(LoggerFactory, ApiService, comment)); - } + Comments.Add(new ReviewCommentViewModel(LoggerFactory, ApiService, comment)); } - // Remove comments that are no longer in the model - foreach (var commentViewModel in Comments.ToArray()) + } + // Remove comments that are no longer in the model + foreach (var commentViewModel in Comments.ToArray()) + { + if (model.ReviewComments.Any(x => x == commentViewModel.GetModel()) == false) { - if (model.ReviewComments.Any(x => x == commentViewModel.GetModel()) == false) - { - Comments.Remove(commentViewModel); - } + Comments.Remove(commentViewModel); } } + } - public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + if (model == null) { - if (model == null) - { - return StatusResult.SuccessResult(); - } - if (ApiService.CurrentLeague == null || ReviewId == 0) - { - return LeagueNullResult(); - } + return StatusResult.SuccessResult(); + } + if (ApiService.CurrentLeague == null || ReviewId == 0) + { + return LeagueNullResult(); + } - UpdateModelMemberList(); + UpdateModelMemberList(); - try + try + { + Loading = true; + // if session was changed -> move review + if (SessionId != null && SessionId != model.SessionId) { - Loading = true; - // if session was changed -> move review - if (SessionId != null && SessionId != model.SessionId) - { - var moveRequest = ApiService.CurrentLeague - .Reviews() - .WithId(ReviewId) - .MoveToSession(SessionId.Value); - var moveResult = await moveRequest.Post(cancellationToken); - if (moveResult.Success == false) - { - return moveResult.ToStatusResult(); - } - } - - var request = ApiService.CurrentLeague + var moveRequest = ApiService.CurrentLeague .Reviews() .WithId(ReviewId) - .Put(model, cancellationToken); - var result = await request; - if (result.Success == false || result.Content is null) + .MoveToSession(SessionId.Value); + var moveResult = await moveRequest.Post(cancellationToken); + if (moveResult.Success == false) { - return result.ToStatusResult(); + return moveResult.ToStatusResult(); } - SetModel(result.Content); - return StatusResult.SuccessResult(); } - finally + + var request = ApiService.CurrentLeague + .Reviews() + .WithId(ReviewId) + .Put(model, cancellationToken); + var result = await request; + if (result.Success == false || result.Content is null) { - Loading = false; + return result.ToStatusResult(); } + SetModel(result.Content); + return StatusResult.SuccessResult(); } - - private void RefreshVoteList() + finally { - Votes = new ObservableCollection(model.VoteResults.Select(x => new VoteViewModel(LoggerFactory, ApiService, x))); + Loading = false; } + } - private IEnumerable GetCountedVotes() + private void RefreshVoteList() + { + Votes = new ObservableCollection(model.VoteResults.Select(x => new VoteViewModel(LoggerFactory, ApiService, x))); + } + + private IEnumerable GetCountedVotes() + { + List countedVotes = new(); + foreach (var vote in Comments.SelectMany(x => x.Votes)) { - List countedVotes = new(); - foreach (var vote in Comments.SelectMany(x => x.Votes)) + CountedVote? countedVote = countedVotes + .FirstOrDefault(x => CompareVotes(vote, x.Vote)); + if (countedVote == null) { - CountedVote? countedVote = countedVotes - .FirstOrDefault(x => CompareVotes(vote, x.Vote)); - if (countedVote == null) - { - countedVote = new(vote); - countedVotes.Add(countedVote); - } - countedVote.Count++; + countedVote = new(vote); + countedVotes.Add(countedVote); } - return countedVotes; + countedVote.Count++; } + return countedVotes; + } + + private bool CompareVotes(VoteViewModel vote1, VoteViewModel vote2) + { + return vote1.MemberAtFault?.MemberId == vote2.MemberAtFault?.MemberId && vote1.VoteCategoryId == vote2.VoteCategoryId; + } - private bool CompareVotes(VoteViewModel vote1, VoteViewModel vote2) + public async Task AddToSessionAsync(long sessionId, CancellationToken cancellationToken = default) + { + if (model == null) { - return vote1.MemberAtFault?.MemberId == vote2.MemberAtFault?.MemberId && vote1.VoteCategoryId == vote2.VoteCategoryId; + return StatusResult.SuccessResult(); } - - public async Task AddToSessionAsync(long sessionId, CancellationToken cancellationToken = default) + if (ApiService.CurrentLeague == null) { - if (model == null) - { - return StatusResult.SuccessResult(); - } - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } + return LeagueNullResult(); + } - UpdateModelMemberList(); + UpdateModelMemberList(); - try - { - Loading = true; - var endpoint = ApiService.CurrentLeague.Sessions() - .WithId(sessionId) - .Reviews(); - var result = await endpoint.Post(model, cancellationToken); - if (result.Success == false) - { - return result.ToStatusResult(); - } - SetModel(model); - return StatusResult.SuccessResult(); - } - finally + try + { + Loading = true; + var endpoint = ApiService.CurrentLeague.Sessions() + .WithId(sessionId) + .Reviews(); + var result = await endpoint.Post(model, cancellationToken); + if (result.Success == false) { - Loading = false; + return result.ToStatusResult(); } + SetModel(model); + return StatusResult.SuccessResult(); } + finally + { + Loading = false; + } + } - public async Task DeleteAsync(CancellationToken cancellationToken = default) + public async Task DeleteAsync(CancellationToken cancellationToken = default) + { + if (model == null) { - if (model == null) - { - return true; - } - if (ApiService.CurrentLeague == null) - { - return false; - } + return true; + } + if (ApiService.CurrentLeague == null) + { + return false; + } - try - { - Loading = true; - var request = ApiService.CurrentLeague.Reviews() - .WithId(ReviewId) - .Delete(cancellationToken); - var result = await request; - if (result.Success == false) - { - result.EnsureSuccess(); - return false; - } - return true; - } - finally + try + { + Loading = true; + var request = ApiService.CurrentLeague.Reviews() + .WithId(ReviewId) + .Delete(cancellationToken); + var result = await request; + if (result.Success == false) { - Loading = false; + result.EnsureSuccess(); + return false; } + return true; } - - public override void SetModel(ReviewModel model) + finally { - base.SetModel(model); - RefreshMemberList(); - RefreshCommentList(); - RefreshVoteList(); - SessionId = model.SessionId; + Loading = false; } } + + public override void SetModel(ReviewModel model) + { + base.SetModel(model); + RefreshMemberList(); + RefreshCommentList(); + RefreshVoteList(); + SessionId = model.SessionId; + } } diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs index 746e5c90..208c6b57 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs @@ -2,68 +2,67 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ReviewsPageViewModel : LeagueViewModelBase { - public class ReviewsPageViewModel : LeagueViewModelBase + public ReviewsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) { - public ReviewsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) - { - } + } - private ObservableCollection reviews = new(); - public ObservableCollection Reviews { get => reviews; set => Set(ref reviews, value); } + private ObservableCollection reviews = new(); + public ObservableCollection Reviews { get => reviews; set => Set(ref reviews, value); } - private IEnumerable eventMembers = Array.Empty(); - public IEnumerable EventMembers { get => eventMembers; set => Set(ref eventMembers, value); } + private IEnumerable eventMembers = Array.Empty(); + public IEnumerable EventMembers { get => eventMembers; set => Set(ref eventMembers, value); } - public async Task LoadFromEventAsync(long eventId, CancellationToken cancellationToken = default) + public async Task LoadFromEventAsync(long eventId, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return; - } + return; + } - try + try + { + Loading = true; + var eventEndpoint = ApiService.CurrentLeague + .Events() + .WithId(eventId); + if (ApiService.CurrentSeason == null) { - Loading = true; - var eventEndpoint = ApiService.CurrentLeague - .Events() - .WithId(eventId); - if (ApiService.CurrentSeason == null) - { - var @event = (await eventEndpoint.Get(cancellationToken)).EnsureSuccess(); - if (@event == null) - { - return; - } - await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, @event.SeasonId); - } - - var reviewsEndpoint = eventEndpoint - .Reviews(); - var result = await reviewsEndpoint.Get(cancellationToken); - if (result.Success == false || result.Content is null) + var @event = (await eventEndpoint.Get(cancellationToken)).EnsureSuccess(); + if (@event == null) { return; } + await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, @event.SeasonId); + } - var reviewModels = result.Content; - Reviews = new(reviewModels.Select(x => new ReviewViewModel(LoggerFactory, ApiService, x))); - - var membersEndpoint = eventEndpoint - .Members(); - var membersResult = await membersEndpoint.Get(cancellationToken); - if (membersResult.Success == false || membersResult.Content is null) - { - return; - } - EventMembers = membersResult.Content; + var reviewsEndpoint = eventEndpoint + .Reviews(); + var result = await reviewsEndpoint.Get(cancellationToken); + if (result.Success == false || result.Content is null) + { + return; } - finally + + var reviewModels = result.Content; + Reviews = new(reviewModels.Select(x => new ReviewViewModel(LoggerFactory, ApiService, x))); + + var membersEndpoint = eventEndpoint + .Members(); + var membersResult = await membersEndpoint.Get(cancellationToken); + if (membersResult.Success == false || membersResult.Content is null) { - Loading = false; + return; } + EventMembers = membersResult.Content; + } + finally + { + Loading = false; } } } diff --git a/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs index a780563f..9c6c8bc6 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs @@ -2,119 +2,95 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ScheduleViewModel : LeagueViewModelBase { - public class ScheduleViewModel : LeagueViewModelBase + private ScheduleModel model; + + public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + this(loggerFactory, apiService, new ScheduleModel()) { - private ScheduleModel model; + } - public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - this(loggerFactory, apiService, new ScheduleModel()) - { - } + public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScheduleModel model) : + base(loggerFactory, apiService) + { + events = new ObservableCollection(); + this.model = model; + } - public ScheduleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScheduleModel model) : - base(loggerFactory, apiService) - { - events = new ObservableCollection(); - this.model = model; - } + public long ScheduleId { get => model.ScheduleId; set => SetP(model.ScheduleId, value => model.ScheduleId = value, value); } + public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } - public long ScheduleId { get => model.ScheduleId; set => SetP(model.ScheduleId, value => model.ScheduleId = value, value); } - public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } + public int MaxRaceCount => Events.Count > 0 ? Events.Max(x => x.RaceCount) : 0; - public int MaxRaceCount => Events.Count > 0 ? Events.Max(x => x.RaceCount) : 0; + private ObservableCollection events; + public ObservableCollection Events { get => events; set => Set(ref events, value); } - private ObservableCollection events; - public ObservableCollection Events { get => events; set => Set(ref events, value); } + public async Task SetModel(ScheduleModel model) + { + this.model = model; + OnPropertyChanged(); + await LoadEvents(); + } - public async Task SetModel(ScheduleModel model) + public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - this.model = model; - OnPropertyChanged(); - await LoadEvents(); + return false; } - - public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + try { - if (ApiService.CurrentLeague == null) - { - return false; - } - try - { - Loading = true; - var result = await ApiService.CurrentLeague.Schedules().WithId(ScheduleId).Put(model, cancellationToken); - - if (result.Success) - { - return true; - } - return false; - } - finally + Loading = true; + var result = await ApiService.CurrentLeague.Schedules().WithId(ScheduleId).Put(model, cancellationToken); + + if (result.Success) { - Loading = false; + return true; } + return false; } - - public async Task Reload(CancellationToken cancellationToken = default) + finally { - if (ApiService.CurrentLeague == null) - { - return; - } - if (ScheduleId == 0) - { - return; - } - - var result = await ApiService.CurrentLeague.Schedules().WithId(ScheduleId).Get(cancellationToken); - if (result.Success == false || result.Content is null) - { - return; - } - await SetModel(result.Content); + Loading = false; } + } - public async Task AddEvent(EventViewModel @event, CancellationToken cancellationToken = default) + public async Task Reload(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } + return; + } + if (ScheduleId == 0) + { + return; + } - try - { - Loading = true; - var request = ApiService.CurrentLeague.Schedules() - .WithId(ScheduleId) - .Events() - .Post(@event.GetModel(), cancellationToken); - var result = await request; - if (result.Success) - { - await LoadEvents(cancellationToken); - } - - return result.ToStatusResult(); - } - finally - { - Loading = false; - } + var result = await ApiService.CurrentLeague.Schedules().WithId(ScheduleId).Get(cancellationToken); + if (result.Success == false || result.Content is null) + { + return; } + await SetModel(result.Content); + } - public async Task RemoveEvent(EventViewModel @event, CancellationToken cancellationToken = default) + public async Task AddEvent(EventViewModel @event, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) - { - return LeagueNullResult(); - } + return LeagueNullResult(); + } - var request = ApiService.CurrentLeague.Events() - .WithId(@event.EventId) - .Delete(cancellationToken); + try + { + Loading = true; + var request = ApiService.CurrentLeague.Schedules() + .WithId(ScheduleId) + .Events() + .Post(@event.GetModel(), cancellationToken); var result = await request; if (result.Success) { @@ -123,25 +99,48 @@ public async Task RemoveEvent(EventViewModel @event, CancellationT return result.ToStatusResult(); } + finally + { + Loading = false; + } + } - public async Task LoadEvents(CancellationToken cancellationToken = default) + public async Task RemoveEvent(EventViewModel @event, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) return; - Loading = true; + return LeagueNullResult(); + } - //await Task.Delay(500); + var request = ApiService.CurrentLeague.Events() + .WithId(@event.EventId) + .Delete(cancellationToken); + var result = await request; + if (result.Success) + { + await LoadEvents(cancellationToken); + } - var result = await ApiService.CurrentLeague.Schedules().WithId(ScheduleId).Events().Get(cancellationToken); - if (result.Success == false || result.Content is null) - { - return; - } + return result.ToStatusResult(); + } - var sessions = result.Content; - Events = new ObservableCollection(sessions.Select(x => - new EventViewModel(LoggerFactory, ApiService, x))); + public async Task LoadEvents(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague == null) return; + Loading = true; - Loading = false; + //await Task.Delay(500); + + var result = await ApiService.CurrentLeague.Schedules().WithId(ScheduleId).Events().Get(cancellationToken); + if (result.Success == false || result.Content is null) + { + return; } + + var sessions = result.Content; + Events = new ObservableCollection(sessions.Select(x => + new EventViewModel(LoggerFactory, ApiService, x))); + + Loading = false; } -} \ No newline at end of file +} diff --git a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs index ef744d6b..04c67930 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs @@ -2,36 +2,35 @@ using iRLeagueManager.Web.Data; using System.ComponentModel.DataAnnotations; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class ScoringViewModel : LeagueViewModelBase { - public class ScoringViewModel : LeagueViewModelBase + public ScoringViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScoringModel model) : + base(loggerFactory, apiService, model) { - public ScoringViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScoringModel model) : - base(loggerFactory, apiService, model) - { - pointRule ??= new(loggerFactory, apiService); - } + pointRule ??= new(loggerFactory, apiService); + } - public long Id => model.Id; - public long LeagueId => model.LeagueId; - [Required] - public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } - public bool ShowResults { get => model.ShowResults; set => SetP(model.ShowResults, value => model.ShowResults = value, value); } - public bool IsCombinedResult { get => model.IsCombinedResult; set => SetP(model.IsCombinedResult, value => model.IsCombinedResult = value, value); } - public bool UseResultSetTeam { get => model.UseResultSetTeam; set => SetP(model.UseResultSetTeam, value => model.UseResultSetTeam = value, value); } - public bool UpdateTeamOnRecalculation { get => model.UpdateTeamOnRecalculation; set => SetP(model.UpdateTeamOnRecalculation, value => model.UpdateTeamOnRecalculation = value, value); } - public int MaxResultsPerGroup { get => model.MaxResultsPerGroup; set => SetP(model.MaxResultsPerGroup, value => model.MaxResultsPerGroup = value, value); } - public bool CalcPoints { get => !model.UseSourcePoints; set => SetP(model.UseSourcePoints, value => model.UseSourcePoints = value, !value); } + public long Id => model.Id; + public long LeagueId => model.LeagueId; + [Required] + public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } + public bool ShowResults { get => model.ShowResults; set => SetP(model.ShowResults, value => model.ShowResults = value, value); } + public bool IsCombinedResult { get => model.IsCombinedResult; set => SetP(model.IsCombinedResult, value => model.IsCombinedResult = value, value); } + public bool UseResultSetTeam { get => model.UseResultSetTeam; set => SetP(model.UseResultSetTeam, value => model.UseResultSetTeam = value, value); } + public bool UpdateTeamOnRecalculation { get => model.UpdateTeamOnRecalculation; set => SetP(model.UpdateTeamOnRecalculation, value => model.UpdateTeamOnRecalculation = value, value); } + public int MaxResultsPerGroup { get => model.MaxResultsPerGroup; set => SetP(model.MaxResultsPerGroup, value => model.MaxResultsPerGroup = value, value); } + public bool CalcPoints { get => !model.UseSourcePoints; set => SetP(model.UseSourcePoints, value => model.UseSourcePoints = value, !value); } - private PointRuleViewModel pointRule; - public PointRuleViewModel PointRule { get => pointRule; set => Set(ref pointRule, value); } + private PointRuleViewModel pointRule; + public PointRuleViewModel PointRule { get => pointRule; set => Set(ref pointRule, value); } - public override void SetModel(ScoringModel model) - { - this.model = model; - model.PointRule ??= new(); - PointRule = new(LoggerFactory, ApiService, model.PointRule); - OnPropertyChanged(); - } + public override void SetModel(ScoringModel model) + { + this.model = model; + model.PointRule ??= new(); + PointRule = new(LoggerFactory, ApiService, model.PointRule); + OnPropertyChanged(); } -} \ No newline at end of file +} diff --git a/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs index 9a4d8444..38144587 100644 --- a/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs @@ -2,54 +2,53 @@ using iRLeagueManager.Web.Data; using System.Linq.Expressions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class SessionResultViewModel : LeagueViewModelBase { - public class SessionResultViewModel : LeagueViewModelBase - { - private ResultModel model; + private ResultModel model; - public SessionResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - this(loggerFactory, apiService, new ResultModel()) - { - } + public SessionResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + this(loggerFactory, apiService, new ResultModel()) + { + } - public SessionResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ResultModel model) : - base(loggerFactory, apiService) - { - this.model = model; - orderByPropertySelector = x => x.FinalPosition; - } + public SessionResultViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ResultModel model) : + base(loggerFactory, apiService) + { + this.model = model; + orderByPropertySelector = x => x.FinalPosition; + } - public long SeasonId => model.SeasonId; - public string SessionName => model.SessionName; - public int? SessionNr => model.SessionNr; + public long SeasonId => model.SeasonId; + public string SessionName => model.SessionName; + public int? SessionNr => model.SessionNr; - private Expression> orderByPropertySelector; - public Expression> OrderByPropertySelector + private Expression> orderByPropertySelector; + public Expression> OrderByPropertySelector + { + get => orderByPropertySelector; + set { - get => orderByPropertySelector; - set + if (Set(ref orderByPropertySelector, value, new SamePropertyEqualityComparer())) { - if (Set(ref orderByPropertySelector, value, new SamePropertyEqualityComparer())) - { - OnPropertyChanged(nameof(ResultRows)); - return; - } - OrderDescending = !OrderDescending; + OnPropertyChanged(nameof(ResultRows)); + return; } + OrderDescending = !OrderDescending; } - public bool OrderDescending { get; private set; } + } + public bool OrderDescending { get; private set; } - public IEnumerable ResultRows + public IEnumerable ResultRows + { + get { - get + if (OrderDescending) { - if (OrderDescending) - { - return model.ResultRows.OrderByDescending(OrderByPropertySelector.Compile()); - } - return model.ResultRows.OrderBy(OrderByPropertySelector.Compile()); + return model.ResultRows.OrderByDescending(OrderByPropertySelector.Compile()); } + return model.ResultRows.OrderBy(OrderByPropertySelector.Compile()); } } } diff --git a/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs index 9105ca26..664b81c5 100644 --- a/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs @@ -2,44 +2,43 @@ using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class SessionViewModel : LeagueViewModelBase { - public class SessionViewModel : LeagueViewModelBase - { - private SessionModel model; + private SessionModel model; - public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) - { - model = new SessionModel(); - } + public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) + { + model = new SessionModel(); + } - public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, SessionModel model) - : base(loggerFactory, apiService) - { - this.model = model; - } + public SessionViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, SessionModel model) + : base(loggerFactory, apiService) + { + this.model = model; + } - public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } - public long SessionId { get => model.SessionId; set => SetP(model.SessionId, value => model.SessionId = value, value); } - public int SessionNr { get => model.SessionNr; set => SetP(model.SessionNr, value => model.SessionNr = value, value); } - public SessionType SessionType { get => model.SessionType; set => SetP(model.SessionType, value => model.SessionType = value, value); } - public DateTime Duration - { - get => DateTime.MinValue.Add(model.Duration); - set => SetP(model.Duration, value => model.Duration = value, value.TimeOfDay); - } - public int Laps { get => model.Laps; set => SetP(model.Laps, value => model.Laps = value, value); } + public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } + public long SessionId { get => model.SessionId; set => SetP(model.SessionId, value => model.SessionId = value, value); } + public int SessionNr { get => model.SessionNr; set => SetP(model.SessionNr, value => model.SessionNr = value, value); } + public SessionType SessionType { get => model.SessionType; set => SetP(model.SessionType, value => model.SessionType = value, value); } + public DateTime Duration + { + get => DateTime.MinValue.Add(model.Duration); + set => SetP(model.Duration, value => model.Duration = value, value.TimeOfDay); + } + public int Laps { get => model.Laps; set => SetP(model.Laps, value => model.Laps = value, value); } - public string LapsString - { - get => Laps.ToString(); - set => Laps = int.TryParse(value, out int laps) ? laps : 0; - } + public string LapsString + { + get => Laps.ToString(); + set => Laps = int.TryParse(value, out int laps) ? laps : 0; + } - public SessionModel GetModel() - { - return model; - } + public SessionModel GetModel() + { + return model; } } diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs index 79c106da..ee86811d 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs @@ -1,129 +1,128 @@ using iRLeagueApiCore.Common.Enums; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class SortOptionViewModel : MvvmBlazor.ViewModel.ViewModelBase { - public class SortOptionViewModel : MvvmBlazor.ViewModel.ViewModelBase - { - private SortOptions model; + private SortOptions model; - public SortOptionViewModel(SortOptions model) - { - SetModel(model); - } + public SortOptionViewModel(SortOptions model) + { + SetModel(model); + } - private SortValue sortValue; - public SortValue SortValue + private SortValue sortValue; + public SortValue SortValue + { + get => sortValue; + set { - get => sortValue; - set + if (Set(ref sortValue, value)) { - if (Set(ref sortValue, value)) - { - model = GetSortOptions(sortValue, sortDirection); - } + model = GetSortOptions(sortValue, sortDirection); } } + } - private SortDirection sortDirection; - public SortDirection SortDirection + private SortDirection sortDirection; + public SortDirection SortDirection + { + get => sortDirection; + set { - get => sortDirection; - set + if (Set(ref sortDirection, value)) { - if (Set(ref sortDirection, value)) - { - model = GetSortOptions(sortValue, sortDirection); - } + model = GetSortOptions(sortValue, sortDirection); } } + } - private (SortValue sortValue, SortDirection direction) GetSortValue(SortOptions value) - { - return value switch - { - SortOptions.PosAsc => (SortValue.Pos, SortDirection.Ascending), - SortOptions.PosDesc => (SortValue.Pos, SortDirection.Descending), - SortOptions.PosChgAsc => (SortValue.PosChg, SortDirection.Ascending), - SortOptions.PosChgDesc => (SortValue.PosChg, SortDirection.Descending), - SortOptions.StartPosAsc => (SortValue.StartPos, SortDirection.Ascending), - SortOptions.StartPosDesc => (SortValue.StartPos, SortDirection.Descending), - SortOptions.RacePtsAsc => (SortValue.RacePts, SortDirection.Ascending), - SortOptions.RacePtsDesc => (SortValue.RacePts, SortDirection.Descending), - SortOptions.PenPtsAsc => (SortValue.PenPts, SortDirection.Ascending), - SortOptions.PenPtsDesc => (SortValue.PenPts, SortDirection.Descending), - SortOptions.BonusPtsAsc => (SortValue.BonusPts, SortDirection.Ascending), - SortOptions.BonusPtsDesc => (SortValue.BonusPts, SortDirection.Descending), - SortOptions.TotalPtsAsc => (SortValue.TotalPts, SortDirection.Ascending), - SortOptions.TotalPtsDesc => (SortValue.TotalPts, SortDirection.Descending), - SortOptions.IntvlAsc => (SortValue.Intvl, SortDirection.Ascending), - SortOptions.IntvlDesc => (SortValue.Intvl, SortDirection.Descending), - SortOptions.ComplLapsAsc => (SortValue.ComplLaps, SortDirection.Ascending), - SortOptions.ComplLapsDesc => (SortValue.ComplLaps, SortDirection.Descending), - SortOptions.LeadLapsAsc => (SortValue.LeadLaps, SortDirection.Ascending), - SortOptions.LeadLapsDesc => (SortValue.LeadLaps, SortDirection.Descending), - SortOptions.IncsAsc => (SortValue.Incs, SortDirection.Ascending), - SortOptions.IncsDesc => (SortValue.Incs, SortDirection.Descending), - SortOptions.FastLapAsc => (SortValue.FastLap, SortDirection.Ascending), - SortOptions.FastLapDesc => (SortValue.FastLap, SortDirection.Descending), - SortOptions.QualLapAsc => (SortValue.QualLap, SortDirection.Ascending), - SortOptions.QualLapDesc => (SortValue.QualLap, SortDirection.Descending), - SortOptions.FinPosAsc => (SortValue.FinalPos, SortDirection.Ascending), - SortOptions.FinPosDesc => (SortValue.FinalPos, SortDirection.Descending), - SortOptions.TotalPtsWoBonusAsc => (SortValue.TotalPtsNoBonus, SortDirection.Ascending), - SortOptions.TotalPtsWoBonusDesc => (SortValue.TotalPtsNoBonus, SortDirection.Descending), - SortOptions.TotalPtsWoPenaltyAsc => (SortValue.TotalPtsNoPenalty, SortDirection.Ascending), - SortOptions.TotalPtsWoPenaltyDesc => (SortValue.TotalPtsNoPenalty, SortDirection.Descending), - _ => (SortValue.TotalPts, SortDirection.Descending), - }; - } - - private SortOptions GetSortOptions(SortValue sortValue, SortDirection direction) + private (SortValue sortValue, SortDirection direction) GetSortValue(SortOptions value) + { + return value switch { - return (sortValue, direction) switch - { - (SortValue.Pos, SortDirection.Ascending) => SortOptions.PosAsc, - (SortValue.Pos, SortDirection.Descending) => SortOptions.PosDesc, - (SortValue.PosChg, SortDirection.Ascending) => SortOptions.PosChgAsc, - (SortValue.PosChg, SortDirection.Descending) => SortOptions.PosChgDesc, - (SortValue.StartPos, SortDirection.Ascending) => SortOptions.StartPosAsc, - (SortValue.StartPos, SortDirection.Descending) => SortOptions.StartPosDesc, - (SortValue.RacePts, SortDirection.Ascending) => SortOptions.RacePtsAsc, - (SortValue.RacePts, SortDirection.Descending) => SortOptions.RacePtsDesc, - (SortValue.PenPts, SortDirection.Ascending) => SortOptions.PenPtsAsc, - (SortValue.PenPts, SortDirection.Descending) => SortOptions.PenPtsDesc, - (SortValue.BonusPts, SortDirection.Ascending) => SortOptions.BonusPtsAsc, - (SortValue.BonusPts, SortDirection.Descending) => SortOptions.BonusPtsDesc, - (SortValue.TotalPts, SortDirection.Ascending) => SortOptions.TotalPtsAsc, - (SortValue.TotalPts, SortDirection.Descending) => SortOptions.TotalPtsDesc, - (SortValue.Intvl, SortDirection.Ascending) => SortOptions.IntvlAsc, - (SortValue.Intvl, SortDirection.Descending) => SortOptions.IntvlDesc, - (SortValue.ComplLaps, SortDirection.Ascending) => SortOptions.ComplLapsAsc, - (SortValue.ComplLaps, SortDirection.Descending) => SortOptions.ComplLapsDesc, - (SortValue.LeadLaps, SortDirection.Ascending) => SortOptions.LeadLapsAsc, - (SortValue.LeadLaps, SortDirection.Descending) => SortOptions.LeadLapsDesc, - (SortValue.Incs, SortDirection.Ascending) => SortOptions.IncsAsc, - (SortValue.Incs, SortDirection.Descending) => SortOptions.IncsDesc, - (SortValue.FastLap, SortDirection.Ascending) => SortOptions.FastLapAsc, - (SortValue.FastLap, SortDirection.Descending) => SortOptions.FastLapDesc, - (SortValue.QualLap, SortDirection.Ascending) => SortOptions.QualLapAsc, - (SortValue.QualLap, SortDirection.Descending) => SortOptions.QualLapDesc, - (SortValue.FinalPos, SortDirection.Ascending) => SortOptions.FinPosAsc, - (SortValue.FinalPos, SortDirection.Descending) => SortOptions.FinPosDesc, - (SortValue.TotalPtsNoBonus, SortDirection.Ascending) => SortOptions.TotalPtsWoBonusAsc, - (SortValue.TotalPtsNoBonus, SortDirection.Descending) => SortOptions.TotalPtsWoBonusDesc, - (SortValue.TotalPtsNoPenalty, SortDirection.Ascending) => SortOptions.TotalPtsWoPenaltyAsc, - (SortValue.TotalPtsNoPenalty, SortDirection.Descending) => SortOptions.TotalPtsWoPenaltyDesc, - _ => SortOptions.TotalPtsDesc, - }; - } + SortOptions.PosAsc => (SortValue.Pos, SortDirection.Ascending), + SortOptions.PosDesc => (SortValue.Pos, SortDirection.Descending), + SortOptions.PosChgAsc => (SortValue.PosChg, SortDirection.Ascending), + SortOptions.PosChgDesc => (SortValue.PosChg, SortDirection.Descending), + SortOptions.StartPosAsc => (SortValue.StartPos, SortDirection.Ascending), + SortOptions.StartPosDesc => (SortValue.StartPos, SortDirection.Descending), + SortOptions.RacePtsAsc => (SortValue.RacePts, SortDirection.Ascending), + SortOptions.RacePtsDesc => (SortValue.RacePts, SortDirection.Descending), + SortOptions.PenPtsAsc => (SortValue.PenPts, SortDirection.Ascending), + SortOptions.PenPtsDesc => (SortValue.PenPts, SortDirection.Descending), + SortOptions.BonusPtsAsc => (SortValue.BonusPts, SortDirection.Ascending), + SortOptions.BonusPtsDesc => (SortValue.BonusPts, SortDirection.Descending), + SortOptions.TotalPtsAsc => (SortValue.TotalPts, SortDirection.Ascending), + SortOptions.TotalPtsDesc => (SortValue.TotalPts, SortDirection.Descending), + SortOptions.IntvlAsc => (SortValue.Intvl, SortDirection.Ascending), + SortOptions.IntvlDesc => (SortValue.Intvl, SortDirection.Descending), + SortOptions.ComplLapsAsc => (SortValue.ComplLaps, SortDirection.Ascending), + SortOptions.ComplLapsDesc => (SortValue.ComplLaps, SortDirection.Descending), + SortOptions.LeadLapsAsc => (SortValue.LeadLaps, SortDirection.Ascending), + SortOptions.LeadLapsDesc => (SortValue.LeadLaps, SortDirection.Descending), + SortOptions.IncsAsc => (SortValue.Incs, SortDirection.Ascending), + SortOptions.IncsDesc => (SortValue.Incs, SortDirection.Descending), + SortOptions.FastLapAsc => (SortValue.FastLap, SortDirection.Ascending), + SortOptions.FastLapDesc => (SortValue.FastLap, SortDirection.Descending), + SortOptions.QualLapAsc => (SortValue.QualLap, SortDirection.Ascending), + SortOptions.QualLapDesc => (SortValue.QualLap, SortDirection.Descending), + SortOptions.FinPosAsc => (SortValue.FinalPos, SortDirection.Ascending), + SortOptions.FinPosDesc => (SortValue.FinalPos, SortDirection.Descending), + SortOptions.TotalPtsWoBonusAsc => (SortValue.TotalPtsNoBonus, SortDirection.Ascending), + SortOptions.TotalPtsWoBonusDesc => (SortValue.TotalPtsNoBonus, SortDirection.Descending), + SortOptions.TotalPtsWoPenaltyAsc => (SortValue.TotalPtsNoPenalty, SortDirection.Ascending), + SortOptions.TotalPtsWoPenaltyDesc => (SortValue.TotalPtsNoPenalty, SortDirection.Descending), + _ => (SortValue.TotalPts, SortDirection.Descending), + }; + } - public void SetModel(SortOptions model) + private SortOptions GetSortOptions(SortValue sortValue, SortDirection direction) + { + return (sortValue, direction) switch { - this.model = model; - (sortValue, sortDirection) = GetSortValue(model); - OnPropertyChanged(); - } + (SortValue.Pos, SortDirection.Ascending) => SortOptions.PosAsc, + (SortValue.Pos, SortDirection.Descending) => SortOptions.PosDesc, + (SortValue.PosChg, SortDirection.Ascending) => SortOptions.PosChgAsc, + (SortValue.PosChg, SortDirection.Descending) => SortOptions.PosChgDesc, + (SortValue.StartPos, SortDirection.Ascending) => SortOptions.StartPosAsc, + (SortValue.StartPos, SortDirection.Descending) => SortOptions.StartPosDesc, + (SortValue.RacePts, SortDirection.Ascending) => SortOptions.RacePtsAsc, + (SortValue.RacePts, SortDirection.Descending) => SortOptions.RacePtsDesc, + (SortValue.PenPts, SortDirection.Ascending) => SortOptions.PenPtsAsc, + (SortValue.PenPts, SortDirection.Descending) => SortOptions.PenPtsDesc, + (SortValue.BonusPts, SortDirection.Ascending) => SortOptions.BonusPtsAsc, + (SortValue.BonusPts, SortDirection.Descending) => SortOptions.BonusPtsDesc, + (SortValue.TotalPts, SortDirection.Ascending) => SortOptions.TotalPtsAsc, + (SortValue.TotalPts, SortDirection.Descending) => SortOptions.TotalPtsDesc, + (SortValue.Intvl, SortDirection.Ascending) => SortOptions.IntvlAsc, + (SortValue.Intvl, SortDirection.Descending) => SortOptions.IntvlDesc, + (SortValue.ComplLaps, SortDirection.Ascending) => SortOptions.ComplLapsAsc, + (SortValue.ComplLaps, SortDirection.Descending) => SortOptions.ComplLapsDesc, + (SortValue.LeadLaps, SortDirection.Ascending) => SortOptions.LeadLapsAsc, + (SortValue.LeadLaps, SortDirection.Descending) => SortOptions.LeadLapsDesc, + (SortValue.Incs, SortDirection.Ascending) => SortOptions.IncsAsc, + (SortValue.Incs, SortDirection.Descending) => SortOptions.IncsDesc, + (SortValue.FastLap, SortDirection.Ascending) => SortOptions.FastLapAsc, + (SortValue.FastLap, SortDirection.Descending) => SortOptions.FastLapDesc, + (SortValue.QualLap, SortDirection.Ascending) => SortOptions.QualLapAsc, + (SortValue.QualLap, SortDirection.Descending) => SortOptions.QualLapDesc, + (SortValue.FinalPos, SortDirection.Ascending) => SortOptions.FinPosAsc, + (SortValue.FinalPos, SortDirection.Descending) => SortOptions.FinPosDesc, + (SortValue.TotalPtsNoBonus, SortDirection.Ascending) => SortOptions.TotalPtsWoBonusAsc, + (SortValue.TotalPtsNoBonus, SortDirection.Descending) => SortOptions.TotalPtsWoBonusDesc, + (SortValue.TotalPtsNoPenalty, SortDirection.Ascending) => SortOptions.TotalPtsWoPenaltyAsc, + (SortValue.TotalPtsNoPenalty, SortDirection.Descending) => SortOptions.TotalPtsWoPenaltyDesc, + _ => SortOptions.TotalPtsDesc, + }; + } - public SortOptions GetModel() => model; + public void SetModel(SortOptions model) + { + this.model = model; + (sortValue, sortDirection) = GetSortValue(model); + OnPropertyChanged(); } + + public SortOptions GetModel() => model; } diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs index 31bdc641..f5b0c800 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs @@ -1,72 +1,71 @@ using iRLeagueApiCore.Common.Enums; using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class SortOptionsViewModel : LeagueViewModelBase> { - public class SortOptionsViewModel : LeagueViewModelBase> + public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + this(loggerFactory, apiService, new List()) { - public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - this(loggerFactory, apiService, new List()) - { - } - - public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, IList model) : - base(loggerFactory, apiService, model) - { - options = new(); - } - - private ObservableCollection options; - public ObservableCollection Options { get => options; set => Set(ref options, value); } + } - public override void SetModel(IList model) - { - base.SetModel(model); - Options = new(model.Select(x => new SortOptionViewModel(x)).ToList()); - } + public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, IList model) : + base(loggerFactory, apiService, model) + { + options = new(); + } - public void AddOption(SortValue value, SortDirection direction) - { - var option = new SortOptionViewModel(new()); - option.SortValue = value; - option.SortDirection = direction; - Options.Add(option); - } + private ObservableCollection options; + public ObservableCollection Options { get => options; set => Set(ref options, value); } - public void RemoveOption(SortOptionViewModel option) - { - Options.Remove(option); - } + public override void SetModel(IList model) + { + base.SetModel(model); + Options = new(model.Select(x => new SortOptionViewModel(x)).ToList()); + } - public override IList GetModel() - { - return Options.Select(x => x.GetModel()).ToList(); - } + public void AddOption(SortValue value, SortDirection direction) + { + var option = new SortOptionViewModel(new()); + option.SortValue = value; + option.SortDirection = direction; + Options.Add(option); } - public enum SortValue + public void RemoveOption(SortOptionViewModel option) { - Pos, - PosChg, - StartPos, - RacePts, - PenPts, - BonusPts, - TotalPts, - TotalPtsNoBonus, - TotalPtsNoPenalty, - Intvl, - ComplLaps, - LeadLaps, - Incs, - FastLap, - QualLap, - FinalPos, + Options.Remove(option); } - public enum SortDirection + public override IList GetModel() { - Ascending, - Descending, + return Options.Select(x => x.GetModel()).ToList(); } } + +public enum SortValue +{ + Pos, + PosChg, + StartPos, + RacePts, + PenPts, + BonusPts, + TotalPts, + TotalPtsNoBonus, + TotalPtsNoPenalty, + Intvl, + ComplLaps, + LeadLaps, + Incs, + FastLap, + QualLap, + FinalPos, +} + +public enum SortDirection +{ + Ascending, + Descending, +} diff --git a/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs index 312a8e54..d69333a6 100644 --- a/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs @@ -2,87 +2,86 @@ using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class StandingsPageViewModel : LeagueViewModelBase { - public class StandingsPageViewModel : LeagueViewModelBase + public StandingsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) { - public StandingsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : - base(loggerFactory, apiService) - { - standings = new ObservableCollection(); - } + standings = new ObservableCollection(); + } - private ObservableCollection standings; - public ObservableCollection Standings { get => standings; set => Set(ref standings, value); } + private ObservableCollection standings; + public ObservableCollection Standings { get => standings; set => Set(ref standings, value); } - private int selectedStandingIndex; - public int SelectedStandingIndex { get => selectedStandingIndex; set { if (Set(ref selectedStandingIndex, value)) OnPropertyChanged(nameof(SelectedStanding)); } } + private int selectedStandingIndex; + public int SelectedStandingIndex { get => selectedStandingIndex; set { if (Set(ref selectedStandingIndex, value)) OnPropertyChanged(nameof(SelectedStanding)); } } - public StandingsModel? SelectedStanding => Standings.ElementAtOrDefault(SelectedStandingIndex); + public StandingsModel? SelectedStanding => Standings.ElementAtOrDefault(SelectedStandingIndex); - public async Task LoadFromEventAsync(long eventId) + public async Task LoadFromEventAsync(long eventId) + { + if (ApiService.CurrentLeague == null) { - if (ApiService.CurrentLeague == null) + return LeagueNullResult(); + } + + try + { + Loading = true; + var request = ApiService.CurrentLeague + .Events() + .WithId(eventId) + .Standings() + .Get(); + var result = await request; + if (result.Success && result.Content is not null) { - return LeagueNullResult(); + var standingsData = result.Content; + Standings = new ObservableCollection(standingsData); } - try - { - Loading = true; - var request = ApiService.CurrentLeague - .Events() - .WithId(eventId) - .Standings() - .Get(); - var result = await request; - if (result.Success && result.Content is not null) - { - var standingsData = result.Content; - Standings = new ObservableCollection(standingsData); - } + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } - return result.ToStatusResult(); - } - finally - { - Loading = false; - } + public async Task LoadAsync(long? seasonId = null) + { + if (ApiService.CurrentLeague == null) + { + return LeagueNullResult(); } - public async Task LoadAsync(long? seasonId = null) + try { - if (ApiService.CurrentLeague == null) + Loading = true; + if ((ApiService.CurrentSeason == null || ApiService.CurrentSeason.Id != seasonId) && seasonId != null) { - return LeagueNullResult(); + await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, seasonId.Value); } - - try + if (ApiService.CurrentSeason == null) { - Loading = true; - if ((ApiService.CurrentSeason == null || ApiService.CurrentSeason.Id != seasonId) && seasonId != null) - { - await ApiService.SetCurrentSeasonAsync(ApiService.CurrentLeague.Name, seasonId.Value); - } - if (ApiService.CurrentSeason == null) - { - return SeasonNullResult(); - } - - var request = ApiService.CurrentSeason.Standings().Get(); - var result = await request; - if (result.Success && result.Content is not null) - { - var standingsData = result.Content; - Standings = new ObservableCollection(standingsData); - } - - return result.ToStatusResult(); + return SeasonNullResult(); } - finally + + var request = ApiService.CurrentSeason.Standings().Get(); + var result = await request; + if (result.Success && result.Content is not null) { - Loading = false; + var standingsData = result.Content; + Standings = new ObservableCollection(standingsData); } + + return result.ToStatusResult(); + } + finally + { + Loading = false; } } } diff --git a/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs b/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs index 8844f8f9..e2ce8c8b 100644 --- a/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs @@ -2,40 +2,39 @@ using iRLeagueApiCore.Common.Models.Reviews; using iRLeagueManager.Web.Data; -namespace iRLeagueManager.Web.ViewModels +namespace iRLeagueManager.Web.ViewModels; + +public class VoteViewModel : LeagueViewModelBase { - public class VoteViewModel : LeagueViewModelBase + public VoteViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, VoteModel model) : + base(loggerFactory, apiService, model) { - public VoteViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, VoteModel model) : - base(loggerFactory, apiService, model) - { - } + } - public long Id => model.Id; - public long? VoteCategoryId { get => model.VoteCategoryId; set => SetP(model.VoteCategoryId, value => model.VoteCategoryId = value, value); } - public string? VoteCategoryText { get => model.VoteCategoryText; } - public string Description { get => model.Description; set => SetP(model.Description, value => model.Description = value, value); } - public MemberInfoModel? MemberAtFault { get => model.MemberAtFault; set => SetP(model.MemberAtFault, value => model.MemberAtFault = value, value); } + public long Id => model.Id; + public long? VoteCategoryId { get => model.VoteCategoryId; set => SetP(model.VoteCategoryId, value => model.VoteCategoryId = value, value); } + public string? VoteCategoryText { get => model.VoteCategoryText; } + public string Description { get => model.Description; set => SetP(model.Description, value => model.Description = value, value); } + public MemberInfoModel? MemberAtFault { get => model.MemberAtFault; set => SetP(model.MemberAtFault, value => model.MemberAtFault = value, value); } - public long? MemberAtFaultId + public long? MemberAtFaultId + { + get => model.MemberAtFault?.MemberId; + set { - get => model.MemberAtFault?.MemberId; - set + if (value is null) { - if (value is null) - { - MemberAtFault = null; - return; - } - if (MemberAtFault?.MemberId != value) + MemberAtFault = null; + return; + } + if (MemberAtFault?.MemberId != value) + { + MemberAtFault = new MemberInfoModel() { - MemberAtFault = new MemberInfoModel() - { - MemberId = value.Value, - }; - } - OnPropertyChanged(); + MemberId = value.Value, + }; } + OnPropertyChanged(); } } -} \ No newline at end of file +} From eff97b9e0978a7b9261015f1722c9d080923e186 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 23 Dec 2022 20:21:47 +0100 Subject: [PATCH 13/33] use sealed classes where applicable --- src/iRLeagueManager.Web/Data/ApplicationDbContext.cs | 2 +- src/iRLeagueManager.Web/Data/AsyncTokenStore.cs | 2 +- .../Data/AuthenticatedHttpClientFactory.cs | 2 +- src/iRLeagueManager.Web/Data/CountedVote.cs | 2 +- src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs | 2 +- src/iRLeagueManager.Web/Data/LeagueApiService.cs | 2 +- .../Data/SamePropertyEqualityComparer.cs | 2 +- src/iRLeagueManager.Web/Data/SharedStateService.cs | 2 +- src/iRLeagueManager.Web/Data/StatusResult.cs | 2 +- src/iRLeagueManager.Web/Data/TrackListService.cs | 2 +- .../Exceptions/BlazorParameterNullException.cs | 2 +- .../Extensions/LeagueApiClientExtensions.cs | 6 +++--- src/iRLeagueManager.Web/Pages/Error.cshtml.cs | 2 +- .../Shared/JwtAuthenticationStateProvicer.cs | 2 +- src/iRLeagueManager.Web/Shared/LoginRedirect.cs | 2 +- src/iRLeagueManager.Web/Shared/RouteView.cs | 2 +- src/iRLeagueManager.Web/Shared/StatusResultValidator.cs | 2 +- src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/EventViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs | 2 +- .../ViewModels/ResultConfigSettingsViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ResultFilterViewModel.cs | 2 +- .../ViewModels/ResultFiltersViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs | 2 +- .../ViewModels/ReviewCommentViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs | 2 +- .../ViewModels/SchedulesPageViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs | 2 +- .../ViewModels/SessionResultViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs | 2 +- .../ViewModels/StandingConfigurationViewModel.cs | 2 +- .../ViewModels/StandingsPageViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs | 2 +- 45 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs b/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs index ffb964a3..c5c1d416 100644 --- a/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs +++ b/src/iRLeagueManager.Web/Data/ApplicationDbContext.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.Data; -public class ApplicationDbContext : IdentityDbContext +internal sealed class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions options) : base(options) diff --git a/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs b/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs index 6b52a566..cb6d6871 100644 --- a/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs +++ b/src/iRLeagueManager.Web/Data/AsyncTokenStore.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.Data; -public class AsyncTokenStore : ITokenStore +internal sealed class AsyncTokenStore : ITokenStore { private readonly ILogger logger; private readonly ProtectedLocalStorage localStore; diff --git a/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs b/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs index 4461a2c8..fb905e4c 100644 --- a/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs +++ b/src/iRLeagueManager.Web/Data/AuthenticatedHttpClientFactory.cs @@ -1,6 +1,6 @@ namespace iRLeagueManager.Web.Server.Data; -public class AuthenticatedHttpClientFactory : IHttpClientFactory +internal sealed class AuthenticatedHttpClientFactory : IHttpClientFactory { diff --git a/src/iRLeagueManager.Web/Data/CountedVote.cs b/src/iRLeagueManager.Web/Data/CountedVote.cs index e53f6bf3..87fc7cf4 100644 --- a/src/iRLeagueManager.Web/Data/CountedVote.cs +++ b/src/iRLeagueManager.Web/Data/CountedVote.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.Data; -public class CountedVote +public sealed class CountedVote { public int Count { get; set; } public VoteViewModel Vote { get; set; } diff --git a/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs b/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs index 547320a8..743eced5 100644 --- a/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs +++ b/src/iRLeagueManager.Web/Data/LeagueApiClientFactory.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.Server.Data; -public class LeagueApiClientFactory +internal sealed class LeagueApiClientFactory { private readonly ILoggerFactory loggerFactory; private readonly ILogger logger; diff --git a/src/iRLeagueManager.Web/Data/LeagueApiService.cs b/src/iRLeagueManager.Web/Data/LeagueApiService.cs index ddf216f3..9306d044 100644 --- a/src/iRLeagueManager.Web/Data/LeagueApiService.cs +++ b/src/iRLeagueManager.Web/Data/LeagueApiService.cs @@ -6,7 +6,7 @@ namespace iRLeagueManager.Web.Data; -public class LeagueApiService +public sealed class LeagueApiService { //private readonly ILogger logger; diff --git a/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs b/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs index c40c1f33..247d997a 100644 --- a/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs +++ b/src/iRLeagueManager.Web/Data/SamePropertyEqualityComparer.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.Data; -public class SamePropertyEqualityComparer : IEqualityComparer>> +internal sealed class SamePropertyEqualityComparer : IEqualityComparer>> { public bool Equals(Expression>? x, Expression>? y) { diff --git a/src/iRLeagueManager.Web/Data/SharedStateService.cs b/src/iRLeagueManager.Web/Data/SharedStateService.cs index 510084aa..33d15428 100644 --- a/src/iRLeagueManager.Web/Data/SharedStateService.cs +++ b/src/iRLeagueManager.Web/Data/SharedStateService.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.Data; -public class SharedStateService +public sealed class SharedStateService { private bool loggedIn; public bool LoggedIn { get => loggedIn; set => Set(ref loggedIn, value); } diff --git a/src/iRLeagueManager.Web/Data/StatusResult.cs b/src/iRLeagueManager.Web/Data/StatusResult.cs index 30fab4bf..13e35187 100644 --- a/src/iRLeagueManager.Web/Data/StatusResult.cs +++ b/src/iRLeagueManager.Web/Data/StatusResult.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.Data; -public class StatusResult +public sealed class StatusResult { public StatusResult(bool success, string status) { diff --git a/src/iRLeagueManager.Web/Data/TrackListService.cs b/src/iRLeagueManager.Web/Data/TrackListService.cs index 18ec0d73..9febdbf6 100644 --- a/src/iRLeagueManager.Web/Data/TrackListService.cs +++ b/src/iRLeagueManager.Web/Data/TrackListService.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.Data; -public class TrackListService +internal sealed class TrackListService { private readonly LeagueApiService apiService; private readonly TimeSpan updateInterval = TimeSpan.FromHours(1); diff --git a/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs b/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs index 185b403a..32f6f694 100644 --- a/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs +++ b/src/iRLeagueManager.Web/Exceptions/BlazorParameterNullException.cs @@ -13,7 +13,7 @@ public static BlazorParameterNullException New : InvalidOperationException +public sealed class BlazorParameterNullException : InvalidOperationException { public BlazorParameterNullException() : base($"Usage of {typeof(TComponent)} requires a Parameter of type {typeof(TParameter)} but value was 'null'") diff --git a/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs b/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs index d0227ac6..10efbf20 100644 --- a/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs +++ b/src/iRLeagueManager.Web/Extensions/LeagueApiClientExtensions.cs @@ -7,7 +7,7 @@ namespace iRLeagueManager.Web.Extensions; -public static class LeagueApiClientExtensions +internal static class LeagueApiClientExtensions { public static T? EnsureSuccess(this ClientActionResult clientActionResult) { @@ -55,7 +55,7 @@ public static string QueryString(this NavigationManager navigationManager, strin } } -public class ActionResultException : InvalidOperationException +public sealed class ActionResultException : InvalidOperationException { public ClientActionResult ActionResult; @@ -72,7 +72,7 @@ public ActionResultException(ClientActionResult actionResult, string message, ActionResult = actionResult; } - protected ActionResultException(ClientActionResult actionResult, SerializationInfo info, StreamingContext context) : base(info, context) + public ActionResultException(ClientActionResult actionResult, SerializationInfo info, StreamingContext context) : base(info, context) { ActionResult = actionResult; } diff --git a/src/iRLeagueManager.Web/Pages/Error.cshtml.cs b/src/iRLeagueManager.Web/Pages/Error.cshtml.cs index 03c21583..56493c06 100644 --- a/src/iRLeagueManager.Web/Pages/Error.cshtml.cs +++ b/src/iRLeagueManager.Web/Pages/Error.cshtml.cs @@ -6,7 +6,7 @@ namespace iRLeagueManager.Web.Pages; [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [IgnoreAntiforgeryToken] -public class ErrorModel : PageModel +internal sealed class ErrorModel : PageModel { public string? RequestId { get; set; } diff --git a/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs b/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs index 1901820c..03c4b0c0 100644 --- a/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs +++ b/src/iRLeagueManager.Web/Shared/JwtAuthenticationStateProvicer.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.Shared; -public class JwtAuthenticationStateProvicer : AuthenticationStateProvider, IDisposable +internal sealed class JwtAuthenticationStateProvicer : AuthenticationStateProvider, IDisposable { private readonly JwtSecurityTokenHandler tokenHandler = new(); private readonly IAsyncTokenProvider tokenStore; diff --git a/src/iRLeagueManager.Web/Shared/LoginRedirect.cs b/src/iRLeagueManager.Web/Shared/LoginRedirect.cs index 0d028a90..5c3eb55b 100644 --- a/src/iRLeagueManager.Web/Shared/LoginRedirect.cs +++ b/src/iRLeagueManager.Web/Shared/LoginRedirect.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.Shared; -public class LoginRedirect : ComponentBase +public sealed class LoginRedirect : ComponentBase { [CascadingParameter] public Task AuthStateTask { get; set; } = default!; diff --git a/src/iRLeagueManager.Web/Shared/RouteView.cs b/src/iRLeagueManager.Web/Shared/RouteView.cs index a5763034..c2aa3ca9 100644 --- a/src/iRLeagueManager.Web/Shared/RouteView.cs +++ b/src/iRLeagueManager.Web/Shared/RouteView.cs @@ -6,7 +6,7 @@ namespace iRLeagueManager.Web.Shared; -public class AppRouteView : RouteView +internal sealed class AppRouteView : RouteView { [Inject] public NavigationManager NavigationManager { get; set; } = default!; diff --git a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs index a3d152bd..cd9875ff 100644 --- a/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs +++ b/src/iRLeagueManager.Web/Shared/StatusResultValidator.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.Shared; -public class StatusResultValidator : ComponentBase +public sealed class StatusResultValidator : ComponentBase { private ValidationMessageStore messageStore = default!; [CascadingParameter] diff --git a/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs index e4c79b6e..de672f3e 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventListViewModel.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class EventListViewModel : LeagueViewModelBase +public sealed class EventListViewModel : LeagueViewModelBase { public EventListViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs index fe99f21f..cb240ef2 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventResultViewModel.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class EventResultViewModel : LeagueViewModelBase +public sealed class EventResultViewModel : LeagueViewModelBase { private EventResultModel model; diff --git a/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs index 167e17a0..f1f6fdfa 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class EventViewModel : LeagueViewModelBase +public sealed class EventViewModel : LeagueViewModelBase { public EventViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new EventModel()) diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs index 52640c15..5b370032 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueUserViewModel.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class LeagueUserViewModel : LeagueViewModelBase +public sealed class LeagueUserViewModel : LeagueViewModelBase { public LeagueUserViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, LeagueUserModel model) : base(loggerFactory, apiService, model) diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs index 2ad703c8..633cd510 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueUsersViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class LeagueUsersViewModel : LeagueViewModelBase +public sealed class LeagueUsersViewModel : LeagueViewModelBase { public LeagueUsersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs index 2cc17da7..e5ce6c8d 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeagueViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public partial class LeagueViewModel : LeagueViewModelBase +public sealed class LeagueViewModel : LeagueViewModelBase { public LeagueViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new()) diff --git a/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs b/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs index bc880a10..f44b0375 100644 --- a/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/LeaguesViewModel.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class LeaguesViewModel : LeagueViewModelBase +public sealed class LeaguesViewModel : LeagueViewModelBase { private string _status; public string Status { get => _status; set => Set(ref _status, value); } diff --git a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs index 74f6b3be..7fdddda7 100644 --- a/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/PointRuleViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class PointRuleViewModel : LeagueViewModelBase +public sealed class PointRuleViewModel : LeagueViewModelBase { public PointRuleViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new()) diff --git a/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs index ef11ca6c..0b2250e0 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultConfigSettingsViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ResultConfigSettingsViewModel : LeagueViewModelBase +public sealed class ResultConfigSettingsViewModel : LeagueViewModelBase { public ResultConfigSettingsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs index b21bff7c..7706b7a3 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultConfigViewModel.cs @@ -5,7 +5,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ResultConfigViewModel : LeagueViewModelBase +public sealed class ResultConfigViewModel : LeagueViewModelBase { public ResultConfigViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new()) diff --git a/src/iRLeagueManager.Web/ViewModels/ResultFilterViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultFilterViewModel.cs index ec330d7c..9d0c9795 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultFilterViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultFilterViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ResultFilterViewModel : LeagueViewModelBase +public sealed class ResultFilterViewModel : LeagueViewModelBase { public ResultFilterViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new()) diff --git a/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs index 6d659934..706351eb 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultFiltersViewModel.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ResultFiltersViewModel : LeagueViewModelBase +public sealed class ResultFiltersViewModel : LeagueViewModelBase { public ResultFiltersViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs index d84e5078..26ae58c3 100644 --- a/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ResultsPageViewModel.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ResultsPageViewModel : LeagueViewModelBase +public sealed class ResultsPageViewModel : LeagueViewModelBase { public ResultsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, EventListViewModel eventList) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs index b06edd36..be3a5fe3 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewCommentViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ReviewCommentViewModel : LeagueViewModelBase +public sealed class ReviewCommentViewModel : LeagueViewModelBase { public ReviewCommentViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService, new()) diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs index 42f1c49b..106b5098 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs @@ -6,7 +6,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ReviewViewModel : LeagueViewModelBase +public sealed class ReviewViewModel : LeagueViewModelBase { public ReviewViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService, new()) diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs index 208c6b57..061f88dc 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ReviewsPageViewModel : LeagueViewModelBase +public sealed class ReviewsPageViewModel : LeagueViewModelBase { public ReviewsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs index 9c6c8bc6..75ddae77 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScheduleViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ScheduleViewModel : LeagueViewModelBase +public sealed class ScheduleViewModel : LeagueViewModelBase { private ScheduleModel model; diff --git a/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs index f5ea486f..cf71d770 100644 --- a/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SchedulesPageViewModel.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SchedulesPageViewModel : LeagueViewModelBase +public sealed class SchedulesPageViewModel : LeagueViewModelBase { public SchedulesPageViewModel(ILoggerFactory loggerFactory, ILogger logger, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs index 04c67930..cdeb8973 100644 --- a/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ScoringViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class ScoringViewModel : LeagueViewModelBase +public sealed class ScoringViewModel : LeagueViewModelBase { public ScoringViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, ScoringModel model) : base(loggerFactory, apiService, model) diff --git a/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs index 299ea567..bd8471c1 100644 --- a/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SeasonViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SeasonViewModel : LeagueViewModelBase +public sealed class SeasonViewModel : LeagueViewModelBase { public SeasonViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new SeasonModel()) diff --git a/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs index d570a8a5..10aa2af6 100644 --- a/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SeasonsViewModel.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SeasonsViewModel : LeagueViewModelBase +public sealed class SeasonsViewModel : LeagueViewModelBase { private string status = string.Empty; public string Status { get => status; set => Set(ref status, value); } diff --git a/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs index 38144587..9f3eaddf 100644 --- a/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SessionResultViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SessionResultViewModel : LeagueViewModelBase +public sealed class SessionResultViewModel : LeagueViewModelBase { private ResultModel model; diff --git a/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs index 664b81c5..1c184fc3 100644 --- a/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SessionViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SessionViewModel : LeagueViewModelBase +public sealed class SessionViewModel : LeagueViewModelBase { private SessionModel model; diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs index ee86811d..49f697c4 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionViewModel.cs @@ -2,7 +2,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SortOptionViewModel : MvvmBlazor.ViewModel.ViewModelBase +public sealed class SortOptionViewModel : MvvmBlazor.ViewModel.ViewModelBase { private SortOptions model; diff --git a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs index f5b0c800..8a56c6e9 100644 --- a/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/SortOptionsViewModel.cs @@ -3,7 +3,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class SortOptionsViewModel : LeagueViewModelBase> +public sealed class SortOptionsViewModel : LeagueViewModelBase> { public SortOptionsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : this(loggerFactory, apiService, new List()) diff --git a/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs b/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs index b18d40da..76bc36d8 100644 --- a/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/StandingConfigurationViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class StandingConfigurationViewModel : LeagueViewModelBase +public sealed class StandingConfigurationViewModel : LeagueViewModelBase { public StandingConfigurationViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, StandingConfigModel model) : base(loggerFactory, apiService, model) diff --git a/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs index d69333a6..1d9836c0 100644 --- a/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/StandingsPageViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class StandingsPageViewModel : LeagueViewModelBase +public sealed class StandingsPageViewModel : LeagueViewModelBase { public StandingsPageViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : base(loggerFactory, apiService) diff --git a/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs b/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs index e2ce8c8b..307072f5 100644 --- a/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs @@ -4,7 +4,7 @@ namespace iRLeagueManager.Web.ViewModels; -public class VoteViewModel : LeagueViewModelBase +public sealed class VoteViewModel : LeagueViewModelBase { public VoteViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, VoteModel model) : base(loggerFactory, apiService, model) From 54c1b0f8d6141eb618164d9a9f6d7502abddf8c0 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Wed, 28 Dec 2022 21:41:14 +0100 Subject: [PATCH 14/33] Add description field for reviews --- .../Components/Reviews/EditReviewModal.razor | 3 +++ .../Components/Reviews/ReviewCard.razor | 12 +++++++++++- .../Components/Reviews/ReviewComment.razor | 2 +- src/iRLeagueManager.Web/wwwroot/css/site.css | 4 ++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/Reviews/EditReviewModal.razor b/src/iRLeagueManager.Web/Components/Reviews/EditReviewModal.razor index bca85d64..f154acba 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/EditReviewModal.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/EditReviewModal.razor @@ -33,6 +33,9 @@ + + + Review.IncidentKind) />
    diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor index 1ba17026..e1a2091a 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor @@ -91,6 +91,16 @@

    + @if (string.IsNullOrWhiteSpace(Review.FullDescription) == false) + { +
    +
    Description
    +
    + @Review.FullDescription +
    +
    +
    + }
    Result
    @@ -102,7 +112,7 @@ }
    -
    +
    @Bind(Review, x => x.ResultText)
    @if (IsSteward && ReadOnly == false) diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor index 04656cc7..b5b3b8c1 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewComment.razor @@ -6,7 +6,7 @@
    @Bind(Comment, x => x.AuthorName)
    -
    +
    @Bind(Comment, x=> x.Text)
    diff --git a/src/iRLeagueManager.Web/wwwroot/css/site.css b/src/iRLeagueManager.Web/wwwroot/css/site.css index ffe99502..d5e2cc24 100644 --- a/src/iRLeagueManager.Web/wwwroot/css/site.css +++ b/src/iRLeagueManager.Web/wwwroot/css/site.css @@ -71,6 +71,10 @@ a, .btn-link { padding-top: 1.1rem; } +.preserve-format { + white-space: pre-wrap; +} + .valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; } From 489efdb7219171608fe1a2651325e195402a830b Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Wed, 28 Dec 2022 21:58:43 +0100 Subject: [PATCH 15/33] Add check when user has commented on review --- src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor index e1a2091a..b0b06c0c 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor @@ -14,10 +14,14 @@ @Review.SessionName: @Bind(Review, x => x.IncidentNr) @Bind(Review, x => x.OnLap) - @Bind(Review, x => x.Corner) + @Bind(Review, x => x.Corner) @Bind(Review, x => x.IncidentKind) @Bind(Review, x => x.Comments).Count @Bind(Review, x => x.Comments).Where(x => x.Votes.Any()).Count() + @if (UserHasCommented(Review)) + { + + }
    @if (OnEditClick.HasDelegate && ReadOnly == false) From 8db61f29671af5b240c39aeb476dbff851bbbccf Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Wed, 28 Dec 2022 22:04:10 +0100 Subject: [PATCH 16/33] edit icon --- src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor index b0b06c0c..ed9cf27d 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor @@ -20,7 +20,7 @@ @Bind(Review, x => x.Comments).Where(x => x.Votes.Any()).Count() @if (UserHasCommented(Review)) { - + }
    From a1eef3a5654a246c56be1474b53073f4387e6c9b Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 29 Dec 2022 23:03:39 +0100 Subject: [PATCH 17/33] Add team management page under settings --- .../Components/Settings/EditTeamModal.razor | 143 ++++++++++++++++++ .../Components/Settings/TeamPreview.razor | 28 ++++ .../Components/Settings/TeamSettings.razor | 100 ++++++++++++ .../Pages/Settings/Settings.razor | 28 ++-- src/iRLeagueManager.Web/Services.cs | 2 + .../ViewModels/TeamViewModel.cs | 53 +++++++ .../ViewModels/TeamsViewModel.cs | 127 ++++++++++++++++ src/iRLeagueManager.Web/appsettings.json | 4 +- .../iRLeagueManager.Web.csproj | 4 +- 9 files changed, 476 insertions(+), 13 deletions(-) create mode 100644 src/iRLeagueManager.Web/Components/Settings/EditTeamModal.razor create mode 100644 src/iRLeagueManager.Web/Components/Settings/TeamPreview.razor create mode 100644 src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor create mode 100644 src/iRLeagueManager.Web/ViewModels/TeamViewModel.cs create mode 100644 src/iRLeagueManager.Web/ViewModels/TeamsViewModel.cs diff --git a/src/iRLeagueManager.Web/Components/Settings/EditTeamModal.razor b/src/iRLeagueManager.Web/Components/Settings/EditTeamModal.razor new file mode 100644 index 00000000..96d36c49 --- /dev/null +++ b/src/iRLeagueManager.Web/Components/Settings/EditTeamModal.razor @@ -0,0 +1,143 @@ +@inherits MvvmComponentBase +@using iRLeagueApiCore.Common.Enums +@using iRLeagueApiCore.Common.Models +@using iRLeagueApiCore.Common.Models.Members +@using iRLeagueManager.Web.ViewModels +@inject TeamViewModel vm + + + +
    + + + + + + +
    +
    +
    +
    + +
    +
    +
    + + + + @member.FirstName @member.LastName + + + @member.FirstName @member.LastName + + + Driver @name Not found! + + +
    +
    + + +
    + +@code { + [CascadingParameter] + public BlazoredModalInstance ModalInstance { get; set; } = default!; + [CascadingParameter] + public IModalService ModalService { get; set; } = default!; + + private TeamModel model = default!; + [Parameter] + public TeamModel Model + { + get => model; + set + { + if (EqualityComparer.Default.Equals(model, value) == false) + { + model = value; + vm.SetModel(model); + } + } + } + [Parameter] + public IEnumerable LeagueMembers { get; set; } = default!; + + [Parameter] + public Func>? OnSubmit { get; set; } + + private CancellationTokenSource cts = new(); + + private StatusResultValidator? ResultValidator { get; set; } + + protected override void OnParametersSet() + { + _ = ModalInstance ?? throw BlazorParameterNullException.New(this, ModalInstance); + _ = ModalService ?? throw BlazorParameterNullException.New(this, ModalService); + _ = Model ?? throw BlazorParameterNullException.New(this, Model); + _ = LeagueMembers ?? throw BlazorParameterNullException.New(this, LeagueMembers); + } + + private async Task> SearchMembers(string searchString) + { + if (string.IsNullOrEmpty(searchString)) + { + return await Task.FromResult(LeagueMembers); + } + + var terms = searchString.ToLower().Split(',', ' ', ';') + .Where(x => string.IsNullOrWhiteSpace(x) == false) + .ToArray(); + return await Task.FromResult(LeagueMembers + .Where(x => MatchMemberSearchTerms(x, terms))); + } + + private bool MatchMemberSearchTerms(MemberInfoModel member, params string[] terms) + { + var searchName = member.FirstName + member.LastName; + return terms.Any(x => searchName.Contains(x, StringComparison.OrdinalIgnoreCase)); + } + + private async Task Submit() + { + var success = true; + if (OnSubmit is not null) + { + var status = await OnSubmit(vm, cts.Token); + success &= status.IsSuccess; + ResultValidator?.ValidateResult(status); + } + if (success) + { + var result = ModalResult.Ok(vm.GetModel()); + await ModalInstance.CloseAsync(result); + } + } + + private async Task Cancel() + { + if (ModalInstance != null) + { + await ModalInstance.CancelAsync(); + } + } + + protected override void Dispose(bool disposing) + { + if (disposing == false) + { + cts.Cancel(); + cts.Dispose(); + } + base.Dispose(disposing); + } +} diff --git a/src/iRLeagueManager.Web/Components/Settings/TeamPreview.razor b/src/iRLeagueManager.Web/Components/Settings/TeamPreview.razor new file mode 100644 index 00000000..1a31256f --- /dev/null +++ b/src/iRLeagueManager.Web/Components/Settings/TeamPreview.razor @@ -0,0 +1,28 @@ +@using iRLeagueManager.Web.ViewModels + +
    +
    +
    @Team.Name
    +
    +
    Team Members
    +
    + @foreach(var member in Team.Members) + { +
    @member.FirstName @member.LastName
    + } +
    +
    + + +@code { + [Parameter(CaptureUnmatchedValues=true)] + public IDictionary? AdditionalAttributes { get; set; } + + [Parameter, EditorRequired] + public TeamViewModel Team { get; set; } = default!; + + protected override void OnParametersSet() + { + _ = Team ?? throw BlazorParameterNullException.New(this, Team); + } +} \ No newline at end of file diff --git a/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor b/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor new file mode 100644 index 00000000..2a208397 --- /dev/null +++ b/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor @@ -0,0 +1,100 @@ +@using iRLeagueApiCore.Common.Enums +@using iRLeagueApiCore.Common.Models +@using iRLeagueApiCore.Common.Models.Members +@using iRLeagueManager.Web.ViewModels +@inherits MvvmComponentBase +@inject TeamsViewModel vm +@inject LeagueApiService apiService +@inject ILogger logger + +
    +
    +
    + Teams +
    +
    + @foreach((var team, var index) in @Bind(vm, x => x.Teams).Select((x, i) => (x, i))) + { +
    OnTeamClick(team))> + + +
    + } +
    +
    + +
    + +@code { + [CascadingParameter] + public IModalService ModalService { get; set; } = default!; + + [Parameter(CaptureUnmatchedValues = true)] + public IReadOnlyDictionary? AdditionalAttributes { get; set; } + + private async Task OnTeamClick(TeamViewModel config) + { + var parameters = new ModalParameters() + .Add(nameof(EditTeamModal.Model), config.CopyModel()) + .Add(nameof(EditTeamModal.LeagueMembers), GetMembersWithoutTeam(vm.Members)) + .Add(nameof(EditTeamModal.OnSubmit), new Func>( + async (team, cancellationToken) => await team.SaveChangesAsync(cancellationToken))); + var options = new ModalOptions() + { + DisableBackgroundCancel = true, + }; + var result = await ModalService.Show("Edit Team", parameters, options).Result; + if (result.Confirmed && result.Data is TeamModel model) + { + config.SetModel(model); + } + } + + private async Task OnAddTeamClick() + { + var parameters = new ModalParameters() + .Add(nameof(EditTeamModal.Model), new TeamModel()) + .Add(nameof(EditTeamModal.LeagueMembers), GetMembersWithoutTeam(vm.Members)) + .Add(nameof(EditTeamModal.OnSubmit), new Func>( + async (team, cancellationToken) => await vm.AddTeam(team.GetModel(), cancellationToken))); + var options = new ModalOptions() + { + DisableBackgroundCancel = true, + }; + var result = await ModalService.Show("Add new Team", parameters, options).Result; + } + + private IEnumerable GetMembersWithoutTeam(IEnumerable members) + { + return members + .Where(member => vm.Teams.Any(team => team.Members.Any(teamMember => member.MemberId == teamMember.MemberId)) == false) + .ToList(); + } + + private async Task OnDeleteTeamClick(TeamViewModel team) + { + var parameters = new ModalParameters() + .Add(nameof(ConfirmModal.Text), $"Really delete Team \"{team.Name}\"?") + .Add(nameof(ConfirmModal.ButtonTypes), ButtonTypes.YesNo); + var result = await ModalService.Show("Delete Result Config", parameters).Result; + if (result.Confirmed) + { + await vm.DeleteTeam(team.GetModel()); + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender == false) + { + return; + } + if (apiService.CurrentLeague != null) + { + await vm.LoadFromLeagueAsync(); + } + await InvokeAsync(StateHasChanged); + } +} diff --git a/src/iRLeagueManager.Web/Pages/Settings/Settings.razor b/src/iRLeagueManager.Web/Pages/Settings/Settings.razor index 4a92f5f5..0e6624fb 100644 --- a/src/iRLeagueManager.Web/Pages/Settings/Settings.razor +++ b/src/iRLeagueManager.Web/Pages/Settings/Settings.razor @@ -9,18 +9,25 @@

    Settings

    - +
    @@ -29,13 +36,16 @@ @switch (selectedTabIndex) { case 0: - + break; case 1: - + break; case 2: - + + break; + case 3: + break; default:

    Index out of bounds!

    diff --git a/src/iRLeagueManager.Web/Services.cs b/src/iRLeagueManager.Web/Services.cs index 6cc3a9b4..3660d2d5 100644 --- a/src/iRLeagueManager.Web/Services.cs +++ b/src/iRLeagueManager.Web/Services.cs @@ -27,6 +27,7 @@ public static IServiceCollection AddViewModels(this IServiceCollection services) services.TryAddTransient(); services.TryAddTransient(); services.TryAddTransient(); + services.TryAddTransient(); services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); @@ -34,6 +35,7 @@ public static IServiceCollection AddViewModels(this IServiceCollection services) services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); + services.TryAddScoped(); return services; } } diff --git a/src/iRLeagueManager.Web/ViewModels/TeamViewModel.cs b/src/iRLeagueManager.Web/ViewModels/TeamViewModel.cs new file mode 100644 index 00000000..39f917a3 --- /dev/null +++ b/src/iRLeagueManager.Web/ViewModels/TeamViewModel.cs @@ -0,0 +1,53 @@ +using iRLeagueApiCore.Common.Models; +using iRLeagueApiCore.Common.Models.Members; +using iRLeagueManager.Web.Data; +using iRLeagueManager.Web.Extensions; + +namespace iRLeagueManager.Web.ViewModels; + +public sealed class TeamViewModel : LeagueViewModelBase +{ + public TeamViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + this(loggerFactory, apiService, new()) + { + } + + public TeamViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, TeamModel model) : + base(loggerFactory, apiService, model) + { + } + + public long TeamId => model.TeamId; + public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } + public string Profile { get => model.Profile; set => SetP(model.Profile, value => model.Profile = value, value); } + public string TeamColor { get => model.TeamColor; set => SetP(model.TeamColor, value => model.TeamColor = value, value); } + public string TeamHomepage { get => model.TeamHomepage; set => SetP(model.TeamHomepage, value => model.TeamHomepage = value, value); } + public IList Members { get => (IList)model.Members; set => SetP(model.Members, value => model.Members = value, value); } + + public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = true; + var request = ApiService.CurrentLeague + .Teams() + .WithId(TeamId) + .Put(model, cancellationToken); + var result = await request; + if (result.Success && result.Content is not null) + { + SetModel(result.Content); + } + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } +} diff --git a/src/iRLeagueManager.Web/ViewModels/TeamsViewModel.cs b/src/iRLeagueManager.Web/ViewModels/TeamsViewModel.cs new file mode 100644 index 00000000..5541b933 --- /dev/null +++ b/src/iRLeagueManager.Web/ViewModels/TeamsViewModel.cs @@ -0,0 +1,127 @@ +using iRLeagueApiCore.Common.Models; +using iRLeagueApiCore.Common.Models.Members; +using iRLeagueManager.Web.Data; +using iRLeagueManager.Web.Extensions; + +namespace iRLeagueManager.Web.ViewModels; + +public sealed class TeamsViewModel : LeagueViewModelBase +{ + public TeamsViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService) : + base(loggerFactory, apiService) + { + teams = new(); + members = new(); + } + + private ObservableCollection teams; + public ObservableCollection Teams { get => teams; set => Set(ref teams, value); } + + private ObservableCollection members; + public ObservableCollection Members { get => members; set => Set(ref members, value); } + + public async Task LoadFromLeagueAsync(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = true; + var request = ApiService.CurrentLeague + .Teams() + .Get(cancellationToken); + var result = await request; + if (result.Success && result.Content is not null) + { + Teams = new(result.Content.Select(x => new TeamViewModel(LoggerFactory, ApiService, x))); + } + return await LoadMembersAsync(cancellationToken); + } + finally + { + Loading = false; + } + } + + public async Task AddTeam(TeamModel team, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = true; + var request = ApiService.CurrentLeague + .Teams() + .Post(team, cancellationToken); + var result = await request; + if (result.Success) + { + return await LoadFromLeagueAsync(cancellationToken); + } + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } + + public async Task DeleteTeam(TeamModel model, CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = true; + var request = ApiService.CurrentLeague + .Teams() + .WithId(model.TeamId) + .Delete(cancellationToken); + var result = await request; + if (result.Success) + { + return await LoadFromLeagueAsync(cancellationToken); + } + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } + + public async Task LoadMembersAsync(CancellationToken cancellationToken = default) + { + if (ApiService.CurrentLeague is null) + { + return LeagueNullResult(); + } + + try + { + Loading = false; + var request = ApiService.CurrentLeague + .Members() + .Get(cancellationToken); + var result = await request; + if (result.Success && result.Content is not null) + { + Members = new(result.Content); + } + return result.ToStatusResult(); + } + finally + { + Loading = false; + } + } +} diff --git a/src/iRLeagueManager.Web/appsettings.json b/src/iRLeagueManager.Web/appsettings.json index bed1c144..79e31d96 100644 --- a/src/iRLeagueManager.Web/appsettings.json +++ b/src/iRLeagueManager.Web/appsettings.json @@ -9,8 +9,8 @@ } }, "AllowedHosts": "*", - //"APIServer": "http://localhost:5000", - "APIServer": "https://irleaguemanager.net/irleagueapi/", + "APIServer": "http://localhost:5000", + //"APIServer": "https://irleaguemanager.net/irleagueapi/", "DefaultUser": "testuser", "DefaultPassword": "TestPass123!" } diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index 368c63be..182fc407 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -20,8 +20,8 @@ - - + + From ecdeb0bd1f3eb2dc57302ce9ceb913d8d222e9cd Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Thu, 29 Dec 2022 23:11:55 +0100 Subject: [PATCH 18/33] Order teams by name --- .../Components/Settings/TeamSettings.razor | 2 +- src/iRLeagueManager.Web/appsettings.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor b/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor index 2a208397..54f91e88 100644 --- a/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor +++ b/src/iRLeagueManager.Web/Components/Settings/TeamSettings.razor @@ -13,7 +13,7 @@ Teams
    - @foreach((var team, var index) in @Bind(vm, x => x.Teams).Select((x, i) => (x, i))) + @foreach(var team in @Bind(vm, x => x.Teams).OrderBy(x => x.Name)) {
    OnTeamClick(team))> diff --git a/src/iRLeagueManager.Web/appsettings.json b/src/iRLeagueManager.Web/appsettings.json index 79e31d96..bed1c144 100644 --- a/src/iRLeagueManager.Web/appsettings.json +++ b/src/iRLeagueManager.Web/appsettings.json @@ -9,8 +9,8 @@ } }, "AllowedHosts": "*", - "APIServer": "http://localhost:5000", - //"APIServer": "https://irleaguemanager.net/irleagueapi/", + //"APIServer": "http://localhost:5000", + "APIServer": "https://irleaguemanager.net/irleagueapi/", "DefaultUser": "testuser", "DefaultPassword": "TestPass123!" } From e6a77992e4f7dd7ab48703e42b3f3381690d7b33 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Sat, 31 Dec 2022 13:03:42 +0100 Subject: [PATCH 19/33] update client --- src/iRLeagueManager.Web/Components/InputMemberSelect.razor | 2 +- .../Components/Reviews/EditCommentModal.razor | 2 +- .../Components/Reviews/EditReviewModal.razor | 2 +- .../Components/Reviews/EditReviewResultModal.razor | 2 +- src/iRLeagueManager.Web/Components/Reviews/ReviewCard.razor | 2 +- .../Components/Reviews/ReviewComment.razor | 2 +- .../Components/Settings/EditTeamModal.razor | 2 +- .../Components/Settings/TeamSettings.razor | 2 +- src/iRLeagueManager.Web/Pages/Reviews.razor | 2 +- src/iRLeagueManager.Web/ViewModels/ReviewViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs | 2 +- src/iRLeagueManager.Web/ViewModels/TeamViewModel.cs | 1 - src/iRLeagueManager.Web/ViewModels/TeamsViewModel.cs | 1 - src/iRLeagueManager.Web/ViewModels/VoteViewModel.cs | 2 +- src/iRLeagueManager.Web/appsettings.json | 4 ++-- src/iRLeagueManager.Web/iRLeagueManager.Web.csproj | 4 ++-- 16 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/iRLeagueManager.Web/Components/InputMemberSelect.razor b/src/iRLeagueManager.Web/Components/InputMemberSelect.razor index 72c15a23..88fcabd8 100644 --- a/src/iRLeagueManager.Web/Components/InputMemberSelect.razor +++ b/src/iRLeagueManager.Web/Components/InputMemberSelect.razor @@ -1,6 +1,6 @@ @using System.Collections.Specialized @using System.Diagnostics.CodeAnalysis -@using iRLeagueApiCore.Common.Models.Members +@using iRLeagueApiCore.Common.Models @*@inherits InputBase>*@ diff --git a/src/iRLeagueManager.Web/Components/Reviews/ProtestCard.razor b/src/iRLeagueManager.Web/Components/Reviews/ProtestCard.razor index 9d54afee..081567e5 100644 --- a/src/iRLeagueManager.Web/Components/Reviews/ProtestCard.razor +++ b/src/iRLeagueManager.Web/Components/Reviews/ProtestCard.razor @@ -11,7 +11,10 @@ @Protest.SessionName:   @Bind(Protest, x => x.OnLap) @Bind(Protest, x => x.Corner) -   By: @Protest.Author.FirstName @Protest.Author.LastName + @if (string.IsNullOrWhiteSpace(Protest.Author.FirstName) == false || string.IsNullOrWhiteSpace(Protest.Author.LastName) == false) + { +   By: @Protest.Author.FirstName @Protest.Author.LastName + }
    @if (OnDeleteClick.HasDelegate) diff --git a/src/iRLeagueManager.Web/Data/ClientLocalTimeProvider.cs b/src/iRLeagueManager.Web/Data/ClientLocalTimeProvider.cs new file mode 100644 index 00000000..499f416b --- /dev/null +++ b/src/iRLeagueManager.Web/Data/ClientLocalTimeProvider.cs @@ -0,0 +1,30 @@ +namespace iRLeagueManager.Web.Data; + +/// +/// Provide functions to convert time into the clients local time zone +/// +public class ClientLocalTimeProvider +{ + private readonly SharedStateService sharedState; + + public ClientLocalTimeProvider(SharedStateService sharedState) + { + this.sharedState = sharedState; + } + + public TimeSpan LocalTimeOffset => sharedState.LocalTimeOffset; + + public DateTime Now => new DateTimeOffset(DateTime.UtcNow).ToOffset(LocalTimeOffset).Date; + + public DateTime ConvertToLocal(DateTime utcTime) + { + var localTimeOffset = new DateTimeOffset(utcTime, TimeSpan.Zero).ToOffset(LocalTimeOffset); + return localTimeOffset.DateTime; + } + + public DateTime ConvertToUtc(DateTime localTime) + { + var localTimeOffset = new DateTimeOffset(localTime, LocalTimeOffset); + return localTimeOffset.UtcDateTime; + } +} diff --git a/src/iRLeagueManager.Web/Data/LeagueApiService.cs b/src/iRLeagueManager.Web/Data/LeagueApiService.cs index 9306d044..abad27a0 100644 --- a/src/iRLeagueManager.Web/Data/LeagueApiService.cs +++ b/src/iRLeagueManager.Web/Data/LeagueApiService.cs @@ -10,17 +10,19 @@ public sealed class LeagueApiService { //private readonly ILogger logger; - public LeagueApiService(ILeagueApiClient apiClient, SharedStateService sharedState, JsonSerializerOptions jsonOptions) + public LeagueApiService(ILeagueApiClient apiClient, SharedStateService sharedState, ClientLocalTimeProvider localTimeProvider, JsonSerializerOptions jsonOptions) { //this.logger = logger; Client = apiClient; Shared = sharedState; JsonOptions = jsonOptions; + ClientTimeProvider= localTimeProvider; } public ILeagueApiClient Client { get; } public SharedStateService Shared { get; } public JsonSerializerOptions JsonOptions { get; } + public ClientLocalTimeProvider ClientTimeProvider { get; } public ILeagueByNameEndpoint? CurrentLeague { get; private set; } public ISeasonByIdEndpoint? CurrentSeason { get; private set; } diff --git a/src/iRLeagueManager.Web/Data/SharedStateService.cs b/src/iRLeagueManager.Web/Data/SharedStateService.cs index 33d15428..1da8ba01 100644 --- a/src/iRLeagueManager.Web/Data/SharedStateService.cs +++ b/src/iRLeagueManager.Web/Data/SharedStateService.cs @@ -27,6 +27,8 @@ public sealed class SharedStateService public ObservableCollection SeasonList { get => seasonList; set => Set(ref seasonList, value); } public event EventHandler? StateChanged; + + public TimeSpan LocalTimeOffset { get; set; } public SharedStateService() { diff --git a/src/iRLeagueManager.Web/Pages/Index.razor b/src/iRLeagueManager.Web/Pages/Index.razor index 67d0a243..15974d7d 100644 --- a/src/iRLeagueManager.Web/Pages/Index.razor +++ b/src/iRLeagueManager.Web/Pages/Index.razor @@ -3,3 +3,8 @@ Index Start! + +@code { + [CascadingParameter] + SharedStateService SharedState { get; set; } = default!; +} diff --git a/src/iRLeagueManager.Web/Pages/Reviews.razor b/src/iRLeagueManager.Web/Pages/Reviews.razor index 2a40d4c8..8fce4a06 100644 --- a/src/iRLeagueManager.Web/Pages/Reviews.razor +++ b/src/iRLeagueManager.Web/Pages/Reviews.razor @@ -10,6 +10,7 @@ @using iRLeagueManager.Web.ViewModels @inherits LeagueComponentBase @inject ReviewsPageViewModel ReviewsVm +@inject ClientLocalTimeProvider ClientTime
    x.Loading))> @@ -18,18 +19,17 @@ - - - - - + @if (ReviewsVm.ProtestsEnabled) + { + + } @switch (SelectedTabIndex) @@ -65,7 +65,7 @@ break; case 1: - @if (ReviewsVm.Protests.Count == 0) + @if (ReviewsVm.Protests.Count == 0 && ReviewsVm.ProtestsPublic) {

    No Protests

    } @@ -83,7 +83,36 @@ } - + @if (Event is not null && Event.HasResult) + { + var protestsOpenAt = Event.End + ReviewsVm.CooldownPeriod; + var protestsCloseAt = Event.End + ReviewsVm.ProtestClosedAfter; + @if (ReviewsVm.CanFileProtest(Event)) + { + + @if (ReviewsVm.ProtestClosedAfter > TimeSpan.Zero) + { +
    + Protests can be filed until @protestsCloseAt.ToString(); +
    + } + } + else + { + @if (ClientTime.Now < protestsOpenAt) + { +
    + Protests can be filed after @protestsOpenAt.ToString(); +
    + } + else if (ClientTime.Now > protestsCloseAt) + { +
    + Protest period ended on @protestsOpenAt.ToString(); +
    + } + } + } break; default: break; diff --git a/src/iRLeagueManager.Web/Pages/_Layout.cshtml b/src/iRLeagueManager.Web/Pages/_Layout.cshtml index d0431dca..92bb61c6 100644 --- a/src/iRLeagueManager.Web/Pages/_Layout.cshtml +++ b/src/iRLeagueManager.Web/Pages/_Layout.cshtml @@ -31,5 +31,11 @@ + diff --git a/src/iRLeagueManager.Web/Program.cs b/src/iRLeagueManager.Web/Program.cs index dc828a6f..099cbe58 100644 --- a/src/iRLeagueManager.Web/Program.cs +++ b/src/iRLeagueManager.Web/Program.cs @@ -25,7 +25,7 @@ var apiHttpClient = new HttpClient(); apiHttpClient.BaseAddress = new Uri(builder.Configuration["APIServer"]); -builder.Services.AddScoped(configure => +builder.Services.AddScoped(configure => { var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); jsonOptions.Converters.Add(new JsonStringEnumConverter()); @@ -34,6 +34,7 @@ return jsonOptions; }); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(x => x.GetRequiredService()); builder.Services.AddScoped(sp => sp.GetRequiredService().CreateClient()); diff --git a/src/iRLeagueManager.Web/Shared/MainLayout.razor b/src/iRLeagueManager.Web/Shared/MainLayout.razor index bf659855..1bb474e5 100644 --- a/src/iRLeagueManager.Web/Shared/MainLayout.razor +++ b/src/iRLeagueManager.Web/Shared/MainLayout.razor @@ -7,18 +7,17 @@
    - - - - - -
    -
    - @Body -
    -
    + + + + +
    +
    + @Body +
    +
    @code { diff --git a/src/iRLeagueManager.Web/Shared/NavMenu.razor b/src/iRLeagueManager.Web/Shared/NavMenu.razor index b099cd4e..50ab4b71 100644 --- a/src/iRLeagueManager.Web/Shared/NavMenu.razor +++ b/src/iRLeagueManager.Web/Shared/NavMenu.razor @@ -105,13 +105,18 @@ - User: @context.User.Identity?.Name;
    - @{var userRoles = @context.User.Claims - .Where(x => x.Type == ClaimTypes.Role) - .Select(x => x.Value);} - Roles: @string.Join(", ", userRoles) +
    + User: @context.User.Identity?.Name;
    + @{var userRoles = @context.User.Claims + .Where(x => x.Type == ClaimTypes.Role) + .Select(x => x.Value);} + Roles: @string.Join(", ", userRoles) +
    +
    + TimeZone: UTC + @SharedState.LocalTimeOffset.AsDateTime().ToString(@"hh\:mm") +
    @code { diff --git a/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs b/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs index f1f6fdfa..429327b7 100644 --- a/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/EventViewModel.cs @@ -21,14 +21,19 @@ public EventViewModel(ILoggerFactory loggerFactory, LeagueApiService apiService, SetModel(model); } + private TimeSpan LocalTimeOffset => ApiService.Shared.LocalTimeOffset; + private ClientLocalTimeProvider ClientTime => ApiService.ClientTimeProvider; + public long EventId { get => model.Id; } public string Name { get => model.Name; set => SetP(model.Name, value => model.Name = value, value); } public DateTime Date { - get => model.Date.GetValueOrDefault(); - set => SetP(model.Date, value => model.Date = value.GetValueOrDefault().Add(model.Date.GetValueOrDefault().TimeOfDay), value); + get => ClientTime.ConvertToLocal(model.Date.GetValueOrDefault()); + set => SetP(ClientTime.ConvertToLocal(model.Date.GetValueOrDefault()), value => model.Date = ClientTime.ConvertToUtc(value.Add(ClientTime.ConvertToLocal(model.Date.GetValueOrDefault()).TimeOfDay)), value); } + public DateTime End => Date + Duration.TimeOfDay; + public long? TrackId { get => model.TrackId; @@ -54,8 +59,8 @@ public string TrackIdString public DateTime StartTime { - get => model.Date.GetValueOrDefault(); - set => SetP(model.Date.GetValueOrDefault().TimeOfDay, value => model.Date = model.Date.GetValueOrDefault().Date.Add(value), value.TimeOfDay); + get => ClientTime.ConvertToLocal(model.Date.GetValueOrDefault()); + set => SetP(ClientTime.ConvertToLocal(model.Date.GetValueOrDefault()).TimeOfDay, value => model.Date = ClientTime.ConvertToUtc(ClientTime.ConvertToLocal(model.Date.GetValueOrDefault()).Date.Add(value)), value.TimeOfDay); } public DateTime Duration diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs index 97f35c56..f65edaaf 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs @@ -1,4 +1,5 @@ -using iRLeagueApiCore.Common.Models; +using iRLeagueApiCore.Common.Enums; +using iRLeagueApiCore.Common.Models; using iRLeagueManager.Web.Data; using iRLeagueManager.Web.Extensions; @@ -9,8 +10,17 @@ public sealed class ReviewsPageViewModel : LeagueViewModelBase leagueModel.EnableProtests; + public bool ProtestsPublic => leagueModel.ProtestsPublic != ProtestPublicSetting.Hidden; + public TimeSpan CooldownPeriod => leagueModel.ProtestCoolDownPeriod; + public TimeSpan ProtestClosedAfter => leagueModel.ProtestsClosedAfter; + + private ObservableCollection reviews = new(); public ObservableCollection Reviews { get => reviews; set => Set(ref reviews, value); } @@ -30,12 +40,24 @@ public async Task LoadFromEventAsync(long eventId, CancellationToken cancellatio try { Loading = true; + + var leagueRequest = ApiService.Client.Leagues() + .WithName(ApiService.CurrentLeague.Name) + .Get(cancellationToken); + var leagueResult = await leagueRequest; + if (leagueResult.Success == false || leagueResult.Content is null) + { + return; + } + leagueModel = leagueResult.Content; + var eventEndpoint = ApiService.CurrentLeague .Events() .WithId(eventId); + EventModel? @event; if (ApiService.CurrentSeason == null) { - var @event = (await eventEndpoint.Get(cancellationToken)).EnsureSuccess(); + @event = (await eventEndpoint.Get(cancellationToken)).EnsureSuccess(); if (@event == null) { return; @@ -102,4 +124,26 @@ public async Task FileProtest(long sessionId, PostProtestModel pro Loading = false; } } + + public bool CanFileProtest(EventViewModel? @event) + { + if (@event is null || @event.HasResult == false) + { + return false; + } + + var canFile = true; + var eventEnd = @event.Date + @event.Duration.TimeOfDay; + if (leagueModel?.ProtestCoolDownPeriod > TimeSpan.Zero) + { + var canFileAfter = eventEnd + leagueModel.ProtestCoolDownPeriod; + canFile &= DateTime.UtcNow > canFileAfter; + } + if (leagueModel?.ProtestsClosedAfter > TimeSpan.Zero) + { + var canFileBefore = eventEnd + leagueModel.ProtestsClosedAfter; + canFile &= DateTime.UtcNow < canFileBefore; + } + return canFile; + } } From db549afad4cfc6ee1287102f2b8a060e8ec73ae7 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 6 Jan 2023 01:16:11 +0100 Subject: [PATCH 31/33] Enable localized culture --- src/iRLeagueManager.Web/Pages/Protests.razor | 2 +- src/iRLeagueManager.Web/Program.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/iRLeagueManager.Web/Pages/Protests.razor b/src/iRLeagueManager.Web/Pages/Protests.razor index 09e00f05..80dc84e3 100644 --- a/src/iRLeagueManager.Web/Pages/Protests.razor +++ b/src/iRLeagueManager.Web/Pages/Protests.razor @@ -68,7 +68,7 @@ @if (EventList.Selected != null) { - @foreach(var session in EventList.Selected.Sessions) + @foreach(var session in EventList.Selected.Sessions.Where(x => x.SessionType == iRLeagueApiCore.Common.Enums.SessionType.Race)) { } diff --git a/src/iRLeagueManager.Web/Program.cs b/src/iRLeagueManager.Web/Program.cs index 099cbe58..572d1e10 100644 --- a/src/iRLeagueManager.Web/Program.cs +++ b/src/iRLeagueManager.Web/Program.cs @@ -44,6 +44,7 @@ builder.Services.AddViewModels(); builder.Services.AddBlazoredModal(); +builder.Services.AddLocalization(); var app = builder.Build(); @@ -69,6 +70,9 @@ app.UseStaticFiles(); app.UseRouting(); +app.UseRequestLocalization(new RequestLocalizationOptions() + .AddSupportedCultures(new[] { "en-US", "de" }) + .AddSupportedUICultures(new[] { "en-US", "de" })); app.UseAuthentication(); app.UseAuthorization(); From a24ace7f872401c8d4771688465e58e8c4efc7b0 Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 6 Jan 2023 01:58:22 +0100 Subject: [PATCH 32/33] Add time checking to protest form --- src/iRLeagueManager.Web/Pages/Protests.razor | 221 ++++++++++-------- src/iRLeagueManager.Web/Pages/Reviews.razor | 2 +- .../ViewModels/ReviewsPageViewModel.cs | 2 +- src/iRLeagueManager.Web/appsettings.json | 4 +- 4 files changed, 130 insertions(+), 99 deletions(-) diff --git a/src/iRLeagueManager.Web/Pages/Protests.razor b/src/iRLeagueManager.Web/Pages/Protests.razor index 80dc84e3..d2297440 100644 --- a/src/iRLeagueManager.Web/Pages/Protests.razor +++ b/src/iRLeagueManager.Web/Pages/Protests.razor @@ -1,8 +1,10 @@ @page "/{LeagueName}/Protests/Events/{EventId:long}" +@page "/{LeagueName}/Protests" @using iRLeagueApiCore.Common.Models @using iRLeagueManager.Web.Components @inherits LeagueComponentBase @inject ReviewsPageViewModel ReviewsVm +@inject ClientLocalTimeProvider ClientTime

    @@ -23,108 +25,136 @@ Back to Reviews

    } - else + else if (Event is not null && ReviewsVm.ProtestsEnabled) { - - - -
    -
    -
    - - member.MemberId) - class="form-control p-0" - EnableDropDown=true - SearchMethod=SearchMembers - MinimumLength=1 - MaximumSuggestions=100 - DeleteItemsOnBackspace=false - placeholder="Search driver by name..."> - - - @{var member = ReviewsVm.EventMembers.FirstOrDefault(x => x.MemberId == memberId);} - @member?.FirstName @member?.LastName - - - @member.FirstName @member.LastName - - - Driver @name Not found! - - -
    Who is filing this protest?
    - -
    -
    - - -
    Enter your iracing user id to confirm identity
    - -
    -
    - - - @if (EventList.Selected != null) - { - @foreach(var session in EventList.Selected.Sessions.Where(x => x.SessionType == iRLeagueApiCore.Common.Enums.SessionType.Race)) + var protestsOpenAt = Event?.End + ReviewsVm.CooldownPeriod; + var protestsCloseAt = Event?.End + ReviewsVm.ProtestClosedAfter; + @if (ReviewsVm.CanFileProtest(Event) == false) + { + @if (ClientTime.Now < protestsOpenAt) + { +
    + Protests can be filed after @protestsOpenAt.ToString(); +
    + } + else if (ClientTime.Now > protestsCloseAt) + { +
    + Protest period ended on @protestsCloseAt.ToString(); +
    + } + } + else + { + @if (ReviewsVm.ProtestClosedAfter > TimeSpan.Zero) + { +
    + Protests can be filed until @protestsCloseAt.ToString(); +
    + } + + + +
    +
    +
    + + member.MemberId) + class="form-control p-0" + EnableDropDown=true + SearchMethod=SearchMembers + MinimumLength=1 + MaximumSuggestions=100 + DeleteItemsOnBackspace=false + placeholder="Search driver by name..."> + + + @{ + var member = ReviewsVm.EventMembers.FirstOrDefault(x => x.MemberId == memberId); + } + @member?.FirstName @member?.LastName + + + @member.FirstName @member.LastName + + + Driver @name Not found! + + +
    Who is filing this protest?
    + +
    +
    + + +
    Enter your iracing user id to confirm identity
    + +
    +
    + + + @if (EventList.Selected != null) { - + @foreach (var session in EventList.Selected.Sessions.Where(x => x.SessionType == iRLeagueApiCore.Common.Enums.SessionType.Race)) + { + + } } - } - -
    In which session did the incident happen?
    -
    -
    -
    - - - + +
    In which session did the incident happen?
    -
    - - - +
    +
    + + + +
    +
    + + + +
    +
    + + +
    Describe what happened in the incident
    + +
    +
    + + + + + @member?.FirstName @member?.LastName + + + @member.FirstName @member.LastName + + + Driver @name Not found! + + +
    Who was involved in this incident?
    + +
    +
    -
    - - -
    Describe what happened in the incident
    - -
    -
    - - - - - @member?.FirstName @member?.LastName - - - @member.FirstName @member.LastName - - - Driver @name Not found! - - -
    Who was involved in this incident?
    - -
    -
    -
    - + + } }
    @@ -163,6 +193,7 @@ await ReviewsVm.LoadFromEventAsync(@event.EventId); } SessionId = @event?.Sessions.FirstOrDefault()?.SessionId; + await InvokeAsync(StateHasChanged); } private bool MatchMemberSearchTerms(MemberInfoModel member, params string[] terms) diff --git a/src/iRLeagueManager.Web/Pages/Reviews.razor b/src/iRLeagueManager.Web/Pages/Reviews.razor index 8fce4a06..eef37861 100644 --- a/src/iRLeagueManager.Web/Pages/Reviews.razor +++ b/src/iRLeagueManager.Web/Pages/Reviews.razor @@ -108,7 +108,7 @@ else if (ClientTime.Now > protestsCloseAt) {
    - Protest period ended on @protestsOpenAt.ToString(); + Protest period ended on @protestsCloseAt.ToString();
    } } diff --git a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs index f65edaaf..e3cad703 100644 --- a/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs +++ b/src/iRLeagueManager.Web/ViewModels/ReviewsPageViewModel.cs @@ -127,7 +127,7 @@ public async Task FileProtest(long sessionId, PostProtestModel pro public bool CanFileProtest(EventViewModel? @event) { - if (@event is null || @event.HasResult == false) + if (@event is null || @event.HasResult == false || leagueModel.EnableProtests == false) { return false; } diff --git a/src/iRLeagueManager.Web/appsettings.json b/src/iRLeagueManager.Web/appsettings.json index 79e31d96..bed1c144 100644 --- a/src/iRLeagueManager.Web/appsettings.json +++ b/src/iRLeagueManager.Web/appsettings.json @@ -9,8 +9,8 @@ } }, "AllowedHosts": "*", - "APIServer": "http://localhost:5000", - //"APIServer": "https://irleaguemanager.net/irleagueapi/", + //"APIServer": "http://localhost:5000", + "APIServer": "https://irleaguemanager.net/irleagueapi/", "DefaultUser": "testuser", "DefaultPassword": "TestPass123!" } From 3c571bddbd12e8ade759b924743f8c3844849a5d Mon Sep 17 00:00:00 2001 From: Simon Schulze Date: Fri, 6 Jan 2023 10:30:46 +0100 Subject: [PATCH 33/33] bump version to 0.4.1 --- src/iRLeagueManager.Web/iRLeagueManager.Web.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj index 6a1482f0..15c09193 100644 --- a/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj +++ b/src/iRLeagueManager.Web/iRLeagueManager.Web.csproj @@ -2,7 +2,7 @@ net6.0 - 0.4.1-dev.1 + 0.4.1 enable enable aspnet-iRLeagueManager.Web-2B05F9DC-55A3-49D1-BD64-31507000EDF3 @@ -20,8 +20,8 @@ - - + +