MozReview: Review Page Redesign: Move commits table above the main content area (
Bug 1309964). r?glob,smacleod
MozReview-Commit-ID: KM0AyJQa31D
--- a/pylib/mozreview/mozreview/extension.py
+++ b/pylib/mozreview/mozreview/extension.py
@@ -53,16 +53,17 @@ from mozreview.fields import (
ImportCommitField,
PullCommitField,
TryField,
)
from mozreview.file_diff_reviewer.resources import (
file_diff_reviewer_resource,
)
from mozreview.hooks import (
+ CommitContextTemplateHook,
MozReviewApprovalHook,
)
from mozreview.hostingservice.bmo_bugtracker import (
BMOBugTracker,
)
from mozreview.hostingservice.hmo_repository import (
HMORepository,
)
@@ -310,19 +311,19 @@ class MozReviewExtension(Extension):
'mozreview/user-data.html')
TemplateHook(self, 'base-after-content',
'mozreview/repository.html')
TemplateHook(self, 'base-after-content',
'mozreview/user_review_flag.html',
apply_to=review_request_url_names)
ReviewRequestFieldsHook(self, 'main', [CommitsListField])
- # This forces the Commits field to be the top item.
- main_fieldset.field_classes.insert(0,
- main_fieldset.field_classes.pop())
+ CommitContextTemplateHook(self, 'mozreview-pre-review-request-box',
+ 'mozreview/commits.html',
+ apply_to=review_request_url_names)
# The above hack forced Commits at the top, but the rest of these
# fields are fine below the Description.
ReviewRequestFieldsHook(self, 'main', [CombinedReviewersField])
ReviewRequestFieldsHook(self, 'main', [TryField])
ReviewRequestFieldsHook(self, 'main', [BaseCommitField])
ReviewRequestFieldsHook(self, 'main', [FileDiffReviewerField])
--- a/pylib/mozreview/mozreview/fields.py
+++ b/pylib/mozreview/mozreview/fields.py
@@ -83,65 +83,28 @@ class CombinedReviewersField(BaseReviewR
class CommitsListField(CommitDataBackedField):
"""The commits list field for review requests.
This field is injected in the details of a review request that
is a "push" based review request.
"""
field_id = COMMITS_KEY
- label = _("Commits")
+ label = ""
can_record_change_entry = True
def has_value_changed(self, old_value, new_value):
# Just to be safe, we de-serialize the json and compare values
if old_value is not None and new_value is not None:
return json.loads(old_value) != json.loads(new_value)
return old_value != new_value
def should_render(self, value):
- return is_pushed(self.review_request_details)
-
- def as_html(self):
- user = self.request.user
- parent = get_parent_rr(self.review_request_details.get_review_request())
- parent_details = parent.get_draft(user) or parent
-
- # If a user can view the parent draft they should also have
- # permission to view every child. We check if the child is
- # accessible anyways in case it has been restricted for other
- # reasons.
- children_details = [
- child for child in gen_child_rrs(parent_details, user=user)
- if child.is_accessible_by(user)]
-
- autoland_requests = AutolandRequest.objects.filter(
- review_request_id=parent.id).order_by('-autoland_id')
-
- repo_urls = set()
- latest_autoland_requests = []
-
-
- # We would like to fetch the latest AutolandRequest for each
- # different repository.
- for request in autoland_requests:
- if request.repository_url in repo_urls:
- continue
-
- repo_urls.add(request.repository_url)
- latest_autoland_requests.append(request)
-
- return get_template('mozreview/commits.html').render(Context({
- 'review_request_details': self.review_request_details,
- 'parent_details': parent_details,
- 'children_details': children_details,
- 'latest_autoland_requests': latest_autoland_requests,
- 'user': user
- }))
+ return False
def render_change_entry_html(self, info):
old_value = json.loads(info.get('old', ['[]'])[0])
old_commits = [c for c, r in old_value]
new_value = json.loads(info.get('new', ['[]'])[0])
new_commits = [c for c, r in new_value]
--- a/pylib/mozreview/mozreview/hooks.py
+++ b/pylib/mozreview/mozreview/hooks.py
@@ -1,32 +1,101 @@
from __future__ import unicode_literals
import logging
-from reviewboard.extensions.hooks import ReviewRequestApprovalHook
+from django.template.loader import Context
+from django.utils.translation import ugettext as _
+from reviewboard.extensions.hooks import (
+ ReviewRequestApprovalHook,
+ ReviewRequestFieldsHook,
+ TemplateHook
+)
+
+from mozreview.autoland.models import AutolandEventLogEntry, AutolandRequest
from mozreview.extra_data import (
COMMIT_ID_KEY,
fetch_commit_data,
gen_child_rrs,
+ get_parent_rr,
is_parent,
is_pushed,
)
from mozreview.models import (
get_profile,
)
from mozreview.review_helpers import (
has_valid_shipit,
has_l3_shipit,
)
logger = logging.getLogger(__name__)
+class CommitContextTemplateHook(TemplateHook):
+ """Gathers all information required for commits table
+
+ This hook allows us to generate a detailed, custom commits table.
+ Information provided includes the parent and child review requests,
+ as well as autoland information.
+ """
+
+ def get_extra_context(self, request, context):
+ """Fetches relevant review request information, returns context"""
+ review_request_details = context['review_request_details']
+ commit_data = fetch_commit_data(review_request_details)
+
+ user = request.user
+ parent = get_parent_rr(review_request_details.get_review_request(), commit_data=commit_data)
+ parent_details = parent.get_draft(user) or parent
+
+ # If a user can view the parent draft they should also have
+ # permission to view every child. We check if the child is
+ # accessible anyways in case it has been restricted for other
+ # reasons.
+ children_details = [
+ child for child in gen_child_rrs(parent_details, user=user)
+ if child.is_accessible_by(user)]
+ n_children = len(children_details)
+ current_child_num = prev_child = next_child = None
+
+ if not is_parent(review_request_details, commit_data=commit_data):
+ cur_index = children_details.index(review_request_details)
+ current_child_num = cur_index + 1
+ next_child = (children_details[cur_index + 1]
+ if cur_index + 1 < n_children else None)
+ prev_child = (children_details[cur_index - 1]
+ if cur_index - 1 >= 0 else None)
+
+ latest_autoland_requests = []
+ repo_urls = set()
+ autoland_requests = AutolandRequest.objects.filter(
+ review_request_id=parent.id).order_by('-autoland_id')
+
+ # We would like to fetch the latest AutolandRequest for each
+ # different repository.
+ for request in autoland_requests:
+ if request.repository_url in repo_urls:
+ continue
+
+ repo_urls.add(request.repository_url)
+ latest_autoland_requests.append(request)
+
+ return {
+ 'review_request_details': review_request_details,
+ 'parent_details': parent_details,
+ 'children_details': children_details,
+ 'num_children': n_children,
+ 'current_child_num': current_child_num,
+ 'next_child': next_child,
+ 'prev_child': prev_child,
+ 'latest_autoland_requests': latest_autoland_requests,
+ 'user': user,
+ }
class MozReviewApprovalHook(ReviewRequestApprovalHook):
"""Calculates landing approval for review requests.
This hook allows us to control the `approved` and `approval_failure`
fields on review request model instances, and Web API results
associated with them. By calculating landing approval and returning
it here we have a nice way to distribute this decision throughout
--- a/pylib/mozreview/mozreview/static/mozreview/css/commits.less
+++ b/pylib/mozreview/mozreview/static/mozreview/css/commits.less
@@ -14,16 +14,17 @@
@issue-opened-link-color: darken(@issue-opened-bg, 60%);
/*******************************************************/
@import (reference) 'mozilla-theme-common.less';
@approval-bg: #DFFFD7;
@approval-border-color: #478A06;
+@table-large-font-size: 18px;
#mozreview-request-series{
margin-top:5px;
}
.help-icon {
display: inline-block;
text-align: center;
@@ -31,24 +32,34 @@
border-radius: 50%;
height: 15px;
width: 15px;
border: 1px solid #3E3E3E;
cursor: default;
margin-top: -1px;
}
+#mozreview-review-header {
+ text-transform: uppercase;
+ color: #777;
+ display: block;
+ font-weight: normal;
+}
+
#mozreview-child-requests {
width: 100%;
table-layout: fixed;
border-spacing: 0px;
margin-top:10px;
min-width: 653px;
- border-top: 1px solid #C1C1C1;
- border-right: 1px solid #C1C1C1;
+ border-top: 1px solid #EEE;
+ border-right: 1px solid #EEE;
+ margin-bottom: 20px;
+ border: 1px solid #CCC;
+ font-size: 110%;
tr, td {
text-align: left;
}
.truncate_text {
white-space: nowrap;
overflow: hidden;
@@ -57,17 +68,17 @@
}
.commits {
width: 60%;
ul {
font-size: 90%;
list-style-type: none;
- margin: 0;
+ margin: 0 0 0 44px;
padding: 6px 0;
li {
display: inline-block;
padding-right: 10px;
margin-right: 10px;
}
@@ -108,56 +119,70 @@
&.review-cleared{
color: grey;
}
&.review-cleared::after {
content: " (r? cleared)";
}
}
- .status {
- width: 90px;
- white-space: nowrap;
+ tbody > tr, tbody > tr:hover {
+ background: #F9F9F9;
}
- tbody > tr {
+ #mozreview-child-requests-nav-row {
background: #fff;
+ font-size: 90%;
+
+ td {
+ padding: 7px;
+ position: relative;
+ text-align: center;
+ }
+
+ a[rel="next"] {
+ position: absolute;
+ right: 10px;
+ }
+
+ a[rel="previous"] {
+ position: absolute;
+ left: 10px;
+ }
}
.mozreview_commit_summary {
font-weight: bold;
text-decoration: none;
+ font-size: @table-large-font-size;
&:hover, &:active, &:focus {
text-decoration: underline;
}
}
.diffstat-insert {
color: green;
}
.diffstat-delete {
- color: #a02222;
- }
-
- & > tbody > tr[current="true"],
- & > tbody > tr:hover {
- background-color: #eee;
+ color: #A02222;
}
td,
th {
padding: 5px;
- border-left: 1px solid #C1C1C1;
- border-bottom: 1px solid #C1C1C1;
+ border-left: 1px solid #EEE;
+ border-bottom: 1px solid #EEE;
}
& > thead > tr {
- background: @moz-blue-dark;
+ background: #EEE;
+ line-height: 1.5;
+ font-size: @table-large-font-size;
}
& > tbody td > a.commit_sha {
font-family: monospace;
}
.reviewers {
.inline-editor-form {
@@ -168,48 +193,22 @@
}
.buttons {
white-space: nowrap;
}
}
/* This was copied from the rb dashboard less file.*/
.status {
- text-align: center;
- }
-
- .no-approval {
- cursor: default;
- }
-
- .approval {
- cursor: default;
- background-color: @approval-bg;
- }
-
- .approval-issues {
- background: #fff4B0;
- position: relative;
+ font-size: @table-large-font-size;
}
-
- .issue-count {
- text-decoration: none;
- color: inherit;
- display: block;
- padding: 10px 0;
- }
+}
- .shipit-count {
- background-image: url("../shipit_bg.png");
- background-position: top left;
- background-repeat: repeat-x;
- background-color: #6bc810;
- border: 1px solid @approval-border-color;
- color: #205003;
- }
+#mozreview-all-commits {
+ font-weight: bold;
}
#error-container {
&:not([haserror="true"]) {
display: none;
}
border: 1px solid red;
--- a/pylib/mozreview/mozreview/static/mozreview/css/mozilla-theme-common.less
+++ b/pylib/mozreview/mozreview/static/mozreview/css/mozilla-theme-common.less
@@ -3,8 +3,17 @@
@light-white: rgba(255, 255, 255, 0.6);
.border-radius(...) {
-moz-border-radius: @arguments;
-webkit-border-radius: @arguments;
border-radius: @arguments;
}
+
+.review-status-icon(...) {
+ width: auto;
+ text-align: center;
+ background: #EEE;
+ font-weight: bold;
+ padding: 3px 10px;
+ display: inline-block;
+}
--- a/pylib/mozreview/mozreview/static/mozreview/css/mozilla-theme-reviews.less
+++ b/pylib/mozreview/mozreview/static/mozreview/css/mozilla-theme-reviews.less
@@ -1,31 +1,106 @@
@import (reference) 'mozilla-theme-common.less';
+/* Maximum with for reviews content */
+#review_request .box-container, #reviews, #mozreview-review-header, #mozreview-child-requests {
+ max-width: 1200px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
/* Review Requests */
.review-request {
.main {
- background: #fff;
+ background: #FFF;
border: 0;
border-radius: 0;
}
.content .field-container > pre {
font-family: inherit;
border: 0;
padding: 0;
font-size: 90%;
}
+
+ .header {
+ display: none;
+ }
}
-.reviewable-page #mozreview-child-requests > thead > tr > .status,
-.reviewable-page #mozreview-child-requests > tbody > tr > .status {
- min-width: 86px;
+#mozreview-review-content {
+ text-align: center;
+
+ h1 {
+ font-size: 28px;
+ font-weight: normal;
+ display: block;
+ line-height: auto;
+ margin-bottom: 10px;
+ }
+
+ .review-request-meta {
+ color: #777;
+ text-align: center;
+ line-height: 1.6;
+ font-size: 110%;
+ }
+
+ #review-request-inputs {
+ margin-top: 20px;
+
+ input {
+ .border-radius(3px);
+ padding: 2px 6px;
+ background: #F9F9F9;
+ border: 1px solid #ddd;
+ font-family: monospace;
+ font-size: 16px !important;
+ width: 300px;
+ margin-right: 20px;
+ }
+ }
}
+.status {
+ .review-status-icon();
+ font-size: 20px;
+ margin-bottom: 10px;
+
+ &.no-approval {
+ cursor: default;
+ }
+
+ &.approval {
+ cursor: default;
+ background-color: @approval-bg;
+ }
+
+ &.approval-issues {
+ background: #fff4B0;
+ }
+
+ .issue-count {
+ text-decoration: none;
+ color: #000;
+ }
+
+ .shipit-count {
+ background-image: url("../shipit_bg.png");
+ background-position: top left;
+ background-repeat: repeat-x;
+ background-color: #6bc810;
+ border: 1px solid @approval-border-color;
+ color: #205003;
+ }
+}
+
+
+
/* Review Banners */
.banner {
border-bottom: 0;
}
/* Review Comments */
.box, .box-inner {
.border-radius(0);
--- a/pylib/mozreview/mozreview/static/mozreview/css/mozilla-theme.less
+++ b/pylib/mozreview/mozreview/static/mozreview/css/mozilla-theme.less
@@ -1,13 +1,14 @@
@import (reference) 'mozilla-theme-common.less';
body {
background: @moz-blue-light;
- font-size: 13px;
+ font-family: Arial, Helvetica, Sans-Serif;
+ font-size: 14px;
padding-top: 8px;
}
/* Logo and Title */
#headerbar {
height: 18px;
#title a {
@@ -260,16 +261,20 @@ body.datagrid-page {
background: @moz-blue-dark;
border: 0;
}
.actions-container {
.border-radius(0);
}
+.review-request-header {
+ line-height: 20px;
+}
+
.review-request-header,
.actions.page-tabs li {
border-bottom: 0;
}
.actions.page-tabs li.active {
border: 0;
background: #fff;
--- a/pylib/mozreview/mozreview/static/mozreview/css/review.less
+++ b/pylib/mozreview/mozreview/static/mozreview/css/review.less
@@ -198,65 +198,33 @@ label[for="id_shipit"] {
}
.box::before, .box::after {
display: none;
}
}
}
// Tooltips for landable and "r?" cells
-#mozreview-child-requests .help-tooltip,
-#mozreview-child-requests .status {
+#mozreview-child-requests .commits {
position: relative;
&:hover .review-tooltip {
display: block;
}
}
.review-tooltip {
display: none;
max-width: 400px;
position: absolute;
- top: -6px;
- right: 90px;
+ bottom: 4px;
+ right: 4px;
font-size: 12px;
border: 1px #b09700 solid;
background: #fff49c;
max-width: 400px;
}
.review-tooltip-text {
position: relative;
padding: 10px;
font-weight: normal;
}
-
-/* shared with before and after */
-.review-tooltip-text:before, .review-tooltip-text:after {
- content: ' ';
- height: 0;
- position: absolute;
- width: 0;
- border: 8px solid transparent; /* arrow size */
-}
-
-/* top-stacked, smaller arrow */
-.review-tooltip-text:before {
- border-left-color: #fff49c; /* arrow color */
-
- /* positioning */
- position: absolute;
- top: 8px;
- right: -15px;
- z-index: 2;
-}
-
-/* arrow which acts as a background shadow */
-.review-tooltip-text:after {
- border-left-color: #b09700; /* arrow color */
-
- /* positioning */
- position: absolute;
- top: 8px;
- right: -16px;
- z-index: 1;
-}
--- a/pylib/mozreview/mozreview/static/mozreview/js/review.js
+++ b/pylib/mozreview/mozreview/static/mozreview/js/review.js
@@ -14,22 +14,29 @@
// Change string of "Review" button to be a verb so people better
// understand what clicking it does.
$("#review-link").text("Finish Review...");
if (MozReview.isParent) {
$('#review_request_extra').prepend(MRParents.parentWarning);
}
+ // Show all commits when link is clicked
+ $('#mozreview-all-commits').on('click', function(e) {
+ e.preventDefault();
+ $('#mozreview-child-requests tr[hidden]').removeAttr('hidden');
+ $(this).hide();
+ });
+
var reviewRequest = RB.PageManager.getPage().reviewRequest;
RB.apiCall({
type: 'GET',
prefix: reviewRequest.get('sitePrefix'),
noActivityIndicator: true,
- url: '/api/review-requests/'+reviewRequest.get('id')+'/reviews/' +
+ url: '/api/review-requests/' + reviewRequest.get('id') + '/reviews/' +
'?max-results=200',
success: function(data) {
_.forEach(data.reviews, function(item) {
var flag = item.extra_data['p2rb.review_flag'];
var flagDesc = '';
var reviewText = $('#review'+item.id+' .body');
switch(flag){
case ' ':
@@ -44,26 +51,26 @@
$(reviewText).prepend(
$('<h4 class="body_top">'+flagDesc+'</h4>')
);
});
}
});
// Tooltips for landable and "r?" cells
- $('#mozreview-child-requests .help-tooltip, #mozreview-child-requests tbody .status').each(function() {
+ $('#mozreview-child-requests tbody .status').each(function() {
var $element = $(this);
var text = $element.attr('title');
- if(!text) return;
+ if (!text) return;
$element.attr('title', '');
// Draw the tooltip title and text
- var $tip = $('<div></div>').attr('class', 'review-tooltip').appendTo($element);
+ var $tip = $('<div></div>').attr('class', 'review-tooltip').appendTo($element.parent());
$('<div></div>').attr('class', 'review-tooltip-text').text(text).appendTo($tip);
});
// Add a link to the parent on submitted children.
if (!MozReview.isParent) {
$('#submitted-banner').append(
$('<a></a>')
.addClass('reopen')
--- a/pylib/mozreview/mozreview/templates/mozreview/commits-requests.html
+++ b/pylib/mozreview/mozreview/templates/mozreview/commits-requests.html
@@ -10,44 +10,80 @@ by both the commits template and the com
<table id="mozreview-child-requests">
<thead>
<tr>
<th class="commits">{% trans "Commit" %}</th>
{% comment "TODO: show this column when the commit author will be available" %}
<th class="submitter">{% trans "Submitter" %}</th>
{% endcomment %}
<th class="reviewers">{% trans "Reviewers" %}</th>
- <th class="status">
- {% trans "Landable" %}
- <div class="help-icon help-tooltip" title="{% trans "Hover over each commit's status to view landable status" %}"><span>?</span></div>
- </th>
</tr>
</thead>
+
+ {% if parent_details.get_review_request.id != review_request_details.get_review_request.id and num_children > 1 %}
+ <tr id="mozreview-child-requests-nav-row">
+ <td colspan="2">
+ {% if prev_child %}
+ <a href="{{prev_child.get_review_request.get_absolute_url}}" rel="previous"><< Previous Commit</a>
+ {% endif %}
+ Viewing commit {{current_child_num}} of {{num_children}}.
+ <a href="javascript:;" id="mozreview-all-commits">View All Commits</a>
+ {% if next_child %}
+ <a href="{{next_child.get_review_request.get_absolute_url}}" rel="next">Next Commit >></a>
+ {% endif %}
+ </td>
+ </tr>
+ {% endif %}
+
+
{% for child_details in children_details %}
- <tr {% if child_details.get_review_request.id = review_request_details.get_review_request.id %}current="true"{% endif %}>
+ <tr
+ {% if child_details.get_review_request.id == review_request_details.get_review_request.id %}
+ current="true"
+ {% else %}
+ {% if parent_details.get_review_request.id != review_request_details.get_review_request.id %}
+ hidden
+ {% endif %}
+ {% endif %}>
<td class="commits">
<div class="truncate_text">
- <a class="mozreview_commit_summary" title="See diff for commit {{child_details|commit_id|slice:":12"}}"
- href="{{child_details.get_review_request.get_absolute_url}}diff/#index_header">
- {{ child_details.summary }}
- </a>
- <ul>
- <li>
- <a href="{{child_details.get_review_request.repository.path}}/raw-rev/{{child_details|commit_id|slice:":12"}}">
- {% trans "View Raw" %}
- </a>
- </li><li>
- <a href="{{child_details.get_review_request.get_absolute_url}}" title="{{ child_details.summary}}">
- {% trans "View Reviews" %}
- </a>
- </li><li class="diffstat" title="{% trans "Lines inserted / deleted" %}">
- {{ child_details.get_review_request|diffstat_text:user }}
- </li>
- </ul>
+ {% if child_details.get_review_request.issue_open_count > 0 %}
+ <div class="status approval-issues" title="{{child_details.get_review_request.issue_open_count}} open issue{{ child_details.get_review_request.issue_open_count|pluralize }}">
+ <a class="issue-count" href="{{child_details.get_review_request.get_absolute_url}}#issue-summary">
+ ! {{child_details.get_review_request.issue_open_count}}
+ </a>
+ </div>
+ {% elif child_details.get_review_request.approved %}
+ <div class="status approval" title="Approved For Landing - You have at least one valid ship it!">
+ r+
+ </div>
+ {% else %}
+ <div class="status no-approval" title="{{child_details.get_review_request.approval_failure}}">
+ r?
+ </div>
+ {% endif %}
+
+ <a class="mozreview_commit_summary" title="See diff for commit {{child_details|commit_id|slice:":12"}}"
+ href="{{child_details.get_review_request.get_absolute_url}}diff/#index_header">
+ {{ child_details.summary }}
+ </a>
+ <ul>
+ <li>
+ <a href="{{child_details.get_review_request.repository.path}}/raw-rev/{{child_details|commit_id|slice:":12"}}">
+ {% trans "View Raw" %}
+ </a>
+ </li><li>
+ <a href="{{child_details.get_review_request.get_absolute_url}}" title="{{ child_details.summary}}">
+ {% trans "View Reviews" %}
+ </a>
+ </li><li class="diffstat" title="{% trans "Lines inserted / deleted" %}">
+ {{ child_details.get_review_request|diffstat_text:user }}
+ </li>
+ </ul>
</div>
</td>
{% comment "TODO: show this column when the commit author will be available" %}
<td>{{ child_details.submitter }}</td>
{% endcomment %}
<td class="reviewers">
@@ -58,28 +94,11 @@ by both the commits template and the com
{% if child_details|isDraft %}
<span class="reviewer-name">{{ reviewer }}</span>
{% else %}
<span class="reviewer-name {% if status.ship_it %}reviewer-ship-it{% endif %} {{status.review_flag|review_flag_class}}">{{ reviewer }}</span>
{% endif %}
{% endfor %}
</span>
</td>
-
- {% if child_details.get_review_request.issue_open_count > 0 %}
- <td class="status approval-issues" title="{{child_details.get_review_request.issue_open_count}} open issues">
- <a class="issue-count" href="{{child_details.get_review_request.get_absolute_url}}#issue-summary">
- ! {{child_details.get_review_request.issue_open_count}}
- </a>
- </td>
- {% elif child_details.get_review_request.approved %}
- <td class="status approval" title="Approved For Landing - You have at least one valid ship it!">
- r+
- </td>
- {% else %}
- <td class="status no-approval" title="{{child_details.get_review_request.approval_failure}}">
- r?
- </td>
- {% endif %}
-
</tr>
{% endfor %}
</table>
--- a/pylib/mozreview/mozreview/templates/mozreview/commits.html
+++ b/pylib/mozreview/mozreview/templates/mozreview/commits.html
@@ -1,36 +1,54 @@
{% comment %}
This is the template for the "Commits" list in a push-based review request.
{% endcomment %}
{% load i18n %}
{% load djblets_utils %}
{% load mozreview %}
+{% load reviewtags %}
<div id="error-container">
<h1>Well, this is embarassing...</h1>
<p>Something's gone wrong in either retrieving or manipulating these review requests. Sorry about that. <a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=MozReview&component=General" target="_blank">Please consider filing a bug,</a> and including the following information:</p>
<p id="error-info"></p>
<pre id="error-stack"></pre>
<a href="#" id="error-stack-toggle">Stack</a>
<a href="#" id="error-close">Close</a>
</div>
<div id="mozreview-data"
data-parent-review-id="{{ parent_details.get_review_request.id }}"
data-selected-review-id="{{ review_request_details.get_review_request.id }}"
></div>
<div id="mozreview-request-series">
- <div id="mozreview-parent-request">
- <a href="{{parent_details.get_review_request.get_absolute_url}}">Review Summary</a>
- <a href="{{parent_details.get_review_request.get_absolute_url}}diff/#index_header">Squashed Diff</a>
+ <div id="mozreview-review-header">
+ {% if child_details.get_review_request.id == review_request_details.get_review_request.id %}
+ Review Summary
+ {% else %}
+ <a href="{{parent_details.get_review_request.get_absolute_url}}">Review Summary</a>
+ {% endif %}
+ •
+ {% if review_request_details.get_review_request.bugs_closed %}
+ {% for bug in review_request_details.get_bug_list %}
+ <a href="{{bug|bug_url:review_request_details}}">Bug #{{bug}}</a>
+ {% if not forloop.last %}, {% endif %}
+ {% endfor %}
+ •
+ {% endif %}
+ {{parent_details.get_review_request.repository}}
+ {% if parent_details.get_review_request.id == review_request_details.get_review_request.id %}
+ • <a href="{{parent_details.get_review_request.get_absolute_url}}diff/#index_header">Squashed Diff</a>
+ {% endif %}
</div>
+
{% include 'mozreview/commits-requests.html' %}
+
{% if latest_autoland_requests %}
<div id="ci-actions">
{% for autoland_request in latest_autoland_requests %}
{% if not forloop.first %}
<div class="action-separator"></div>
{% endif %}
{% if autoland_request.last_known_status == 'P' %}