Iceshrimp.NET/Iceshrimp.Backend/Pages/Queue.cshtml

207 lines
No EOL
7 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@page "/queue/{queue?}/{pagination:int?}/{status?}"
@inject QueueService QueueSvc
@using Iceshrimp.Backend.Core.Database.Tables
@using Iceshrimp.Backend.Core.Extensions
@using Iceshrimp.Backend.Core.Services
@model QueueModel
@{
ViewData["title"] = $"Queue dashboard - {Model.InstanceName}";
}
@section head {
<link rel="stylesheet" href="~/css/queue.css"/>
}
@section scripts {
<script src="~/js/queue.js"></script>
@if (Model.Queue == null)
{
<script src="~/js/queue-index.js"></script>
}
}
<h1>Queue Dashboard</h1>
<button role="link" data-target="/queue" onclick="navigate(event)">overview</button>
@foreach (var queue in QueueSvc.QueueNames)
{
<button role="link" data-target="/queue/@queue" onclick="navigate(event)">@queue</button>
}
<br/>
@if (Model.Queue == null)
{
<p>Please pick a queue.</p>
<form onsubmit="return lookupJob(event)">
<input type="text" id="lookup" placeholder="Lookup job by id" minlength="36" maxlength="36" class="inline"/>
<button type="submit">Submit</button>
</form>
<h3>Queue status &mdash; <span id="update-status" class="status-delayed">Connecting...</span></h3>
<table class="auto-table" id="queue-status">
<thead>
<th>Name</th>
@foreach (var status in Enum.GetValues<Job.JobStatus>())
{
<th class="justify-right">@Enum.GetName(status)</th>
}
</thead>
<tbody>
@foreach (var queue in Model.QueueStatuses ?? throw new Exception("Model.QueueStatuses must not be null here"))
{
<tr>
<td>@queue.Name</td>
@foreach (var status in Enum.GetValues<Job.JobStatus>())
{
<td class="status-@Enum.GetName(status)!.ToLowerInvariant() justify-right">@queue.JobCounts[status]</td>
}
</tr>
}
</tbody>
</table>
<h3>Recent jobs</h3>
<table class="auto-table" id="recent-jobs">
<thead>
<th class="width0">ID</th>
<th>Queue</th>
<th>Status</th>
<th>Actions</th>
</thead>
<tbody>
@foreach (var job in Model.Jobs)
{
await RenderJob(job, true);
}
</tbody>
</table>
var last = Model.Jobs.FirstOrDefault();
var lastUpdated = last != null ? new DateTimeOffset(last.LastUpdatedAt).ToUnixTimeMilliseconds() : 0;
<div class="display-none" id="last-updated">@lastUpdated</div>
}
else
{
if (Model.Filter == null)
{
<p>Listing @Model.TotalCount <b>@Model.Queue</b> jobs, out of which <span class="status-running">@Model.RunningCount</span> are <span class="status-running">running</span>, <span class="status-queued">@Model.QueuedCount</span> are <span class="status-queued">queued</span> and <span class="status-delayed">@Model.DelayedCount</span> are <span class="status-delayed">delayed</span>.</p>
}
else
{
<p>Listing @Model.TotalCount <span class="status-@Model.Filter.Value.ToString().ToLowerInvariant()">@Model.Filter.Value.ToString().ToLowerInvariant()</span> <b>@Model.Queue</b> jobs.</p>
}
<table class="auto-table">
<thead>
<th class="width0">ID</th>
<th>Status</th>
<th>Actions</th>
</thead>
<tbody>
@foreach (var job in Model.Jobs)
{
await RenderJob(job);
}
</tbody>
</table>
<div class="flex">
@if (Model.PrevPage != null)
{
if (Model.Filter.HasValue)
{
<button role="link" data-target="/queue/@Model.Queue/@Model.PrevPage/@Model.Filter.Value.ToString().ToLowerInvariant()" onclick="navigate"> Previous page</button>
}
else
{
<button role="link" data-target="/queue/@Model.Queue/@Model.PrevPage" onclick="navigate(event)"> Previous page</button>
}
}
else
{
<button disabled> Previous page</button>
}
@if (Model.NextPage != null)
{
if (Model.Filter.HasValue)
{
<button role="link" data-target="/queue/@Model.Queue/@Model.NextPage/@Model.Filter.Value.ToString().ToLowerInvariant()" onclick="navigate(event)">Next page </button>
}
else
{
<button role="link" data-target="/queue/@Model.Queue/@Model.NextPage" onclick="navigate(event)">Next page </button>
}
}
else
{
<button disabled>Next page </button>
}
<select onchange="filter('@Model.Queue')" id="filter" class="inline-flex">
@if (Model.Filter == null)
{
<option value="all" selected>All</option>
}
else
{
<option value="all">All</option>
}
@foreach (var status in Enum.GetValues<Job.JobStatus>())
{
if (Model.Filter.Equals(status))
{
<option value="@status.ToString().ToLowerInvariant()" selected>@status.ToString()</option>
}
else
{
<option value="@status.ToString().ToLowerInvariant()">@status.ToString()</option>
}
}
</select>
<form onsubmit="return lookupJob(event)" class="inline-flex flex-grow">
<input type="text" id="lookup" placeholder="Lookup job by id" minlength="36" maxlength="36" class="flex-grow"/>
</form>
</div>
}
@{
async Task RenderJob(Job job, bool withQueue = false)
{
var id = job.Id.ToStringLower();
var additional = job.Status switch
{
Job.JobStatus.Queued => $"for {job.QueueDuration.ToDurationDisplayString()}",
Job.JobStatus.Running => $"for {job.Duration.ToDurationDisplayString()}",
Job.JobStatus.Delayed => $"until {job.DelayedUntil?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
Job.JobStatus.Completed => $"at {job.FinishedAt?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
Job.JobStatus.Failed => $"at {job.FinishedAt?.ToLocalTime().ToDisplayStringTz() ?? "<unknown>"}",
_ => throw new ArgumentOutOfRangeException()
};
var classes = Model.Last != null && new DateTimeOffset(job.LastUpdatedAt).ToUnixTimeMilliseconds() > Model.Last
? "new-item"
: "";
<tr class="@classes">
@if (withQueue)
{
<td class="uuid-abbrev">@id[..8]...@id[24..]</td>
<td>@job.Queue</td>
}
else
{
<td class="uuid">@id</td>
}
<td class="status-@job.Status.ToString().ToLowerInvariant()">
<b>@job.Status</b> <small>@additional</small>
<td>
<a href="/queue/job/@id">View details</a>
</td>
</tr>
}
}