Skip to content

Commit

Permalink
Dev
Browse files Browse the repository at this point in the history
Ongoing work
  • Loading branch information
Bernhard Straub committed Apr 17, 2024
1 parent d6fbbf2 commit 3d96564
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 190 deletions.
2 changes: 1 addition & 1 deletion DexieNETCloudSample/Components/InviteForm.razor
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<MudTd DataLabel="Invite User"><MudText>@context</MudText></MudTd>
<MudTd DataLabel="Invite" Style="text-align:center">
<MudIconButtonAsyncPRx Color="Color.Info" Icon=@Icons.Material.Filled.PersonAdd
RxCommandAsyncFactory=@(() => Service.InviteUser) Parameter=@context PrepareExecutionAsync=@GetUser />
RxCommandAsyncFactory=@(() => Service.AddMember) Parameter=@context PrepareExecutionAsync=@GetUser />
</MudTd>
</RowTemplate>
</MudTable>
Expand Down
2 changes: 1 addition & 1 deletion DexieNETCloudSample/Components/Share.razor
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{
<MemberForm List=@List />
}
@if (Service.CanAddMember())
@if (Service.DoCanAddMember())
{
<InviteForm />
}
Expand Down
34 changes: 34 additions & 0 deletions DexieNETCloudSample/Components/ToDoDBItemAddOrUpdate.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@inherits RxBLServiceSubscriber<ToDoItemService>

@if (AddMode)
{
<MudFabAsyncRx StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanAdd Class="mr-2" Color="Color.Success" StartIcon="@Icons.Material.Filled.Add" Size="Size.Small" ExecuteAsyncCallback=@ShowAddUpdateDialog />
}
else
{
<MudIconButtonAsyncRx StateCommand=@Service.DBCMDAsync CanChangeCallback=@(() => Service.CanUpdate(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; }

[Inject]
public required IDialogService DialogService { get; init; }

private async Task ShowAddUpdateDialog(IStateCommandAsync _)
{
var parameters = new DialogParameters { ["Item"] = Item };
var dialog = DialogService.Show<AddToDoItem>(AddMode ? "Add ToDo" : "Edit ToDo", parameters);
var result = await dialog.Result;

if (!result.Canceled)
{
var scope = (ToDoItemService.ToDoItemItemInput)result.Data;
await scope.SubmitAsync();
}
}
}
24 changes: 15 additions & 9 deletions DexieNETCloudSample/Components/ToDoItem.razor
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@
</CardHeaderContent>
<CardHeaderActions>
<MudHidden Breakpoint="Breakpoint.SmAndDown">
<MudFabPRx Class="mr-2" Color="Color.Success" StartIcon="@Icons.Material.Filled.Add" Size="Size.Small" StateTransformer=@Scope.AddItem ValueFactoryAsync=@(st => AddOrUpdate(st, null)) />
<MudFabRx Color="Color.Error" StartIcon="@Icons.Material.Filled.AutoDelete" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.Completed)) StateProvider=@Scope.DeleteCompletedItems />
<MudFabRx Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.All)) StateProvider=@Scope.ClearItems />
<ToDoDBItemAddOrUpdate AddMode=@true Item=@null />
<MudFabAsyncRx Color="Color.Error" StartIcon="@Icons.Material.Filled.AutoDelete" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.Completed))
StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanDeleteCompletedItems ExecuteAsyncCallback=@Service.DeleteCompletedItems />
<MudFabAsyncRx Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.All))
StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems />
</MudHidden>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
<MudHidden Breakpoint="Breakpoint.MdAndUp">
<MudContainer Class="ml-n3 mb-8">
<MudFabPRx Class="mr-2" Color="Color.Success" StartIcon="@Icons.Material.Filled.Add" Size="Size.Small" StateTransformer=@Scope.AddItem ValueFactoryAsync=@(st => AddOrUpdate(st, null)) />
<MudFabRx Color="Color.Error" StartIcon="@Icons.Material.Filled.AutoDelete" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.Completed)) StateProvider=@Scope.DeleteCompletedItems />
<MudFabRx Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.All)) StateProvider=@Scope.ClearItems />
<ToDoDBItemAddOrUpdate AddMode=@true Item=@null />
<MudFabAsyncRx Color="Color.Error" StartIcon="@Icons.Material.Filled.AutoDelete" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.Completed))
StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanDeleteCompletedItems ExecuteAsyncCallback=@Service.DeleteCompletedItems />
<MudFabAsyncRx Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.All))
StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanClearItems ExecuteAsyncCallback=@Service.ClearItems />
</MudContainer>
</MudHidden>
<MudTable T="ToDoDBItem" Items=@(Service.ToDoItems) Dense="true">
Expand Down Expand Up @@ -58,13 +62,15 @@
<MudTd DataLabel="ToDo"><MudText Style=@ColorForItem(context)>@context.Text</MudText></MudTd>
<MudTd DataLabel="DueDate"><MudText Style=@ColorForItem(context)>@DateTimeForItem(context)</MudText></MudTd>
<MudTd DataLabel="Completed" Style="text-align:center">
<MudIconButtonPRx Icon=@(context.Completed ? Icons.Material.Filled.CheckBox : Icons.Material.Filled.CheckBoxOutlineBlank) Context=@context StateTransformer=@Scope.ToggledItemCompleted ValueFactoryAsync=@(_ => Task.FromResult(context)) />
<MudIconButtonAsyncRx Icon=@(context.Completed ? Icons.Material.Filled.CheckBox : Icons.Material.Filled.CheckBoxOutlineBlank) StateCommand=@Service.DBCMDAsync
HasProgress=@false CanChangeCallback=@Service.CanToggledItemCompleted(context) ExecuteAsyncCallback=@(Service.ToggledItemCompleted(context)) />
</MudTd>
<MudTd DataLabel="Edit" Style="text-align:center">
<MudIconButtonPRx Color="Color.Info" Icon=@Icons.Material.Filled.Edit Context=@context StateTransformer=@Scope.UpdateItem ValueFactoryAsync=@(st => AddOrUpdate(st, context)) />
<ToDoDBItemAddOrUpdate AddMode=@false Item=@context />
</MudTd>
<MudTd DataLabel="DeleteItem" Style="text-align:center">
<MudIconButtonPRx Color="Color.Error" Icon=@Icons.Material.Filled.Delete Context=@context StateTransformer=@Scope.DeleteItem ValueFactoryAsync=@(st => DeleteItem(st, context)) />
<MudIconButtonAsyncRx Color="Color.Error" Icon=@Icons.Material.Filled.Delete StateCommand=@Service.DBCMDAsync CanChangeCallback=@Service.CanDeleteItem(context)
ConfirmExecutionAsync=@(() => ConfirmDelete(DeleteType.One)) ExecuteAsyncCallback=@(Service.DeleteItem(context)) />
</MudTd>
</RowTemplate>
</MudTable>
Expand Down
41 changes: 1 addition & 40 deletions DexieNETCloudSample/Components/ToDoItem.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using DexieNETCloudSample.Logic;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using RxBlazorLightCore;

