Port queue page to maud

This commit is contained in:
Joscha 2024-05-12 13:17:38 +02:00
parent b3f8c6390c
commit 5d4232ac6b
6 changed files with 131 additions and 159 deletions

View file

@ -70,3 +70,15 @@ pub fn format_value(value: f64) -> String {
format!("{value:.2}") format!("{value:.2}")
} }
} }
pub fn truncate(text: &str, width: usize) -> String {
let truncate = text.chars().take(width + 1).count() > width;
if truncate {
text.chars()
.take(80 - 3)
.chain("...".chars())
.collect::<String>()
} else {
text.to_string()
}
}

View file

@ -57,17 +57,7 @@ impl LinkCommit {
pub fn html(&self) -> Markup { pub fn html(&self) -> Markup {
let (class, title) = self.class_and_title(); let (class, title) = self.class_and_title();
let short = util::truncate(&self.short, 80);
let truncate = self.short.chars().take(81).count() > 80;
let short = if truncate {
self.short
.chars()
.take(80 - 3)
.chain("...".chars())
.collect::<String>()
} else {
self.short.to_string()
};
html! { html! {
a href=(self.link) .(class) title=(title) { (short) } a href=(self.link) .(class) title=(title) { (short) }
@ -92,6 +82,12 @@ impl LinkRunShort {
short: util::format_commit_short(hash, message), short: util::format_commit_short(hash, message),
} }
} }
pub fn html(&self) -> Markup {
html! {
a href=(self.link) { "Run of " (util::truncate(&self.short, 80)) }
}
}
} }
#[derive(Template)] #[derive(Template)]
@ -133,4 +129,10 @@ impl LinkWorker {
name, name,
} }
} }
pub fn html(&self) -> Markup {
html! {
a href=(self.link) { (self.name) }
}
}
} }

View file

@ -3,13 +3,13 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use askama::Template;
use axum::{ use axum::{
extract::State, extract::State,
http::StatusCode, http::StatusCode,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
}; };
use futures::TryStreamExt; use futures::TryStreamExt;
use maud::{html, Markup};
use sqlx::SqlitePool; use sqlx::SqlitePool;
use crate::{ use crate::{
@ -152,11 +152,71 @@ async fn get_queue_data(
Ok(tasks) Ok(tasks)
} }
#[derive(Template)] fn page_inner(workers: Vec<Worker>, tasks: Vec<Task>) -> Markup {
#[template(path = "pages/queue_inner.html")] html! {
struct PageInner { h2 { "Workers" }
workers: Vec<Worker>, @if workers.is_empty() {
tasks: Vec<Task>, p { "No workers connected" }
} @else {
table .queue-workers {
thead {
tr {
th { "worker" }
th { "status" }
}
}
tbody {
@for worker in workers { tr {
td { (worker.link.html()) }
td { @match worker.status {
Status::Idle => "idle",
Status::Busy => "busy",
Status::Working(link) => (link.html()),
} }
} }
}
}
}
h2 { "Queue (" (tasks.len()) ")" }
form .queue-commits method="post" {
table #queue data-count=(tasks.len()) {
thead {
tr {
th { "commit" }
th { "since" }
th { "priority" }
th { "worker" }
}
}
tbody {
@for task in tasks { tr .odd[task.odd] {
td { (task.commit.html()) }
td {
(task.since) " ["
a href=(task.link_delete) title="Delete from queue" { "del" }
"]"
}
td {
(task.priority) " ["
button .linkish title="Increase priority by 1" formaction=(task.link_increase) name="hash" value=(task.hash) { "inc" }
"/"
button .linkish title="Decrease priority by 1" formaction=(task.link_decrease) name="hash" value=(task.hash) { "dec" }
"]"
td {
@if task.workers.is_empty() {
"-"
}
@for (i, worker) in task.workers.iter().enumerate() {
@if i > 0 { ", " }
(worker.html())
}
}
}
} }
}
}
}
}
} }
pub async fn get_queue_inner( pub async fn get_queue_inner(
@ -169,16 +229,7 @@ pub async fn get_queue_inner(
let sorted_workers = sorted_workers(&workers); let sorted_workers = sorted_workers(&workers);
let workers = get_workers(&db, &sorted_workers, &base).await?; let workers = get_workers(&db, &sorted_workers, &base).await?;
let tasks = get_queue_data(&db, &sorted_workers, &base).await?; let tasks = get_queue_data(&db, &sorted_workers, &base).await?;
Ok(PageInner { workers, tasks }) Ok(page_inner(workers, tasks))
}
#[derive(Template)]
#[template(path = "pages/queue.html")]
struct Page {
link_queue_js: Link,
link_admin_queue_add_batch: Link,
base: Base,
inner: PageInner,
} }
pub async fn get_queue( pub async fn get_queue(
@ -191,23 +242,29 @@ pub async fn get_queue(
let sorted_workers = sorted_workers(&workers); let sorted_workers = sorted_workers(&workers);
let workers = get_workers(&db, &sorted_workers, &base).await?; let workers = get_workers(&db, &sorted_workers, &base).await?;
let tasks = get_queue_data(&db, &sorted_workers, &base).await?; let tasks = get_queue_data(&db, &sorted_workers, &base).await?;
Ok(Page {
link_queue_js: base.link(QUEUE_JS),
link_admin_queue_add_batch: base.link(PathAdminQueueAddBatch {}),
base,
inner: PageInner { workers, tasks },
})
}
#[derive(Template)] Ok(base.html(
#[template(path = "pages/queue_delete.html")] &format!("queue ({})", tasks.len()),
struct PageDelete { html! {
base: Base, script type="module" src=(base.link(QUEUE_JS)) {}
link_delete: Link, },
html! {
short: String, div #inner { (page_inner(workers, tasks)) }
commit: LinkCommit, form method="post" action=(base.link(PathAdminQueueAddBatch {})) {
hash: String, label {
"Batch size: "
input name="amount" type="number" value="10" min="1";
}
" "
label {
"Priority: "
input #priority name="priority" type="number" value="-1" min="-2147483648" max="2147483647";
}
" "
button { "Add batch to queue" }
}
},
))
} }
pub async fn get_queue_delete( pub async fn get_queue_delete(
@ -231,13 +288,22 @@ pub async fn get_queue_delete(
return Ok(StatusCode::NOT_FOUND.into_response()); return Ok(StatusCode::NOT_FOUND.into_response());
}; };
Ok(PageDelete { let commit = LinkCommit::new(&base, r.hash.clone(), &r.message, r.reachable);
short: util::format_commit_short(&r.hash, &r.message),
commit: LinkCommit::new(&base, r.hash.clone(), &r.message, r.reachable),
hash: r.hash,
link_delete: base.link(PathAdminQueueDelete {}), Ok(base
base, .html(
&format!("del {}", util::format_commit_short(&r.hash, &r.message)),
html! {},
html! {
h2 { "Delete commit from queue" }
p { "You are about to delete this commit from the queue:" }
p { (commit.html()) }
p { "All runs of this commit currently in progress will be aborted!" }
form method="post" action=(base.link(PathAdminQueueDelete {})) {
input name="hash" type="hidden" value=(r.hash);
button { "Delete commit and abort runs" }
} }
},
)
.into_response()) .into_response())
} }

