samjeston / openhub Public
Sam Jeston Working vertical 9aa3c45 · History
256 lines· 14.5 KB ·HTML
Raw
1{% extends "layout_repo.html" %}
2{% block page_title %}{{ pr.title }} · Pull request #{{ pr.number }} · {% endblock %}
3{% block content %}
4{% let base = r.base() %}
5{% let purl = r.pull_url(pr.number) %}
6<div class="pull-header">
7 <div class="pull-title-row">
8 <h1 class="pull-title">{{ pr.title }} <span class="text-muted">#{{ pr.number }}</span></h1>
9 {% if can_close %}<button type="button" class="btn btn-sm" data-toggle="edit-pull">Edit</button>{% endif %}
10 </div>
11 {% if can_close %}
12 <form id="edit-pull" class="box box-body form edit-pull" method="post" action="{{ purl }}/edit" hidden>
13 <label class="field"><span class="field-label">Title</span><input class="input" type="text" name="title" value="{{ pr.title }}" maxlength="256" required></label>
14 <label class="field"><span class="field-label">Description</span><textarea class="input" name="body" rows="6">{{ pr.body }}</textarea></label>
15 <div class="form-actions">
16 <button class="btn btn-primary" type="submit">Save</button>
17 <button class="btn" type="button" data-toggle="edit-pull">Cancel</button>
18 </div>
19 </form>
20 {% endif %}
21 <div class="pull-meta">
22 {% if pr.state == "merged" %}
23 <span class="state state-merged">{{ crate::web::fmt::icon("git-merge")|safe }} Merged</span>
24 <span><strong>{{ pr.merged_by.clone().unwrap_or(pr.author.clone()) }}</strong> merged {{ crate::web::fmt::plural(data.commits.len(), "commit") }} into <span class="branch-label">{{ pr.base_branch }}</span> from <span class="branch-label">{{ pr.head_branch }}</span>{% if let Some(t) = pr.merged_at %} <time title="{{ crate::web::fmt::datetime_full(t) }}">{{ crate::web::fmt::ago(t) }}</time>{% endif %}</span>
25 {% else if pr.state == "closed" %}
26 <span class="state state-closed">{{ crate::web::fmt::icon("git-pull-request-closed")|safe }} Closed</span>
27 <span><strong>{{ pr.author }}</strong> wanted to merge {{ crate::web::fmt::plural(data.commits.len(), "commit") }} into <span class="branch-label">{{ pr.base_branch }}</span> from <span class="branch-label">{{ pr.head_branch }}</span></span>
28 {% else %}
29 <span class="state state-open">{{ crate::web::fmt::icon("git-pull-request")|safe }} Open</span>
30 <span><strong>{{ pr.author }}</strong> wants to merge {{ crate::web::fmt::plural(data.commits.len(), "commit") }} into <span class="branch-label">{{ pr.base_branch }}</span> from <span class="branch-label">{{ pr.head_branch }}</span></span>
31 {% endif %}
32 </div>
33</div>
34
35<nav class="tabs tabs-sub" aria-label="Pull request">
36 <a class="tab{% if pull_tab == "conversation" %} selected{% endif %}" href="{{ purl }}">{{ crate::web::fmt::icon("message-square")|safe }} Conversation <span class="counter">{{ pr.comments }}</span></a>
37 <a class="tab{% if pull_tab == "commits" %} selected{% endif %}" href="{{ purl }}/commits">{{ crate::web::fmt::icon("git-commit-horizontal")|safe }} Commits <span class="counter">{{ data.commits.len() }}</span></a>
38 <a class="tab{% if pull_tab == "files" %} selected{% endif %}" href="{{ purl }}/files">{{ crate::web::fmt::icon("file-text")|safe }} Files changed <span class="counter">{{ data.files }}</span></a>
39 <span class="tabs-extra"><span class="text-success">+{{ data.additions }}</span> <span class="text-danger">−{{ data.deletions }}</span></span>
40</nav>
41
42{% if pull_tab == "conversation" %}
43<div class="layout-pull">
44 <div class="timeline">
45 <div class="timeline-comment">
46 <div class="timeline-avatar">{{ crate::web::fmt::avatar(pr.author, 40)|safe }}</div>
47 <div class="comment">
48 <div class="comment-header">
49 <strong>{{ pr.author }}</strong> <span class="text-muted">opened this <time title="{{ crate::web::fmt::datetime_full(pr.created_at) }}">{{ crate::web::fmt::ago(pr.created_at) }}</time></span>
50 <span class="label comment-role">Author</span>
51 </div>
52 <div class="comment-body markdown-body">
53 {% if pr.body.is_empty() %}<p class="text-muted"><em>No description provided.</em></p>{% else %}{{ body_html|safe }}{% endif %}
54 </div>
55 </div>
56 </div>
57
58 {% for item in timeline %}
59 {% let e = item.event %}
60 {% if e.kind == "comment" %}
61 <div class="timeline-comment" id="event-{{ e.id }}">
62 <div class="timeline-avatar">{{ crate::web::fmt::avatar(e.author, 40)|safe }}</div>
63 <div class="comment">
64 <div class="comment-header">
65 <strong>{{ e.author }}</strong> <span class="text-muted">commented <a class="text-muted" href="#event-{{ e.id }}"><time title="{{ crate::web::fmt::datetime_full(e.created_at) }}">{{ crate::web::fmt::ago(e.created_at) }}</time></a></span>
66 {% if e.author == pr.author %}<span class="label comment-role">Author</span>{% endif %}
67 </div>
68 <div class="comment-body markdown-body">{{ item.html|safe }}</div>
69 </div>
70 </div>
71 {% else %}
72 <div class="timeline-event">
73 {% if e.kind == "merged" %}
74 <span class="event-badge badge-merged">{{ crate::web::fmt::icon("git-merge")|safe }}</span>
75 <span>{% if e.author.is_empty() %}This pull request was <strong>merged</strong>{% else %}<strong>{{ e.author }}</strong> merged{% endif %}
76 {% if let Some(sha) = pr.merge_commit_sha %}commit <a class="text-mono" href="{{ base }}/commit/{{ sha }}">{{ crate::web::fmt::short_sha(sha) }}</a>{% endif %}
77 into <span class="branch-label">{{ pr.base_branch }}</span>
78 {% else if e.kind == "closed" %}
79 <span class="event-badge badge-closed">{{ crate::web::fmt::icon("git-pull-request-closed")|safe }}</span>
80 <span><strong>{{ e.author }}</strong> closed this
81 {% else if e.kind == "reopened" %}
82 <span class="event-badge badge-open">{{ crate::web::fmt::icon("git-pull-request")|safe }}</span>
83 <span><strong>{{ e.author }}</strong> reopened this
84 {% else if e.kind == "branch_deleted" %}
85 <span class="event-badge">{{ crate::web::fmt::icon("git-branch")|safe }}</span>
86 <span><strong>{{ e.author }}</strong> deleted the <span class="branch-label">{{ e.body }}</span> branch
87 {% else %}
88 <span class="event-badge">{{ crate::web::fmt::icon("clock")|safe }}</span>
89 <span>{{ e.kind }}
90 {% endif %}
91 <time class="text-muted" title="{{ crate::web::fmt::datetime_full(e.created_at) }}">{{ crate::web::fmt::ago(e.created_at) }}</time></span>
92 </div>
93 {% endif %}
94 {% endfor %}
95
96 {% if pr.state == "open" %}
97 <div class="timeline-comment merge-section">
98 <div class="timeline-avatar merge-avatar state-{% if data.mergeability == Some(crate::git::Mergeability::Clean) %}open{% else %}neutral{% endif %}">{{ crate::web::fmt::icon("git-merge")|safe }}</div>
99 <div class="merge-box{% if data.mergeability == Some(crate::git::Mergeability::Clean) %} merge-box-ready{% endif %}">
100 {% if !data.head_exists %}
101 <div class="merge-status">
102 <span class="merge-status-icon status-neutral">{{ crate::web::fmt::icon("git-branch")|safe }}</span>
103 <div><strong>The head branch {{ pr.head_branch }} no longer exists.</strong><div class="text-muted">Push the branch again or close this pull request.</div></div>
104 </div>
105 {% else if !data.base_exists %}
106 <div class="merge-status">
107 <span class="merge-status-icon status-neutral">{{ crate::web::fmt::icon("git-branch")|safe }}</span>
108 <div><strong>The base branch {{ pr.base_branch }} no longer exists.</strong></div>
109 </div>
110 {% else if data.mergeability == Some(crate::git::Mergeability::Conflicts) %}
111 <div class="merge-status">
112 <span class="merge-status-icon status-danger">{{ crate::web::fmt::icon("x")|safe }}</span>
113 <div><strong>This branch has conflicts that must be resolved</strong><div class="text-muted">Resolve them locally and push the result:</div></div>
114 </div>
115 <pre class="command merge-instructions">git fetch origin
116git checkout {{ pr.head_branch }}
117git merge origin/{{ pr.base_branch }}
118# fix conflicts, then
119git commit
120git push origin {{ pr.head_branch }}</pre>
121 {% else %}
122 <div class="merge-status">
123 <span class="merge-status-icon status-success">{{ crate::web::fmt::icon("check")|safe }}</span>
124 <div><strong>This branch has no conflicts with the base branch</strong><div class="text-muted">Merging can be performed automatically.</div></div>
125 </div>
126 {% if r.access.write %}
127 <form class="merge-form" method="post" action="{{ purl }}/merge">
128 <select class="input input-sm" name="method" aria-label="Merge method">
129 <option value="merge">Create a merge commit</option>
130 <option value="squash">Squash and merge</option>
131 <option value="rebase">Rebase and merge</option>
132 </select>
133 <button class="btn btn-success" type="submit">{{ crate::web::fmt::icon("git-merge")|safe }} Merge pull request</button>
134 </form>
135 {% else %}
136 <p class="merge-note text-muted">Only people with write access to this repository can merge pull requests.</p>
137 {% endif %}
138 {% endif %}
139 </div>
140 </div>
141 {% else if pr.state == "merged" %}
142 <div class="timeline-comment merge-section">
143 <div class="timeline-avatar merge-avatar state-merged">{{ crate::web::fmt::icon("git-merge")|safe }}</div>
144 <div class="merge-box merge-box-merged">
145 <div class="merge-status">
146 <div><strong>Pull request successfully merged and closed</strong><div class="text-muted">{% if can_delete_branch %}The <span class="branch-label">{{ pr.head_branch }}</span> branch can be safely deleted.{% else %}You're all set.{% endif %}</div></div>
147 {% if can_delete_branch %}
148 <form method="post" action="{{ base }}/branches/delete">
149 <input type="hidden" name="branch" value="{{ pr.head_branch }}">
150 <input type="hidden" name="return_to" value="{{ purl }}">
151 <input type="hidden" name="pr" value="{{ pr.number }}">
152 <button class="btn btn-sm" type="submit">Delete branch</button>
153 </form>
154 {% endif %}
155 </div>
156 </div>
157 </div>
158 {% else %}
159 <div class="timeline-comment merge-section">
160 <div class="timeline-avatar merge-avatar state-closed">{{ crate::web::fmt::icon("git-pull-request-closed")|safe }}</div>
161 <div class="merge-box">
162 <div class="merge-status">
163 <div><strong>Closed with unmerged commits</strong><div class="text-muted">This pull request is closed, but the <span class="branch-label">{{ pr.head_branch }}</span> branch has unmerged commits.</div></div>
164 {% if can_delete_branch %}
165 <form method="post" action="{{ base }}/branches/delete" data-confirm="Delete the branch “{{ pr.head_branch }}”? Its commits are not merged.">
166 <input type="hidden" name="branch" value="{{ pr.head_branch }}">
167 <input type="hidden" name="return_to" value="{{ purl }}">
168 <input type="hidden" name="pr" value="{{ pr.number }}">
169 <button class="btn btn-sm btn-danger" type="submit">Delete branch</button>
170 </form>
171 {% endif %}
172 </div>
173 </div>
174 </div>
175 {% endif %}
176
177 {% if let Some(u) = ctx.user %}
178 <div class="timeline-comment comment-form-row">
179 <div class="timeline-avatar">{{ crate::web::fmt::avatar(u.username, 40)|safe }}</div>
180 <form class="comment comment-form" method="post" action="{{ purl }}/comment">
181 <div class="comment-header"><strong>Add a comment</strong></div>
182 <div class="comment-form-body">
183 <textarea class="input" name="body" rows="5" placeholder="Leave a comment. Markdown is supported."></textarea>
184 <div class="form-actions form-actions-end">
185 {% if pr.state == "open" && can_close %}
186 <button class="btn" type="submit" name="close" value="1">{{ crate::web::fmt::icon("git-pull-request-closed")|safe }} Close pull request</button>
187 {% endif %}
188 <button class="btn btn-primary" type="submit">Comment</button>
189 </div>
190 </div>
191 </form>
192 </div>
193 {% if pr.state == "closed" && can_close %}
194 <form class="reopen-form" method="post" action="{{ purl }}/state">
195 <input type="hidden" name="action" value="reopen">
196 <button class="btn" type="submit">Reopen pull request</button>
197 </form>
198 {% endif %}
199 {% else %}
200 <div class="banner"><span><a href="/login?next={{ crate::web::fmt::urlencode(ctx.path) }}">Sign in</a> to join the conversation.</span></div>
201 {% endif %}
202 </div>
203
204 <aside class="pull-sidebar">
205 <div class="sidebar-item">
206 <h3>Branches</h3>
207 <p><span class="branch-label">{{ pr.base_branch }}</span> ← <span class="branch-label">{{ pr.head_branch }}</span></p>
208 </div>
209 <div class="sidebar-item">
210 <h3>Changes</h3>
211 <p>{{ crate::web::fmt::plural(data.commits.len(), "commit") }}, {{ crate::web::fmt::plural(data.files, "file") }}<br>
212 <span class="text-success">+{{ data.additions }}</span> <span class="text-danger">−{{ data.deletions }}</span></p>
213 </div>
214 <div class="sidebar-item">
215 <h3>Checkout locally</h3>
216 <pre class="command command-sm">git fetch origin pull/{{ pr.number }}/head:pr-{{ pr.number }}
217git checkout pr-{{ pr.number }}</pre>
218 </div>
219 </aside>
220</div>
221
222{% else if pull_tab == "commits" %}
223{% if data.commits.is_empty() %}
224<div class="blankslate box"><p>No commits to show.</p></div>
225{% else %}
226<div class="box">
227 {% for c in data.commits %}
228 <div class="box-row commit-row">
229 <div class="commit-main">
230 <a class="commit-title" href="{{ base }}/commit/{{ c.id }}">{{ c.summary }}</a>
231 <div class="commit-meta">
232 {{ crate::web::fmt::avatar(c.author_name, 18)|safe }}
233 <strong>{{ c.author_name }}</strong> committed <time title="{{ crate::web::fmt::datetime_full(c.committer_time) }}">{{ crate::web::fmt::ago(c.committer_time) }}</time>
234 </div>
235 </div>
236 <div class="commit-actions">
237 <div class="btn-group">
238 <a class="btn btn-sm btn-mono" href="{{ base }}/commit/{{ c.id }}">{{ c.short_id }}</a>
239 <button type="button" class="btn btn-sm" data-copy-text="{{ c.id }}" title="Copy full SHA">{{ crate::web::fmt::icon("copy")|safe }}</button>
240 </div>
241 <a class="btn btn-sm btn-ghost" href="{{ base }}/tree/{{ c.id }}" title="Browse the repository at this point">{{ crate::web::fmt::icon("code")|safe }}</a>
242 </div>
243 </div>
244 {% endfor %}
245</div>
246{% endif %}
247
248{% else %}
249{% if let Some(diff) = data.diff %}
250{% let file_ref = pr.head_sha.clone().unwrap_or(crate::web::fmt::urlpath(pr.head_branch)) %}
251{% include "partials/diff.html" %}
252{% else %}
253<div class="blankslate box"><p>The changes for this pull request are no longer available.</p></div>
254{% endif %}
255{% endif %}
256{% endblock %}