namespace DexieNETCloudSample.Components
{
Expand All @@ -12,9 +11,6 @@ public partial class ToDoItem
[CascadingParameter]
public required ToDoItemService Service { get; init; }

[CascadingParameter]
public required ToDoItemService.Scope Scope { get; init; }

[Inject]
public required IDialogService DialogService { get; init; }

Expand All @@ -36,47 +32,12 @@ protected override Task OnParametersSetAsync()

if (Service.CurrentList.Value != List)
{
Service.CurrentList.Transform(List);
Service.CurrentList.Value = List;
}

return base.OnParametersSetAsync();
}

private async Task AddOrUpdate(IStateTransformer<ToDoDBItem> tf, ToDoDBItem? item)
{
ArgumentNullException.ThrowIfNull(Service.CurrentList.Value);

ToDoItemData data = item is null ? new ToDoItemData(string.Empty, DateTime.Now) : new ToDoItemData(item.Text, item.DueDate);

bool canUpdateText = item is null || Service.CanUpdate(item, i => i.Text);
bool canUpdateDueDate = item is null || Service.CanUpdate(item, i => i.DueDate);

var parameters = new DialogParameters { ["Item"] = data, ["CanUpdateText"] = canUpdateText, ["CanUpdateDueDate"] = canUpdateDueDate };
var dialog = DialogService.Show<AddToDoItem>(item is null ? "Add ToDo" : "Edit ToDo", parameters);

var result = await dialog.Result;

if (!result.Canceled)
{
data = (ToDoItemData)result.Data;
item = item is null ?
ToDoItemService.CreateItem(data.Text, data.DueDate, Service.CurrentList.Value) :
ToDoItemService.CreateItem(data.Text, data.DueDate, Service.CurrentList.Value, item);

tf.Transform(item);
}
}

private async Task DeleteItem(IStateTransformer<ToDoDBItem> tf, ToDoDBItem item)
{
var confirmed = await ConfirmDelete(DeleteType.One);

if (confirmed)
{
tf.Transform(item);
}
}

private async Task<bool> ConfirmDelete(DeleteType type)
{
var message = type switch
Expand Down
29 changes: 12 additions & 17 deletions DexieNETCloudSample/Dexie/Services/CrudService.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ await DbService.DB.Transaction(async _ =>

public Func<bool> CanAddItem => () => CanAdd();

protected virtual bool CanAdd()
public virtual bool CanAdd()
{
return (Permissions?.CanAdd()).True();
}
Expand All @@ -43,7 +43,7 @@ await DbService.DB.Transaction(async _ =>

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

protected virtual bool CanUpdate(T? item)
public virtual bool CanUpdate(T? item)
{
return true;
}
Expand Down Expand Up @@ -71,28 +71,23 @@ protected bool CanDelete(T? item)
return item is not null && (Permissions?.CanDelete(item)).True();
}

public Func<IStateCommandAsync, Task> ClearItems(T value)
public Func<IStateCommandAsync, Task> ClearItems => async _ =>
{
ArgumentNullException.ThrowIfNull(DbService.DB);
ArgumentNullException.ThrowIfNull(value.ID);
var itemsToClear = await GetTable().ToArray();
return async _ =>
foreach (var item in itemsToClear)
{
var itemsToClear = await GetTable().ToArray();
ArgumentNullException.ThrowIfNull(item.ID);
foreach (var item in itemsToClear)
await DbService.DB.Transaction(async _ =>
{
ArgumentNullException.ThrowIfNull(item.ID);
await DbService.DB.Transaction(async _ =>
{
await PreDeleteAction(item.ID);
await GetTable().Delete(item.ID);
await PostDeleteAction(item.ID);
});
}
await PreDeleteAction(item.ID);
await GetTable().Delete(item.ID);
await PostDeleteAction(item.ID);
});
};
}
};

