diff --git a/Readme.md b/Readme.md
index 8eeb2a7..e3d3831 100644
--- a/Readme.md
+++ b/Readme.md
@@ -18,7 +18,7 @@ This is a rewrite of my [New Tab Page project](https://github.com/NeilBrommer/Ne
- [x] Bookmarks
- [ ] Manage bookmark containers
- [x] Create
- - [ ] Delete
+ - [x] Delete
- [ ] Edit
- [ ] Manage bookmark groups
- [x] Create
diff --git a/Start/Client/Components/BookmarkGroup.razor b/Start/Client/Components/BookmarkGroup.razor
index eb4613a..e50c064 100644
--- a/Start/Client/Components/BookmarkGroup.razor
+++ b/Start/Client/Components/BookmarkGroup.razor
@@ -1,6 +1,7 @@
@using System.Drawing
@using Fluxor
@using Start.Client.Store.State
+@using Start.Client.Store.Features.DeleteGroup
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@@ -12,6 +13,14 @@
@this.Group.Title
+
+ @if (this.state.Value.EditMode)
+ {
+
+ }
@@ -72,6 +81,12 @@
}
}
+ protected void OnDeleteGroupClicked()
+ {
+ dispatch.Dispatch(new ShowDeleteGroupFormAction(
+ this.Group.BookmarkGroupId, this.Group.Title));
+ }
+
protected void OnCreateBookmarkClicked()
{
// Placeholder
diff --git a/Start/Client/Components/DeleteGroup.razor b/Start/Client/Components/DeleteGroup.razor
new file mode 100644
index 0000000..50398f4
--- /dev/null
+++ b/Start/Client/Components/DeleteGroup.razor
@@ -0,0 +1,46 @@
+@using Start.Client.Store.Features.DeleteGroup
+@using Fluxor
+
+@inherits Fluxor.Blazor.Web.Components.FluxorComponent
+
+@inject IDispatcher dispatch
+@inject IState state
+
+@{ string title = $"Delete Group \"{this.state.Value.BookmarkGroupTitleToDelete}\""; }
+
+
+
+@code {
+ public void OnDialogClose() {
+ this.dispatch.Dispatch(new HideDeleteGroupFormAction());
+ }
+
+ public void OnConfirmDelete() {
+ this.dispatch.Dispatch(new SubmitDeleteGroupFormAction(
+ this.state.Value.BookmarkGroupIdToDelete));
+ }
+}
diff --git a/Start/Client/Pages/Index.razor b/Start/Client/Pages/Index.razor
index 1a601cf..c13ebbb 100644
--- a/Start/Client/Pages/Index.razor
+++ b/Start/Client/Pages/Index.razor
@@ -79,6 +79,7 @@ else
+
}
diff --git a/Start/Client/Sass/app.scss b/Start/Client/Sass/app.scss
index d048cb0..9d520ed 100644
--- a/Start/Client/Sass/app.scss
+++ b/Start/Client/Sass/app.scss
@@ -170,6 +170,9 @@
.card-title {
margin-top: 0.5em;
+ font-weight: bold;
+ // Keep the delete button from increasing the height of the header
+ line-height: 1.25;
}
.card-body {
diff --git a/Start/Client/Start.Client.csproj b/Start/Client/Start.Client.csproj
index 7a8c2a3..43324b0 100644
--- a/Start/Client/Start.Client.csproj
+++ b/Start/Client/Start.Client.csproj
@@ -129,6 +129,7 @@
+
@@ -145,5 +146,6 @@
+
diff --git a/Start/Client/Store/Features/DeleteContainer/DeleteContainerEffects.cs b/Start/Client/Store/Features/DeleteContainer/DeleteContainerEffects.cs
index 83d56c7..5c1ceaf 100644
--- a/Start/Client/Store/Features/DeleteContainer/DeleteContainerEffects.cs
+++ b/Start/Client/Store/Features/DeleteContainer/DeleteContainerEffects.cs
@@ -4,18 +4,14 @@ using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Start.Client.Store.Features.CurrentContainer;
using Start.Shared.Api;
using System.Net;
-using Start.Client.Store.State;
using Start.Client.Store.Features.ContainersList;
namespace Start.Client.Store.Features.DeleteContainer {
public class DeleteContainerEffects {
public IBookmarkContainersApi BookmarkContainersApi { get; init; }
- public IState RootState { get; set; }
- public DeleteContainerEffects(IBookmarkContainersApi bookmarkContainersApi,
- IState rootState) {
+ public DeleteContainerEffects(IBookmarkContainersApi bookmarkContainersApi) {
this.BookmarkContainersApi = bookmarkContainersApi;
- this.RootState = rootState;
}
[EffectMethod]
diff --git a/Start/Client/Store/Features/DeleteGroup/DeleteGroupActions.cs b/Start/Client/Store/Features/DeleteGroup/DeleteGroupActions.cs
new file mode 100644
index 0000000..8ee2b7d
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteGroup/DeleteGroupActions.cs
@@ -0,0 +1,33 @@
+namespace Start.Client.Store.Features.DeleteGroup {
+ public class ShowDeleteGroupFormAction {
+ public int GroupIdToDelete { get; init; }
+ public string GroupTitleToDelete { get; init; }
+
+ public ShowDeleteGroupFormAction(int groupIdToDelete, string groupTitleToDelete) {
+ this.GroupIdToDelete = groupIdToDelete;
+ this.GroupTitleToDelete = groupTitleToDelete;
+ }
+ }
+
+ public class HideDeleteGroupFormAction { }
+
+ public class FetchDeleteGroupFormAction { }
+
+ public class SubmitDeleteGroupFormAction {
+ public int GroupIdToDelete { get; init; }
+
+ public SubmitDeleteGroupFormAction(int groupIdToDelete) {
+ this.GroupIdToDelete = groupIdToDelete;
+ }
+ }
+
+ public class ReceivedDeleteGroupAction { }
+
+ public class ErrorFetchingDeleteGroupAction {
+ public string ErrorMessage { get; init; }
+
+ public ErrorFetchingDeleteGroupAction(string errorMessage) {
+ this.ErrorMessage = errorMessage;
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteGroup/DeleteGroupEffects.cs b/Start/Client/Store/Features/DeleteGroup/DeleteGroupEffects.cs
new file mode 100644
index 0000000..2b7411b
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteGroup/DeleteGroupEffects.cs
@@ -0,0 +1,49 @@
+using System.Threading.Tasks;
+using Fluxor;
+using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
+using Start.Shared.Api;
+using Start.Client.Store.Features.CurrentContainer;
+
+namespace Start.Client.Store.Features.DeleteGroup {
+ public class DeleteGroupEffects {
+ public IBookmarkGroupsApi BookmarkGroupsApi { get; init; }
+
+ public DeleteGroupEffects(IBookmarkGroupsApi bookmarkGroupsApi) {
+ this.BookmarkGroupsApi = bookmarkGroupsApi;
+ }
+
+ [EffectMethod]
+ public async Task SubmitDeleteGroupForm(SubmitDeleteGroupFormAction action,
+ IDispatcher dispatch) {
+ dispatch.Dispatch(new FetchDeleteGroupFormAction());
+
+ try {
+ System.Net.Http.HttpResponseMessage? apiResonse = await this.BookmarkGroupsApi
+ .DeleteBookmarkGroup(action.GroupIdToDelete);
+
+ if (apiResonse == null) {
+ dispatch.Dispatch(new ErrorFetchingDeleteGroupAction(
+ "Failed to submit request"));
+ return;
+ }
+
+ if (apiResonse.StatusCode == System.Net.HttpStatusCode.NotFound) {
+ dispatch.Dispatch(new ErrorFetchingDeleteGroupAction(
+ "The bookmark group to delete doesn't exist"));
+ return;
+ }
+
+ if (!apiResonse.IsSuccessStatusCode) {
+ dispatch.Dispatch(new ErrorFetchingDeleteGroupAction(
+ "There was an error deleting the bookmark group"));
+ return;
+ }
+
+ dispatch.Dispatch(new RemoveBookmarkGroupAction(action.GroupIdToDelete));
+ dispatch.Dispatch(new ReceivedDeleteGroupAction());
+ } catch (AccessTokenNotAvailableException e) {
+ e.Redirect();
+ }
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteGroup/DeleteGroupFeature.cs b/Start/Client/Store/Features/DeleteGroup/DeleteGroupFeature.cs
new file mode 100644
index 0000000..25ae21b
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteGroup/DeleteGroupFeature.cs
@@ -0,0 +1,11 @@
+using Fluxor;
+
+namespace Start.Client.Store.Features.DeleteGroup {
+ public class DeleteGroupFeature : Feature {
+ public override string GetName() => "Delete Group";
+
+ protected override DeleteGroupState GetInitialState() {
+ return new DeleteGroupState();
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteGroup/DeleteGroupReducers.cs b/Start/Client/Store/Features/DeleteGroup/DeleteGroupReducers.cs
new file mode 100644
index 0000000..b964dfc
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteGroup/DeleteGroupReducers.cs
@@ -0,0 +1,49 @@
+using Fluxor;
+
+namespace Start.Client.Store.Features.DeleteGroup {
+ public static class DeleteGroupReducers {
+ [ReducerMethod]
+ public static DeleteGroupState ShowDeleteGroupForm(DeleteGroupState state,
+ ShowDeleteGroupFormAction action) {
+ return state with {
+ ShowDeleteGroupForm = true,
+ BookmarkGroupIdToDelete = action.GroupIdToDelete,
+ BookmarkGroupTitleToDelete = action.GroupTitleToDelete,
+ IsLoadingDeleteGroup = false,
+ DeleteGroupErrorMessage = null
+ };
+ }
+
+ [ReducerMethod(typeof(HideDeleteGroupFormAction))]
+ public static DeleteGroupState HideDeleteGroupForm(DeleteGroupState state) {
+ return state with {
+ ShowDeleteGroupForm = false
+ };
+ }
+
+ [ReducerMethod(typeof(FetchDeleteGroupFormAction))]
+ public static DeleteGroupState FetchDeleteGroup(DeleteGroupState state) {
+ return state with {
+ IsLoadingDeleteGroup = true,
+ DeleteGroupErrorMessage = null
+ };
+ }
+
+ [ReducerMethod(typeof(ReceivedDeleteGroupAction))]
+ public static DeleteGroupState ReceivedDeleteGroup(DeleteGroupState state) {
+ return state with {
+ IsLoadingDeleteGroup = false,
+ ShowDeleteGroupForm = false
+ };
+ }
+
+ [ReducerMethod]
+ public static DeleteGroupState ErrorFetchingDeleteGroup(DeleteGroupState state,
+ ErrorFetchingDeleteGroupAction action) {
+ return state with {
+ IsLoadingDeleteGroup = false,
+ DeleteGroupErrorMessage = action.ErrorMessage
+ };
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteGroup/DeleteGroupState.cs b/Start/Client/Store/Features/DeleteGroup/DeleteGroupState.cs
new file mode 100644
index 0000000..7dbd809
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteGroup/DeleteGroupState.cs
@@ -0,0 +1,24 @@
+using System;
+namespace Start.Client.Store.Features.DeleteGroup {
+ public record DeleteGroupState {
+ public bool ShowDeleteGroupForm { get; init; }
+ public int BookmarkGroupIdToDelete { get; init; }
+ public string BookmarkGroupTitleToDelete { get; init; }
+ public bool IsLoadingDeleteGroup { get; init; }
+ public string? DeleteGroupErrorMessage { get; init; }
+
+ public DeleteGroupState() {
+ this.BookmarkGroupTitleToDelete = "";
+ }
+
+ public DeleteGroupState(bool showDeleteGroupForm, int bookmarkGroupIdToDelete,
+ string bookmarkTitleToDelete, bool isLoadingDeleteGroup,
+ string? deleteGroupErrorMessage) {
+ this.ShowDeleteGroupForm = showDeleteGroupForm;
+ this.BookmarkGroupIdToDelete = bookmarkGroupIdToDelete;
+ this.BookmarkGroupTitleToDelete = bookmarkTitleToDelete;
+ this.IsLoadingDeleteGroup = isLoadingDeleteGroup;
+ this.DeleteGroupErrorMessage = deleteGroupErrorMessage;
+ }
+ }
+}