From 9f761bc44b9ce45c4f0725a94639f6c9940e5e18 Mon Sep 17 00:00:00 2001 From: Christiaan Bloemendaal Date: Tue, 2 Jan 2024 11:15:09 +0100 Subject: [PATCH] feat(frontend): tasks view --- src/Mangarr.Frontend/Api/BackendApi.cs | 13 ++++++- src/Mangarr.Frontend/Mangarr.Frontend.csproj | 1 + .../Pages/Settings/Tasks/Queue.razor | 33 ++++++++++++++++ .../Pages/Settings/Tasks/Queue.razor.cs | 39 +++++++++++++++++++ .../Pages/Settings/Tasks/QueueItem.razor | 34 ++++++++++++++++ .../Pages/Settings/Tasks/Schedule.razor | 34 ++++++++++++++++ .../Pages/Settings/Tasks/Schedule.razor.cs | 37 ++++++++++++++++++ .../Pages/Settings/Tasks/ScheduleItem.razor | 39 +++++++++++++++++++ .../Settings/Tasks/ScheduleItem.razor.cs | 24 ++++++++++++ .../Pages/Settings/Tasks/Tasks.razor | 6 +++ .../Shared/NavigationLayout.razor | 7 ++++ 11 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor.cs create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/QueueItem.razor create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor.cs create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor.cs create mode 100644 src/Mangarr.Frontend/Pages/Settings/Tasks/Tasks.razor diff --git a/src/Mangarr.Frontend/Api/BackendApi.cs b/src/Mangarr.Frontend/Api/BackendApi.cs index 367af48..832db4a 100644 --- a/src/Mangarr.Frontend/Api/BackendApi.cs +++ b/src/Mangarr.Frontend/Api/BackendApi.cs @@ -45,7 +45,7 @@ public Task> RequestManga( bool newChaptersOnly ) => _httpClient.Post("manga/request", - new MangaRequestRequest() + new MangaRequestRequest { SearchId = searchId, ProviderId = providerIdentifier, @@ -55,7 +55,16 @@ bool newChaptersOnly public Task DeleteManga(string id, bool deleteChaptersFromDisk) => _httpClient.Post($"manga/{id}/delete", - new MangaDeleteRequest() { Id = id, DeleteChaptersFromDisk = deleteChaptersFromDisk }); + new MangaDeleteRequest { Id = id, DeleteChaptersFromDisk = deleteChaptersFromDisk }); public Task> RefreshManga(string id) => _httpClient.Get($"manga/{id}/refresh"); + + public Task> GetJobQueue() => + _httpClient.Get("jobs/queue"); + + public Task> GetJobSchedule() => + _httpClient.Get("jobs/schedule"); + + public Task> TriggerJob(string group, string name) => + _httpClient.Get($"jobs/{group}/{name}/trigger"); } diff --git a/src/Mangarr.Frontend/Mangarr.Frontend.csproj b/src/Mangarr.Frontend/Mangarr.Frontend.csproj index 7e342e3..548d7a5 100644 --- a/src/Mangarr.Frontend/Mangarr.Frontend.csproj +++ b/src/Mangarr.Frontend/Mangarr.Frontend.csproj @@ -25,6 +25,7 @@ + diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor b/src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor new file mode 100644 index 0000000..b693047 --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor @@ -0,0 +1,33 @@ +@using Mangarr.Shared.Models +
+

Queue