public Func<bool> CanClearItems => () => CanClearItemsDo();

Expand Down
2 changes: 1 addition & 1 deletion DexieNETCloudSample/Dexie/Services/CrudService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected override ValueTask ContextReadyAsync()

_dbDisposable = DbService.Subscribe(s =>
{
if (s.StateID == DbService.State.ID && DbService.State.Value is DBState.Cloud)
if (s.ID == DbService.State.ID && DbService.State.Value is DBState.Cloud)
{
InitDB();
}
Expand Down
7 changes: 7 additions & 0 deletions DexieNETCloudSample/Dexie/Services/ToDoItemService.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ public Func<bool> CanToggledItemCompleted(ToDoDBItem? item) => () =>
await _db.ToDoDBItems.BulkDelete(itemsToDelete);
};

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


public Func<bool> CanProvide() => () =>
{
if (Items is not null)
Expand Down
79 changes: 75 additions & 4 deletions DexieNETCloudSample/Dexie/Services/ToDoItemService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,72 @@ namespace DexieNETCloudSample.Dexie.Services
{
public sealed partial class ToDoItemService : CrudService<ToDoDBItem>
{
public sealed partial class ToDoItemItemInput(ToDoItemService service, ToDoDBItem? item)
{
public IState<string> Text { get; } = service.CreateState(item is null ? string.Empty : item.Text);
public IState<DateTime> DueDateDate { get; } = service.CreateState(item is null ? DateTime.Now.Date : item.DueDate.Date);
public IState<TimeSpan> DueDateTime { get; } = service.CreateState(item is null ? DateTime.Now.TimeOfDay : item.DueDate.TimeOfDay);

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));
}
public bool CanSubmit()
{
var dateItem = NoSeconds(item?.DueDate);
var dateNew = NoSeconds(DueDateDate.Value.Date + DueDateTime.Value);

return Text.Value != string.Empty && DueDateDate.Value.Date >= DateTime.Now.Date &&
(Text.Value != item?.Text || dateNew != dateItem);
}

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

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

public static Func<string, StateValidation> ValidateText => v =>
{
return new("Text can not be empty!", v.Length == 0);
};

public static Func<DateTime, StateValidation> ValidateDueDate => v =>
{
return new("DueDate can not be in the past!", v.Date < DateTime.Now.Date);
};

public Func<TimeSpan, StateValidation> ValidateDueDateTime => v =>
{
var dateNowNS = NoSeconds(DateTime.Now);
var dateNew = item is null ? NoSeconds(DueDateDate.Value.Date + v) : dateNowNS;
return new("DueDate can not be in the past!", dateNew < dateNowNS);
};

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

private static DateTime? NoSeconds(DateTime? dateTime)
{
if (dateTime.HasValue)
{
return new(dateTime.Value.Year, dateTime.Value.Month, dateTime.Value.Day, dateTime.Value.Hour,
dateTime.Value.Minute, 0, dateTime.Value.Kind);
}

return null;
}
}

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

Expand All @@ -19,11 +85,16 @@ public ToDoItemService(IServiceProvider serviceProvider) : base(serviceProvider)
CurrentList = this.CreateState((ToDoDBList?)null);
}

public static ToDoDBItem CreateItem(string text, DateTime dueDate, ToDoDBList list, ToDoDBItem? item = null)
public ToDoItemItemInput CreateItemInput(ToDoDBItem? item = null)
{
return ToDoDBItem.Create(text, dueDate, list, item);
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<ToDoDBItem, string> GetTable()
{
ArgumentNullException.ThrowIfNull(_db);
Expand All @@ -37,12 +108,12 @@ protected override LiveQuery<IEnumerable<ToDoDBItem>> InitializeDB(ToDoDB db)
return db.LiveQuery(async () => await GetTable().Where(i => i.ListID).Equal(CurrentList.Value.ID).ToArray());
}

protected override bool CanAdd()
public override bool CanAdd()
{
return (Permissions?.CanAdd(CurrentList.Value)).True();
}

protected override bool CanUpdate(ToDoDBItem? item)
public override bool CanUpdate(ToDoDBItem? item)
{
return CanUpdate(item, i => i.Text) || CanUpdate(item, i => i.DueDate);
}
Expand Down
Loading

0 comments on commit 3d96564

Please sign in to comment.