View file

@ -1,23 +0,0 @@
{% extends "base.html" %}
{% block title %}queue ({{ inner.tasks.len() }}){% endblock %}
{% block head %}
<script type="module" src="{{ link_queue_js }}"></script>
{% endblock %}
{% block body %}
<div id="inner">{{ inner|safe }}</div>
<form method="post" action="{{ link_admin_queue_add_batch }}">
<label>
Batch size:
<input type="number" name="amount" value="10" min="1">
</label>
<label>
Priority:
<input type="number" id="priority" name="priority" value="-1" min="-2147483648" max="2147483647">
</label>
<button>Add batch to queue</button>
</form>
{% endblock %}

View file

@ -1,18 +0,0 @@
{% extends "base.html" %}
{% block title %}del {{ short }}{% endblock %}
{% block body %}
<h2>Delete commit from queue</h2>
<p>You are about to delete this commit from the queue:</p>
<p>{{ commit|safe }}</p>
<p>All runs of this commit currently in progress will be aborted!</p>
<form method="post" action="{{ link_delete }}">
<input type="hidden" name="hash" value="{{ hash }}">
<button>Delete commit and abort runs</button>
</form>
{% endblock %}

View file

@ -1,67 +0,0 @@
<h2>Workers</h2>
{% if workers.is_empty() %}
<p>No workers connected</p>
{% else %}
<table class="queue-workers">
<thead>
<tr>
<th>worker</th>
<th>status</th>
</tr>
</thead>
<tbody>
{% for worker in workers %}
<tr>
<td>{{ worker.link|safe }}</td>
{% match worker.status %}
{% when Status::Idle %}
<td>idle</td>
{% when Status::Busy %}
<td>busy</td>
{% when Status::Working with (link) %}
<td>{{ link|safe }}</td>
{% endmatch %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<h2>Queue ({{ tasks.len() }})</h2>
<form class="queue-commits" method="post">
<table id="queue" data-count="{{ tasks.len() }}">
<thead>
<tr>
<th>commit</th>
<th>since</th>
<th>priority</th>
<th>worker</th>
</tr>
</thead>
<tbody>
{% for task in tasks %}
<tr {% if task.odd %} class="odd" {% endif %}>
<td>{{ task.commit|safe }}</td>
<td>
{{ task.since }}
[<a href="{{ task.link_delete }}" title="Delete from queue">del</a>]
</td>
<td>
{{ task.priority }}
[<button class="linkish" title="Increase priority by 1" formaction="{{ task.link_increase }}"
name="hash" value="{{ task.hash }}">inc</button>/<button class="linkish"
title="Decrease priority by 1" formaction="{{ task.link_decrease }}" name="hash"
value="{{ task.hash }}">dec</button>]
</td>
{% if task.workers.is_empty() %}
<td>-</td>
{% else %}
<td>{{ task.workers|join(", ")|safe }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</form>