+ + @if (_isRefreshing) + { + + } + else if (_items.Count == 0) + { +

The queue is empty at the moment

+ } + else + { +
+ + + + + + + + + + @foreach (JobQueueItemModel item in _items) + { + + } + +
DescriptionLast runNext run
+
+ } +
diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor.cs b/src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor.cs new file mode 100644 index 0000000..21be8d7 --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/Queue.razor.cs @@ -0,0 +1,39 @@ +using FluentResults; +using Mangarr.Frontend.Api; +using Mangarr.Shared.Models; +using Mangarr.Shared.Responses; +using Microsoft.AspNetCore.Components; + +namespace Mangarr.Frontend.Pages.Settings.Tasks; + +public partial class Queue +{ + private readonly List _items = new(); + + private bool _isRefreshing = false; + + [Inject] public BackendApi BackendApi { get; set; } + + protected override void OnInitialized() => RefreshAsync(); + + private async void RefreshAsync() + { + _isRefreshing = true; + await InvokeAsync(StateHasChanged); + + Result result = await BackendApi.GetJobQueue(); + + if (result.IsFailed) + { + // TODO: Log error + } + else + { + _items.Clear(); + _items.AddRange(result.Value.Data); + } + + _isRefreshing = false; + await InvokeAsync(StateHasChanged); + } +} diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/QueueItem.razor b/src/Mangarr.Frontend/Pages/Settings/Tasks/QueueItem.razor new file mode 100644 index 0000000..df5428f --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/QueueItem.razor @@ -0,0 +1,34 @@ +@using Humanizer +@using Mangarr.Shared.Models + +@code { + [Parameter] public JobQueueItemModel Item { get; set; } +} + + + + @Item.Description + + + @if (Item.PreviousFireTime.HasValue) + { + TimeSpan timeSinceLastRun = DateTimeOffset.UtcNow - Item.PreviousFireTime.Value; + @timeSinceLastRun.Humanize() ago + } + else + { + - + } + + + @if (Item.NextFireTime.HasValue) + { + TimeSpan timeUntilNextRun = Item.NextFireTime.Value - DateTimeOffset.UtcNow; + in @timeUntilNextRun.Humanize() + } + else + { + - + } + + diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor b/src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor new file mode 100644 index 0000000..3087787 --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor @@ -0,0 +1,34 @@ +@using Mangarr.Shared.Models +
+

Schedule

+ + @if (_isRefreshing) + { + + } + else if (_items.Count == 0) + { +

The queue is empty at the moment

+ } + else + { +
+ + + + + + + + + + + @foreach (JobScheduleItemModel item in _items) + { + + } + +
DescriptionLast runNext runRequest run
+
+ } +
diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor.cs b/src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor.cs new file mode 100644 index 0000000..da021af --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/Schedule.razor.cs @@ -0,0 +1,37 @@ +using FluentResults; +using Mangarr.Frontend.Api; +using Mangarr.Shared.Models; +using Mangarr.Shared.Responses; +using Microsoft.AspNetCore.Components; + +namespace Mangarr.Frontend.Pages.Settings.Tasks; + +public partial class Schedule +{ + private readonly List _items = new(); + private bool _isRefreshing; + [Inject] public BackendApi BackendApi { get; set; } + + protected override void OnInitialized() => RefreshAsync(); + + private async void RefreshAsync() + { + _isRefreshing = true; + await InvokeAsync(StateHasChanged); + + Result result = await BackendApi.GetJobSchedule(); + + if (result.IsFailed) + { + // TODO: Log error + } + else + { + _items.Clear(); + _items.AddRange(result.Value.Data); + } + + _isRefreshing = false; + await InvokeAsync(StateHasChanged); + } +} diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor b/src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor new file mode 100644 index 0000000..63ad63a --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor @@ -0,0 +1,39 @@ +@using Humanizer + + + @Item.Description + + + @if (Item.PreviousFireTime.HasValue) + { + TimeSpan timeSinceLastRun = DateTimeOffset.UtcNow - Item.PreviousFireTime.Value; + @timeSinceLastRun.Humanize() ago + } + else + { + - + } + + + @if (Item.NextFireTime.HasValue) + { + TimeSpan timeUntilNextRun = Item.NextFireTime.Value - DateTimeOffset.UtcNow; + in @timeUntilNextRun.Humanize() + } + else + { + - + } + + + @if (_isRequesting) + { + + } + else + { + + } + + + diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor.cs b/src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor.cs new file mode 100644 index 0000000..e07d532 --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/ScheduleItem.razor.cs @@ -0,0 +1,24 @@ +using Mangarr.Frontend.Api; +using Mangarr.Shared.Models; +using Microsoft.AspNetCore.Components; + +namespace Mangarr.Frontend.Pages.Settings.Tasks; + +public partial class ScheduleItem +{ + private bool _isRequesting; + [Parameter] public JobScheduleItemModel Item { get; set; } + + [Inject] public BackendApi BackendApi { get; set; } + + private async void RequestClicked() + { + _isRequesting = true; + await InvokeAsync(StateHasChanged); + + await BackendApi.TriggerJob(Item.Group, Item.Name); + + _isRequesting = true; + await InvokeAsync(StateHasChanged); + } +} diff --git a/src/Mangarr.Frontend/Pages/Settings/Tasks/Tasks.razor b/src/Mangarr.Frontend/Pages/Settings/Tasks/Tasks.razor new file mode 100644 index 0000000..a3dffb5 --- /dev/null +++ b/src/Mangarr.Frontend/Pages/Settings/Tasks/Tasks.razor @@ -0,0 +1,6 @@ +@page "/settings/tasks" + +
+ + +
diff --git a/src/Mangarr.Frontend/Shared/NavigationLayout.razor b/src/Mangarr.Frontend/Shared/NavigationLayout.razor index 2d78366..6caf692 100644 --- a/src/Mangarr.Frontend/Shared/NavigationLayout.razor +++ b/src/Mangarr.Frontend/Shared/NavigationLayout.razor @@ -39,6 +39,13 @@ General + + + + + + Tasks +