Skip to content

Commit 115c268

Browse files
committed
Add elapsed time in pending status
1 parent cbc8276 commit 115c268

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;
@@ -70,3 +72,18 @@ pub struct QueueTemplate {
7072
#[derive(Template)]
7173
#[template(path = "not_found.html")]
7274
pub struct NotFoundTemplate {}
75+
76+
pub fn get_pending_build(pr: &PullRequestModel) -> Option<&BuildModel> {
77+
if let Some(auto_build) = &pr.auto_build
78+
&& auto_build.status == BuildStatus::Pending
79+
{
80+
return Some(auto_build);
81+
}
82+
83+
if let Some(try_build) = &pr.try_build
84+
&& try_build.status == BuildStatus::Pending
85+
{
86+
return Some(try_build);
87+
}
88+
None
89+
}

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%;
@@ -34,6 +50,30 @@
3450
td.select-checkbox {
3551
width: 2.5rem;
3652
}
53+
table.dataTable > tbody > tr > td.status {
54+
position: relative;
55+
overflow: hidden;
56+
padding-left: 16px;
57+
white-space: nowrap;
58+
}
59+
td.status:before {
60+
content: " ";
61+
position: absolute;
62+
display: block;
63+
left: 6px;
64+
width: 6px;
65+
top: 0;
66+
bottom: 0;
67+
}
68+
td.status[data-status="pending"]:before {
69+
/* Give the pending state a little bit of animation to make it
70+
clear that these items are the ones that are being tested
71+
right now. */
72+
bottom: -20px;
73+
background-color: #F0DE57;
74+
background-image: repeating-linear-gradient(135deg, #F0DE57 0, #F0DE57 4px, #FBEE97 4px, #FBEE97 8px, #F0DE57 0);
75+
animation: barber-pole 1s linear infinite;
76+
}
3777

3878
#rollupModal {
3979
display: none;
@@ -114,12 +154,18 @@ <h1>
114154
<td data-pr-number="{{ pr.number.0 }}">
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 %}
@@ -364,5 +410,28 @@ <h1>
364410

365411
window.location.href = oauthUrl.toString();
366412
});
413+
414+
function formatElapsedTime(ms) {
415+
const minutes = Math.floor(ms / 60000);
416+
if (minutes > 0) {
417+
return ` (${minutes}m)`;
418+
}
419+
return '';
420+
}
421+
422+
function updateElapsedTimes() {
423+
const now = Date.now();
424+
document.querySelectorAll('[data-created-at]').forEach(td => {
425+
const createdAtMs = parseInt(td.getAttribute('data-created-at'), 10);
426+
if (createdAtMs > 0) {
427+
const elapsedMs = now - createdAtMs;
428+
const formattedTime = formatElapsedTime(elapsedMs);
429+
let display = td.querySelector('.elapsed-time-display');
430+
display.textContent = formattedTime;
431+
}
432+
});
433+
}
434+
435+
updateElapsedTimes();
367436
</script>
368437
{% endblock %}

0 commit comments

Comments
 (0)