Skip to content

Commit

Permalink
Dev
Browse files Browse the repository at this point in the history
First working solution with new Rx library
  • Loading branch information
b-straub committed Apr 19, 2024
1 parent 1976bd5 commit 6d0e4fe
Show file tree
Hide file tree
Showing 17 changed files with 112 additions and 89 deletions.
3 changes: 2 additions & 1 deletion DexieNETCloudSample/Aministration/Administration.razor
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
}
</CardHeaderContent>
<CardHeaderActions>
<MudButtonAsyncRx Color="Color.Primary" Variant="Variant.Filled" StateCommand=@Service.CancellableCommandAsync ExecuteAsyncCallback=@GetUsers CancelText="Cancel Get Users">
<MudButtonAsyncRx Color="Color.Primary" Variant="Variant.Filled" StateCommand=@Service.CancellableCommandAsync
ExecuteAsyncCallback=@GetUsers DeferredNotification=@true CancelText="Cancel Get Users">
Get Users
</MudButtonAsyncRx>
</CardHeaderActions>
Expand Down
2 changes: 2 additions & 0 deletions DexieNETCloudSample/Aministration/Administration.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public partial class Administration
var result = await dialog.Result;
if (!result.Canceled)
{
stateCommandAsync.NotifyChanging();
await Task.Delay(2000, stateCommandAsync.CancellationToken);
await stateCommandAsync.ExecuteAsync(Service.GetUsers((CloudKeyData)result.Data));
}
};
Expand Down
4 changes: 3 additions & 1 deletion DexieNETCloudSample/Components/InvitesForm.razor
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@
<MudTd DataLabel="Accept" Style="text-align:center">
<MudIconButtonRx Color="Color.Success" Icon=@Icons.Material.Outlined.AddCircleOutline
StateCommand=@Service.CommandAsync
CanChangeCallback=@ToDoListService.CanAcceptInvite(context)
ExecuteCallback=@Service.AcceptInvite(context)
ConfirmExecutionAsync=@(async () => await ConfirmInvite(true)) />
</MudTd>
<MudTd DataLabel="Reject" Style="text-align:center">
<MudIconButtonRx Color="Color.Success" Icon=@Icons.Material.Outlined.RemoveCircleOutline
StateCommand=@Service.CommandAsync
CanChangeCallback=@ToDoListService.CanRejectInvite(context)
ExecuteCallback=@Service.RejectInvite(context)
ConfirmExecutionAsync=@(async () => await ConfirmInvite(true)) />
ConfirmExecutionAsync=@(async () => await ConfirmInvite(false)) />
</MudTd>
</RowTemplate>
</MudTable>
Expand Down
4 changes: 3 additions & 1 deletion DexieNETCloudSample/Components/MemberForm.razor
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<MudTh>Role</MudTh>
</HeaderContent>
<RowTemplate>
<MemberRow List=@List Member=@context />
<RxBLStateScope TScope=@ToDoListMemberService.MemberRowScope TService=@ToDoListMemberService ScopeFactory=@Service.CreateRowScope>
<MemberRow List=@List Member=@context />
</RxBLStateScope>
</RowTemplate>
</MudTable>

