From 1976bd5fe27ea341261c2b8b20ebe113e7f477eb Mon Sep 17 00:00:00 2001 From: Bernhard Straub Date: Fri, 19 Apr 2024 13:34:40 +0200 Subject: [PATCH] Dev Ongoing work --- .../Aministration/Administration.razor | 11 +-- .../Aministration/Administration.razor.cs | 9 +-- .../AdministrationService.State.cs | 22 ++++++ .../AdministrationService.Transformers.cs | 31 -------- .../Aministration/AdministrationService.cs | 25 ++---- .../Components/DBContainer.razor | 55 ++++--------- .../Components/InviteForm.razor | 27 +++---- .../Components/InvitesForm.razor | 20 ++--- .../Components/MemberForm.razor | 4 +- .../Components/MemberRow.razor | 12 ++- DexieNETCloudSample/Components/Share.razor | 12 ++- .../Components/ToDoDBItemAddOrUpdate.razor | 4 +- DexieNETCloudSample/Components/ToDoItem.razor | 19 ++--- .../Components/ToDoItem.razor.cs | 6 +- DexieNETCloudSample/Components/ToDoList.razor | 37 +++++---- .../Components/ToDoList.razor.cs | 18 ++--- .../Dexie/Services/CrudService.cs | 4 +- .../Dexie/Services/ToDoItemService.cs | 7 +- .../Services/ToDoListMemberService.Share.cs | 40 +++++----- .../Services/ToDoListMemberService.State.cs | 35 +++------ .../Dexie/Services/ToDoListMemberService.cs | 41 +++++----- .../DexieNETCloudSample.csproj | 2 +- .../Dialogs/HandleLicense.razor | 77 +++++-------------- DexieNETCloudSample/Dialogs/HandleLogin.razor | 21 ++--- DexieNETCloudSample/Pages/ToDoListPage.razor | 4 +- DexieNETCloudSample/Program.cs | 12 +-- 26 files changed, 214 insertions(+), 341 deletions(-) create mode 100644 DexieNETCloudSample/Aministration/AdministrationService.State.cs delete mode 100644 DexieNETCloudSample/Aministration/AdministrationService.Transformers.cs diff --git a/DexieNETCloudSample/Aministration/Administration.razor b/DexieNETCloudSample/Aministration/Administration.razor index 198da85..00d06f8 100644 --- a/DexieNETCloudSample/Aministration/Administration.razor +++ b/DexieNETCloudSample/Aministration/Administration.razor @@ -1,4 +1,5 @@ - +@inherits RxBLServiceSubscriber + @@ -10,17 +11,17 @@ Administration @if (Service.Exceptions.Any()) { - Error: @Service.Exceptions.FirstOrDefault()?.Message + Error: @GetExceptions() } - + Get Users - + - + UserId LastLogin diff --git a/DexieNETCloudSample/Aministration/Administration.razor.cs b/DexieNETCloudSample/Aministration/Administration.razor.cs index adfc189..a6b1303 100644 --- a/DexieNETCloudSample/Aministration/Administration.razor.cs +++ b/DexieNETCloudSample/Aministration/Administration.razor.cs @@ -7,13 +7,10 @@ namespace DexieNETCloudSample.Aministration { public partial class Administration { - [CascadingParameter] - public required AdministrationService Service { get; init; } - [Inject] public required IDialogService DialogService { get; init; } - private async Task GetCloudKeyData(IStateTransformer st) + private Func GetUsers => async stateCommandAsync => { CloudKeyData data = new("clientId", "clientSecret"); @@ -23,9 +20,9 @@ private async Task GetCloudKeyData(IStateTransformer st) var result = await dialog.Result; if (!result.Canceled) { - st.Transform((CloudKeyData)result.Data); + await stateCommandAsync.ExecuteAsync(Service.GetUsers((CloudKeyData)result.Data)); } - } + }; private string GetExceptions() { diff --git a/DexieNETCloudSample/Aministration/AdministrationService.State.cs b/DexieNETCloudSample/Aministration/AdministrationService.State.cs new file mode 100644 index 0000000..d9f648a --- /dev/null +++ b/DexieNETCloudSample/Aministration/AdministrationService.State.cs @@ -0,0 +1,22 @@ +using RxBlazorLightCore; + +namespace DexieNETCloudSample.Aministration +{ + public partial class AdministrationService + { + public Func GetUsers(CloudKeyData value) => async c => + { + await DoGetUsers(value, c.CancellationToken); + }; + + public Func DeleteUser => async c => + { + await DoDeleteUser(c.CancellationToken); + }; + + public bool CanDeleteUser() + { + return DBService.UserLogin.HasValue(); + } + } +} diff --git a/DexieNETCloudSample/Aministration/AdministrationService.Transformers.cs b/DexieNETCloudSample/Aministration/AdministrationService.Transformers.cs deleted file mode 100644 index 69cd3c4..0000000 --- a/DexieNETCloudSample/Aministration/AdministrationService.Transformers.cs +++ /dev/null @@ -1,31 +0,0 @@ -using RxBlazorLightCore; - -namespace DexieNETCloudSample.Aministration -{ - public partial class AdministrationService - { - private class GetUsersST(AdministrationService service, IState, List> state) : - StateRefTransformerAsync, List>(service, state) - { - protected override async Task TransformStateAsync(CloudKeyData value, List stateRef, CancellationToken cancellationToken) - { - await Service.DoGetUsers(value, stateRef, cancellationToken); - } - - public override bool CanCancel => true; - public override bool LongRunning => true; - } - - private class DeleteUserSP(AdministrationService service) : StateProviderAsync(service) - { - protected override async Task ProvideStateAsync(CancellationToken cancellationToken) - { - await Service.DoDeleteUser(cancellationToken); - } - - protected override bool CanProvide() => Service.DBService.UserLogin.HasValue(); - public override bool CanCancel => true; - public override bool LongRunning => true; - } - } -} diff --git a/DexieNETCloudSample/Aministration/AdministrationService.cs b/DexieNETCloudSample/Aministration/AdministrationService.cs index de2f19c..9c29fa8 100644 --- a/DexieNETCloudSample/Aministration/AdministrationService.cs +++ b/DexieNETCloudSample/Aministration/AdministrationService.cs @@ -6,25 +6,14 @@ namespace DexieNETCloudSample.Aministration { - public sealed partial class AdministrationService : RxBLService + public sealed partial class AdministrationService(IServiceProvider serviceProvider) : RxBLService { - public IState, List> Users { get; } - public DexieCloudService DBService { get; } + public List Users { get; } = []; + public DexieCloudService DBService { get; } = serviceProvider.GetRequiredService(); - // Commands - public IStateTransformer GetUsers => new GetUsersST(this, Users); - public IStateProvider DeleteUser => new DeleteUserSP(this); + private readonly HttpClient _httpClient = serviceProvider.GetRequiredService(); - private readonly HttpClient _httpClient; - - public AdministrationService(IServiceProvider serviceProvider) - { - DBService = serviceProvider.GetRequiredService(); - _httpClient = serviceProvider.GetRequiredService(); - Users = this.CreateState, List>([]); - } - - private async Task DoGetUsers(CloudKeyData data, List users, CancellationToken cancellationToken) + private async Task DoGetUsers(CloudKeyData data, CancellationToken cancellationToken) { var body = new AccesssTokenRequest([DBScopes.AccessDB, DBScopes.GlobalRead, DBScopes.GlobalWrite], data.ClientId, data.ClientSecret); var bodyJson = JsonSerializer.Serialize(body, AccesssTokenRequestContext.Default.AccesssTokenRequest); @@ -60,8 +49,8 @@ private async Task DoGetUsers(CloudKeyData data, List users, Cance if (usersResponse is not null) { - users.Clear(); - users.AddRange(usersResponse.Data); + Users.Clear(); + Users.AddRange(usersResponse.Data); } } } diff --git a/DexieNETCloudSample/Components/DBContainer.razor b/DexieNETCloudSample/Components/DBContainer.razor index 509a6ef..13e955e 100644 --- a/DexieNETCloudSample/Components/DBContainer.razor +++ b/DexieNETCloudSample/Components/DBContainer.razor @@ -1,4 +1,4 @@ -@inherits OwningComponentBase +@inherits RxBLServiceSubscriber @@ -17,47 +17,26 @@ [Inject] public required IConfiguration Configuration { get; init; } - [CascadingParameter] - public required DexieCloudService Service { get; init; } - - private IDisposable? _sDisposable; - - protected override async Task OnInitializedAsync() + protected override async Task ServiceStateHasChangedAsync(ServiceChangeReason cr) { - await base.OnInitializedAsync(); - - _sDisposable = Service.Subscribe(async cr => - { - switch (cr.ID) + switch (cr.ID) + { + case var value when value == Service.UIInteraction.ID: + if (Service.DB is not null && Service.UIInteraction.HasValue()) { - case var value when value == Service.UIInteraction.ID: - if (Service.DB is not null && Service.UIInteraction.HasValue()) - { - bool res = await Authenticate.HandleUIInteraction(Service.DB, Service.UIInteraction.Value, DialogService); - if (Service.UIInteraction.Value.Type is UIInteraction.InteractionType.LOGOUT_CONFIRMATION && res) - { - await Service.DB.Logout(true); - } - } - break; - case var value when value == Service.State.ID: - if (Service.State.Value is DBState.Closed) - { - await OpenDB(); - } - break; + bool res = await Authenticate.HandleUIInteraction(Service.DB, Service.UIInteraction.Value, DialogService); + if (Service.UIInteraction.Value.Type is UIInteraction.InteractionType.LOGOUT_CONFIRMATION && res) + { + await Service.DB.Logout(true); + } } - }); - } + break; + } - protected override void Dispose(bool disposing) - { - if (disposing) + if (Service.State.Value is DBState.Closed) { - _sDisposable?.Dispose(); + await OpenDB(); } - - base.Dispose(disposing); } private async Task OpenDB() @@ -68,7 +47,7 @@ Service.ConfigureCloud(Configuration.GetDBUrl()); } - private string GetPhaseIcon(IState state) + private string GetPhaseIcon(IState state) { if (!state.HasValue()) { @@ -88,7 +67,7 @@ }; } - private string GetStatusIcon(IState state) + private string GetStatusIcon(IState state) { if (!state.HasValue()) { diff --git a/DexieNETCloudSample/Components/InviteForm.razor b/DexieNETCloudSample/Components/InviteForm.razor index d7624e2..5823ad7 100644 --- a/DexieNETCloudSample/Components/InviteForm.razor +++ b/DexieNETCloudSample/Components/InviteForm.razor @@ -1,4 +1,5 @@ @using DexieNET +@inherits RxBLServiceSubscriber @@ -14,16 +15,13 @@ @context - Service.AddMember) Parameter=@context PrepareExecutionAsync=@GetUser /> + @code { - [CascadingParameter] - public required ToDoListMemberService Service { get; init; } - [Inject] public required DexieCloudService DBService { get; init; } @@ -37,10 +35,8 @@ return base.OnInitializedAsync(); } - private async Task GetUser(ICommandAsync cmd, CancellationToken cancellationToken) + private Func AddMember(string user) => async _ => { - var user = cmd.Parameter; - if (user == Service.Users.Last()) { ArgumentNullException.ThrowIfNull(DialogService); @@ -53,11 +49,11 @@ var result = await dialog.Result; if (result.Canceled) { - return false; + return; } else - { - user = data.Email; + { + user = data.Email; } } else @@ -70,13 +66,10 @@ if (res.Canceled) { - return false; + return; } - - return true; } - cmd.SetParameter(user); - return true; - } + await Service.AddMember(user); + }; } diff --git a/DexieNETCloudSample/Components/InvitesForm.razor b/DexieNETCloudSample/Components/InvitesForm.razor index c315b60..cc84c3e 100644 --- a/DexieNETCloudSample/Components/InvitesForm.razor +++ b/DexieNETCloudSample/Components/InvitesForm.razor @@ -1,6 +1,7 @@ @using DexieNET +@inherits RxBLServiceSubscriber - + @@ -18,22 +19,21 @@ @GetInviteText(context) - Service?.AcceptInvite) Parameter=@context - ConfirmExecution=@(async _ => await ConfirmInvite(true)) /> + await ConfirmInvite(true)) /> - Service?.RejectInvite) Parameter=@context - ConfirmExecution=@(async _ => await ConfirmInvite(false)) /> + await ConfirmInvite(true)) /> @code { - [CascadingParameter] - public required ToDoListService Service { get; init; } - [Inject] public required DexieCloudService DBService { get; init; } diff --git a/DexieNETCloudSample/Components/MemberForm.razor b/DexieNETCloudSample/Components/MemberForm.razor index f0b25f8..bed2a39 100644 --- a/DexieNETCloudSample/Components/MemberForm.razor +++ b/DexieNETCloudSample/Components/MemberForm.razor @@ -1,4 +1,5 @@ @using DexieNET +@inherits RxBLServiceSubscriber @@ -15,9 +16,6 @@ @code { - [CascadingParameter] - public required ToDoListMemberService Service { get; init; } - [Parameter, EditorRequired] public required ToDoDBList List { get; set; } } \ No newline at end of file diff --git a/DexieNETCloudSample/Components/MemberRow.razor b/DexieNETCloudSample/Components/MemberRow.razor index 7d32c6d..b76be3a 100644 --- a/DexieNETCloudSample/Components/MemberRow.razor +++ b/DexieNETCloudSample/Components/MemberRow.razor @@ -1,15 +1,16 @@ @using DexieNET +@inherits RxBLServiceSubscriber @MemberName(Member) - Service.MemberRoleSelection) + - Service.ChangeMemberState) Parameter=@Member /> + @if (_isOwnList && _currentMemberAction is not MemberAction.OWNER) { @@ -17,9 +18,6 @@ @code { - [CascadingParameter] - public required ToDoListMemberService Service { get; init; } - [Inject] public required DexieCloudService DBService { get; init; } @@ -88,7 +86,7 @@ }; } - private async Task DoPrepareChangeMemberState(ICommandAsync cmd, CancellationToken token) + private async Task ConfirmChangeMemberStateAsync() { var message = _currentMemberAction switch { diff --git a/DexieNETCloudSample/Components/Share.razor b/DexieNETCloudSample/Components/Share.razor index 7dae1db..68a6358 100644 --- a/DexieNETCloudSample/Components/Share.razor +++ b/DexieNETCloudSample/Components/Share.razor @@ -1,4 +1,5 @@ @using DexieNET +@inherits RxBLServiceSubscriber @@ -16,7 +17,7 @@ { } - @if (Service.DoCanAddMember()) + @if (Service.CanAddMember()) { } @@ -25,24 +26,21 @@ @code { - [CascadingParameter] - public required ToDoListMemberService Service { get; init; } - [Parameter, EditorRequired] public required ToDoDBList List { get; init; } protected override Task OnInitializedAsync() { - Service.SetList.Transform(List); + Service.List.Value = List; return base.OnInitializedAsync(); } protected override async Task OnParametersSetAsync() { - if (Service.List != List) + if (Service.List.Value != List) { - Service.SetList.Transform(List); + Service.List.Value = List; } await base.OnParametersSetAsync(); diff --git a/DexieNETCloudSample/Components/ToDoDBItemAddOrUpdate.razor b/DexieNETCloudSample/Components/ToDoDBItemAddOrUpdate.razor index bae10c2..c588950 100644 --- a/DexieNETCloudSample/Components/ToDoDBItemAddOrUpdate.razor +++ b/DexieNETCloudSample/Components/ToDoDBItemAddOrUpdate.razor @@ -2,11 +2,11 @@ @if (AddMode) { - + } else { - Service.CanUpdate(Item)) Color="Color.Info" Icon=@Icons.Material.Filled.Edit ExecuteAsyncCallback=@ShowAddUpdateDialog /> + Service.CanUpdate(Item)) Color="Color.Info" Icon=@Icons.Material.Filled.Edit ExecuteAsyncCallback=@ShowAddUpdateDialog /> } @code { diff --git a/DexieNETCloudSample/Components/ToDoItem.razor b/DexieNETCloudSample/Components/ToDoItem.razor index ba087db..47a2c5a 100644 --- a/DexieNETCloudSample/Components/ToDoItem.razor +++ b/DexieNETCloudSample/Components/ToDoItem.razor @@ -1,4 +1,5 @@ - +@inherits RxBLServiceSubscriber + @@ -17,9 +18,9 @@ ConfirmDelete(DeleteType.Completed)) - StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanDeleteCompletedItems ExecuteAsyncCallback=@Service.DeleteCompletedItems /> + StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanDeleteCompletedItems ExecuteAsyncCallback=@Service.DeleteCompletedItems /> ConfirmDelete(DeleteType.All)) - StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems /> + StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems /> @@ -28,9 +29,9 @@ ConfirmDelete(DeleteType.Completed)) - StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanDeleteCompletedItems ExecuteAsyncCallback=@Service.DeleteCompletedItems /> + StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanDeleteCompletedItems ExecuteAsyncCallback=@Service.DeleteCompletedItems /> ConfirmDelete(DeleteType.All)) - StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems /> + StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems /> @@ -62,15 +63,15 @@ @context.Text @DateTimeForItem(context) - + - ConfirmDelete(DeleteType.One)) ExecuteAsyncCallback=@(Service.DeleteItem(context)) /> + ConfirmDelete(DeleteType.One)) ExecuteAsyncCallback=@Service.DeleteItem(context) /> diff --git a/DexieNETCloudSample/Components/ToDoItem.razor.cs b/DexieNETCloudSample/Components/ToDoItem.razor.cs index d964d5c..d3c6cf8 100644 --- a/DexieNETCloudSample/Components/ToDoItem.razor.cs +++ b/DexieNETCloudSample/Components/ToDoItem.razor.cs @@ -1,5 +1,4 @@ -using DexieNETCloudSample.Dexie.Services; -using DexieNETCloudSample.Dialogs; +using DexieNETCloudSample.Dialogs; using DexieNETCloudSample.Logic; using Microsoft.AspNetCore.Components; using MudBlazor; @@ -8,9 +7,6 @@ namespace DexieNETCloudSample.Components { public partial class ToDoItem { - [CascadingParameter] - public required ToDoItemService Service { get; init; } - [Inject] public required IDialogService DialogService { get; init; } diff --git a/DexieNETCloudSample/Components/ToDoList.razor b/DexieNETCloudSample/Components/ToDoList.razor index 8f4995f..d3147d5 100644 --- a/DexieNETCloudSample/Components/ToDoList.razor +++ b/DexieNETCloudSample/Components/ToDoList.razor @@ -1,4 +1,5 @@ - +@inherits RxBLServiceSubscriber + @@ -17,8 +18,9 @@ @if (Service.IsDBOpen) { - AddOrUpdate(st, null)) /> - ConfirmDelete(DeleteType.All)) StateProvider=@Scope.ClearItems /> + + ConfirmDelete(DeleteType.All)) + StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems /> } @@ -33,8 +35,9 @@ - AddOrUpdate(st, null)) /> - ConfirmDelete(DeleteType.All)) StateProvider=@Scope.ClearItems /> + + ConfirmDelete(DeleteType.All)) + StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems /> @@ -62,21 +65,21 @@ - Task.FromResult(context)) /> + @context.Title - Task.FromResult(context)) /> + - AddOrUpdate(st, context)) /> + - DeleteList(st, context)) /> + ConfirmDelete(DeleteType.One)) ExecuteAsyncCallback=@Service.DeleteItem(context) /> @@ -86,17 +89,13 @@ { - - - + } - - - + } diff --git a/DexieNETCloudSample/Components/ToDoList.razor.cs b/DexieNETCloudSample/Components/ToDoList.razor.cs index 77e5db0..13fcb14 100644 --- a/DexieNETCloudSample/Components/ToDoList.razor.cs +++ b/DexieNETCloudSample/Components/ToDoList.razor.cs @@ -9,12 +9,6 @@ namespace DexieNETCloudSample.Components { public partial class ToDoList { - [CascadingParameter] - public required ToDoListService Service { get; init; } - - [CascadingParameter] - public required ToDoListService.Scope Scope { get; init; } - [Inject] public required IDialogService DialogService { get; init; } @@ -24,7 +18,7 @@ private enum DeleteType One } - private async Task AddOrUpdate(IStateTransformer tf, ToDoDBList? item) + private Func AddOrUpdate(ToDoDBList? item) => async commandAsync => { ToDoListData data = item is null ? new ToDoListData(string.Empty) : new ToDoListData(item.Title); @@ -42,9 +36,9 @@ private async Task AddOrUpdate(IStateTransformer tf, ToDoDBList? ite ToDoListService.CreateList(data.Title) : ToDoListService.CreateList(data.Title, item); - tf.Transform(list); + await commandAsync.ExecuteAsync(Service.AddItem(list)); } - } + }; private async Task ConfirmDelete(DeleteType type) { @@ -68,14 +62,14 @@ private async Task ConfirmDelete(DeleteType type) return true; } - private async Task DeleteList(IStateTransformer tf, ToDoDBList list) + private Func DeleteList(ToDoDBList list) => async commandAsync => { var confirmed = await ConfirmDelete(DeleteType.One); if (confirmed) { - tf.Transform(list); + await commandAsync.ExecuteAsync(Service.DeleteItem(list)); } - } + }; } } \ No newline at end of file diff --git a/DexieNETCloudSample/Dexie/Services/CrudService.cs b/DexieNETCloudSample/Dexie/Services/CrudService.cs index 1950c08..3b36362 100644 --- a/DexieNETCloudSample/Dexie/Services/CrudService.cs +++ b/DexieNETCloudSample/Dexie/Services/CrudService.cs @@ -11,8 +11,6 @@ namespace DexieNETCloudSample.Dexie.Services public abstract partial class CrudService : RxBLService, IDisposable where T : IIDPrimaryIndex, IDBStore, IDBCloudEntity { public IEnumerable Items { get; private set; } - public IStateCommandAsync DBCMDAsync { get; } - public bool IsDBOpen => DbService.DB is not null; // Transformers @@ -27,7 +25,6 @@ public CrudService(IServiceProvider serviceProvider) { Items = []; DbService = serviceProvider.GetRequiredService(); - DBCMDAsync = this.CreateStateCommandAsync(); } protected override ValueTask ContextReadyAsync() @@ -93,6 +90,7 @@ private void InitDB() Console.WriteLine($"CRUD new items: {l.Aggregate(string.Empty, (p, n) => p += n.ToString())}"); #endif Items = l; + StateHasChanged(); })); Permissions = GetTable().CreateUsePermissions(); diff --git a/DexieNETCloudSample/Dexie/Services/ToDoItemService.cs b/DexieNETCloudSample/Dexie/Services/ToDoItemService.cs index 7bf019c..c1d1f10 100644 --- a/DexieNETCloudSample/Dexie/Services/ToDoItemService.cs +++ b/DexieNETCloudSample/Dexie/Services/ToDoItemService.cs @@ -19,7 +19,7 @@ public async Task SubmitAsync() { ArgumentNullException.ThrowIfNull(service.CurrentList.Value); var newItem = ToDoDBItem.Create(Text.Value, DueDateDate.Value + DueDateTime.Value, service.CurrentList.Value, item); - await service.DBCMDAsync.ExecuteAsync(service.AddItem(newItem)); + await service.CommandAsync.ExecuteAsync(service.AddItem(newItem)); } public bool CanSubmit() { @@ -90,11 +90,6 @@ public ToDoItemItemInput CreateItemInput(ToDoDBItem? item = null) return new ToDoItemItemInput(this, item); } - /*public static ToDoDBItem CreateItem(string text, DateTime dueDate, ToDoDBList list, ToDoDBItem? item = null) - { - return ToDoDBItem.Create(text, dueDate, list, item); - }*/ - protected override Table GetTable() { ArgumentNullException.ThrowIfNull(_db); diff --git a/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.Share.cs b/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.Share.cs index 189b7b4..5951c81 100644 --- a/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.Share.cs +++ b/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.Share.cs @@ -67,63 +67,63 @@ private async Task Leave(ToDoDBList list) await _dbService.DB.Members.Where(m => m.RealmId, list.RealmId, m => m.UserId, currentUserId).Delete(); } - private async Task ChangeAccess((Member Member, MemberRole Role, MemberRole NewRole)? MemberAccess) + private async Task ChangeAccess(Member Member, MemberRole Role, MemberRole NewRole) { ArgumentNullException.ThrowIfNull(_dbService.DB); - ArgumentNullException.ThrowIfNull(List?.ID); - ArgumentNullException.ThrowIfNull(List?.Owner); - ArgumentNullException.ThrowIfNull(MemberAccess?.Member.Id); - ArgumentNullException.ThrowIfNull(MemberAccess?.Role); - ArgumentNullException.ThrowIfNull(MemberAccess?.NewRole); + ArgumentNullException.ThrowIfNull(List.Value?.ID); + ArgumentNullException.ThrowIfNull(List.Value?.Owner); + ArgumentNullException.ThrowIfNull(Member.Id); + ArgumentNullException.ThrowIfNull(Role); + ArgumentNullException.ThrowIfNull(NewRole); - var realmId = _dbService.DB.GetTiedRealmID(List.ID); + var realmId = _dbService.DB.GetTiedRealmID(List.Value.ID); await _dbService.DB.Transaction(async _ => { - if (MemberAccess.Value.Role is not MemberRole.OWNER && MemberAccess.Value.NewRole is MemberRole.OWNER) + if (Role is not MemberRole.OWNER && NewRole is MemberRole.OWNER) { // Cannot give ownership to user before invite is accepted. - ArgumentNullException.ThrowIfNull(MemberAccess?.Member.UserId); + ArgumentNullException.ThrowIfNull(Member.UserId); // Before changing owner, give full permissions to the old owner: await _dbService.DB.Members - .Where(m => m.RealmId, realmId, m => m.UserId, List.Owner) + .Where(m => m.RealmId, realmId, m => m.UserId, List.Value.Owner) .Modify(m => m.Roles, new[] { MemberRole.ADMIN.ToString().ToLowerInvariant() }); // Change owner of all members in the realm: await _dbService.DB.Members .Where(m => m.RealmId, realmId) - .Modify(m => m.Owner, MemberAccess.Value.Member.UserId); + .Modify(m => m.Owner, Member.UserId); // Change owner of the todo list: await _dbService.DB.ToDoDBLists - .Update(List.ID, l => l.Owner, MemberAccess.Value.Member.UserId); + .Update(List.Value.ID, l => l.Owner, Member.UserId); // Change owner of the todo list items await _dbService.DB.ToDoDBItems - .Where(i => i.ListID, List.ID) - .Modify(i => i.Owner, MemberAccess.Value.Member.UserId); + .Where(i => i.ListID, List.Value.ID) + .Modify(i => i.Owner, Member.UserId); // Change owner of realm: await _dbService.DB.Realms - .Update(realmId, r => r.Owner, MemberAccess.Value.Member.UserId); + .Update(realmId, r => r.Owner, Member.UserId); } - if (MemberAccess.Value.NewRole is not MemberRole.OWNER) + if (NewRole is not MemberRole.OWNER) { await _dbService.DB.Members - .Update(MemberAccess.Value.Member.Id, m => m.Permissions, new Permission(), m => m.Roles, new[] { MemberAccess.Value.NewRole.ToString().ToLowerInvariant() }); + .Update(Member.Id, m => m.Permissions, new Permission(), m => m.Roles, new[] { NewRole.ToString().ToLowerInvariant() }); } - if (MemberAccess.Value.Role is MemberRole.OWNER && MemberAccess.Value.NewRole is not MemberRole.OWNER) + if (Role is MemberRole.OWNER && NewRole is not MemberRole.OWNER) { // Remove ownership by letting current user take ownership instead: await _dbService.DB.ToDoDBLists - .Update(List.ID, l => l.Owner, _dbService.DB.CurrentUserId()); + .Update(List.Value.ID, l => l.Owner, _dbService.DB.CurrentUserId()); // Change ownership of the todo list items await _dbService.DB.ToDoDBItems - .Where(i => i.ListID).Equal(List.ID) + .Where(i => i.ListID).Equal(List.Value.ID) .Modify(i => i.Owner, _dbService.DB.CurrentUserId()); await _dbService.DB.Realms diff --git a/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.State.cs b/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.State.cs index e7ca564..1e39f97 100644 --- a/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.State.cs +++ b/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.State.cs @@ -2,46 +2,29 @@ using DexieNETCloudSample.Extensions; using DexieNETCloudSample.Logic; using RxBlazorLightCore; -using System.Reflection.Metadata; namespace DexieNETCloudSample.Dexie.Services { public partial class ToDoListMemberService { - public Action SetList(ToDoDBList list) => () => - { - List = list; - }; - public Func CanSetList(ToDoDBList? list) => () => { - return list is not null && list != List; - }; - - public Func AddMember(string user) => async _ => - { - await DoAddMember(user); - }; - - public Func CanAddMember() => () => - { - return DoCanAddMember(); - + return list is not null && list != List.Value; }; public Func ChangeMemberState(Member member) => async _ => { - ArgumentNullException.ThrowIfNull(List); + ArgumentNullException.ThrowIfNull(List.Value); var memberAction = GetMemberAction(member); if (memberAction is MemberAction.DELETE) { - await UnShareWith(List, member); + await UnShareWith(List.Value, member); } else if (memberAction is MemberAction.LEAVE) { - await Leave(List); + await Leave(List.Value); } else if (memberAction is MemberAction.ACCEPT) { @@ -76,7 +59,7 @@ public Func CanChangeMemberState(Member? member) => () => new(MemberRole.GUEST), ]; - public MemberRoleSelection GetInitialMemberRole(Member? member) + public Func GetInitialMemberRole(Member? member) => () => { ArgumentNullException.ThrowIfNull(member); var role = GetMemberRole(member); @@ -95,12 +78,12 @@ public MemberRoleSelection GetInitialMemberRole(Member? member) ArgumentNullException.ThrowIfNull(initialSelection); return initialSelection; - } + }; - public async Task MemberRoleChangingAsync(Member member, MemberRoleSelection oldValue, MemberRoleSelection newValue) + public Func MemberRoleChangingAsync(Member member) => async (or, nr) => { - await ChangeAccess((member, oldValue.Role, newValue.Role)); - } + await ChangeAccess(member, or.Role, nr.Role); + }; public Func CanChangeMemberRole(Member member) => () => { diff --git a/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.cs b/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.cs index 2b2dd79..b3c4cb9 100644 --- a/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.cs +++ b/DexieNETCloudSample/Dexie/Services/ToDoListMemberService.cs @@ -52,10 +52,7 @@ public enum MemberState public sealed partial class ToDoListMemberService : RxBLService { public bool IsDBOpen => _dbService.DB is not null; - public ToDoDBList? List { get; private set; } - - public IStateCommandAsync MemberCMDAsync { get; } - + public IState List { get; } public IEnumerable Members { get; private set; } = []; public IEnumerable Users { get; private set; } = []; @@ -75,7 +72,7 @@ public ToDoListMemberService(IServiceProvider serviceProvider) _dbService = serviceProvider.GetRequiredService(); _configuration = serviceProvider.GetRequiredService(); - MemberCMDAsync = this.CreateStateCommandAsync(); + List = this.CreateState((ToDoDBList?)null); MemberRoleSelection = this.CreateStateGroupAsync(_roleSelections); } @@ -89,9 +86,9 @@ protected override ValueTask ContextReadyAsync() ArgumentNullException.ThrowIfNull(_dbService.DB); var memberQuery = _dbService.DB.LiveQuery(async () => - await _dbService.DB.Members.Where(m => m.RealmId).Equal(List?.RealmId).ToArray()); + await _dbService.DB.Members.Where(m => m.RealmId).Equal(List.Value?.RealmId).ToArray()); - var useMemberQuery = memberQuery.UseLiveQuery(this.CreateStatePhaseObservable(SetList)); + var useMemberQuery = memberQuery.UseLiveQuery(this.Where(cr => cr.ID == List.ID).Select(_ => Unit.Default)); _dbDisposeBag.Add(useMemberQuery.Select(m => { @@ -107,15 +104,15 @@ protected override ValueTask ContextReadyAsync() }) .Append("by eMail"); return Unit.Default; - }).Subscribe(MemberStateProvider)); + }).Subscribe(this)); return ValueTask.CompletedTask; } - public bool DoCanAddMember() + public bool CanAddMember() { return Users.Any() && _membersTable is not null && - (_permissionsMember?.CanAdd(List, _membersTable)).True(); + (_permissionsMember?.CanAdd(List.Value, _membersTable)).True(); } public bool CanUpdateRole(Member Member) @@ -129,10 +126,10 @@ public bool CanChangeToRole(Member? Member, MemberRole newRole) { ArgumentNullException.ThrowIfNull(_dbService.DB); ArgumentNullException.ThrowIfNull(Member); - ArgumentNullException.ThrowIfNull(List); + ArgumentNullException.ThrowIfNull(List.Value); var canUpdateRoles = (_permissionsMember?.CanUpdate(Member, m => m.Roles)).True(); - var canUpdateOwner = (_permissionsRealm?.CanUpdate(List, m => m.Owner)).True(); + var canUpdateOwner = (_permissionsRealm?.CanUpdate(List.Value, m => m.Owner)).True(); return newRole switch { @@ -149,9 +146,9 @@ public MemberAction GetMemberAction(Member? member) } ArgumentNullException.ThrowIfNull(_dbService.DB); - ArgumentNullException.ThrowIfNull(List); + ArgumentNullException.ThrowIfNull(List.Value); - var isOwner = member.UserId == List.Owner; + var isOwner = member.UserId == List.Value.Owner; var isCurrentUser = member.UserId == _dbService.DB.CurrentUserId(); var aTime = member.Accepted ?? DateTime.UtcNow; var rTime = member.Rejected ?? member.Accepted; @@ -204,7 +201,7 @@ public static MemberState GetMemberState(Member? member) public MemberRole GetMemberRole(Member member) { ArgumentNullException.ThrowIfNull(_dbService?.Roles); - ArgumentNullException.ThrowIfNull(List); + ArgumentNullException.ThrowIfNull(List.Value); var roleName = member.Roles?.FirstOrDefault(); var memberRole = MemberRole.GUEST; @@ -217,7 +214,7 @@ public MemberRole GetMemberRole(Member member) } } - memberRole = member.UserId == List.Owner ? MemberRole.OWNER : memberRole; + memberRole = member.UserId == List.Value.Owner ? MemberRole.OWNER : memberRole; return memberRole; } @@ -263,19 +260,17 @@ private void InitDB() _membersTable = _dbService.DB.Members; _permissionsMember = _dbService.DB.Members.CreateUsePermissions(); - - _permissionsDisposeBag.Add(_permissionsMember.Subscribe(MemberStateProvider)); + _permissionsDisposeBag.Add(_permissionsMember.Subscribe(this)); _permissionsRealm = _dbService.DB.Realms.CreateUsePermissions(); - - _permissionsDisposeBag.Add(_permissionsRealm.Subscribe(MemberStateProvider)); + _permissionsDisposeBag.Add(_permissionsRealm.Subscribe(this)); } - private async Task DoAddMember(string user) + public async Task AddMember(string user) { - ArgumentNullException.ThrowIfNull(List); + ArgumentNullException.ThrowIfNull(List.Value); - await ShareWith(List, user, user, true, MemberRole.USER); + await ShareWith(List.Value, user, user, true, MemberRole.USER); } } } diff --git a/DexieNETCloudSample/DexieNETCloudSample.csproj b/DexieNETCloudSample/DexieNETCloudSample.csproj index 8236de5..6aad92d 100644 --- a/DexieNETCloudSample/DexieNETCloudSample.csproj +++ b/DexieNETCloudSample/DexieNETCloudSample.csproj @@ -10,7 +10,7 @@ - + diff --git a/DexieNETCloudSample/Dialogs/HandleLicense.razor b/DexieNETCloudSample/Dialogs/HandleLicense.razor index 28bb7d0..dad773c 100644 --- a/DexieNETCloudSample/Dialogs/HandleLicense.razor +++ b/DexieNETCloudSample/Dialogs/HandleLicense.razor @@ -1,11 +1,11 @@ @using DexieNET -@inherits OwningComponentBase +@inherits RxBLServiceSubscriber -@if (_userLogin?.License is not null && (_userLogin.License.Status is not LicenseStatus.OK || _userLogin.License.EvalDaysLeft < 7)) +@if (Service2.UserLogin.Value?.License is not null && (Service2.UserLogin.Value.License.Status is not LicenseStatus.OK || Service2.UserLogin.Value.License.EvalDaysLeft < 7)) { @@ -14,66 +14,31 @@ - @if (_userLogin.License.Status is not LicenseStatus.OK) + @if (Service2.UserLogin.Value.License.Status is not LicenseStatus.OK) { - Delete account for: @_userLogin.UserId + Delete account for: @Service2.UserLogin.Value.UserId } - @if (_userLogin.License.Status is LicenseStatus.EXPIRED || _userLogin.License.EvalDaysLeft < 7) + @if (Service2.UserLogin.Value.License.Status is LicenseStatus.EXPIRED || Service2.UserLogin.Value.License.EvalDaysLeft < 7) { - Buy license for: @_userLogin.UserId + Buy license for: @Service2.UserLogin.Value.UserId } } @code { - [Inject] - public required AdministrationService AdministrationService { get; init; } - [Inject] public required IDialogService DialogService { get; init; } - private UserLogin? _userLogin; - private IDisposable? _sDisposable; - //private readonly License _testLicense = new(LicenseType.EVAL, LicenseStatus.EXPIRED, null, 6); - - protected override void OnInitialized() - { - ArgumentNullException.ThrowIfNull(AdministrationService.DBService); - - _sDisposable = AdministrationService.DBService.Subscribe(() => - { - if (AdministrationService.DBService.State is DBState.UserLogin) - { - _userLogin = AdministrationService.DBService.UserLogin; - /*if (_userLogin is not null) - { - _userLogin = _userLogin with { License = _testLicense }; - }*/ - InvokeAsync(StateHasChanged); - } - }); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _sDisposable?.Dispose(); - } - - base.Dispose(disposing); - } - private async Task ConfirmDeleteUser() { - ArgumentNullException.ThrowIfNull(AdministrationService.DeleteUser); - ArgumentNullException.ThrowIfNull(_userLogin); + ArgumentNullException.ThrowIfNull(Service1.DeleteUser); + ArgumentNullException.ThrowIfNull(Service2.UserLogin.Value); - var message = $"Are you sure you want to delete your user completely along all stored data for {_userLogin.UserId}? Private data will be deleted. Shared data will not be deleted. This action cannot be undone."; + var message = $"Are you sure you want to delete your user completely along all stored data for {Service2.UserLogin.Value.UserId}? Private data will be deleted. Shared data will not be deleted. This action cannot be undone."; - return await DialogAsyncRx.Show(DialogService, AdministrationService.DeleteUser, $"Delete {_userLogin.UserId}", - message, $"Delete {_userLogin.UserId}", "Cancel", false, "Cancel Delete"); + return await DialogAsyncRx.Show(DialogService, Service1.CommandAsync, Service1.DeleteUser, $"Delete {Service2.UserLogin.Value.UserId}", + message, $"Delete {Service2.UserLogin.Value.UserId}", "Cancel", false, "Cancel Delete"); } private async Task BuyLicense() @@ -83,49 +48,49 @@ private string GetLicenseIcon() { - @if (_userLogin?.License is null) + @if (Service2.UserLogin.Value?.License is null) { return Icons.Material.Outlined.QuestionMark; } - return _userLogin.License.Type switch + return Service2.UserLogin.Value.License.Type switch { LicenseType.DEMO => Icons.Material.Outlined.Quiz, LicenseType.EVAL => Icons.Material.Outlined.AddShoppingCart, LicenseType.PROD => Icons.Material.Outlined.Paid, LicenseType.CLIENT => Icons.Material.Outlined.AccountBalance, - _ => throw new ArgumentOutOfRangeException(nameof(_userLogin.License.Type)) + _ => throw new ArgumentOutOfRangeException(nameof(Service2.UserLogin.Value.License.Type)) }; } private string GetLicenseTooltip() { - @if (_userLogin?.License is null) + @if (Service2.UserLogin.Value?.License is null) { return "No user logged in."; } - @if (_userLogin.License.Type is LicenseType.DEMO) + @if (Service2.UserLogin.Value.License.Type is LicenseType.DEMO) { return "You are in demonstration mode."; } - @if (_userLogin.License.Type is LicenseType.EVAL) + @if (Service2.UserLogin.Value.License.Type is LicenseType.EVAL) { - return $"You are in evaluation mode. {_userLogin.License.EvalDaysLeft} days left."; + return $"You are in evaluation mode. {Service2.UserLogin.Value.License.EvalDaysLeft} days left."; } - @if (_userLogin.License.Type is LicenseType.PROD) + @if (Service2.UserLogin.Value.License.Type is LicenseType.PROD) { return $"You have a valid purchased license."; } - @if (_userLogin.License.Type is LicenseType.CLIENT) + @if (Service2.UserLogin.Value.License.Type is LicenseType.CLIENT) { return $"You have a valid site license."; } - return _userLogin.License.Status switch + return Service2.UserLogin.Value.License.Status switch { LicenseStatus.OK => "You have a valid license.", LicenseStatus.EXPIRED => "Your license has expired.You are in offline mode until a valid license is purchased.", diff --git a/DexieNETCloudSample/Dialogs/HandleLogin.razor b/DexieNETCloudSample/Dialogs/HandleLogin.razor index 013a5be..e9c211a 100644 --- a/DexieNETCloudSample/Dialogs/HandleLogin.razor +++ b/DexieNETCloudSample/Dialogs/HandleLogin.razor @@ -1,15 +1,16 @@ @using DexieNET +@inherits RxBLServiceSubscriber - + "Sign in or create your account" - @if (DBService.UserLogin is not null && DBService.UserLogin.IsLoggedIn) + @if (Service.UserLogin.HasValue() && Service.UserLogin.Value.IsLoggedIn) { - Sign Out: @DBService.UserLogin.UserId + Sign Out: @Service.UserLogin.Value.UserId } else { @@ -39,14 +40,16 @@ [Inject] public required IConfiguration Configuration { get; init; } - [CascadingParameter] - public required DexieCloudService DBService { get; init; } - private IEnumerable users = Enumerable.Empty(); + protected override void OnInitialized() + { + users = Configuration.GetUsers(); + } + private async Task Logout() { - await DBService.Logout(); + await Service.Logout(); } private async ValueTask Login(string? eMail = null) @@ -56,7 +59,7 @@ if (eMail is not null) { LoginInformation li = new(eMail, null, GrantType.DEMO); - error = await DBService.Login(li); + error = await Service.Login(li); } else { @@ -70,7 +73,7 @@ { data = (EmailData)result.Data; LoginInformation li = new(data.Email, null, GrantType.OTP); - error = await DBService.Login(li); + error = await Service.Login(li); } } diff --git a/DexieNETCloudSample/Pages/ToDoListPage.razor b/DexieNETCloudSample/Pages/ToDoListPage.razor index 73857a0..350d04b 100644 --- a/DexieNETCloudSample/Pages/ToDoListPage.razor +++ b/DexieNETCloudSample/Pages/ToDoListPage.razor @@ -1,5 +1,3 @@ @page "/" - - - \ No newline at end of file + diff --git a/DexieNETCloudSample/Program.cs b/DexieNETCloudSample/Program.cs index d31b7d0..ba2ff56 100644 --- a/DexieNETCloudSample/Program.cs +++ b/DexieNETCloudSample/Program.cs @@ -20,11 +20,13 @@ }); builder.Services.AddDexieNET(); -builder.Services.AddRxBLService(sp => new DexieCloudService(sp)); -builder.Services.AddRxBLService(sp => new AdministrationService(sp)); -builder.Services.AddRxBLService(sp => new ToDoItemService(sp)); -builder.Services.AddRxBLService(sp => new ToDoListService(sp)); -builder.Services.AddRxBLService(sp => new ToDoListMemberService(sp)); +var collector = builder.Services.AddRxBLServiceCollector(); + +builder.Services.AddRxBLService(collector, sp => new DexieCloudService(sp)); +builder.Services.AddRxBLService(collector, sp => new AdministrationService(sp)); +builder.Services.AddRxBLService(collector, sp => new ToDoItemService(sp)); +builder.Services.AddRxBLService(collector, sp => new ToDoListService(sp)); +builder.Services.AddRxBLService(collector, sp => new ToDoListMemberService(sp)); await builder.LoadConfigurationAsync(); // also adds HttpClient