| 1 |
{% extends "base.html" %} |
| 2 |
{% import "repo_tabs.html" as m %} |
| 3 |
{% block title %}Issue #{{ i.number }} {{ i.title }} · {{ repo.owner }}/{{ repo.name }}{% endblock %} |
| 4 |
{% block bodyattrs %} data-repo="{{ repo.url }}"{% endblock %} |
| 5 |
{% block tabs %}{% call m::tabs(repo, "issues") %}{% endblock %} |
| 6 |
{% block content %} |
| 7 |
<div class="head"><h1>{{ i.title }} <small class="px kind-issue">issue #{{ i.number }}</small> |
| 8 |
<small><span class="tag{% if i.state == "closed" %} bad{% else %} head{% endif %}">{{ i.state }}{% if !i.reason.is_empty() %}: {{ i.reason.replace("_", " ") }}{% endif %}</span> {{ i.author }} opened this <time title="{{ i.created_ms|when_i }}">{{ i.created_ms|ago_i }}</time> · {{ comments.len()|plural("comment", "comments") }}{% if i.locked %} · <span class="tag">locked</span>{% endif %}</small> |
| 9 |
</h1></div> |
| 10 |
{% if !closed_by.is_empty() %}<p class="chain" aria-label="The chain of work"><span class="chain-link kind-issue st-{{ i.state }}"><span class="chain-kind">issue #{{ i.number }}</span> <span class="chain-state">{{ i.state }}</span></span> |
| 11 |
<span class="chain-arrow">←</span> closed by {% for c in closed_by %}<a class="chain-link kind-proposal st-{{ c.state }}" href="{{ c.url }}" title="{{ c.title }}"><span class="chain-kind">proposal #{{ c.number }}</span> {{ c.title }} <span class="chain-state">{{ c.state }}</span></a>{% if !loop.last %} <span class="chain-and">·</span> {% endif %}{% endfor %}</p>{% endif %} |
| 12 |
{% if let Some(n) = notice %}<p class="note">{{ n }}</p>{% endif %} |
| 13 |
{% if let Some(e) = error %}<p class="error">{{ e }}</p>{% endif %} |
| 14 |
<div class="side-layout"> |
| 15 |
<div> |
| 16 |
<div class="comment"><span class="who">{{ i.author }}</span> <time class="mute" title="{{ i.created_ms|when_i }}">{{ i.created_ms|ago_i }}</time> |
| 17 |
{% if can_edit %}<details class="inline-edit"><summary class="small">edit</summary><form method="post" action="{{ repo.url }}/issue/{{ i.number }}/edit"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><input type="text" name="title" value="{{ i.title }}"><textarea name="body" rows="6">{{ i.body }}</textarea><button type="submit">SAVE</button></form></details>{% endif %} |
| 18 |
<div class="body">{% if i.body.is_empty() %}<p class="mute">No description.</p>{% else %}{{ body_html|safe }}{% endif %}</div></div> |
| 19 |
{% for item in timeline %} |
| 20 |
{% match item %} |
| 21 |
{% when crate::web::issues::Item::Comment with (c, html) %} |
| 22 |
<div class="comment" id="c{{ c.id }}"><span class="who">{{ c.author }}</span> <time class="mute" title="{{ c.created_ms|when_i }}">{{ c.created_ms|ago_i }}</time>{% if c.edited_ms.is_some() %} <span class="mute small">edited</span>{% endif %} |
| 23 |
{% if let Some(u) = shell.user %}{% if *u == c.author || can_triage %}<form class="tiny" method="post" action="{{ repo.url }}/issue/{{ i.number }}/comment/{{ c.id }}/delete"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><button>delete</button></form>{% endif %}{% endif %} |
| 24 |
<div class="body">{{ html|safe }}</div></div> |
| 25 |
{% when crate::web::issues::Item::Event with (e) %} |
| 26 |
<p class="small mute timeline">{{ e.actor }} {{ e.event }}{% if e.event.ends_with("by change") && !e.detail.is_empty() %}{% let hash = e.detail.split(' ').next().unwrap_or("") %} <a href="{{ repo.url }}/change/{{ hash }}"><code>{{ hash }}</code></a>{{ e.detail[hash.len()..] }}{% else if !e.detail.is_empty() %} {{ e.detail }}{% endif %} · <time title="{{ e.at_ms|when_i }}">{{ e.at_ms|ago_i }}</time></p> |
| 27 |
{% endmatch %} |
| 28 |
{% endfor %} |
| 29 |
{% if shell.user.is_some() && (!i.locked || can_triage) %} |
| 30 |
<form class="card wide" method="post" action="{{ repo.url }}/issue/{{ i.number }}/comment"> |
| 31 |
<input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 32 |
<label for="body">Comment (Markdown)</label><textarea id="body" name="body" class="md" rows="5" required></textarea> |
| 33 |
<div class="choice"> |
| 34 |
<button type="submit">COMMENT</button> |
| 35 |
{% if i.state == "open" %}<button type="submit" name="close" value="completed">COMMENT AND CLOSE</button>{% else %}<button type="submit" name="reopen" value="1">COMMENT AND REOPEN</button>{% endif %} |
| 36 |
</div> |
| 37 |
</form> |
| 38 |
{% else if i.locked %}<p class="empty">This issue is locked.</p>{% endif %} |
| 39 |
</div> |
| 40 |
<aside class="side"> |
| 41 |
{% if shell.user.is_some() %} |
| 42 |
<h3>Subscription</h3> |
| 43 |
<form method="post" action="{{ repo.url }}/issue/{{ i.number }}/subscribe"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><button type="submit" class="small">{% if subscribed %}UNSUBSCRIBE{% else %}SUBSCRIBE{% endif %}</button></form> |
| 44 |
{% endif %} |
| 45 |
<h3>Labels</h3> |
| 46 |
{% if labels.is_empty() %}<p class="mute small">None.</p>{% else %}<p>{% for l in labels %}<span class="label" style="--c: {{ l.colour }}" title="{{ l.description }}">{{ l.name }}</span> {% endfor %}</p>{% endif %} |
| 47 |
{% if can_triage && !all_labels.is_empty() %} |
| 48 |
<form class="tiny-form" method="post" action="{{ repo.url }}/issue/{{ i.number }}/labels"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 49 |
{% for l in all_labels %}<label class="small"><input type="checkbox" name="label" value="{{ l.id }}"{% if labels.contains(l) %} checked{% endif %}> {{ l.name }}</label> {% endfor %} |
| 50 |
<button type="submit" class="small">SET</button></form> |
| 51 |
{% endif %} |
| 52 |
<h3>Assignees</h3> |
| 53 |
{% if assignees.is_empty() %}<p class="mute small">Nobody.</p>{% else %}<ul class="plain">{% for a in assignees %}<li><a href="/{{ a }}">{{ a }}</a></li>{% endfor %}</ul>{% endif %} |
| 54 |
{% if can_triage %}<form class="tiny-form" method="post" action="{{ repo.url }}/issue/{{ i.number }}/assign"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><input type="text" name="username" placeholder="username" size="12"> <button type="submit" name="action" value="add" class="small">ADD</button> <button type="submit" name="action" value="remove" class="small">REMOVE</button></form>{% endif %} |
| 55 |
<h3>Milestone</h3> |
| 56 |
{% if let Some(ms) = milestone %}<p><a href="{{ repo.url }}/milestones">{{ ms.title }}</a></p>{% else %}<p class="mute small">None.</p>{% endif %} |
| 57 |
{% if can_triage && !milestones.is_empty() %}<form class="tiny-form" method="post" action="{{ repo.url }}/issue/{{ i.number }}/milestone"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><select name="milestone"><option value="">none</option>{% for (ms, sel) in milestones %}<option value="{{ ms.id }}"{% if *sel %} selected{% endif %}>{{ ms.title }}</option>{% endfor %}</select> <button type="submit" class="small">SET</button></form>{% endif %} |
| 58 |
<h3>Projects</h3> |
| 59 |
{% if projects.is_empty() %}<p class="mute small">None.</p>{% else %}<ul class="plain small">{% for (pr, col) in projects %}<li><a href="/projects/{{ pr.owner }}/{{ pr.number }}">{{ pr.title }}</a> <span class="mute">· {{ col }}</span>{% if project_choices.is_some() %}<form class="tiny" method="post" action="{{ repo.url }}/issue/{{ i.number }}/project"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><input type="hidden" name="project" value="{{ pr.number }}"><button name="action" value="remove" class="linkish" title="Take it off this project">remove</button></form>{% endif %}</li>{% endfor %}</ul>{% endif %} |
| 60 |
{% if let Some(choices) = project_choices %}{% if choices.is_empty() %}{% if projects.is_empty() %}<p class="small mute"><a href="/projects/{{ repo.owner }}">{{ repo.owner }}'s projects</a></p>{% endif %}{% else %}<form class="side-picker-inline" method="post" action="{{ repo.url }}/issue/{{ i.number }}/project"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"><select name="project" aria-label="Project">{% for pr in choices %}<option value="{{ pr.number }}">{{ pr.title }}</option>{% endfor %}</select> <button name="action" value="add" class="small">Add</button></form>{% endif %}{% endif %} |
| 61 |
{% if can_triage %} |
| 62 |
<h3>Moderation</h3> |
| 63 |
<form class="tiny-form" method="post" action="{{ repo.url }}/issue/{{ i.number }}/state"><input type="hidden" name="_csrf" value="{{ shell.csrf }}"> |
| 64 |
<div class="choice"> |
| 65 |
{% if i.state == "open" %}<button type="submit" name="action" value="close" class="small">CLOSE</button><button type="submit" name="action" value="not_planned" class="small">NOT PLANNED</button>{% else %}<button type="submit" name="action" value="reopen" class="small">REOPEN</button>{% endif %} |
| 66 |
<button type="submit" name="action" value="{% if i.locked %}unlock{% else %}lock{% endif %}" class="small">{% if i.locked %}UNLOCK{% else %}LOCK{% endif %}</button> |
| 67 |
<button type="submit" name="action" value="{% if i.pinned %}unpin{% else %}pin{% endif %}" class="small">{% if i.pinned %}UNPIN{% else %}PIN{% endif %}</button> |
| 68 |
</div></form> |
| 69 |
{% endif %} |
| 70 |
</aside> |
| 71 |
</div> |
| 72 |
{% endblock %} |