Expand Down
10 changes: 8 additions & 2 deletions DexieNETCloudSample/Components/MemberRow.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
<MudText>@MemberName(Member)</MudText>
</MudTd>
<MudTd DataLabel="Role">
<MudSelectAsyncRx StateGroupAsync=@Service.MemberRoleSelection InitializeCallback=@Service.GetInitialMemberRole(Member) ChangingAsyncCallback=@Service.MemberRoleChangingAsync(Member)
<MudSelectAsyncRx StateGroupAsync=@Scope.MemberRoleSelection InitializeCallback=@Scope.GetInitialMemberRole(Member)
CanChangeCallback=@(Scope.CanChangeMemberRole(Member)) ChangingAsyncCallback=@Scope.MemberRoleChangingAsync(Member)
HideDisabled=@true Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter" />
</MudTd>
<MudTd>
<MudFabAsyncRx Color=@(_currentMemberAction is MemberAction.ACCEPT ? Color.Success : Color.Error)
StartIcon=@GetMemberActionIcon() Size="Size.Small" StateCommand=@Service.CommandAsync ConfirmExecutionAsync=@ConfirmChangeMemberStateAsync ExecuteAsyncCallback=@Service.ChangeMemberState(Member) />
StartIcon=@GetMemberActionIcon() Size="Size.Small" StateCommand=@Service.CommandAsync
CanChangeCallback=@Service.CanChangeMemberState(Member)
ConfirmExecutionAsync=@ConfirmChangeMemberStateAsync ExecuteAsyncCallback=@Service.ChangeMemberState(Member) />
@if (_isOwnList && _currentMemberAction is not MemberAction.OWNER)
{
<MudIcon Class="ml-4" Color=@(_currentMemberState is MemberState.ACCEPTED ? Color.Success : Color.Error) Icon=@GetMemberStateIcon() />
Expand All @@ -30,6 +33,9 @@
[Parameter, EditorRequired]
public required Member Member { get; init; }

[CascadingParameter]
public required ToDoListMemberService.MemberRowScope Scope { get; set; }

private MemberAction _currentMemberAction = MemberAction.NONE;
private MemberState _currentMemberState = MemberState.NONE;
private bool _isOwnList = false;
Expand Down
4 changes: 2 additions & 2 deletions DexieNETCloudSample/Components/ToDoDBItemAddOrUpdate.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
}
else
{
<MudIconButtonAsyncRx StateCommand=@Service.CommandAsync CanChangeCallback=@(() => Service.CanUpdate(Item)) Color="Color.Info" Icon=@Icons.Material.Filled.Edit ExecuteAsyncCallback=@ShowAddUpdateDialog />
<MudIconButtonAsyncRx StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanUpdateItem(Item) Color="Color.Info" Icon=@Icons.Material.Filled.Edit ExecuteAsyncCallback=@ShowAddUpdateDialog />
}

@code {
[Parameter, EditorRequired]
public required bool AddMode { get; init; }

[Parameter, EditorRequired]
public required ToDoDBItem? Item { get; init; }
public required ToDoDBItem Item { get; init; }

[Inject]
public required IDialogService DialogService { get; init; }
Expand Down
2 changes: 1 addition & 1 deletion DexieNETCloudSample/Components/ToDoList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
</MudTd>
<MudTd DataLabel="Edit" Style="text-align:center">
<MudIconButtonAsyncRx Color="Color.Info" Icon=@Icons.Material.Filled.Edit
StateCommand=@Service.CommandAsync ExecuteAsyncCallback=@AddOrUpdate(context) />
StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanUpdateItem(context) ExecuteAsyncCallback=@AddOrUpdate(context) />
</MudTd>
<MudTd DataLabel="DeleteItem" Style="text-align:center">
<MudIconButtonAsyncRx Color="Color.Error" Icon=@Icons.Material.Filled.Delete StateCommand=@Service.CommandAsync CanChangeCallback=@Service.CanDeleteItem(context)
Expand Down
10 changes: 0 additions & 10 deletions DexieNETCloudSample/Components/ToDoList.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,5 @@ private async Task<bool> ConfirmDelete(DeleteType type)

return true;
}

