Skip to content

Commit 3b08b91

Browse files
committed
Add elapsed time in pending status
1 parent a007de5 commit 3b08b91

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

src/templates.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::database::{MergeableState::*, PullRequestModel, QueueStatus, TreeState};
1+
use crate::database::{
2+
BuildModel, BuildStatus, MergeableState::*, PullRequestModel, QueueStatus, TreeState,
3+
};
24
use askama::Template;
35
use axum::response::{Html, IntoResponse, Response};
46
use http::StatusCode;
@@ -68,3 +70,18 @@ pub struct QueueTemplate {
6870
#[derive(Template)]
6971
#[template(path = "not_found.html")]
7072
pub struct NotFoundTemplate {}
73+
74+
pub fn get_pending_build(pr: &PullRequestModel) -> Option<&BuildModel> {
75+
if let Some(auto_build) = &pr.auto_build
76+
&& auto_build.status == BuildStatus::Pending
77+
{
78+
return Some(auto_build);
79+
}
80+
81+
if let Some(try_build) = &pr.try_build
82+
&& try_build.status == BuildStatus::Pending
83+
{
84+
return Some(try_build);
85+
}
86+
None
87+
}

templates/queue.html

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@
66
<link rel="stylesheet" href="https://cdn.datatables.net/2.3.4/css/dataTables.dataTables.min.css" />
77
<link rel="stylesheet" href="https://cdn.datatables.net/rowgroup/1.5.1/css/rowGroup.dataTables.min.css" />
88
<style>
9+
@keyframes barber-pole {
10+
/* This animation is used to make the status indicator next to
11+
pending pulls look like a barber poll. We do that with a
12+
diagonal linear gradient. CSS does not allow us to animate a
13+
gradient, so instead we make the indicator a little taller
14+
than shown, and then animate the whole thing upward. */
15+
from{
16+
transform: translate(0, 0);
17+
}
18+
to {
19+
/* The magic number 11.314 is sqrt(8^2 + 8^2), based on how
20+
far vertically it takes to repeat a 45 degree gradient
21+
that is 8 pixels long before it repeats. */
22+
transform: translate(0, -11.314px);
23+
}
24+
}
925
main {
1026
max-width: 100rem;
1127
width: 100%;
@@ -31,6 +47,30 @@
3147
td.select-checkbox {
3248
width: 2.5rem;
3349
}
50+
table.dataTable > tbody > tr > td.status {
51+
position: relative;
52+
overflow: hidden;
53+
padding-left: 16px;
54+
white-space: nowrap;
55+
}
56+
td.status:before {
57+
content: " ";
58+
position: absolute;
59+
display: block;
60+
left: 6px;
61+
width: 6px;
62+
top: 0;
63+
bottom: 0;
64+
}
65+
td.status[data-status="pending"]:before {
66+
/* Give the pending state a little bit of animation to make it
67+
clear that these items are the ones that are being tested
68+
right now. */
69+
bottom: -20px;
70+
background-color: #F0DE57;
71+
background-image: repeating-linear-gradient(135deg, #F0DE57 0, #F0DE57 4px, #FBEE97 4px, #FBEE97 8px, #F0DE57 0);
72+
animation: barber-pole 1s linear infinite;
73+
}
3474

3575
#rollupModal {
3676
display: none;
@@ -114,12 +154,18 @@ <h1>
114154
<td>
115155
<a href="{{ repo_url }}/pull/{{ pr.number }}">{{ pr.number.0 }}</a>
116156
</td>
117-
<td data-status="{{ crate::templates::status_text(pr) }}">
157+
{% let pending_build = crate::templates::get_pending_build(pr) %}
158+
<td class="status" data-status="{{ crate::templates::status_text(pr) }}"
159+
data-created-at="{% if let Some(build) = pending_build %}
160+
{{ build.created_at.timestamp_millis() }}
161+
{% endif %}">
162+
118163
{% if let Some(try_build) = pr.try_build %}
119164
<a href="../results/{{ repo_name }}/{{ pr.number }}">{{ crate::templates::status_text(pr) }}</a> (try)
120165
{% else %}
121166
{{ crate::templates::status_text(pr) }}
122167
{% endif %}
168+
<span class="elapsed-time-display"></span>
123169
</td>
124170
<td>
125171
{% match pr.mergeable_state %}
@@ -340,5 +386,28 @@ <h1>
340386
modalMessage.innerHTML = message;
341387
modal.style.display = "block";
342388
});
389+
390+
function formatElapsedTime(ms) {
391+
const minutes = Math.floor(ms / 60000);
392+
if (minutes > 0) {
393+
return ` (${minutes}m)`;
394+
}
395+
return '';
396+
}
397+
398+
function updateElapsedTimes() {
399+
const now = Date.now();
400+
document.querySelectorAll('[data-created-at]').forEach(td => {
401+
const createdAtMs = parseInt(td.getAttribute('data-created-at'), 10);
402+
if (createdAtMs > 0) {
403+
const elapsedMs = now - createdAtMs;
404+
const formattedTime = formatElapsedTime(elapsedMs);
405+
let display = td.querySelector('.elapsed-time-display');
406+
display.textContent = formattedTime;
407+
}
408+
});
409+
}
410+
411+
updateElapsedTimes();
343412
</script>
344413
{% endblock %}

0 commit comments

Comments
 (0)