pull-requests: simplified the UI for pr view....
marcink -
r4136:12e6938f default
Not Reviewed
Show More
Add another comment
TODOs: 0 unresolved 0 Resolved
COMMENTS: 0 General 0 Inline
@@ -101,12 +101,11
101 for commit_id in pull_request.revisions:
101 for commit_id in pull_request.revisions:
102 response.mustcontain(commit_id)
102 response.mustcontain(commit_id)
103
103
104 assert pull_request.target_ref_parts.type in response
104 response.mustcontain(pull_request.target_ref_parts.type)
105 assert pull_request.target_ref_parts.name in response
105 response.mustcontain(pull_request.target_ref_parts.name)
106 target_clone_url = pull_request.target_repo.clone_url()
107 assert target_clone_url in response
108
106
109 assert 'class="pull-request-merge"' in response
107 response.mustcontain('class="pull-request-merge"')
108
110 if pr_merge_enabled:
109 if pr_merge_enabled:
111 response.mustcontain('Pull request reviewer approval is pending')
110 response.mustcontain('Pull request reviewer approval is pending')
112 else:
111 else:
@@ -536,9 +535,9
536
535
537 # Check generated diff contents
536 # Check generated diff contents
538 response = response.follow()
537 response = response.follow()
539 assert 'content_of_ancestor' not in response.body
538 response.mustcontain(no=['content_of_ancestor'])
540 assert 'content_of_ancestor-child' not in response.body
539 response.mustcontain(no=['content_of_ancestor-child'])
541 assert 'content_of_change' in response.body
540 response.mustcontain('content_of_change')
542
541
543 def test_merge_pull_request_enabled(self, pr_util, csrf_token):
542 def test_merge_pull_request_enabled(self, pr_util, csrf_token):
544 # Clear any previous calls to rcextensions
543 # Clear any previous calls to rcextensions
@@ -689,8 +688,8
689 pull_request_id=pull_request.pull_request_id))
688 pull_request_id=pull_request.pull_request_id))
690
689
691 assert response.status_int == 200
690 assert response.status_int == 200
692 assert 'Pull request updated to' in response.body
691 response.mustcontain('Pull request updated to')
693 assert 'with 1 added, 0 removed commits.' in response.body
692 response.mustcontain('with 1 added, 0 removed commits.')
694
693
695 # check that we have now both revisions
694 # check that we have now both revisions
696 pull_request = PullRequest.get(pull_request_id)
695 pull_request = PullRequest.get(pull_request_id)
@@ -752,8 +751,8
752 repo_name=target.repo_name,
751 repo_name=target.repo_name,
753 pull_request_id=pull_request.pull_request_id))
752 pull_request_id=pull_request.pull_request_id))
754 assert response.status_int == 200
753 assert response.status_int == 200
755 assert 'Pull request updated to' in response.body
754 response.mustcontain('Pull request updated to')
756 assert 'with 1 added, 1 removed commits.' in response.body
755 response.mustcontain('with 1 added, 1 removed commits.')
757
756
758 def test_update_target_revision_with_removal_of_1_commit_git(self, backend_git, csrf_token):
757 def test_update_target_revision_with_removal_of_1_commit_git(self, backend_git, csrf_token):
759 backend = backend_git
758 backend = backend_git
@@ -994,12 +993,13
994 pull_request_id=pull_request.pull_request_id))
993 pull_request_id=pull_request.pull_request_id))
995 assert response.status_int == 200
994 assert response.status_int == 200
996
995
997 origin = response.assert_response().get_element('.pr-origininfo .tag')
996 source = response.assert_response().get_element('.pr-source-info')
998 origin_children = origin.getchildren()
997 source_parent = source.getparent()
999 assert len(origin_children) == 1
998 assert len(source_parent) == 1
1000 target = response.assert_response().get_element('.pr-targetinfo .tag')
999
1001 target_children = target.getchildren()
1000 target = response.assert_response().get_element('.pr-target-info')
1002 assert len(target_children) == 1
1001 target_parent = target.getparent()
1002 assert len(target_parent) == 1
1003
1003
1004 expected_origin_link = route_path(
1004 expected_origin_link = route_path(
1005 'repo_commits',
1005 'repo_commits',
@@ -1009,10 +1009,8
1009 'repo_commits',
1009 'repo_commits',
1010 repo_name=pull_request.target_repo.scm_instance().name,
1010 repo_name=pull_request.target_repo.scm_instance().name,
1011 params=dict(branch='target'))
1011 params=dict(branch='target'))
1012 assert origin_children[0].attrib['href'] == expected_origin_link
1012 assert source_parent.attrib['href'] == expected_origin_link
1013 assert origin_children[0].text == 'branch: origin'
1013 assert target_parent.attrib['href'] == expected_target_link
1014 assert target_children[0].attrib['href'] == expected_target_link
1015 assert target_children[0].text == 'branch: target'
1016
1014
1017 def test_bookmark_is_not_a_link(self, pr_util):
1015 def test_bookmark_is_not_a_link(self, pr_util):
1018 pull_request = pr_util.create_pull_request()
1016 pull_request = pr_util.create_pull_request()
@@ -1027,13 +1025,13
1027 pull_request_id=pull_request.pull_request_id))
1025 pull_request_id=pull_request.pull_request_id))
1028 assert response.status_int == 200
1026 assert response.status_int == 200
1029
1027
1030 origin = response.assert_response().get_element('.pr-origininfo .tag')
1028 source = response.assert_response().get_element('.pr-source-info')
1031 assert origin.text.strip() == 'bookmark: origin'
1029 assert source.text.strip() == 'bookmark:origin'
1032 assert origin.getchildren() == []
1030 assert source.getparent().attrib.get('href') is None
1033
1031
1034 target = response.assert_response().get_element('.pr-targetinfo .tag')
1032 target = response.assert_response().get_element('.pr-target-info')
1035 assert target.text.strip() == 'bookmark: target'
1033 assert target.text.strip() == 'bookmark:target'
1036 assert target.getchildren() == []
1034 assert target.getparent().attrib.get('href') is None
1037
1035
1038 def test_tag_is_not_a_link(self, pr_util):
1036 def test_tag_is_not_a_link(self, pr_util):
1039 pull_request = pr_util.create_pull_request()
1037 pull_request = pr_util.create_pull_request()
@@ -1048,13 +1046,13
1048 pull_request_id=pull_request.pull_request_id))
1046 pull_request_id=pull_request.pull_request_id))
1049 assert response.status_int == 200
1047 assert response.status_int == 200
1050
1048
1051 origin = response.assert_response().get_element('.pr-origininfo .tag')
1049 source = response.assert_response().get_element('.pr-source-info')
1052 assert origin.text.strip() == 'tag: origin'
1050 assert source.text.strip() == 'tag:origin'
1053 assert origin.getchildren() == []
1051 assert source.getparent().attrib.get('href') is None
1054
1052
1055 target = response.assert_response().get_element('.pr-targetinfo .tag')
1053 target = response.assert_response().get_element('.pr-target-info')
1056 assert target.text.strip() == 'tag: target'
1054 assert target.text.strip() == 'tag:target'
1057 assert target.getchildren() == []
1055 assert target.getparent().attrib.get('href') is None
1058
1056
1059 @pytest.mark.parametrize('mergeable', [True, False])
1057 @pytest.mark.parametrize('mergeable', [True, False])
1060 def test_shadow_repository_link(
1058 def test_shadow_repository_link(
@@ -726,7 +726,7
726 local_timezone = tzlocal.get_localzone()
726 local_timezone = tzlocal.get_localzone()
727
727
728
728
729 def age_component(datetime_iso, value=None, time_is_local=False):
729 def age_component(datetime_iso, value=None, time_is_local=False, tooltip=True):
730 title = value or format_date(datetime_iso)
730 title = value or format_date(datetime_iso)
731 tzinfo = '+00:00'
731 tzinfo = '+00:00'
732
732
@@ -740,9 +740,11
740 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
740 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
741
741
742 return literal(
742 return literal(
743 '<time class="timeago tooltip" '
743 '<time class="timeago {cls}" title="{tt_title}" datetime="{dt}{tzinfo}">{title}</time>'.format(
744 'title="{1}{2}" datetime="{0}{2}">{1}</time>'.format(
744 cls='tooltip' if tooltip else '',
745 datetime_iso, title, tzinfo))
745 tt_title=('{title}{tzinfo}'.format(title=title, tzinfo=tzinfo)) if tooltip else '',
746 title=title, dt=datetime_iso, tzinfo=tzinfo
747 ))
746
748
747
749
748 def _shorten_commit_id(commit_id, commit_len=None):
750 def _shorten_commit_id(commit_id, commit_len=None):
@@ -379,8 +379,9
379 font-family: @text-bold;
379 font-family: @text-bold;
380 }
380 }
381
381
382 .pr-origininfo, .pr-targetinfo {
382 .pr-commit-flow {
383 position: relative;
383 position: relative;
384 font-weight: 600;
384
385
385 .tag {
386 .tag {
386 display: inline-block;
387 display: inline-block;
@@ -413,7 +414,6
413 padding: 0 0;
414 padding: 0 0;
414 }
415 }
415
416
416
417 .pr-title-input {
417 .pr-title-input {
418 width: 80%;
418 width: 80%;
419 font-size: 1em;
419 font-size: 1em;
@@ -438,6 +438,19
438 }
438 }
439 }
439 }
440
440
441 .pr-title-closed-tag {
442 font-size: 16px;
443 }
444
445 #pr-desc {
446 padding: 10px 0;
447
448 .markdown-block {
449 padding: 0;
450 margin-bottom: -30px;
451 }
452 }
453
441 #pullrequest_title {
454 #pullrequest_title {
442 width: 100%;
455 width: 100%;
443 box-sizing: border-box;
456 box-sizing: border-box;
@@ -451,6 +464,31
451 overflow: hidden;
464 overflow: hidden;
452 }
465 }
453
466
467 .pr-details-title {
468 height: 16px
469 }
470
471 .pr-details-title-author-pref {
472 padding-right: 10px
473 }
474
475 .label-pr-detail {
476 display: table-cell;
477 width: 120px;
478 padding-top: 7.5px;
479 padding-bottom: 7.5px;
480 padding-right: 7.5px;
481 }
482
483 .source-details ul {
484 padding: 10px 16px;
485 }
486
487 .source-details-action {
488 color: @grey4;
489 font-size: 11px
490 }
491
454 .pr-submit-button {
492 .pr-submit-button {
455 float: right;
493 float: right;
456 margin: 0 0 0 5px;
494 margin: 0 0 0 5px;
@@ -469,6 +507,15
469 vertical-align: top;
507 vertical-align: top;
470 }
508 }
471
509
510 #close_edit_pullrequest {
511 padding-left: 1em
512 }
513
514 #delete_pullrequest {
515 clear: inherit;
516 padding: 0
517 }
518
472 .perms_section_head {
519 .perms_section_head {
473 min-width: 625px;
520 min-width: 625px;
474
521
@@ -1880,9 +1927,10
1880
1927
1881 .pr-versions {
1928 .pr-versions {
1882 font-size: 1.1em;
1929 font-size: 1.1em;
1930 padding: 7.5px;
1883
1931
1884 table {
1932 table {
1885 padding: 0px 5px;
1933
1886 }
1934 }
1887
1935
1888 td {
1936 td {
@@ -558,6 +558,21
558 }
558 }
559
559
560 return false
560 return false
561 };
562
563 this.toggleElement = function (elem, target) {
564 var $elem = $(elem);
565 var $target = $(target);
566
567 if ($target.is(':visible')) {
568 $target.hide();
569 $elem.html($elem.data('toggleOn'))
570 } else {
571 $target.show();
572 $elem.html($elem.data('toggleOff'))
573 }
574
575 return false
561 }
576 }
562
577
563 };
578 };
This diff has been collapsed as it changes many lines, (877 lines changed) Show them Hide them
@@ -10,14 +10,12
10 </%def>
10 </%def>
11
11
12 <%def name="breadcrumbs_links()">
12 <%def name="breadcrumbs_links()">
13 <%
14 pr_title = c.pull_request.title
15 if c.pull_request.is_closed():
16 pr_title = '[{}] {}'.format(_('Closed'), pr_title)
17 %>
18
13
19 <div id="pr-title">
14 <div id="pr-title">
20 <input class="pr-title-input large disabled" disabled="disabled" name="pullrequest_title" type="text" value="${pr_title}">
15 % if c.pull_request.is_closed():
16 <span class="pr-title-closed-tag tag">${_('Closed')}</span>
17 % endif
18 <input class="pr-title-input large disabled" disabled="disabled" name="pullrequest_title" type="text" value="${c.pull_request.title}">
21 </div>
19 </div>
22 <div id="pr-title-edit" class="input" style="display: none;">
20 <div id="pr-title-edit" class="input" style="display: none;">
23 <input class="pr-title-input large" id="pr-title-input" name="pullrequest_title" type="text" value="${c.pull_request.title}">
21 <input class="pr-title-input large" id="pr-title-input" name="pullrequest_title" type="text" value="${c.pull_request.title}">
@@ -39,324 +37,340
39 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
37 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
40 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
38 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
41 </script>
39 </script>
40
42 <div class="box">
41 <div class="box">
43
42
44 ${self.breadcrumbs()}
43 ${self.breadcrumbs()}
45
44
46 <div class="box pr-summary">
45 <div class="box pr-summary">
47
46
48 <div class="summary-details block-left">
47 <div class="summary-details block-left">
49 <% summary = lambda n:{False:'summary-short'}.get(n) %>
48 <% summary = lambda n:{False:'summary-short'}.get(n) %>
50 <div class="pr-details-title">
49 <div class="pr-details-title">
51 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request !{}').format(c.pull_request.pull_request_id)}</a> ${_('From')} ${h.format_date(c.pull_request.created_on)}
50 <div class="pull-left">
52 %if c.allowed_to_update:
51 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request !{}').format(c.pull_request.pull_request_id)}</a>
53 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
52 ${_('Created on')}
54 % if c.allowed_to_delete:
53 <span class="tooltip" title="${_('Last updated on')} ${h.format_date(c.pull_request.updated_on)}">${h.format_date(c.pull_request.created_on)},</span>
55 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
54 <span class="pr-details-title-author-pref">${_('by')}</span>
56 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
55 </div>
57 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
56
58 ${h.end_form()}
57 <div class="pull-left">
59 % else:
58 ${self.gravatar_with_user(c.pull_request.author.email, 16, tooltip=True)}
60 ${_('Delete')}
61 % endif
62 </div>
63 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
64 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
65 %endif
66 </div>
59 </div>
67
60
68 <div id="summary" class="fields pr-details-content">
61 %if c.allowed_to_update:
69 <div class="field">
62 <div id="delete_pullrequest" class="pull-right action_button ${('' if c.allowed_to_delete else 'disabled' )}" >
70 <div class="label-summary">
63 % if c.allowed_to_delete:
71 <label>${_('Source')}:</label>
64 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
72 </div>
65 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
73 <div class="input">
66 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
74 <div class="pr-origininfo">
67 ${h.end_form()}
75 ## branch link is only valid if it is a branch
68 % else:
76 <span class="tag">
69 ${_('Delete')}
77 %if c.pull_request.source_ref_parts.type == 'branch':
70 % endif
78 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
71 </div>
79 %else:
72 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
80 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
73 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;">${_('Cancel')}</div>
81 %endif
74 <div id="edit_pull_request" class="pull-right action_button pr-save" style="display: none;">${_('Save Changes')}</div>
82 </span>
75 %endif
83 <span class="clone-url">
76 </div>
84 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.clone_url()}</a>
77
85 </span>
78 <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}">
86 <br/>
79 ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)}
87 % if c.ancestor_commit:
80 </div>
88 ${_('Common ancestor')}:
81
89 <code><a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
82 <div id="pr-desc-edit" class="input textarea" style="display: none;">
90 % endif
83 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
91 </div>
84 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
92 %if h.is_hg(c.pull_request.source_repo):
85 </div>
93 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
86
94 %elif h.is_git(c.pull_request.source_repo):
87 <div id="summary" class="fields pr-details-content">
95 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
88
89 ## review
90 <div class="field">
91 <div class="label-pr-detail">
92 <label>${_('Review status')}:</label>
93 </div>
94 <div class="input">
95 %if c.pull_request_review_status:
96 <div class="tag status-tag-${c.pull_request_review_status}">
97 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
98 <span class="changeset-status-lbl">
99 %if c.pull_request.is_closed():
100 ${_('Closed')},
101 %endif
102
103 ${h.commit_status_lbl(c.pull_request_review_status)}
104
105 </span>
106 </div>
107 - ${_ungettext('calculated based on {} reviewer vote', 'calculated based on {} reviewers votes', len(c.pull_request_reviewers)).format(len(c.pull_request_reviewers))}
108 %endif
109 </div>
110 </div>
111
112 ## source
113 <div class="field">
114 <div class="label-pr-detail">
115 <label>${_('Commit flow')}:</label>
116 </div>
117 <div class="input">
118 <div class="pr-commit-flow">
119 ## Source
120 %if c.pull_request.source_ref_parts.type == 'branch':
121 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}"><code class="pr-source-info">${c.pull_request.source_ref_parts.type}:${c.pull_request.source_ref_parts.name}</code></a>
122 %else:
123 <code class="pr-source-info">${'{}:{}'.format(c.pull_request.source_ref_parts.type, c.pull_request.source_ref_parts.name)}</code>
124 %endif
125 ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.repo_name}</a>
126 &rarr;
127 ## Target
128 %if c.pull_request.target_ref_parts.type == 'branch':
129 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}"><code class="pr-target-info">${c.pull_request.target_ref_parts.type}:${c.pull_request.target_ref_parts.name}</code></a>
130 %else:
131 <code class="pr-target-info">${'{}:{}'.format(c.pull_request.target_ref_parts.type, c.pull_request.target_ref_parts.name)}</code>
96 %endif
132 %endif
97
133
98 <div class="">
134 ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.repo_name}</a>
99 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
135
100 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
136 <a class="source-details-action" href="#expand-source-details" onclick="return versionController.toggleElement(this, '.source-details')" data-toggle-on='<i class="icon-angle-down">more details</i>' data-toggle-off='<i class="icon-angle-up">less details</i>'>
101 </div>
137 <i class="icon-angle-down">more details</i>
138 </a>
102
139
103 </div>
140 </div>
104 </div>
141
105 <div class="field">
142 <div class="source-details" style="display: none">
106 <div class="label-summary">
143
107 <label>${_('Target')}:</label>
144 <ul>
108 </div>
145
109 <div class="input">
146 ## common ancestor
110 <div class="pr-targetinfo">
147 <li>
111 ## branch link is only valid if it is a branch
148 ${_('Common ancestor')}:
112 <span class="tag">
149 % if c.ancestor_commit:
113 %if c.pull_request.target_ref_parts.type == 'branch':
150 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a>
114 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
151 % else:
115 %else:
152 ${_('not available')}
116 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
153 % endif
117 %endif
154 </li>
118 </span>
155
119 <span class="clone-url">
156 ## pull url
120 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.clone_url()}</a>
157 <li>
121 </span>
158 %if h.is_hg(c.pull_request.source_repo):
122 </div>
159 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
123 </div>
160 %elif h.is_git(c.pull_request.source_repo):
124 </div>
161 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
162 %endif
125
163
126 ## Link to the shadow repository.
164 <span>${_('Pull changes from source')}</span>: <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
127 <div class="field">
165 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
128 <div class="label-summary">
166 </li>
129 <label>${_('Merge')}:</label>
167
130 </div>
168 ## Shadow repo
131 <div class="input">
169 <li>
132 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
170 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
133 %if h.is_hg(c.pull_request.target_repo):
171 %if h.is_hg(c.pull_request.target_repo):
134 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
172 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
135 %elif h.is_git(c.pull_request.target_repo):
173 %elif h.is_git(c.pull_request.target_repo):
136 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
174 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
137 %endif
175 %endif
138 <div class="">
176
139 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
177 <span class="tooltip" title="${_('Clone repository in its merged state using shadow repository')}">${_('Clone from shadow repository')}</span>: <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
140 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
178 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
141 </div>
179
142 % else:
180 % else:
143 <div class="">
181 <div class="">
144 ${_('Shadow repository data not available')}.
182 ${_('Shadow repository data not available')}.
145 </div>
183 </div>
146 % endif
184 % endif
147 </div>
185 </li>
186
187 </ul>
188
148 </div>
189 </div>
149
190
150 <div class="field">
191 </div>
151 <div class="label-summary">
192
152 <label>${_('Review')}:</label>
193 </div>
153 </div>
194
154 <div class="input">
195 ## versions
155 %if c.pull_request_review_status:
196 <div class="field">
156 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
197 <div class="label-pr-detail">
157 <span class="changeset-status-lbl">
198 <label>${_('Versions')}:</label>
158 %if c.pull_request.is_closed():
159 ${_('Closed')},
160 %endif
161 ${h.commit_status_lbl(c.pull_request_review_status)}
162 </span>
163 - ${_ungettext('calculated based on %s reviewer vote', 'calculated based on %s reviewers votes', len(c.pull_request_reviewers)) % len(c.pull_request_reviewers)}
164 %endif
165 </div>
166 </div>
167 <div class="field">
168 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
169 <label>${_('Description')}:</label>
170 </div>
171 <div id="pr-desc" class="input">
172 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)}</div>
173 </div>
174 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
175 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
176 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
177 </div>
178 </div>
199 </div>
179
200
180 <div class="field">
201 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
181 <div class="label-summary">
202 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
182 <label>${_('Versions')}:</label>
183 </div>
184
185 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
186 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
187
203
188 <div class="pr-versions">
204 <div class="pr-versions">
189 % if c.show_version_changes:
205 % if c.show_version_changes:
190 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
206 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
191 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
207 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
192 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
208 ${_ungettext('{} version available for this pull request, ', '{} versions available for this pull request, ', len(c.versions)).format(len(c.versions))}
193 data-toggle-on="${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}"
209 <a id="show-pr-versions" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
194 data-toggle-off="${_('Hide all versions of this pull request')}">
210 data-toggle-on="${_('show versions')}."
195 ${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}
211 data-toggle-off="${_('hide versions')}.">
196 </a>
212 ${_('show versions')}.
197 <table>
213 </a>
198 ## SHOW ALL VERSIONS OF PR
214 <table>
199 <% ver_pr = None %>
215 ## SHOW ALL VERSIONS OF PR
216 <% ver_pr = None %>
200
217
201 % for data in reversed(list(enumerate(c.versions, 1))):
218 % for data in reversed(list(enumerate(c.versions, 1))):
202 <% ver_pos = data[0] %>
219 <% ver_pos = data[0] %>
203 <% ver = data[1] %>
220 <% ver = data[1] %>
204 <% ver_pr = ver.pull_request_version_id %>
221 <% ver_pr = ver.pull_request_version_id %>
205 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
222 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
206
223
207 <tr class="version-pr" style="display: ${display_row}">
224 <tr class="version-pr" style="display: ${display_row}">
208 <td>
225 <td>
209 <code>
226 <code>
210 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
227 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
211 </code>
228 </code>
212 </td>
229 </td>
213 <td>
230 <td>
214 <input ${('checked="checked"' if c.from_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
231 <input ${('checked="checked"' if c.from_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
215 <input ${('checked="checked"' if c.at_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
232 <input ${('checked="checked"' if c.at_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
216 </td>
233 </td>
217 <td>
234 <td>
218 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
235 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
219 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
236 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
220
237
221 </td>
238 </td>
222 <td>
239 <td>
223 % if c.at_version_num != ver_pr:
240 % if c.at_version_num != ver_pr:
224 <i class="icon-comment"></i>
241 <i class="tooltip icon-comment" title="${_('Comments from pull request version v{0}').format(ver_pos)}"></i>
225 <code class="tooltip" title="${_('Comment from pull request version v{0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}">
242 <code>
226 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
243 General:${len(c.comment_versions[ver_pr]['at'])} / Inline:${len(c.inline_versions[ver_pr]['at'])}
227 </code>
244 </code>
228 % endif
245 % endif
229 </td>
246 </td>
230 <td>
247 <td>
231 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
248 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
232 </td>
249 </td>
233 <td>
250 <td>
234 ${h.age_component(ver.updated_on, time_is_local=True)}
251 <code>${h.age_component(ver.updated_on, time_is_local=True, tooltip=False)}</code>
235 </td>
236 </tr>
237 % endfor
238
239 <tr>
240 <td colspan="6">
241 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
242 data-label-text-locked="${_('select versions to show changes')}"
243 data-label-text-diff="${_('show changes between versions')}"
244 data-label-text-show="${_('show pull request for this version')}"
245 >
246 ${_('select versions to show changes')}
247 </button>
248 </td>
252 </td>
249 </tr>
253 </tr>
250 </table>
254 % endfor
251 % else:
255
252 <div class="input">
256 <tr>
253 ${_('Pull request versions not available')}.
257 <td colspan="6">
254 </div>
258 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
255 % endif
259 data-label-text-locked="${_('select versions to show changes')}"
260 data-label-text-diff="${_('show changes between versions')}"
261 data-label-text-show="${_('show pull request for this version')}"