private Func<IStateCommandAsync, Task> DeleteList(ToDoDBList list) => async commandAsync =>
{
var confirmed = await ConfirmDelete(DeleteType.One);

if (confirmed)
{
await commandAsync.ExecuteAsync(Service.DeleteItem(list));
}
};
}
}
4 changes: 2 additions & 2 deletions DexieNETCloudSample/Dexie/Services/CrudService.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ await DbService.DB.Transaction(async _ =>

public Func<bool> CanUpdateItem(T value) => () => CanUpdate(value);

public virtual bool CanUpdate(T? item)
protected virtual bool CanUpdate(T? value)
{
return true;
}
Expand Down Expand Up @@ -93,7 +93,7 @@ await DbService.DB.Transaction(async _ =>

private bool CanClearItemsDo()
{
return Items.Any(CanDelete);
return ItemsState.Value.Any(CanDelete);
}
}
}
12 changes: 6 additions & 6 deletions DexieNETCloudSample/Dexie/Services/CrudService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace DexieNETCloudSample.Dexie.Services
{
public abstract partial class CrudService<T> : RxBLService, IDisposable where T : IIDPrimaryIndex, IDBStore, IDBCloudEntity
{
public IEnumerable<T> Items { get; private set; }
public IState<IEnumerable<T>> ItemsState { get; }
public bool IsDBOpen => DbService.DB is not null;

// Transformers
Expand All @@ -23,7 +23,8 @@ public abstract partial class CrudService<T> : RxBLService, IDisposable where T

public CrudService(IServiceProvider serviceProvider)
{
Items = [];
ItemsState = this.CreateState(Enumerable.Empty<T>());

DbService = serviceProvider.GetRequiredService<DexieCloudService>();
}

Expand All @@ -46,9 +47,9 @@ protected override ValueTask ContextReadyAsync()
}


public bool CanUpdate<Q>(T? item, Expression<Func<T, Q>> query)
public bool CanUpdate<Q>(IDBCloudEntity? entity, Expression<Func<T, Q>> query)
{
return item is not null && (Permissions?.CanUpdate(item, query)).True();
return entity is not null && (Permissions?.CanUpdate(entity, query)).True();
}

public void Dispose()
Expand Down Expand Up @@ -89,8 +90,7 @@ private void InitDB()
#if DEBUG
Console.WriteLine($"CRUD new items: {l.Aggregate(string.Empty, (p, n) => p += n.ToString())}");
#endif
Items = l;
StateHasChanged();
ItemsState.Value = l;
}));

Permissions = GetTable().CreateUsePermissions();
Expand Down
6 changes: 3 additions & 3 deletions DexieNETCloudSample/Dexie/Services/ToDoItemService.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ public Func<bool> CanToggledItemCompleted(ToDoDBItem? item) => () =>

public Func<bool> CanDeleteCompletedItems => () =>
{
var item = Items.Where(i => i.Completed).FirstOrDefault();
var item = ItemsState.Value.Where(i => i.Completed).FirstOrDefault();
return CanDelete(item);
};


public Func<bool> CanProvide() => () =>
{
if (Items is not null)
if (ItemsState is not null)
{
var item = Items.Where(i => i.Completed).FirstOrDefault();
var item = ItemsState.Value.Where(i => i.Completed).FirstOrDefault();
return CanDelete(item);
}

Expand Down
19 changes: 13 additions & 6 deletions DexieNETCloudSample/Dexie/Services/ToDoItemService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ 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.CommandAsync.ExecuteAsync(service.AddItem(newItem));
if (item is null)
{
await service.CommandAsync.ExecuteAsync(service.AddItem(newItem));
}
else
{
await service.CommandAsync.ExecuteAsync(service.UpdateItem(newItem));
}
}
public bool CanSubmit()
{
Expand All @@ -32,12 +39,12 @@ public bool CanSubmit()

public Func<string, bool> CanUpdateText => _ =>
{
return service.CanUpdate(item, i => i.Text);
return service.CanUpdate(service.CurrentList.Value, i => i.Text);
};

public Func<DateTime, bool> CanUpdateDueDate => _ =>
{
return service.CanUpdate(item, i => i.DueDate);
return service.CanUpdate(service.CurrentList.Value, i => i.DueDate);
};

public static Func<string, StateValidation> ValidateText => v =>
Expand All @@ -60,7 +67,7 @@ public bool CanSubmit()

public Func<TimeSpan, bool> CanUpdateTime => _ =>
{
return service.CanUpdate(item, i => i.DueDate);
return service.CanUpdate(service.CurrentList.Value, i => i.DueDate);
};

private static DateTime? NoSeconds(DateTime? dateTime)
Expand All @@ -75,7 +82,7 @@ public bool CanSubmit()
}
}

