{% extends "base.html" %} {% import "repo_tabs.html" as m %} {% block title %}Proposal #{{ p.number }} {{ p.title }} · {{ repo.owner }}/{{ repo.name }}{% endblock %} {% block bodyattrs %} data-repo="{{ repo.url }}"{% endblock %} {% block tabs %}{% call m::tabs(repo, "proposals") %}{% endblock %} {% block mainclass %}{% if tab != "conversation" %} class="wide"{% endif %}{% endblock %} {% block content %} {% include "repo_backdrop.html" %}

{{ p.title }}{% if can_edit %} {% endif %} proposal #{{ p.number }} {{ p.state }} {{ p.author }} wants {{ source_label }} into {{ p.target }} · {{ changes.len()|plural("change", "changes") }} · opened

{% if !closes.is_empty() %}

{% for c in closes %}issue #{{ c.number }} {{ c.title }} {{ c.state }}{% if !loop.last %} + {% endif %}{% endfor %} → proposal #{{ p.number }} {{ p.state }} → {{ p.target }}{% if p.state == "landed" %} landed{% endif %}

{% endif %} {% if let Some(n) = notice %}

{{ n }}

{% endif %} {% if let Some(e) = error %}

{{ e }}

{% endif %} {% if conflicted %}
Landing would carry {{ conflicts.len()|plural("conflict", "conflicts") }}. Any collaborator can push a resolution change to the source; the proposal follows it. See them
{% endif %} {% if landed_already && p.state != "landed" %}
Every change is already in {{ p.target }}.
{% endif %}
conversation ({{ comments.len() + reviews.len() }}) changes ({{ changes.len() }}) files ({{ files.len() }}) projected state {{ state_hash|short }} · {{ heads.len()|plural("head", "heads") }} · browse · json
{% if tab == "changes" %} {% if changes.is_empty() %}

Nothing to add: the target already has everything.

{% endif %} {% for c in changes %}{% call m::change_row(repo, c) %}{% endfor %} {% else if tab == "files" %} {% if !conflicts.is_empty() %}

Conflicts the landing would carry

{% for c in conflicts %}

{{ c.path }} {{ c.kind }}

{% if let Some(t) = c.marked %}
{{ t }}
{% endif %}{% endfor %}
{% endif %} {% if !files.is_empty() %}{% call m::diff_bar(ignore_ws, "tab=files&") %}{% endif %} {% for f in files %}
{{ f.kind }} {{ f.path }} +{{ f.added }} −{{ f.removed }} {% if f.lines.is_empty() %}

No line changes.

{% else %} {% for l in f.lines %} {% if let Some(n) = l.new_no %}{% if let Some(idxs) = placed.get(&crate::web::proposals::key(&f.path, n)) %} {% endif %}{% endif %} {% endfor %}
{% if let Some(n) = l.old_no %}{{ n }}{% endif %} {% if let Some(n) = l.new_no %}{{ n }}{% endif %} {{ l.kind.sign() }} {% call m::line_text(l) %}{% if let Some(n) = l.new_no %}{% if shell.user.is_some() && p.is_open() %}
+
{% endif %}{% endif %}
{% for i in idxs %}{% let c = comments[*i] %}
{{ c.row.author }} {% if c.row.resolved %} resolved{% endif %} {% if shell.user.is_some() %}
{% endif %}
{{ c.body_html|safe }}
{% endfor %}
{% endif %}
{% endfor %} {% if !outdated.is_empty() %}

Comments on lines that are gone

{% for i in outdated %}{% let c = comments[*i] %}
{{ c.row.author }} on {{ c.row.path }}
{{ c.body_html|safe }}
{% endfor %}
{% endif %} {% else %}
{{ p.author }} opened this proposal
{% if p.body.is_empty() %}

No description.

{% else %}
{{ body_html|safe }}
{% endif %}
{% if can_edit %}
{% if draft.is_some() %}

Drafted by an assistant; nothing is saved until you update the proposal.

{% endif %}
Cancel {% for a in assistants %} {% endfor %}
{% endif %}
{% for t in timeline %} {% if t.kind == "comment" %}{% let c = comments[t.index] %}
{{ c.row.author }}{% if !c.row.via.is_empty() %} agent {{ c.row.via }}{% endif %} commented
{{ c.body_html|safe }}
{% else if t.kind == "review" %}{% let r = reviews[t.index] %}
{{ r.row.author }}{% if !r.row.via.is_empty() %} agent {{ r.row.via }}{% endif %} {% if r.row.verdict == "approve" %}{% if r.sealed %}◈ approved and sealed{% else %}○ approved, seal pending{% endif %}{% else if r.row.verdict == "changes" %}✘ requested changes{% else %}reviewed{% endif %}
{% if !r.row.body.is_empty() %}
{{ r.body_html|safe }}
{% endif %}
{% else %}{% let e = events[t.index] %}

{{ e.actor }} {{ e.event }}{% if e.event.ends_with("by change") && !e.detail.is_empty() %}{% let hash = e.detail.split(' ').next().unwrap_or("") %} {{ hash }}{{ e.detail[hash.len()..] }}{% else if !e.detail.is_empty() %}: {{ e.detail|state_label }}{% endif %}

{% endif %} {% endfor %} {% if p.state == "landed" %}
Proposal landed

{% if !p.landed_by.is_empty() %}{{ p.landed_by }} landed{% else %}Landed{% endif %} {{ changes.len()|plural("change", "changes") }} into {{ p.target }}{% if p.landed_ms > 0 %} {% endif %}.{% if let Some(b) = deletable_source %} The {{ b }} bookmark can be safely deleted.{% endif %}

{% if let Some(b) = deletable_source %}
{% endif %}
{% else if p.state == "closed" %}
Proposal closed

It was not landed{% if can_edit %}; reopen it below to carry on{% endif %}.

{% endif %} {% for a in pending %}

{{ a }} is answering… this updates by itself

{% endfor %}
{% if let Some(me) = shell.user %} {% if can_edit && (p.state == "draft" || p.is_open() || p.state == "closed") %}{% endif %}

Add a comment

{% if can_edit %} {% if p.state == "draft" %}{% endif %} {% if p.state == "open" %}{% endif %} {% if p.is_open() %}{% endif %} {% if p.state == "closed" %}{% endif %} {% endif %}
{% if p.is_open() %}

Review this proposal

An approval counts once you seal the changes from a client: oxy seal --proposal {{ shell.base_url }}{{ repo.url }}/proposal/{{ p.number }}

{% endif %} {% endif %}
{% endif %}
{% endblock %}