| 1 |
{% extends "base.html" %} |
| 2 |
{% import "repo_tabs.html" as m %} |
| 3 |
{% block title %}{{ report.title }} · Reports · {{ repo.owner }}/{{ repo.name }}{% endblock %} |
| 4 |
{% block tabs %}{% call m::tabs(repo, "reports") %}{% endblock %} |
| 5 |
{% block content %} |
| 6 |
<section class="cov-hero"> |
| 7 |
<div class="cov-hero-head"> |
| 8 |
<div> |
| 9 |
<div class="small"><a href="{{ repo.url }}/reports">Reports</a> /</div> |
| 10 |
<h1>{{ report.title }} <span class="tag rep-kind rep-{{ report.kind }}">{{ report.kind }}</span></h1> |
| 11 |
<div class="cov-sub">{% if bookmarks.len() > 1 %}<form class="inline" method="get" action="{{ repo.url }}/reports/{{ report.name }}"><label for="rep-bm" class="mute">bookmark</label> <select id="rep-bm" name="bookmark" onchange="this.form.submit()">{% for b in bookmarks %}<option value="{{ b }}"{% if b.as_str() == report.bookmark.as_str() %} selected{% endif %}>{{ b }}</option>{% endfor %}</select> <noscript><button>Show</button></noscript></form>{% else %}<span class="mute">on</span> <strong>{{ report.bookmark }}</strong>{% endif %} |
| 12 |
{% if let Some(n) = report.run_number %}· <a href="{{ repo.url }}/flow/{{ n }}">run #{{ n }}</a>{% endif %} · job {{ report.job }} · <time title="{{ report.created_ms|when_i }}">{{ report.created_ms|ago_i }}</time> · {{ report.files }} files, {{ report.bytes|bytes }} · <a href="{{ files_base }}/report.toml" target="_blank" rel="noopener">report.toml</a></div> |
| 13 |
{% if !report.summary.is_empty() %}<p class="rep-summary">{{ report.summary }}</p>{% endif %} |
| 14 |
</div> |
| 15 |
</div> |
| 16 |
</section> |
| 17 |
|
| 18 |
{% if timeline.len() > 1 %} |
| 19 |
<section class="rep-timeline" data-timeline{% if let Some(p) = play %} data-play="{{ p }}"{% endif %}> |
| 20 |
<div class="rep-tl-bar"> |
| 21 |
<button type="button" class="rep-tl-btn" data-tl-play aria-label="{% if play.is_some() %}Stop playing{% else %}Play through the runs{% endif %}">{% if play.is_some() %}■ Stop{% else %}▶ Play{% endif %}</button> |
| 22 |
<label class="small mute">every <select data-tl-speed aria-label="Seconds per run">{% for s in [1u32, 2, 3, 5, 10] %}<option value="{{ s }}"{% if play.unwrap_or(2) == *s %} selected{% endif %}>{{ s }} s</option>{% endfor %}</select></label> |
| 23 |
<form class="inline small" method="get" action="{{ repo.url }}/reports/{{ report.name }}"> |
| 24 |
<input type="hidden" name="id" value="{{ report.id }}"> |
| 25 |
<label class="mute">compare with <select name="compare" onchange="this.form.submit()" aria-label="Run to compare with"><option value="">none</option>{% for t in timeline %}{% if !t.current %}<option value="{{ t.id }}"{% if t.compared %} selected{% endif %}>{{ t.label }}</option>{% endif %}{% endfor %}</select></label> |
| 26 |
<noscript><button>Compare</button></noscript> |
| 27 |
</form> |
| 28 |
<span class="small mute rep-tl-keys">← → step through runs</span> |
| 29 |
</div> |
| 30 |
<ol class="rep-tl-stops"> |
| 31 |
{% for t in timeline %}<li><a href="{{ t.href }}" class="rep-tl-stop{% if t.current %} on{% endif %}{% if t.compared %} cmp{% endif %}" title="{{ t.tip }}"{% if t.current %} aria-current="true"{% endif %} data-tl-stop><span class="sr">{{ t.label }}</span></a></li>{% endfor %} |
| 32 |
</ol> |
| 33 |
<div class="rep-tl-ends small mute"><span>{% if let Some(f) = timeline.first() %}{{ f.label }}{% endif %}</span><span>{% if let Some(l) = timeline.last() %}{{ l.label }}{% endif %}</span></div> |
| 34 |
</section> |
| 35 |
{% endif %} |
| 36 |
|
| 37 |
{% if let Some((other, rows, _)) = compare %} |
| 38 |
<section class="panel"> |
| 39 |
<h2 class="rep-cmp-h">This run against {% if let Some(n) = other.run_number %}run #{{ n }}{% else %}an upload{% endif %} <a class="small" href="{{ repo.url }}/reports/{{ report.name }}?id={{ report.id }}">stop comparing</a></h2> |
| 40 |
<table class="rep-table"> |
| 41 |
<thead><tr><th>Metric</th><th class="num">{% if let Some(n) = report.run_number %}run #{{ n }}{% else %}this{% endif %}</th><th class="num">{% if let Some(n) = other.run_number %}run #{{ n }}{% else %}that{% endif %}</th><th class="num">Difference</th></tr></thead> |
| 42 |
<tbody> |
| 43 |
{% for c in rows %} |
| 44 |
<tr><td><code>{{ c.key }}</code></td><td class="num"><strong>{{ c.here }}</strong>{% if !c.unit.is_empty() %} <small class="mute">{{ c.unit }}</small>{% endif %}</td><td class="num">{{ c.there }}</td><td class="num">{% if !c.delta.is_empty() %}<span class="rep-delta {{ c.trend }}">{{ c.delta }}</span>{% else %}<span class="mute">–</span>{% endif %}</td></tr> |
| 45 |
{% endfor %} |
| 46 |
</tbody> |
| 47 |
</table> |
| 48 |
</section> |
| 49 |
{% endif %} |
| 50 |
|
| 51 |
{% if !metrics.is_empty() && compare.is_none() %} |
| 52 |
<section class="panel"> |
| 53 |
<table class="rep-table"> |
| 54 |
<thead><tr><th>Metric</th><th class="num">Value</th><th class="num">Change</th><th>Across runs</th><th>Threshold</th></tr></thead> |
| 55 |
<tbody> |
| 56 |
{% for v in metrics %} |
| 57 |
<tr class="{% if v.failing %}rep-failing{% endif %}"> |
| 58 |
<td><code>{{ v.key }}</code></td> |
| 59 |
<td class="num"><strong>{{ v.value }}</strong>{% if !v.unit.is_empty() %} <small class="mute">{{ v.unit }}</small>{% endif %}</td> |
| 60 |
<td class="num">{% if !v.delta.is_empty() %}<span class="rep-delta {{ v.trend }}">{{ v.delta }}</span>{% else %}<span class="mute">–</span>{% endif %}</td> |
| 61 |
<td>{{ v.spark|safe }}</td> |
| 62 |
<td class="small">{% if v.failing %}<span class="error">{{ v.threshold }}: failing</span>{% else %}<span class="mute">{{ v.threshold }}</span>{% endif %}</td> |
| 63 |
</tr> |
| 64 |
{% endfor %} |
| 65 |
</tbody> |
| 66 |
</table> |
| 67 |
</section> |
| 68 |
{% endif %} |
| 69 |
|
| 70 |
{% if let Some(src) = frame %} |
| 71 |
<section class="rep-frame-wrap{% if let Some((_, _, Some(_))) = compare %} rep-side{% endif %}"> |
| 72 |
<iframe class="rep-frame" src="{{ src }}" sandbox="allow-scripts" referrerpolicy="no-referrer" loading="lazy" title="{{ report.title }}" data-report-runs="{{ runs_json }}" data-report-current="{{ report.id }}"></iframe> |
| 73 |
{% if let Some((other, _, Some(osrc))) = compare %}<iframe class="rep-frame" src="{{ osrc }}" sandbox="allow-scripts" referrerpolicy="no-referrer" loading="lazy" title="{{ report.title }}, {% if let Some(n) = other.run_number %}run #{{ n }}{% else %}upload{% endif %}" data-report-runs="{{ runs_json }}" data-report-current="{{ other.id }}"></iframe>{% endif %} |
| 74 |
<p class="small mute">The report's own page, in a sandbox: its scripts run with no access to your session or this hub. <a href="{{ src }}" target="_blank" rel="noopener">Open it alone</a>.</p> |
| 75 |
</section> |
| 76 |
{% endif %} |
| 77 |
|
| 78 |
<div class="cov-grid"> |
| 79 |
{% if !context.is_empty() %} |
| 80 |
<section class="panel cov-card"> |
| 81 |
<h2>Context</h2> |
| 82 |
<dl class="rep-context">{% for (k, v) in context %}<dt>{{ k }}</dt><dd>{{ v }}</dd>{% endfor %}</dl> |
| 83 |
</section> |
| 84 |
{% endif %} |
| 85 |
<section class="panel cov-card"> |
| 86 |
<h2>Runs on {{ report.bookmark }}</h2> |
| 87 |
<ul class="rep-runs"> |
| 88 |
{% for r in runs.iter().take(15) %} |
| 89 |
<li{% if r.id == report.id %} class="on"{% endif %}><a href="{{ repo.url }}/reports/{{ report.name }}?id={{ r.id }}">{% if let Some(n) = r.run_number %}run #{{ n }}{% else %}upload{% endif %}</a> <span class="mute small"><time title="{{ r.created_ms|when_i }}">{{ r.created_ms|ago_i }}</time>{% if !r.summary.is_empty() %} · {{ r.summary }}{% endif %}</span></li> |
| 90 |
{% endfor %} |
| 91 |
</ul> |
| 92 |
</section> |
| 93 |
</div> |
| 94 |
{% endblock %} |