public IEnumerable<ToDoDBItem> ToDoItems => Items ?? [];
public IEnumerable<ToDoDBItem> ToDoItems => ItemsState.Value;
public IState<ToDoDBList?> CurrentList { get; }

private ToDoDB? _db;
Expand Down Expand Up @@ -108,7 +115,7 @@ public override bool CanAdd()
return (Permissions?.CanAdd(CurrentList.Value)).True();
}

public override bool CanUpdate(ToDoDBItem? item)
protected override bool CanUpdate(ToDoDBItem? item)
{
return CanUpdate(item, i => i.Text) || CanUpdate(item, i => i.DueDate);
}
Expand Down
96 changes: 51 additions & 45 deletions DexieNETCloudSample/Dexie/Services/ToDoListMemberService.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@ namespace DexieNETCloudSample.Dexie.Services
{
public partial class ToDoListMemberService
{
public class MemberRowScope(ToDoListMemberService service) : RxBLStateScope<ToDoListMemberService>(service)
{
private static readonly MemberRoleSelection[] _roleSelections =
[
new(MemberRole.OWNER),
new(MemberRole.ADMIN),
new(MemberRole.USER),
new(MemberRole.GUEST),
];

public IStateGroupAsync<MemberRoleSelection> MemberRoleSelection =
service.CreateStateGroupAsync(_roleSelections);

public Func<MemberRoleSelection> GetInitialMemberRole(Member? member) => () =>
{
ArgumentNullException.ThrowIfNull(member);
var role = Service.GetMemberRole(member);

MemberRoleSelection? initialSelection = null;

foreach (var roleSelection in _roleSelections)
{
var displayName = Service.GetRoleDisplayName(roleSelection.Role);
roleSelection.RoleName = displayName;
if (roleSelection.Role == role)
{
initialSelection = roleSelection;
}
}

ArgumentNullException.ThrowIfNull(initialSelection);
return initialSelection;
};

public Func<MemberRoleSelection, MemberRoleSelection, Task> MemberRoleChangingAsync(Member member) => async (or, nr) =>
{
await Service.ChangeAccess(member, or.Role, nr.Role);
};

public Func<bool> CanChangeMemberRole(Member member) => () =>
{
return Service.CanUpdateRole(member);
};

public bool IsMemberRoleDisabled(Member member, int index)
{
var role = _roleSelections[index].Role;
return !Service.CanChangeToRole(member, role);
}
}

public Func<bool> CanSetList(ToDoDBList? list) => () =>
{
return list is not null && list != List.Value;
Expand Down Expand Up @@ -50,50 +101,5 @@ public Func<bool> CanChangeMemberState(Member? member) => () =>
_ => false
};
};

private static readonly MemberRoleSelection[] _roleSelections =
[
new(MemberRole.OWNER),
new(MemberRole.ADMIN),
new(MemberRole.USER),
new(MemberRole.GUEST),
];

public Func<MemberRoleSelection> GetInitialMemberRole(Member? member) => () =>
{
ArgumentNullException.ThrowIfNull(member);
var role = GetMemberRole(member);

MemberRoleSelection? initialSelection = null;

foreach (var roleSelection in _roleSelections)
{
var displayName = GetRoleDisplayName(roleSelection.Role);
roleSelection.RoleName = displayName;
if (roleSelection.Role == role)
{
initialSelection = roleSelection;
}
}

ArgumentNullException.ThrowIfNull(initialSelection);
return initialSelection;
};

public Func<MemberRoleSelection, MemberRoleSelection, Task> MemberRoleChangingAsync(Member member) => async (or, nr) =>
{
await ChangeAccess(member, or.Role, nr.Role);
};

public Func<bool> CanChangeMemberRole(Member member) => () =>
{
return CanUpdateRole(member);
};

public bool IsMemberRoleDisabled(Member member, int index)
{
var role = _roleSelections[index].Role;
return !CanChangeToRole(member, role);
}
}
}
Loading

0 comments on commit 6d0e4fe

Please sign in to comment.