diff --git a/Start/Client/Components/Bookmark.razor b/Start/Client/Components/Bookmark.razor
index e2ae192..9560da2 100644
--- a/Start/Client/Components/Bookmark.razor
+++ b/Start/Client/Components/Bookmark.razor
@@ -1,20 +1,41 @@
-
+@using Start.Client.Store.State
+@using Start.Client.Store.Features.DeleteBookmark
+@using Fluxor
+
+@inherits Fluxor.Blazor.Web.Components.FluxorComponent
+
+@inject IDispatcher dispatch
+@inject IState state
+
+
@if (!String.IsNullOrEmpty(this.Model.Notes))
{
-
+
@this.Model.Title
- @this.Model.Notes
+ @this.Model.Notes
}
else
{
- @this.Model.Title
+ @this.Model.Title
+ }
+
+ @if (this.state.Value.EditMode)
+ {
+
}
@code {
[Parameter]
public BookmarkDto Model { get; set; } = null!;
+
+ public void OnDeleteBookmarkClick()
+ {
+ this.dispatch.Dispatch(new ShowDeleteBookmarkFormAction(this.Model));
+ }
}
diff --git a/Start/Client/Components/DeleteBookmark.razor b/Start/Client/Components/DeleteBookmark.razor
new file mode 100644
index 0000000..20443b8
--- /dev/null
+++ b/Start/Client/Components/DeleteBookmark.razor
@@ -0,0 +1,75 @@
+@using Start.Client.Store.Features.DeleteBookmark
+@using Fluxor
+
+@inherits Fluxor.Blazor.Web.Components.FluxorComponent
+
+@inject IDispatcher dispatch
+@inject IState state
+
+@{ string title = $"Delete Bookmark \"{this.state.Value.BookmarkToDelete?.Title}\""; }
+
+
+
+@code {
+ private void OnClose()
+ {
+ this.dispatch.Dispatch(new HideDeleteBookmarkFormAction());
+ }
+
+ private void OnConfirmDelete()
+ {
+ if (this.state.Value.BookmarkToDelete == null)
+ {
+ dispatch.Dispatch(new ErrorFetchingDeleteBookmarkAction(
+ "No bookmark to delete is selected"));
+ return;
+ }
+
+ this.dispatch.Dispatch(new SubmitDeleteBookmarkFormAction(
+ this.state.Value.BookmarkToDelete.BookmarkId));
+ }
+}
diff --git a/Start/Client/Pages/Index.razor b/Start/Client/Pages/Index.razor
index 227fcd6..96a793e 100644
--- a/Start/Client/Pages/Index.razor
+++ b/Start/Client/Pages/Index.razor
@@ -75,6 +75,8 @@ else
+ @* Data management forms *@
+
@@ -82,6 +84,7 @@ else
+
}
diff --git a/Start/Client/Sass/app.scss b/Start/Client/Sass/app.scss
index 08c1eb0..7538403 100644
--- a/Start/Client/Sass/app.scss
+++ b/Start/Client/Sass/app.scss
@@ -195,8 +195,14 @@ ul.bookmarks {
.bookmark {
margin-top: 0;
+ display: flex;
+ flex-direction: row;
- a {
+ .bookmarkDetails {
+ flex: 1;
+ }
+
+ .bookmarkLink {
display: inline-block;
width: 100%;
padding: 0.5em 0.83em;
diff --git a/Start/Client/Start.Client.csproj b/Start/Client/Start.Client.csproj
index 56ef6d0..125eba0 100644
--- a/Start/Client/Start.Client.csproj
+++ b/Start/Client/Start.Client.csproj
@@ -131,6 +131,7 @@
+
@@ -149,5 +150,6 @@
+
diff --git a/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkActions.cs b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkActions.cs
new file mode 100644
index 0000000..d019efc
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkActions.cs
@@ -0,0 +1,33 @@
+using Start.Shared;
+
+namespace Start.Client.Store.Features.DeleteBookmark {
+ public class ShowDeleteBookmarkFormAction {
+ public BookmarkDto BookmarkToDelete { get; init; }
+
+ public ShowDeleteBookmarkFormAction(BookmarkDto bookmarkToDelete) {
+ this.BookmarkToDelete = bookmarkToDelete;
+ }
+ }
+
+ public class HideDeleteBookmarkFormAction { }
+
+ public class FetchDeleteBookmarkAction { }
+
+ public class RecievedDeleteBookmarkAction { }
+
+ public class ErrorFetchingDeleteBookmarkAction {
+ public string ErrorMessage { get; init; }
+
+ public ErrorFetchingDeleteBookmarkAction(string errorMessage) {
+ this.ErrorMessage = errorMessage;
+ }
+ }
+
+ public class SubmitDeleteBookmarkFormAction {
+ public int BookmarkIdToDelete { get; init; }
+
+ public SubmitDeleteBookmarkFormAction(int bookmarkIdToDelete) {
+ this.BookmarkIdToDelete = bookmarkIdToDelete;
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkEffects.cs b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkEffects.cs
new file mode 100644
index 0000000..682365d
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkEffects.cs
@@ -0,0 +1,50 @@
+using System.Threading.Tasks;
+using Fluxor;
+using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
+using Start.Client.Store.Features.CurrentContainer;
+using Start.Shared.Api;
+
+namespace Start.Client.Store.Features.DeleteBookmark {
+ public class DeleteBookmarkEffects {
+ public IBookmarksApi BookmarksApi { get; init; }
+
+ public DeleteBookmarkEffects(IBookmarksApi bookmarksApi) {
+ this.BookmarksApi = bookmarksApi;
+ }
+
+ [EffectMethod]
+ public async Task SubmitDeleteBookmarkForm(SubmitDeleteBookmarkFormAction action,
+ IDispatcher dispatch) {
+ dispatch.Dispatch(new FetchDeleteBookmarkAction());
+
+ try {
+ System.Net.Http.HttpResponseMessage? apiResponse = await this.BookmarksApi
+ .DeleteBookmark(action.BookmarkIdToDelete);
+
+ if (apiResponse == null) {
+ dispatch.Dispatch(new ErrorFetchingDeleteBookmarkAction(
+ "Failed to make submit request"));
+ return;
+ }
+
+ if (apiResponse.StatusCode == System.Net.HttpStatusCode.NotFound) {
+ dispatch.Dispatch(new ErrorFetchingDeleteBookmarkAction(
+ "The bookmark to delete doesn't exist"));
+ return;
+ }
+
+ if (!apiResponse.IsSuccessStatusCode) {
+ dispatch.Dispatch(new ErrorFetchingDeleteBookmarkAction(
+ "There was an error deleting the bookmark"));
+ return;
+ }
+
+ dispatch.Dispatch(new RemoveBookmarkAction(action.BookmarkIdToDelete));
+ dispatch.Dispatch(new RecievedDeleteBookmarkAction());
+ dispatch.Dispatch(new HideDeleteBookmarkFormAction());
+ } catch (AccessTokenNotAvailableException e) {
+ e.Redirect();
+ }
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkFeature.cs b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkFeature.cs
new file mode 100644
index 0000000..a014cb2
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkFeature.cs
@@ -0,0 +1,11 @@
+using Fluxor;
+
+namespace Start.Client.Store.Features.DeleteBookmark {
+ public class DeleteBookmarkFeature : Feature {
+ public override string GetName() => "Delete Bookmark";
+
+ protected override DeleteBookmarkState GetInitialState() {
+ return new DeleteBookmarkState();
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkReducers.cs b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkReducers.cs
new file mode 100644
index 0000000..bc983fb
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkReducers.cs
@@ -0,0 +1,39 @@
+using Fluxor;
+
+namespace Start.Client.Store.Features.DeleteBookmark {
+ public static class DeleteBookmarkReducers {
+ [ReducerMethod]
+ public static DeleteBookmarkState ShowDeleteBookmarkForm(DeleteBookmarkState state,
+ ShowDeleteBookmarkFormAction action) {
+ return state with {
+ ShowDeleteBookmarkForm = true,
+ BookmarkToDelete = action.BookmarkToDelete,
+ IsLoadingDeleteBookmark = false,
+ DeleteBookmarkErrorMessage = null
+ };
+ }
+
+ [ReducerMethod(typeof(HideDeleteBookmarkFormAction))]
+ public static DeleteBookmarkState HideDeleteBookmarkForm(DeleteBookmarkState state) {
+ return state with {
+ ShowDeleteBookmarkForm = false
+ };
+ }
+
+ [ReducerMethod(typeof(FetchDeleteBookmarkAction))]
+ public static DeleteBookmarkState FetchDeleteBookmark(DeleteBookmarkState state) {
+ return state with {
+ IsLoadingDeleteBookmark = true,
+ DeleteBookmarkErrorMessage = null
+ };
+ }
+
+ [ReducerMethod(typeof(RecievedDeleteBookmarkAction))]
+ public static DeleteBookmarkState RecievedDeleteBookmark(DeleteBookmarkState state) {
+ return state with {
+ IsLoadingDeleteBookmark = false,
+ DeleteBookmarkErrorMessage = null
+ };
+ }
+ }
+}
diff --git a/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkState.cs b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkState.cs
new file mode 100644
index 0000000..e120095
--- /dev/null
+++ b/Start/Client/Store/Features/DeleteBookmark/DeleteBookmarkState.cs
@@ -0,0 +1,21 @@
+using Start.Client.Store.State;
+using Start.Shared;
+
+namespace Start.Client.Store.Features.DeleteBookmark {
+ public record DeleteBookmarkState : RootState {
+ public bool ShowDeleteBookmarkForm { get; init; }
+ public BookmarkDto? BookmarkToDelete { get; init; }
+ public bool IsLoadingDeleteBookmark { get; init; }
+ public string? DeleteBookmarkErrorMessage { get; init; }
+
+ public DeleteBookmarkState() { }
+
+ public DeleteBookmarkState(bool showDeleteBookmarkForm, BookmarkDto bookmarkToDelete,
+ bool isLoadingDeleteBookmark, string? deleteBookmarkErrorMessage) {
+ this.ShowDeleteBookmarkForm = showDeleteBookmarkForm;
+ this.BookmarkToDelete = bookmarkToDelete;
+ this.IsLoadingDeleteBookmark = isLoadingDeleteBookmark;
+ this.DeleteBookmarkErrorMessage = deleteBookmarkErrorMessage;
+ }
+ }
+}