Add deleting bookmarks

This commit is contained in:
Neil Brommer 2021-12-16 10:46:22 -08:00
parent 07a3245bfc
commit 93888369ce
10 changed files with 266 additions and 5 deletions

View file

@ -1,20 +1,41 @@
<li class="bookmark">
@using Start.Client.Store.State
@using Start.Client.Store.Features.DeleteBookmark
@using Fluxor
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@inject IDispatcher dispatch
@inject IState<RootState> state
<li class="bookmark">
@if (!String.IsNullOrEmpty(this.Model.Notes))
{
<details>
<details class="bookmarkDetails">
<summary>
<a href="@this.Model.Url" class="bookmarkLink">@this.Model.Title</a>
</summary>
@this.Model.Notes
<pre>@this.Model.Notes</pre>
</details>
}
else
{
<a href="@this.Model.Url" class="bookmarkLink">@this.Model.Title</a>
<a href="@this.Model.Url" class="bookmarkLink bookmarkDetails">@this.Model.Title</a>
}
@if (this.state.Value.EditMode)
{
<button class="btn btn-link text-error" @onclick="this.OnDeleteBookmarkClick">
<i class="icon icon-delete"></i>
</button>
}
</li>
@code {
[Parameter]
public BookmarkDto Model { get; set; } = null!;
public void OnDeleteBookmarkClick()
{
this.dispatch.Dispatch(new ShowDeleteBookmarkFormAction(this.Model));
}
}

View file

@ -0,0 +1,75 @@
@using Start.Client.Store.Features.DeleteBookmark
@using Fluxor
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@inject IDispatcher dispatch
@inject IState<DeleteBookmarkState> state
@{ string title = $"Delete Bookmark \"{this.state.Value.BookmarkToDelete?.Title}\""; }
<Dialog Title="@title" Active="this.state.Value.ShowDeleteBookmarkForm" OnClose="this.OnClose">
@if (this.state.Value.DeleteBookmarkErrorMessage != null)
{
<Alert Type="Alert.AlertType.Error">
@this.state.Value.DeleteBookmarkErrorMessage
</Alert>
}
@if (this.state.Value.BookmarkToDelete == null)
{
<Alert Type="Alert.AlertType.Error">
There is no bookmark to delete selected
</Alert>
}
else
{
<p>Are you sure you want to delete this bookmark?</p>
<dl>
<dt>Title</dt>
<dd>@this.state.Value.BookmarkToDelete.Title</dd>
<dt>URL</dt>
<dd>@this.state.Value.BookmarkToDelete.Url</dd>
@if (!string.IsNullOrWhiteSpace(this.state.Value.BookmarkToDelete.Notes))
{
<dt>Notes</dt>
<dd>@this.state.Value.BookmarkToDelete.Notes</dd>
}
</dl>
<div class="text-right">
@if (!this.state.Value.IsLoadingDeleteBookmark)
{
<button type="button" class="btn" @onclick="this.OnClose">Cancel</button>
<button type="submit" class="btn btn-error" @onclick="this.OnConfirmDelete">Delete</button>
}
else
{
<button type="button" disabled class="btn" @onclick="this.OnClose">Cancel</button>
<button type="submit" disabled class="btn btn-error loading" @onclick="this.OnConfirmDelete">Delete</button>
}
</div>
}
</Dialog>
@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));
}
}

View file

@ -75,6 +75,8 @@ else
<BookmarkContainer />
@* Data management forms *@
<CreateContainer />
<DeleteContainer />
@ -82,6 +84,7 @@ else
<DeleteGroup />
<CreateBookmark />
<DeleteBookmark />
</Sidebar>
}

View file

@ -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;

View file

@ -131,6 +131,7 @@
<None Remove="Sass\Spectre\" />
<None Remove="Store\Features\DeleteGroup\" />
<None Remove="Store\Features\CreateBookmark\" />
<None Remove="Store\Features\DeleteBookmark\" />
</ItemGroup>
<ItemGroup>
<Content Remove="wwwroot\css\Spectre\" />
@ -149,5 +150,6 @@
<Folder Include="Sass\Spectre\" />
<Folder Include="Store\Features\DeleteGroup\" />
<Folder Include="Store\Features\CreateBookmark\" />
<Folder Include="Store\Features\DeleteBookmark\" />
</ItemGroup>
</Project>

View file

@ -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;
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -0,0 +1,11 @@
using Fluxor;
namespace Start.Client.Store.Features.DeleteBookmark {
public class DeleteBookmarkFeature : Feature<DeleteBookmarkState> {
public override string GetName() => "Delete Bookmark";
protected override DeleteBookmarkState GetInitialState() {
return new DeleteBookmarkState();
}
}
}

View file

@ -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
};
}
}
}

View file

@ -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;
}
}
}