##// END OF EJS Templates
diff-navigation: small improvements on text and display of navigation menu.
marcink -
r4446:e6192ffb default
parent child Browse files
Show More
@@ -1,302 +1,302 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.mako"/>
3 <%inherit file="/base/base.mako"/>
4 <%namespace name="base" file="/base/base.mako"/>
4 <%namespace name="base" file="/base/base.mako"/>
5 <%namespace name="diff_block" file="/changeset/diff_block.mako"/>
5 <%namespace name="diff_block" file="/changeset/diff_block.mako"/>
6 <%namespace name="file_base" file="/files/base.mako"/>
6 <%namespace name="file_base" file="/files/base.mako"/>
7
7
8 <%def name="title()">
8 <%def name="title()">
9 ${_('{} Commit').format(c.repo_name)} - ${h.show_id(c.commit)}
9 ${_('{} Commit').format(c.repo_name)} - ${h.show_id(c.commit)}
10 %if c.rhodecode_name:
10 %if c.rhodecode_name:
11 &middot; ${h.branding(c.rhodecode_name)}
11 &middot; ${h.branding(c.rhodecode_name)}
12 %endif
12 %endif
13 </%def>
13 </%def>
14
14
15 <%def name="menu_bar_nav()">
15 <%def name="menu_bar_nav()">
16 ${self.menu_items(active='repositories')}
16 ${self.menu_items(active='repositories')}
17 </%def>
17 </%def>
18
18
19 <%def name="menu_bar_subnav()">
19 <%def name="menu_bar_subnav()">
20 ${self.repo_menu(active='commits')}
20 ${self.repo_menu(active='commits')}
21 </%def>
21 </%def>
22
22
23 <%def name="main()">
23 <%def name="main()">
24 <script type="text/javascript">
24 <script type="text/javascript">
25 // TODO: marcink switch this to pyroutes
25 // TODO: marcink switch this to pyroutes
26 AJAX_COMMENT_DELETE_URL = "${h.route_path('repo_commit_comment_delete',repo_name=c.repo_name,commit_id=c.commit.raw_id,comment_id='__COMMENT_ID__')}";
26 AJAX_COMMENT_DELETE_URL = "${h.route_path('repo_commit_comment_delete',repo_name=c.repo_name,commit_id=c.commit.raw_id,comment_id='__COMMENT_ID__')}";
27 templateContext.commit_data.commit_id = "${c.commit.raw_id}";
27 templateContext.commit_data.commit_id = "${c.commit.raw_id}";
28 </script>
28 </script>
29
29
30 <div class="box">
30 <div class="box">
31
31
32 <div class="summary">
32 <div class="summary">
33
33
34 <div class="fieldset">
34 <div class="fieldset">
35 <div class="left-content">
35 <div class="left-content">
36 <%
36 <%
37 rc_user = h.discover_user(c.commit.author_email)
37 rc_user = h.discover_user(c.commit.author_email)
38 %>
38 %>
39 <div class="left-content-avatar">
39 <div class="left-content-avatar">
40 ${base.gravatar(c.commit.author_email, 30, tooltip=(True if rc_user else False), user=rc_user)}
40 ${base.gravatar(c.commit.author_email, 30, tooltip=(True if rc_user else False), user=rc_user)}
41 </div>
41 </div>
42
42
43 <div class="left-content-message">
43 <div class="left-content-message">
44 <div class="fieldset collapsable-content no-hide" data-toggle="summary-details">
44 <div class="fieldset collapsable-content no-hide" data-toggle="summary-details">
45 <div class="commit truncate-wrap">${h.urlify_commit_message(h.chop_at_smart(c.commit.message, '\n', suffix_if_chopped='...'), c.repo_name)}</div>
45 <div class="commit truncate-wrap">${h.urlify_commit_message(h.chop_at_smart(c.commit.message, '\n', suffix_if_chopped='...'), c.repo_name)}</div>
46 </div>
46 </div>
47
47
48 <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none">
48 <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none">
49 <div class="commit">${h.urlify_commit_message(c.commit.message,c.repo_name)}</div>
49 <div class="commit">${h.urlify_commit_message(c.commit.message,c.repo_name)}</div>
50 </div>
50 </div>
51
51
52 <div class="fieldset" data-toggle="summary-details">
52 <div class="fieldset" data-toggle="summary-details">
53 <div class="">
53 <div class="">
54 <table>
54 <table>
55 <tr class="file_author">
55 <tr class="file_author">
56
56
57 <td>
57 <td>
58 <span class="user commit-author">${h.link_to_user(rc_user or c.commit.author)}</span>
58 <span class="user commit-author">${h.link_to_user(rc_user or c.commit.author)}</span>
59 <span class="commit-date">- ${h.age_component(c.commit.date)}</span>
59 <span class="commit-date">- ${h.age_component(c.commit.date)}</span>
60 </td>
60 </td>
61
61
62 <td>
62 <td>
63 ## second cell for consistency with files
63 ## second cell for consistency with files
64 </td>
64 </td>
65 </tr>
65 </tr>
66 </table>
66 </table>
67 </div>
67 </div>
68 </div>
68 </div>
69
69
70 </div>
70 </div>
71 </div>
71 </div>
72
72
73 <div class="right-content">
73 <div class="right-content">
74
74
75 <div data-toggle="summary-details">
75 <div data-toggle="summary-details">
76 <div class="tags tags-main">
76 <div class="tags tags-main">
77 <code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
77 <code><a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">${h.show_id(c.commit)}</a></code>
78 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${c.commit.raw_id}" title="${_('Copy the full commit id')}"></i>
78 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${c.commit.raw_id}" title="${_('Copy the full commit id')}"></i>
79 ${file_base.refs(c.commit)}
79 ${file_base.refs(c.commit)}
80
80
81 ## phase
81 ## phase
82 % if hasattr(c.commit, 'phase') and getattr(c.commit, 'phase') != 'public':
82 % if hasattr(c.commit, 'phase') and getattr(c.commit, 'phase') != 'public':
83 <span class="tag phase-${c.commit.phase} tooltip" title="${_('Commit phase')}">
83 <span class="tag phase-${c.commit.phase} tooltip" title="${_('Commit phase')}">
84 <i class="icon-info"></i>${c.commit.phase}
84 <i class="icon-info"></i>${c.commit.phase}
85 </span>
85 </span>
86 % endif
86 % endif
87
87
88 ## obsolete commits
88 ## obsolete commits
89 % if getattr(c.commit, 'obsolete', False):
89 % if getattr(c.commit, 'obsolete', False):
90 <span class="tag obsolete-${c.commit.obsolete} tooltip" title="${_('Evolve State')}">
90 <span class="tag obsolete-${c.commit.obsolete} tooltip" title="${_('Evolve State')}">
91 ${_('obsolete')}
91 ${_('obsolete')}
92 </span>
92 </span>
93 % endif
93 % endif
94
94
95 ## hidden commits
95 ## hidden commits
96 % if getattr(c.commit, 'hidden', False):
96 % if getattr(c.commit, 'hidden', False):
97 <span class="tag hidden-${c.commit.hidden} tooltip" title="${_('Evolve State')}">
97 <span class="tag hidden-${c.commit.hidden} tooltip" title="${_('Evolve State')}">
98 ${_('hidden')}
98 ${_('hidden')}
99 </span>
99 </span>
100 % endif
100 % endif
101 </div>
101 </div>
102
102
103 %if c.statuses:
103 %if c.statuses:
104 <div class="tag status-tag-${c.statuses[0]} pull-right">
104 <div class="tag status-tag-${c.statuses[0]} pull-right">
105 <i class="icon-circle review-status-${c.statuses[0]}"></i>
105 <i class="icon-circle review-status-${c.statuses[0]}"></i>
106 <div class="pull-right">${h.commit_status_lbl(c.statuses[0])}</div>
106 <div class="pull-right">${h.commit_status_lbl(c.statuses[0])}</div>
107 </div>
107 </div>
108 %endif
108 %endif
109
109
110 </div>
110 </div>
111
111
112 </div>
112 </div>
113 </div>
113 </div>
114
114
115 <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none;">
115 <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none;">
116 <div class="left-label-summary">
116 <div class="left-label-summary">
117 <p>${_('Commit navigation')}:</p>
117 <p>${_('Commit navigation')}:</p>
118 <div class="right-label-summary">
118 <div class="right-label-summary">
119 <span id="parent_link" class="tag tagtag">
119 <span id="parent_link" class="tag tagtag">
120 <a href="#parentCommit" title="${_('Parent Commit')}"><i class="icon-left icon-no-margin"></i>${_('parent')}</a>
120 <a href="#parentCommit" title="${_('Parent Commit')}"><i class="icon-left icon-no-margin"></i>${_('parent')}</a>
121 </span>
121 </span>
122
122
123 <span id="child_link" class="tag tagtag">
123 <span id="child_link" class="tag tagtag">
124 <a href="#childCommit" title="${_('Child Commit')}">${_('child')}<i class="icon-right icon-no-margin"></i></a>
124 <a href="#childCommit" title="${_('Child Commit')}">${_('child')}<i class="icon-right icon-no-margin"></i></a>
125 </span>
125 </span>
126 </div>
126 </div>
127 </div>
127 </div>
128 </div>
128 </div>
129
129
130 <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none;">
130 <div class="fieldset collapsable-content" data-toggle="summary-details" style="display: none;">
131 <div class="left-label-summary">
131 <div class="left-label-summary">
132 <p>${_('Diff options')}:</p>
132 <p>${_('Diff options')}:</p>
133 <div class="right-label-summary">
133 <div class="right-label-summary">
134 <div class="diff-actions">
134 <div class="diff-actions">
135 <a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">
135 <a href="${h.route_path('repo_commit_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">
136 ${_('Raw Diff')}
136 ${_('Raw Diff')}
137 </a>
137 </a>
138 |
138 |
139 <a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">
139 <a href="${h.route_path('repo_commit_patch',repo_name=c.repo_name,commit_id=c.commit.raw_id)}">
140 ${_('Patch Diff')}
140 ${_('Patch Diff')}
141 </a>
141 </a>
142 |
142 |
143 <a href="${h.route_path('repo_commit_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,_query=dict(diff='download'))}">
143 <a href="${h.route_path('repo_commit_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,_query=dict(diff='download'))}">
144 ${_('Download Diff')}
144 ${_('Download Diff')}
145 </a>
145 </a>
146 </div>
146 </div>
147 </div>
147 </div>
148 </div>
148 </div>
149 </div>
149 </div>
150
150
151 <div class="clear-fix"></div>
151 <div class="clear-fix"></div>
152
152
153 <div class="btn-collapse" data-toggle="summary-details">
153 <div class="btn-collapse" data-toggle="summary-details">
154 ${_('Show More')}
154 ${_('Show More')}
155 </div>
155 </div>
156
156
157 </div>
157 </div>
158
158
159 <div class="cs_files">
159 <div class="cs_files">
160 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
160 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
161 ${cbdiffs.render_diffset_menu(c.changes[c.commit.raw_id])}
161 ${cbdiffs.render_diffset_menu(c.changes[c.commit.raw_id], commit=c.commit)}
162 ${cbdiffs.render_diffset(
162 ${cbdiffs.render_diffset(
163 c.changes[c.commit.raw_id], commit=c.commit, use_comments=True,inline_comments=c.inline_comments )}
163 c.changes[c.commit.raw_id], commit=c.commit, use_comments=True,inline_comments=c.inline_comments )}
164 </div>
164 </div>
165
165
166 ## template for inline comment form
166 ## template for inline comment form
167 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
167 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
168
168
169 ## comments heading with count
169 ## comments heading with count
170 <div class="comments-heading">
170 <div class="comments-heading">
171 <i class="icon-comment"></i>
171 <i class="icon-comment"></i>
172 ${_('Comments')} ${len(c.comments)}
172 ${_('Comments')} ${len(c.comments)}
173 </div>
173 </div>
174
174
175 ## render comments
175 ## render comments
176 ${comment.generate_comments(c.comments)}
176 ${comment.generate_comments(c.comments)}
177
177
178 ## main comment form and it status
178 ## main comment form and it status
179 ${comment.comments(h.route_path('repo_commit_comment_create', repo_name=c.repo_name, commit_id=c.commit.raw_id),
179 ${comment.comments(h.route_path('repo_commit_comment_create', repo_name=c.repo_name, commit_id=c.commit.raw_id),
180 h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))}
180 h.commit_status(c.rhodecode_db_repo, c.commit.raw_id))}
181 </div>
181 </div>
182
182
183 ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
183 ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
184 <script type="text/javascript">
184 <script type="text/javascript">
185
185
186 $(document).ready(function() {
186 $(document).ready(function() {
187
187
188 var boxmax = parseInt($('#trimmed_message_box').css('max-height'), 10);
188 var boxmax = parseInt($('#trimmed_message_box').css('max-height'), 10);
189 if($('#trimmed_message_box').height() === boxmax){
189 if($('#trimmed_message_box').height() === boxmax){
190 $('#message_expand').show();
190 $('#message_expand').show();
191 }
191 }
192
192
193 $('#message_expand').on('click', function(e){
193 $('#message_expand').on('click', function(e){
194 $('#trimmed_message_box').css('max-height', 'none');
194 $('#trimmed_message_box').css('max-height', 'none');
195 $(this).hide();
195 $(this).hide();
196 });
196 });
197
197
198 $('.show-inline-comments').on('click', function(e){
198 $('.show-inline-comments').on('click', function(e){
199 var boxid = $(this).attr('data-comment-id');
199 var boxid = $(this).attr('data-comment-id');
200 var button = $(this);
200 var button = $(this);
201
201
202 if(button.hasClass("comments-visible")) {
202 if(button.hasClass("comments-visible")) {
203 $('#{0} .inline-comments'.format(boxid)).each(function(index){
203 $('#{0} .inline-comments'.format(boxid)).each(function(index){
204 $(this).hide();
204 $(this).hide();
205 });
205 });
206 button.removeClass("comments-visible");
206 button.removeClass("comments-visible");
207 } else {
207 } else {
208 $('#{0} .inline-comments'.format(boxid)).each(function(index){
208 $('#{0} .inline-comments'.format(boxid)).each(function(index){
209 $(this).show();
209 $(this).show();
210 });
210 });
211 button.addClass("comments-visible");
211 button.addClass("comments-visible");
212 }
212 }
213 });
213 });
214
214
215 // next links
215 // next links
216 $('#child_link').on('click', function(e){
216 $('#child_link').on('click', function(e){
217 // fetch via ajax what is going to be the next link, if we have
217 // fetch via ajax what is going to be the next link, if we have
218 // >1 links show them to user to choose
218 // >1 links show them to user to choose
219 if(!$('#child_link').hasClass('disabled')){
219 if(!$('#child_link').hasClass('disabled')){
220 $.ajax({
220 $.ajax({
221 url: '${h.route_path('repo_commit_children',repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
221 url: '${h.route_path('repo_commit_children',repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
222 success: function(data) {
222 success: function(data) {
223 if(data.results.length === 0){
223 if(data.results.length === 0){
224 $('#child_link').html("${_('No Child Commits')}").addClass('disabled');
224 $('#child_link').html("${_('No Child Commits')}").addClass('disabled');
225 }
225 }
226 if(data.results.length === 1){
226 if(data.results.length === 1){
227 var commit = data.results[0];
227 var commit = data.results[0];
228 window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
228 window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
229 }
229 }
230 else if(data.results.length === 2){
230 else if(data.results.length === 2){
231 $('#child_link').addClass('disabled');
231 $('#child_link').addClass('disabled');
232 $('#child_link').addClass('double');
232 $('#child_link').addClass('double');
233
233
234 var _html = '';
234 var _html = '';
235 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> '
235 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> '
236 .replace('__branch__', data.results[0].branch)
236 .replace('__branch__', data.results[0].branch)
237 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
237 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
238 .replace('__title__', data.results[0].message)
238 .replace('__title__', data.results[0].message)
239 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
239 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
240 _html +=' | ';
240 _html +=' | ';
241 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> '
241 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a> '
242 .replace('__branch__', data.results[1].branch)
242 .replace('__branch__', data.results[1].branch)
243 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
243 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
244 .replace('__title__', data.results[1].message)
244 .replace('__title__', data.results[1].message)
245 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
245 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
246 $('#child_link').html(_html);
246 $('#child_link').html(_html);
247 }
247 }
248 }
248 }
249 });
249 });
250 e.preventDefault();
250 e.preventDefault();
251 }
251 }
252 });
252 });
253
253
254 // prev links
254 // prev links
255 $('#parent_link').on('click', function(e){
255 $('#parent_link').on('click', function(e){
256 // fetch via ajax what is going to be the next link, if we have
256 // fetch via ajax what is going to be the next link, if we have
257 // >1 links show them to user to choose
257 // >1 links show them to user to choose
258 if(!$('#parent_link').hasClass('disabled')){
258 if(!$('#parent_link').hasClass('disabled')){
259 $.ajax({
259 $.ajax({
260 url: '${h.route_path("repo_commit_parents",repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
260 url: '${h.route_path("repo_commit_parents",repo_name=c.repo_name, commit_id=c.commit.raw_id)}',
261 success: function(data) {
261 success: function(data) {
262 if(data.results.length === 0){
262 if(data.results.length === 0){
263 $('#parent_link').html('${_('No Parent Commits')}').addClass('disabled');
263 $('#parent_link').html('${_('No Parent Commits')}').addClass('disabled');
264 }
264 }
265 if(data.results.length === 1){
265 if(data.results.length === 1){
266 var commit = data.results[0];
266 var commit = data.results[0];
267 window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
267 window.location = pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': commit.raw_id});
268 }
268 }
269 else if(data.results.length === 2){
269 else if(data.results.length === 2){
270 $('#parent_link').addClass('disabled');
270 $('#parent_link').addClass('disabled');
271 $('#parent_link').addClass('double');
271 $('#parent_link').addClass('double');
272
272
273 var _html = '';
273 var _html = '';
274 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>'
274 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>'
275 .replace('__branch__', data.results[0].branch)
275 .replace('__branch__', data.results[0].branch)
276 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
276 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
277 .replace('__title__', data.results[0].message)
277 .replace('__title__', data.results[0].message)
278 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
278 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[0].raw_id}));
279 _html +=' | ';
279 _html +=' | ';
280 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>'
280 _html +='<a title="__title__" href="__url__"><span class="tag branchtag"><i class="icon-code-fork"></i>__branch__</span> __rev__</a>'
281 .replace('__branch__', data.results[1].branch)
281 .replace('__branch__', data.results[1].branch)
282 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
282 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
283 .replace('__title__', data.results[1].message)
283 .replace('__title__', data.results[1].message)
284 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
284 .replace('__url__', pyroutes.url('repo_commit', {'repo_name': '${c.repo_name}','commit_id': data.results[1].raw_id}));
285 $('#parent_link').html(_html);
285 $('#parent_link').html(_html);
286 }
286 }
287 }
287 }
288 });
288 });
289 e.preventDefault();
289 e.preventDefault();
290 }
290 }
291 });
291 });
292
292
293 // browse tree @ revision
293 // browse tree @ revision
294 $('#files_link').on('click', function(e){
294 $('#files_link').on('click', function(e){
295 window.location = '${h.route_path('repo_files:default_path',repo_name=c.repo_name, commit_id=c.commit.raw_id)}';
295 window.location = '${h.route_path('repo_files:default_path',repo_name=c.repo_name, commit_id=c.commit.raw_id)}';
296 e.preventDefault();
296 e.preventDefault();
297 });
297 });
298
298
299 })
299 })
300 </script>
300 </script>
301
301
302 </%def>
302 </%def>
@@ -1,1355 +1,1369 b''
1 <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/>
1 <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/>
2
2
3 <%def name="diff_line_anchor(commit, filename, line, type)"><%
3 <%def name="diff_line_anchor(commit, filename, line, type)"><%
4 return '%s_%s_%i' % (h.md5_safe(commit+filename), type, line)
4 return '%s_%s_%i' % (h.md5_safe(commit+filename), type, line)
5 %></%def>
5 %></%def>
6
6
7 <%def name="action_class(action)">
7 <%def name="action_class(action)">
8 <%
8 <%
9 return {
9 return {
10 '-': 'cb-deletion',
10 '-': 'cb-deletion',
11 '+': 'cb-addition',
11 '+': 'cb-addition',
12 ' ': 'cb-context',
12 ' ': 'cb-context',
13 }.get(action, 'cb-empty')
13 }.get(action, 'cb-empty')
14 %>
14 %>
15 </%def>
15 </%def>
16
16
17 <%def name="op_class(op_id)">
17 <%def name="op_class(op_id)">
18 <%
18 <%
19 return {
19 return {
20 DEL_FILENODE: 'deletion', # file deleted
20 DEL_FILENODE: 'deletion', # file deleted
21 BIN_FILENODE: 'warning' # binary diff hidden
21 BIN_FILENODE: 'warning' # binary diff hidden
22 }.get(op_id, 'addition')
22 }.get(op_id, 'addition')
23 %>
23 %>
24 </%def>
24 </%def>
25
25
26
26
27
27
28 <%def name="render_diffset(diffset, commit=None,
28 <%def name="render_diffset(diffset, commit=None,
29
29
30 # collapse all file diff entries when there are more than this amount of files in the diff
30 # collapse all file diff entries when there are more than this amount of files in the diff
31 collapse_when_files_over=20,
31 collapse_when_files_over=20,
32
32
33 # collapse lines in the diff when more than this amount of lines changed in the file diff
33 # collapse lines in the diff when more than this amount of lines changed in the file diff
34 lines_changed_limit=500,
34 lines_changed_limit=500,
35
35
36 # add a ruler at to the output
36 # add a ruler at to the output
37 ruler_at_chars=0,
37 ruler_at_chars=0,
38
38
39 # show inline comments
39 # show inline comments
40 use_comments=False,
40 use_comments=False,
41
41
42 # disable new comments
42 # disable new comments
43 disable_new_comments=False,
43 disable_new_comments=False,
44
44
45 # special file-comments that were deleted in previous versions
45 # special file-comments that were deleted in previous versions
46 # it's used for showing outdated comments for deleted files in a PR
46 # it's used for showing outdated comments for deleted files in a PR
47 deleted_files_comments=None,
47 deleted_files_comments=None,
48
48
49 # for cache purpose
49 # for cache purpose
50 inline_comments=None,
50 inline_comments=None,
51
51
52 # additional menu for PRs
52 # additional menu for PRs
53 pull_request_menu=None,
53 pull_request_menu=None,
54
54
55 # show/hide todo next to comments
55 # show/hide todo next to comments
56 show_todos=True,
56 show_todos=True,
57
57
58 )">
58 )">
59
59
60 <%
60 <%
61 diffset_container_id = h.md5(diffset.target_ref)
61 diffset_container_id = h.md5(diffset.target_ref)
62 collapse_all = len(diffset.files) > collapse_when_files_over
62 collapse_all = len(diffset.files) > collapse_when_files_over
63 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
63 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
64 %>
64 %>
65
65
66 %if use_comments:
66 %if use_comments:
67
67
68 ## Template for injecting comments
68 ## Template for injecting comments
69 <div id="cb-comments-inline-container-template" class="js-template">
69 <div id="cb-comments-inline-container-template" class="js-template">
70 ${inline_comments_container([])}
70 ${inline_comments_container([])}
71 </div>
71 </div>
72
72
73 <div class="js-template" id="cb-comment-inline-form-template">
73 <div class="js-template" id="cb-comment-inline-form-template">
74 <div class="comment-inline-form ac">
74 <div class="comment-inline-form ac">
75
75
76 %if c.rhodecode_user.username != h.DEFAULT_USER:
76 %if c.rhodecode_user.username != h.DEFAULT_USER:
77 ## render template for inline comments
77 ## render template for inline comments
78 ${commentblock.comment_form(form_type='inline')}
78 ${commentblock.comment_form(form_type='inline')}
79 %else:
79 %else:
80 ${h.form('', class_='inline-form comment-form-login', method='get')}
80 ${h.form('', class_='inline-form comment-form-login', method='get')}
81 <div class="pull-left">
81 <div class="pull-left">
82 <div class="comment-help pull-right">
82 <div class="comment-help pull-right">
83 ${_('You need to be logged in to leave comments.')} <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
83 ${_('You need to be logged in to leave comments.')} <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
84 </div>
84 </div>
85 </div>
85 </div>
86 <div class="comment-button pull-right">
86 <div class="comment-button pull-right">
87 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
87 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
88 ${_('Cancel')}
88 ${_('Cancel')}
89 </button>
89 </button>
90 </div>
90 </div>
91 <div class="clearfix"></div>
91 <div class="clearfix"></div>
92 ${h.end_form()}
92 ${h.end_form()}
93 %endif
93 %endif
94 </div>
94 </div>
95 </div>
95 </div>
96
96
97 %endif
97 %endif
98
98
99 %if c.user_session_attrs["diffmode"] == 'sideside':
99 %if c.user_session_attrs["diffmode"] == 'sideside':
100 <style>
100 <style>
101 .wrapper {
101 .wrapper {
102 max-width: 1600px !important;
102 max-width: 1600px !important;
103 }
103 }
104 </style>
104 </style>
105 %endif
105 %endif
106
106
107 %if ruler_at_chars:
107 %if ruler_at_chars:
108 <style>
108 <style>
109 .diff table.cb .cb-content:after {
109 .diff table.cb .cb-content:after {
110 content: "";
110 content: "";
111 border-left: 1px solid blue;
111 border-left: 1px solid blue;
112 position: absolute;
112 position: absolute;
113 top: 0;
113 top: 0;
114 height: 18px;
114 height: 18px;
115 opacity: .2;
115 opacity: .2;
116 z-index: 10;
116 z-index: 10;
117 //## +5 to account for diff action (+/-)
117 //## +5 to account for diff action (+/-)
118 left: ${ruler_at_chars + 5}ch;
118 left: ${ruler_at_chars + 5}ch;
119 </style>
119 </style>
120 %endif
120 %endif
121
121
122 <div class="diffset ${disable_new_comments and 'diffset-comments-disabled'}">
122 <div class="diffset ${disable_new_comments and 'diffset-comments-disabled'}">
123
123
124 <div style="height: 20px; line-height: 20px">
124 <div style="height: 20px; line-height: 20px">
125 ## expand/collapse action
125 ## expand/collapse action
126 <div class="pull-left">
126 <div class="pull-left">
127 <a class="${'collapsed' if collapse_all else ''}" href="#expand-files" onclick="toggleExpand(this, '${diffset_container_id}'); return false">
127 <a class="${'collapsed' if collapse_all else ''}" href="#expand-files" onclick="toggleExpand(this, '${diffset_container_id}'); return false">
128 % if collapse_all:
128 % if collapse_all:
129 <i class="icon-plus-squared-alt icon-no-margin"></i>${_('Expand all files')}
129 <i class="icon-plus-squared-alt icon-no-margin"></i>${_('Expand all files')}
130 % else:
130 % else:
131 <i class="icon-minus-squared-alt icon-no-margin"></i>${_('Collapse all files')}
131 <i class="icon-minus-squared-alt icon-no-margin"></i>${_('Collapse all files')}
132 % endif
132 % endif
133 </a>
133 </a>
134
134
135 </div>
135 </div>
136
136
137 ## todos
137 ## todos
138 % if show_todos and getattr(c, 'at_version', None):
138 % if show_todos and getattr(c, 'at_version', None):
139 <div class="pull-right">
139 <div class="pull-right">
140 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
140 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
141 ${_('not available in this view')}
141 ${_('not available in this view')}
142 </div>
142 </div>
143 % elif show_todos:
143 % elif show_todos:
144 <div class="pull-right">
144 <div class="pull-right">
145 <div class="comments-number" style="padding-left: 10px">
145 <div class="comments-number" style="padding-left: 10px">
146 % if hasattr(c, 'unresolved_comments') and hasattr(c, 'resolved_comments'):
146 % if hasattr(c, 'unresolved_comments') and hasattr(c, 'resolved_comments'):
147 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
147 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
148 % if c.unresolved_comments:
148 % if c.unresolved_comments:
149 <a href="#show-todos" onclick="$('#todo-box').toggle(); return false">
149 <a href="#show-todos" onclick="$('#todo-box').toggle(); return false">
150 ${_('{} unresolved').format(len(c.unresolved_comments))}
150 ${_('{} unresolved').format(len(c.unresolved_comments))}
151 </a>
151 </a>
152 % else:
152 % else:
153 ${_('0 unresolved')}
153 ${_('0 unresolved')}
154 % endif
154 % endif
155
155
156 ${_('{} Resolved').format(len(c.resolved_comments))}
156 ${_('{} Resolved').format(len(c.resolved_comments))}
157 % endif
157 % endif
158 </div>
158 </div>
159 </div>
159 </div>
160 % endif
160 % endif
161
161
162 ## comments
162 ## comments
163 <div class="pull-right">
163 <div class="pull-right">
164 <div class="comments-number" style="padding-left: 10px">
164 <div class="comments-number" style="padding-left: 10px">
165 % if hasattr(c, 'comments') and hasattr(c, 'inline_cnt'):
165 % if hasattr(c, 'comments') and hasattr(c, 'inline_cnt'):
166 <i class="icon-comment" style="color: #949494">COMMENTS:</i>
166 <i class="icon-comment" style="color: #949494">COMMENTS:</i>
167 % if c.comments:
167 % if c.comments:
168 <a href="#comments">${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))}</a>,
168 <a href="#comments">${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))}</a>,
169 % else:
169 % else:
170 ${_('0 General')}
170 ${_('0 General')}
171 % endif
171 % endif
172
172
173 % if c.inline_cnt:
173 % if c.inline_cnt:
174 <a href="#" onclick="return Rhodecode.comments.nextComment();"
174 <a href="#" onclick="return Rhodecode.comments.nextComment();"
175 id="inline-comments-counter">${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(c.inline_cnt)}
175 id="inline-comments-counter">${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(c.inline_cnt)}
176 </a>
176 </a>
177 % else:
177 % else:
178 ${_('0 Inline')}
178 ${_('0 Inline')}
179 % endif
179 % endif
180 % endif
180 % endif
181
181
182 % if pull_request_menu:
182 % if pull_request_menu:
183 <%
183 <%
184 outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver']
184 outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver']
185 %>
185 %>
186
186
187 % if outdated_comm_count_ver:
187 % if outdated_comm_count_ver:
188 <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">
188 <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">
189 (${_("{} Outdated").format(outdated_comm_count_ver)})
189 (${_("{} Outdated").format(outdated_comm_count_ver)})
190 </a>
190 </a>
191 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a>
191 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a>
192 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a>
192 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a>
193 % else:
193 % else:
194 (${_("{} Outdated").format(outdated_comm_count_ver)})
194 (${_("{} Outdated").format(outdated_comm_count_ver)})
195 % endif
195 % endif
196
196
197 % endif
197 % endif
198
198
199 </div>
199 </div>
200 </div>
200 </div>
201
201
202 </div>
202 </div>
203
203
204 % if diffset.limited_diff:
204 % if diffset.limited_diff:
205 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
205 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
206 <h2 class="clearinner">
206 <h2 class="clearinner">
207 ${_('The requested changes are too big and content was truncated.')}
207 ${_('The requested changes are too big and content was truncated.')}
208 <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
208 <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
209 </h2>
209 </h2>
210 </div>
210 </div>
211 ## commit range header for each individual diff
211 ## commit range header for each individual diff
212 % elif commit and hasattr(c, 'commit_ranges') and len(c.commit_ranges) > 1:
212 % elif commit and hasattr(c, 'commit_ranges') and len(c.commit_ranges) > 1:
213 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
213 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
214 <div class="clearinner">
214 <div class="clearinner">
215 <a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.route_path('repo_commit',repo_name=diffset.repo_name,commit_id=commit.raw_id)}">${('r%s:%s' % (commit.idx,h.short_id(commit.raw_id)))}</a>
215 <a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.route_path('repo_commit',repo_name=diffset.repo_name,commit_id=commit.raw_id)}">${('r%s:%s' % (commit.idx,h.short_id(commit.raw_id)))}</a>
216 </div>
216 </div>
217 </div>
217 </div>
218 % endif
218 % endif
219
219
220 <div id="todo-box">
220 <div id="todo-box">
221 % if hasattr(c, 'unresolved_comments') and c.unresolved_comments:
221 % if hasattr(c, 'unresolved_comments') and c.unresolved_comments:
222 % for co in c.unresolved_comments:
222 % for co in c.unresolved_comments:
223 <a class="permalink" href="#comment-${co.comment_id}"
223 <a class="permalink" href="#comment-${co.comment_id}"
224 onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'))">
224 onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'))">
225 <i class="icon-flag-filled-red"></i>
225 <i class="icon-flag-filled-red"></i>
226 ${co.comment_id}</a>${('' if loop.last else ',')}
226 ${co.comment_id}</a>${('' if loop.last else ',')}
227 % endfor
227 % endfor
228 % endif
228 % endif
229 </div>
229 </div>
230 %if diffset.has_hidden_changes:
230 %if diffset.has_hidden_changes:
231 <p class="empty_data">${_('Some changes may be hidden')}</p>
231 <p class="empty_data">${_('Some changes may be hidden')}</p>
232 %elif not diffset.files:
232 %elif not diffset.files:
233 <p class="empty_data">${_('No files')}</p>
233 <p class="empty_data">${_('No files')}</p>
234 %endif
234 %endif
235
235
236 <div class="filediffs">
236 <div class="filediffs">
237
237
238 ## initial value could be marked as False later on
238 ## initial value could be marked as False later on
239 <% over_lines_changed_limit = False %>
239 <% over_lines_changed_limit = False %>
240 %for i, filediff in enumerate(diffset.files):
240 %for i, filediff in enumerate(diffset.files):
241
241
242 <%
242 <%
243 lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted']
243 lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted']
244 over_lines_changed_limit = lines_changed > lines_changed_limit
244 over_lines_changed_limit = lines_changed > lines_changed_limit
245 %>
245 %>
246 ## anchor with support of sticky header
246 ## anchor with support of sticky header
247 <div class="anchor" id="a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></div>
247 <div class="anchor" id="a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></div>
248
248
249 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filediff)}" type="checkbox" onchange="updateSticky();">
249 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filediff)}" type="checkbox" onchange="updateSticky();">
250 <div
250 <div
251 class="filediff"
251 class="filediff"
252 data-f-path="${filediff.patch['filename']}"
252 data-f-path="${filediff.patch['filename']}"
253 data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}"
253 data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}"
254 >
254 >
255 <label for="filediff-collapse-${id(filediff)}" class="filediff-heading">
255 <label for="filediff-collapse-${id(filediff)}" class="filediff-heading">
256 <%
256 <%
257 file_comments = (get_inline_comments(inline_comments, filediff.patch['filename']) or {}).values()
257 file_comments = (get_inline_comments(inline_comments, filediff.patch['filename']) or {}).values()
258 total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not _c.outdated]
258 total_file_comments = [_c for _c in h.itertools.chain.from_iterable(file_comments) if not _c.outdated]
259 %>
259 %>
260 <div class="filediff-collapse-indicator icon-"></div>
260 <div class="filediff-collapse-indicator icon-"></div>
261 <span class="pill-group pull-right" >
261 <span class="pill-group pull-right" >
262 <span class="pill" op="comments">
262 <span class="pill" op="comments">
263
263
264 <i class="icon-comment"></i> ${len(total_file_comments)}
264 <i class="icon-comment"></i> ${len(total_file_comments)}
265 </span>
265 </span>
266 </span>
266 </span>
267 ${diff_ops(filediff)}
267 ${diff_ops(filediff)}
268
268
269 </label>
269 </label>
270
270
271 ${diff_menu(filediff, use_comments=use_comments)}
271 ${diff_menu(filediff, use_comments=use_comments)}
272 <table data-f-path="${filediff.patch['filename']}" data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}" class="code-visible-block cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
272 <table data-f-path="${filediff.patch['filename']}" data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}" class="code-visible-block cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
273
273
274 ## new/deleted/empty content case
274 ## new/deleted/empty content case
275 % if not filediff.hunks:
275 % if not filediff.hunks:
276 ## Comment container, on "fakes" hunk that contains all data to render comments
276 ## Comment container, on "fakes" hunk that contains all data to render comments
277 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
277 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
278 % endif
278 % endif
279
279
280 %if filediff.limited_diff:
280 %if filediff.limited_diff:
281 <tr class="cb-warning cb-collapser">
281 <tr class="cb-warning cb-collapser">
282 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
282 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
283 ${_('The requested commit or file is too big and content was truncated.')} <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
283 ${_('The requested commit or file is too big and content was truncated.')} <a href="${h.current_route_path(request, fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
284 </td>
284 </td>
285 </tr>
285 </tr>
286 %else:
286 %else:
287 %if over_lines_changed_limit:
287 %if over_lines_changed_limit:
288 <tr class="cb-warning cb-collapser">
288 <tr class="cb-warning cb-collapser">
289 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
289 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
290 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
290 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
291 <a href="#" class="cb-expand"
291 <a href="#" class="cb-expand"
292 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
292 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
293 </a>
293 </a>
294 <a href="#" class="cb-collapse"
294 <a href="#" class="cb-collapse"
295 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
295 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
296 </a>
296 </a>
297 </td>
297 </td>
298 </tr>
298 </tr>
299 %endif
299 %endif
300 %endif
300 %endif
301
301
302 % for hunk in filediff.hunks:
302 % for hunk in filediff.hunks:
303 <tr class="cb-hunk">
303 <tr class="cb-hunk">
304 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
304 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
305 ## TODO: dan: add ajax loading of more context here
305 ## TODO: dan: add ajax loading of more context here
306 ## <a href="#">
306 ## <a href="#">
307 <i class="icon-more"></i>
307 <i class="icon-more"></i>
308 ## </a>
308 ## </a>
309 </td>
309 </td>
310 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
310 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
311 @@
311 @@
312 -${hunk.source_start},${hunk.source_length}
312 -${hunk.source_start},${hunk.source_length}
313 +${hunk.target_start},${hunk.target_length}
313 +${hunk.target_start},${hunk.target_length}
314 ${hunk.section_header}
314 ${hunk.section_header}
315 </td>
315 </td>
316 </tr>
316 </tr>
317
317
318 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
318 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
319 % endfor
319 % endfor
320
320
321 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
321 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
322
322
323 ## outdated comments that do not fit into currently displayed lines
323 ## outdated comments that do not fit into currently displayed lines
324 % for lineno, comments in unmatched_comments.items():
324 % for lineno, comments in unmatched_comments.items():
325
325
326 %if c.user_session_attrs["diffmode"] == 'unified':
326 %if c.user_session_attrs["diffmode"] == 'unified':
327 % if loop.index == 0:
327 % if loop.index == 0:
328 <tr class="cb-hunk">
328 <tr class="cb-hunk">
329 <td colspan="3"></td>
329 <td colspan="3"></td>
330 <td>
330 <td>
331 <div>
331 <div>
332 ${_('Unmatched/outdated inline comments below')}
332 ${_('Unmatched/outdated inline comments below')}
333 </div>
333 </div>
334 </td>
334 </td>
335 </tr>
335 </tr>
336 % endif
336 % endif
337 <tr class="cb-line">
337 <tr class="cb-line">
338 <td class="cb-data cb-context"></td>
338 <td class="cb-data cb-context"></td>
339 <td class="cb-lineno cb-context"></td>
339 <td class="cb-lineno cb-context"></td>
340 <td class="cb-lineno cb-context"></td>
340 <td class="cb-lineno cb-context"></td>
341 <td class="cb-content cb-context">
341 <td class="cb-content cb-context">
342 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
342 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
343 </td>
343 </td>
344 </tr>
344 </tr>
345 %elif c.user_session_attrs["diffmode"] == 'sideside':
345 %elif c.user_session_attrs["diffmode"] == 'sideside':
346 % if loop.index == 0:
346 % if loop.index == 0:
347 <tr class="cb-comment-info">
347 <tr class="cb-comment-info">
348 <td colspan="2"></td>
348 <td colspan="2"></td>
349 <td class="cb-line">
349 <td class="cb-line">
350 <div>
350 <div>
351 ${_('Unmatched/outdated inline comments below')}
351 ${_('Unmatched/outdated inline comments below')}
352 </div>
352 </div>
353 </td>
353 </td>
354 <td colspan="2"></td>
354 <td colspan="2"></td>
355 <td class="cb-line">
355 <td class="cb-line">
356 <div>
356 <div>
357 ${_('Unmatched/outdated comments below')}
357 ${_('Unmatched/outdated comments below')}
358 </div>
358 </div>
359 </td>
359 </td>
360 </tr>
360 </tr>
361 % endif
361 % endif
362 <tr class="cb-line">
362 <tr class="cb-line">
363 <td class="cb-data cb-context"></td>
363 <td class="cb-data cb-context"></td>
364 <td class="cb-lineno cb-context"></td>
364 <td class="cb-lineno cb-context"></td>
365 <td class="cb-content cb-context">
365 <td class="cb-content cb-context">
366 % if lineno.startswith('o'):
366 % if lineno.startswith('o'):
367 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
367 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
368 % endif
368 % endif
369 </td>
369 </td>
370
370
371 <td class="cb-data cb-context"></td>
371 <td class="cb-data cb-context"></td>
372 <td class="cb-lineno cb-context"></td>
372 <td class="cb-lineno cb-context"></td>
373 <td class="cb-content cb-context">
373 <td class="cb-content cb-context">
374 % if lineno.startswith('n'):
374 % if lineno.startswith('n'):
375 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
375 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
376 % endif
376 % endif
377 </td>
377 </td>
378 </tr>
378 </tr>
379 %endif
379 %endif
380
380
381 % endfor
381 % endfor
382
382
383 </table>
383 </table>
384 </div>
384 </div>
385 %endfor
385 %endfor
386
386
387 ## outdated comments that are made for a file that has been deleted
387 ## outdated comments that are made for a file that has been deleted
388 % for filename, comments_dict in (deleted_files_comments or {}).items():
388 % for filename, comments_dict in (deleted_files_comments or {}).items():
389
389
390 <%
390 <%
391 display_state = 'display: none'
391 display_state = 'display: none'
392 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
392 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
393 if open_comments_in_file:
393 if open_comments_in_file:
394 display_state = ''
394 display_state = ''
395 fid = str(id(filename))
395 fid = str(id(filename))
396 %>
396 %>
397 <div class="filediffs filediff-outdated" style="${display_state}">
397 <div class="filediffs filediff-outdated" style="${display_state}">
398 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
398 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
399 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
399 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
400 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
400 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
401 <div class="filediff-collapse-indicator icon-"></div>
401 <div class="filediff-collapse-indicator icon-"></div>
402
402
403 <span class="pill">
403 <span class="pill">
404 ## file was deleted
404 ## file was deleted
405 ${filename}
405 ${filename}
406 </span>
406 </span>
407 <span class="pill-group pull-left" >
407 <span class="pill-group pull-left" >
408 ## file op, doesn't need translation
408 ## file op, doesn't need translation
409 <span class="pill" op="removed">unresolved comments</span>
409 <span class="pill" op="removed">unresolved comments</span>
410 </span>
410 </span>
411 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}">ΒΆ</a>
411 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}">ΒΆ</a>
412 <span class="pill-group pull-right">
412 <span class="pill-group pull-right">
413 <span class="pill" op="deleted">
413 <span class="pill" op="deleted">
414 % if comments_dict['stats'] >0:
414 % if comments_dict['stats'] >0:
415 -${comments_dict['stats']}
415 -${comments_dict['stats']}
416 % else:
416 % else:
417 ${comments_dict['stats']}
417 ${comments_dict['stats']}
418 % endif
418 % endif
419 </span>
419 </span>
420 </span>
420 </span>
421 </label>
421 </label>
422
422
423 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
423 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
424 <tr>
424 <tr>
425 % if c.user_session_attrs["diffmode"] == 'unified':
425 % if c.user_session_attrs["diffmode"] == 'unified':
426 <td></td>
426 <td></td>
427 %endif
427 %endif
428
428
429 <td></td>
429 <td></td>
430 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
430 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
431 <strong>${_('This file was removed from diff during updates to this pull-request.')}</strong><br/>
431 <strong>${_('This file was removed from diff during updates to this pull-request.')}</strong><br/>
432 ${_('There are still outdated/unresolved comments attached to it.')}
432 ${_('There are still outdated/unresolved comments attached to it.')}
433 </td>
433 </td>
434 </tr>
434 </tr>
435 %if c.user_session_attrs["diffmode"] == 'unified':
435 %if c.user_session_attrs["diffmode"] == 'unified':
436 <tr class="cb-line">
436 <tr class="cb-line">
437 <td class="cb-data cb-context"></td>
437 <td class="cb-data cb-context"></td>
438 <td class="cb-lineno cb-context"></td>
438 <td class="cb-lineno cb-context"></td>
439 <td class="cb-lineno cb-context"></td>
439 <td class="cb-lineno cb-context"></td>
440 <td class="cb-content cb-context">
440 <td class="cb-content cb-context">
441 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
441 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
442 </td>
442 </td>
443 </tr>
443 </tr>
444 %elif c.user_session_attrs["diffmode"] == 'sideside':
444 %elif c.user_session_attrs["diffmode"] == 'sideside':
445 <tr class="cb-line">
445 <tr class="cb-line">
446 <td class="cb-data cb-context"></td>
446 <td class="cb-data cb-context"></td>
447 <td class="cb-lineno cb-context"></td>
447 <td class="cb-lineno cb-context"></td>
448 <td class="cb-content cb-context"></td>
448 <td class="cb-content cb-context"></td>
449
449
450 <td class="cb-data cb-context"></td>
450 <td class="cb-data cb-context"></td>
451 <td class="cb-lineno cb-context"></td>
451 <td class="cb-lineno cb-context"></td>
452 <td class="cb-content cb-context">
452 <td class="cb-content cb-context">
453 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
453 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
454 </td>
454 </td>
455 </tr>
455 </tr>
456 %endif
456 %endif
457 </table>
457 </table>
458 </div>
458 </div>
459 </div>
459 </div>
460 % endfor
460 % endfor
461
461
462 </div>
462 </div>
463 </div>
463 </div>
464 </%def>
464 </%def>
465
465
466 <%def name="diff_ops(filediff)">
466 <%def name="diff_ops(filediff)">
467 <%
467 <%
468 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
468 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
469 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
469 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
470 %>
470 %>
471 <span class="pill">
471 <span class="pill">
472 <i class="icon-file-text"></i>
472 <i class="icon-file-text"></i>
473 %if filediff.source_file_path and filediff.target_file_path:
473 %if filediff.source_file_path and filediff.target_file_path:
474 %if filediff.source_file_path != filediff.target_file_path:
474 %if filediff.source_file_path != filediff.target_file_path:
475 ## file was renamed, or copied
475 ## file was renamed, or copied
476 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
476 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
477 ${filediff.target_file_path} β¬… <del>${filediff.source_file_path}</del>
477 ${filediff.target_file_path} β¬… <del>${filediff.source_file_path}</del>
478 <% final_path = filediff.target_file_path %>
478 <% final_path = filediff.target_file_path %>
479 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
479 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
480 ${filediff.target_file_path} β¬… ${filediff.source_file_path}
480 ${filediff.target_file_path} β¬… ${filediff.source_file_path}
481 <% final_path = filediff.target_file_path %>
481 <% final_path = filediff.target_file_path %>
482 %endif
482 %endif
483 %else:
483 %else:
484 ## file was modified
484 ## file was modified
485 ${filediff.source_file_path}
485 ${filediff.source_file_path}
486 <% final_path = filediff.source_file_path %>
486 <% final_path = filediff.source_file_path %>
487 %endif
487 %endif
488 %else:
488 %else:
489 %if filediff.source_file_path:
489 %if filediff.source_file_path:
490 ## file was deleted
490 ## file was deleted
491 ${filediff.source_file_path}
491 ${filediff.source_file_path}
492 <% final_path = filediff.source_file_path %>
492 <% final_path = filediff.source_file_path %>
493 %else:
493 %else:
494 ## file was added
494 ## file was added
495 ${filediff.target_file_path}
495 ${filediff.target_file_path}
496 <% final_path = filediff.target_file_path %>
496 <% final_path = filediff.target_file_path %>
497 %endif
497 %endif
498 %endif
498 %endif
499 <i style="color: #aaa" class="on-hover-icon icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="${_('Copy file path')}" onclick="return false;"></i>
499 <i style="color: #aaa" class="on-hover-icon icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="${_('Copy file path')}" onclick="return false;"></i>
500 </span>
500 </span>
501 ## anchor link
501 ## anchor link
502 <a class="pill filediff-anchor" href="#a_${h.FID(filediff.raw_id, filediff.patch['filename'])}">ΒΆ</a>
502 <a class="pill filediff-anchor" href="#a_${h.FID(filediff.raw_id, filediff.patch['filename'])}">ΒΆ</a>
503
503
504 <span class="pill-group pull-right">
504 <span class="pill-group pull-right">
505
505
506 ## ops pills
506 ## ops pills
507 %if filediff.limited_diff:
507 %if filediff.limited_diff:
508 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
508 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
509 %endif
509 %endif
510
510
511 %if NEW_FILENODE in filediff.patch['stats']['ops']:
511 %if NEW_FILENODE in filediff.patch['stats']['ops']:
512 <span class="pill" op="created">created</span>
512 <span class="pill" op="created">created</span>
513 %if filediff['target_mode'].startswith('120'):
513 %if filediff['target_mode'].startswith('120'):
514 <span class="pill" op="symlink">symlink</span>
514 <span class="pill" op="symlink">symlink</span>
515 %else:
515 %else:
516 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
516 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
517 %endif
517 %endif
518 %endif
518 %endif
519
519
520 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
520 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
521 <span class="pill" op="renamed">renamed</span>
521 <span class="pill" op="renamed">renamed</span>
522 %endif
522 %endif
523
523
524 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
524 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
525 <span class="pill" op="copied">copied</span>
525 <span class="pill" op="copied">copied</span>
526 %endif
526 %endif
527
527
528 %if DEL_FILENODE in filediff.patch['stats']['ops']:
528 %if DEL_FILENODE in filediff.patch['stats']['ops']:
529 <span class="pill" op="removed">removed</span>
529 <span class="pill" op="removed">removed</span>
530 %endif
530 %endif
531
531
532 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
532 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
533 <span class="pill" op="mode">
533 <span class="pill" op="mode">
534 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
534 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
535 </span>
535 </span>
536 %endif
536 %endif
537
537
538 %if BIN_FILENODE in filediff.patch['stats']['ops']:
538 %if BIN_FILENODE in filediff.patch['stats']['ops']:
539 <span class="pill" op="binary">binary</span>
539 <span class="pill" op="binary">binary</span>
540 %if MOD_FILENODE in filediff.patch['stats']['ops']:
540 %if MOD_FILENODE in filediff.patch['stats']['ops']:
541 <span class="pill" op="modified">modified</span>
541 <span class="pill" op="modified">modified</span>
542 %endif
542 %endif
543 %endif
543 %endif
544
544
545 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
545 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
546 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
546 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
547
547
548 </span>
548 </span>
549
549
550 </%def>
550 </%def>
551
551
552 <%def name="nice_mode(filemode)">
552 <%def name="nice_mode(filemode)">
553 ${(filemode.startswith('100') and filemode[3:] or filemode)}
553 ${(filemode.startswith('100') and filemode[3:] or filemode)}
554 </%def>
554 </%def>
555
555
556 <%def name="diff_menu(filediff, use_comments=False)">
556 <%def name="diff_menu(filediff, use_comments=False)">
557 <div class="filediff-menu">
557 <div class="filediff-menu">
558
558
559 %if filediff.diffset.source_ref:
559 %if filediff.diffset.source_ref:
560
560
561 ## FILE BEFORE CHANGES
561 ## FILE BEFORE CHANGES
562 %if filediff.operation in ['D', 'M']:
562 %if filediff.operation in ['D', 'M']:
563 <a
563 <a
564 class="tooltip"
564 class="tooltip"
565 href="${h.route_path('repo_files',repo_name=filediff.diffset.target_repo_name,commit_id=filediff.diffset.source_ref,f_path=filediff.source_file_path)}"
565 href="${h.route_path('repo_files',repo_name=filediff.diffset.target_repo_name,commit_id=filediff.diffset.source_ref,f_path=filediff.source_file_path)}"
566 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
566 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
567 >
567 >
568 ${_('Show file before')}
568 ${_('Show file before')}
569 </a> |
569 </a> |
570 %else:
570 %else:
571 <span
571 <span
572 class="tooltip"
572 class="tooltip"
573 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
573 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
574 >
574 >
575 ${_('Show file before')}
575 ${_('Show file before')}
576 </span> |
576 </span> |
577 %endif
577 %endif
578
578
579 ## FILE AFTER CHANGES
579 ## FILE AFTER CHANGES
580 %if filediff.operation in ['A', 'M']:
580 %if filediff.operation in ['A', 'M']:
581 <a
581 <a
582 class="tooltip"
582 class="tooltip"
583 href="${h.route_path('repo_files',repo_name=filediff.diffset.source_repo_name,commit_id=filediff.diffset.target_ref,f_path=filediff.target_file_path)}"
583 href="${h.route_path('repo_files',repo_name=filediff.diffset.source_repo_name,commit_id=filediff.diffset.target_ref,f_path=filediff.target_file_path)}"
584 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
584 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
585 >
585 >
586 ${_('Show file after')}
586 ${_('Show file after')}
587 </a>
587 </a>
588 %else:
588 %else:
589 <span
589 <span
590 class="tooltip"
590 class="tooltip"
591 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
591 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
592 >
592 >
593 ${_('Show file after')}
593 ${_('Show file after')}
594 </span>
594 </span>
595 %endif
595 %endif
596
596
597 % if use_comments:
597 % if use_comments:
598 |
598 |
599 <a href="#" onclick="return Rhodecode.comments.toggleComments(this);">
599 <a href="#" onclick="return Rhodecode.comments.toggleComments(this);">
600 <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span>
600 <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span>
601 </a>
601 </a>
602 % endif
602 % endif
603
603
604 %endif
604 %endif
605
605
606 </div>
606 </div>
607 </%def>
607 </%def>
608
608
609
609
610 <%def name="inline_comments_container(comments, active_pattern_entries=None)">
610 <%def name="inline_comments_container(comments, active_pattern_entries=None)">
611
611
612 <div class="inline-comments">
612 <div class="inline-comments">
613 %for comment in comments:
613 %for comment in comments:
614 ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)}
614 ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)}
615 %endfor
615 %endfor
616 % if comments and comments[-1].outdated:
616 % if comments and comments[-1].outdated:
617 <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}">
617 <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}">
618 ${_('Add another comment')}
618 ${_('Add another comment')}
619 </span>
619 </span>
620 % else:
620 % else:
621 <span onclick="return Rhodecode.comments.createComment(this)" class="btn btn-secondary cb-comment-add-button">
621 <span onclick="return Rhodecode.comments.createComment(this)" class="btn btn-secondary cb-comment-add-button">
622 ${_('Add another comment')}
622 ${_('Add another comment')}
623 </span>
623 </span>
624 % endif
624 % endif
625
625
626 </div>
626 </div>
627 </%def>
627 </%def>
628
628
629 <%!
629 <%!
630
630
631 def get_inline_comments(comments, filename):
631 def get_inline_comments(comments, filename):
632 if hasattr(filename, 'unicode_path'):
632 if hasattr(filename, 'unicode_path'):
633 filename = filename.unicode_path
633 filename = filename.unicode_path
634
634
635 if not isinstance(filename, (unicode, str)):
635 if not isinstance(filename, (unicode, str)):
636 return None
636 return None
637
637
638 if comments and filename in comments:
638 if comments and filename in comments:
639 return comments[filename]
639 return comments[filename]
640
640
641 return None
641 return None
642
642
643 def get_comments_for(diff_type, comments, filename, line_version, line_number):
643 def get_comments_for(diff_type, comments, filename, line_version, line_number):
644 if hasattr(filename, 'unicode_path'):
644 if hasattr(filename, 'unicode_path'):
645 filename = filename.unicode_path
645 filename = filename.unicode_path
646
646
647 if not isinstance(filename, (unicode, str)):
647 if not isinstance(filename, (unicode, str)):
648 return None
648 return None
649
649
650 file_comments = get_inline_comments(comments, filename)
650 file_comments = get_inline_comments(comments, filename)
651 if file_comments is None:
651 if file_comments is None:
652 return None
652 return None
653
653
654 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
654 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
655 if line_key in file_comments:
655 if line_key in file_comments:
656 data = file_comments.pop(line_key)
656 data = file_comments.pop(line_key)
657 return data
657 return data
658 %>
658 %>
659
659
660 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
660 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
661
661
662 <% chunk_count = 1 %>
662 <% chunk_count = 1 %>
663 %for loop_obj, item in h.looper(hunk.sideside):
663 %for loop_obj, item in h.looper(hunk.sideside):
664 <%
664 <%
665 line = item
665 line = item
666 i = loop_obj.index
666 i = loop_obj.index
667 prev_line = loop_obj.previous
667 prev_line = loop_obj.previous
668 old_line_anchor, new_line_anchor = None, None
668 old_line_anchor, new_line_anchor = None, None
669
669
670 if line.original.lineno:
670 if line.original.lineno:
671 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
671 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
672 if line.modified.lineno:
672 if line.modified.lineno:
673 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
673 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
674
674
675 line_action = line.modified.action or line.original.action
675 line_action = line.modified.action or line.original.action
676 prev_line_action = prev_line and (prev_line.modified.action or prev_line.original.action)
676 prev_line_action = prev_line and (prev_line.modified.action or prev_line.original.action)
677 %>
677 %>
678
678
679 <tr class="cb-line">
679 <tr class="cb-line">
680 <td class="cb-data ${action_class(line.original.action)}"
680 <td class="cb-data ${action_class(line.original.action)}"
681 data-line-no="${line.original.lineno}"
681 data-line-no="${line.original.lineno}"
682 >
682 >
683
683
684 <% line_old_comments = None %>
684 <% line_old_comments = None %>
685 %if line.original.get_comment_args:
685 %if line.original.get_comment_args:
686 <% line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args) %>
686 <% line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args) %>
687 %endif
687 %endif
688 %if line_old_comments:
688 %if line_old_comments:
689 <% has_outdated = any([x.outdated for x in line_old_comments]) %>
689 <% has_outdated = any([x.outdated for x in line_old_comments]) %>
690 % if has_outdated:
690 % if has_outdated:
691 <i class="tooltip icon-comment-toggle" title="${_('comments including outdated: {}. Click here to display them.').format(len(line_old_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
691 <i class="tooltip icon-comment-toggle" title="${_('comments including outdated: {}. Click here to display them.').format(len(line_old_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
692 % else:
692 % else:
693 <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(line_old_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
693 <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(line_old_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
694 % endif
694 % endif
695 %endif
695 %endif
696 </td>
696 </td>
697 <td class="cb-lineno ${action_class(line.original.action)}"
697 <td class="cb-lineno ${action_class(line.original.action)}"
698 data-line-no="${line.original.lineno}"
698 data-line-no="${line.original.lineno}"
699 %if old_line_anchor:
699 %if old_line_anchor:
700 id="${old_line_anchor}"
700 id="${old_line_anchor}"
701 %endif
701 %endif
702 >
702 >
703 %if line.original.lineno:
703 %if line.original.lineno:
704 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
704 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
705 %endif
705 %endif
706 </td>
706 </td>
707 <td class="cb-content ${action_class(line.original.action)}"
707 <td class="cb-content ${action_class(line.original.action)}"
708 data-line-no="o${line.original.lineno}"
708 data-line-no="o${line.original.lineno}"
709 >
709 >
710 %if use_comments and line.original.lineno:
710 %if use_comments and line.original.lineno:
711 ${render_add_comment_button()}
711 ${render_add_comment_button()}
712 %endif
712 %endif
713 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
713 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
714
714
715 %if use_comments and line.original.lineno and line_old_comments:
715 %if use_comments and line.original.lineno and line_old_comments:
716 ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries)}
716 ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries)}
717 %endif
717 %endif
718
718
719 </td>
719 </td>
720 <td class="cb-data ${action_class(line.modified.action)}"
720 <td class="cb-data ${action_class(line.modified.action)}"
721 data-line-no="${line.modified.lineno}"
721 data-line-no="${line.modified.lineno}"
722 >
722 >
723 <div>
723 <div>
724
724
725 %if line.modified.get_comment_args:
725 %if line.modified.get_comment_args:
726 <% line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args) %>
726 <% line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args) %>
727 %else:
727 %else:
728 <% line_new_comments = None%>
728 <% line_new_comments = None%>
729 %endif
729 %endif
730 %if line_new_comments:
730 %if line_new_comments:
731
731
732 <% has_outdated = any([x.outdated for x in line_new_comments]) %>
732 <% has_outdated = any([x.outdated for x in line_new_comments]) %>
733 % if has_outdated:
733 % if has_outdated:
734 <i class="tooltip icon-comment-toggle" title="${_('comments including outdated: {}. Click here to display them.').format(len(line_new_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
734 <i class="tooltip icon-comment-toggle" title="${_('comments including outdated: {}. Click here to display them.').format(len(line_new_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
735 % else:
735 % else:
736 <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(line_new_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
736 <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(line_new_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
737 % endif
737 % endif
738 %endif
738 %endif
739 </div>
739 </div>
740 </td>
740 </td>
741 <td class="cb-lineno ${action_class(line.modified.action)}"
741 <td class="cb-lineno ${action_class(line.modified.action)}"
742 data-line-no="${line.modified.lineno}"
742 data-line-no="${line.modified.lineno}"
743 %if new_line_anchor:
743 %if new_line_anchor:
744 id="${new_line_anchor}"
744 id="${new_line_anchor}"
745 %endif
745 %endif
746 >
746 >
747 %if line.modified.lineno:
747 %if line.modified.lineno:
748 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
748 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
749 %endif
749 %endif
750 </td>
750 </td>
751 <td class="cb-content ${action_class(line.modified.action)}"
751 <td class="cb-content ${action_class(line.modified.action)}"
752 data-line-no="n${line.modified.lineno}"
752 data-line-no="n${line.modified.lineno}"
753 >
753 >
754 %if use_comments and line.modified.lineno:
754 %if use_comments and line.modified.lineno:
755 ${render_add_comment_button()}
755 ${render_add_comment_button()}
756 %endif
756 %endif
757 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
757 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
758 %if use_comments and line.modified.lineno and line_new_comments:
758 %if use_comments and line.modified.lineno and line_new_comments:
759 ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)}
759 ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)}
760 %endif
760 %endif
761 % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']:
761 % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']:
762 <div class="nav-chunk" style="visibility: hidden">
762 <div class="nav-chunk" style="visibility: hidden">
763 <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i>
763 <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i>
764 </div>
764 </div>
765 <% chunk_count +=1 %>
765 <% chunk_count +=1 %>
766 % endif
766 % endif
767 </td>
767 </td>
768 </tr>
768 </tr>
769 %endfor
769 %endfor
770 </%def>
770 </%def>
771
771
772
772
773 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
773 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
774 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
774 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
775
775
776 <%
776 <%
777 old_line_anchor, new_line_anchor = None, None
777 old_line_anchor, new_line_anchor = None, None
778 if old_line_no:
778 if old_line_no:
779 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
779 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
780 if new_line_no:
780 if new_line_no:
781 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
781 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
782 %>
782 %>
783 <tr class="cb-line">
783 <tr class="cb-line">
784 <td class="cb-data ${action_class(action)}">
784 <td class="cb-data ${action_class(action)}">
785 <div>
785 <div>
786
786
787 %if comments_args:
787 %if comments_args:
788 <% comments = get_comments_for('unified', inline_comments, *comments_args) %>
788 <% comments = get_comments_for('unified', inline_comments, *comments_args) %>
789 %else:
789 %else:
790 <% comments = None %>
790 <% comments = None %>
791 %endif
791 %endif
792
792
793 % if comments:
793 % if comments:
794 <% has_outdated = any([x.outdated for x in comments]) %>
794 <% has_outdated = any([x.outdated for x in comments]) %>
795 % if has_outdated:
795 % if has_outdated:
796 <i class="tooltip icon-comment-toggle" title="${_('comments including outdated: {}. Click here to display them.').format(len(comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
796 <i class="tooltip icon-comment-toggle" title="${_('comments including outdated: {}. Click here to display them.').format(len(comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
797 % else:
797 % else:
798 <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
798 <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
799 % endif
799 % endif
800 % endif
800 % endif
801 </div>
801 </div>
802 </td>
802 </td>
803 <td class="cb-lineno ${action_class(action)}"
803 <td class="cb-lineno ${action_class(action)}"
804 data-line-no="${old_line_no}"
804 data-line-no="${old_line_no}"
805 %if old_line_anchor:
805 %if old_line_anchor:
806 id="${old_line_anchor}"
806 id="${old_line_anchor}"
807 %endif
807 %endif
808 >
808 >
809 %if old_line_anchor:
809 %if old_line_anchor:
810 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
810 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
811 %endif
811 %endif
812 </td>
812 </td>
813 <td class="cb-lineno ${action_class(action)}"
813 <td class="cb-lineno ${action_class(action)}"
814 data-line-no="${new_line_no}"
814 data-line-no="${new_line_no}"
815 %if new_line_anchor:
815 %if new_line_anchor:
816 id="${new_line_anchor}"
816 id="${new_line_anchor}"
817 %endif
817 %endif
818 >
818 >
819 %if new_line_anchor:
819 %if new_line_anchor:
820 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
820 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
821 %endif
821 %endif
822 </td>
822 </td>
823 <td class="cb-content ${action_class(action)}"
823 <td class="cb-content ${action_class(action)}"
824 data-line-no="${(new_line_no and 'n' or 'o')}${(new_line_no or old_line_no)}"
824 data-line-no="${(new_line_no and 'n' or 'o')}${(new_line_no or old_line_no)}"
825 >
825 >
826 %if use_comments:
826 %if use_comments:
827 ${render_add_comment_button()}
827 ${render_add_comment_button()}
828 %endif
828 %endif
829 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
829 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
830 %if use_comments and comments:
830 %if use_comments and comments:
831 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
831 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
832 %endif
832 %endif
833 </td>
833 </td>
834 </tr>
834 </tr>
835 %endfor
835 %endfor
836 </%def>
836 </%def>
837
837
838
838
839 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)">
839 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)">
840 % if diff_mode == 'unified':
840 % if diff_mode == 'unified':
841 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
841 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
842 % elif diff_mode == 'sideside':
842 % elif diff_mode == 'sideside':
843 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
843 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
844 % else:
844 % else:
845 <tr class="cb-line">
845 <tr class="cb-line">
846 <td>unknown diff mode</td>
846 <td>unknown diff mode</td>
847 </tr>
847 </tr>
848 % endif
848 % endif
849 </%def>file changes
849 </%def>file changes
850
850
851
851
852 <%def name="render_add_comment_button()">
852 <%def name="render_add_comment_button()">
853 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)">
853 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)">
854 <span><i class="icon-comment"></i></span>
854 <span><i class="icon-comment"></i></span>
855 </button>
855 </button>
856 </%def>
856 </%def>
857
857
858 <%def name="render_diffset_menu(diffset, range_diff_on=None)">
858 <%def name="render_diffset_menu(diffset, range_diff_on=None, commit=None, pull_request_menu=None)">
859 <% diffset_container_id = h.md5(diffset.target_ref) %>
859 <% diffset_container_id = h.md5(diffset.target_ref) %>
860
860
861 <div id="diff-file-sticky" class="diffset-menu clearinner">
861 <div id="diff-file-sticky" class="diffset-menu clearinner">
862 ## auto adjustable
862 ## auto adjustable
863 <div class="sidebar__inner">
863 <div class="sidebar__inner">
864 <div class="sidebar__bar">
864 <div class="sidebar__bar">
865 <div class="pull-right">
865 <div class="pull-right">
866 <div class="btn-group">
866 <div class="btn-group">
867 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
867 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
868 <i class="icon-wide-mode"></i>
868 <i class="icon-wide-mode"></i>
869 </a>
869 </a>
870 </div>
870 </div>
871 <div class="btn-group">
871 <div class="btn-group">
872
872
873 <a
873 <a
874 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
874 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
875 title="${h.tooltip(_('View diff as side by side'))}"
875 title="${h.tooltip(_('View diff as side by side'))}"
876 href="${h.current_route_path(request, diffmode='sideside')}">
876 href="${h.current_route_path(request, diffmode='sideside')}">
877 <span>${_('Side by Side')}</span>
877 <span>${_('Side by Side')}</span>
878 </a>
878 </a>
879
879
880 <a
880 <a
881 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
881 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
882 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
882 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
883 <span>${_('Unified')}</span>
883 <span>${_('Unified')}</span>
884 </a>
884 </a>
885
885
886 % if range_diff_on is True:
886 % if range_diff_on is True:
887 <a
887 <a
888 title="${_('Turn off: Show the diff as commit range')}"
888 title="${_('Turn off: Show the diff as commit range')}"
889 class="btn btn-primary"
889 class="btn btn-primary"
890 href="${h.current_route_path(request, **{"range-diff":"0"})}">
890 href="${h.current_route_path(request, **{"range-diff":"0"})}">
891 <span>${_('Range Diff')}</span>
891 <span>${_('Range Diff')}</span>
892 </a>
892 </a>
893 % elif range_diff_on is False:
893 % elif range_diff_on is False:
894 <a
894 <a
895 title="${_('Show the diff as commit range')}"
895 title="${_('Show the diff as commit range')}"
896 class="btn"
896 class="btn"
897 href="${h.current_route_path(request, **{"range-diff":"1"})}">
897 href="${h.current_route_path(request, **{"range-diff":"1"})}">
898 <span>${_('Range Diff')}</span>
898 <span>${_('Range Diff')}</span>
899 </a>
899 </a>
900 % endif
900 % endif
901 </div>
901 </div>
902 <div class="btn-group">
902 <div class="btn-group">
903
903
904 <div class="pull-left">
904 <div class="pull-left">
905 ${h.hidden('diff_menu_{}'.format(diffset_container_id))}
905 ${h.hidden('diff_menu_{}'.format(diffset_container_id))}
906 </div>
906 </div>
907
907
908 </div>
908 </div>
909 </div>
909 </div>
910 <div class="pull-left">
910 <div class="pull-left">
911 <div class="btn-group">
911 <div class="btn-group">
912 <div class="pull-left">
912 <div class="pull-left">
913 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
913 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
914 </div>
914 </div>
915
915
916 </div>
916 </div>
917 </div>
917 </div>
918 </div>
918 </div>
919 <div class="fpath-placeholder pull-left">
919 <div class="fpath-placeholder pull-left">
920 <i class="icon-file-text"></i>
920 <i class="icon-file-text"></i>
921 <strong class="fpath-placeholder-text">
921 <strong class="fpath-placeholder-text">
922 Context file:
922 Context file:
923 </strong>
923 </strong>
924 </div>
924 </div>
925 <div class="pull-right noselect">
925 <div class="pull-right noselect">
926 <span id="diff_nav">Loading diff...:</span>
926
927 <span class="cursor-pointer" onclick="scrollToPrevChunk(); return false">
927 %if commit:
928 <i class="icon-angle-up"></i>
928 <span>
929 </span>
929 <code>${h.show_id(commit)}</code>
930 <span class="cursor-pointer" onclick="scrollToNextChunk(); return false">
930 </span>
931 <i class="icon-angle-down"></i>
931 %elif pull_request_menu and pull_request_menu.get('pull_request'):
932 </span>
932 <span>
933 <code>!${pull_request_menu['pull_request'].pull_request_id}</code>
934 </span>
935 %endif
936 % if commit or pull_request_menu:
937 <span id="diff_nav">Loading diff...:</span>
938 <span class="cursor-pointer" onclick="scrollToPrevChunk(); return false">
939 <i class="icon-angle-up"></i>
940 </span>
941 <span class="cursor-pointer" onclick="scrollToNextChunk(); return false">
942 <i class="icon-angle-down"></i>
943 </span>
944 % endif
933 </div>
945 </div>
934 <div class="sidebar_inner_shadow"></div>
946 <div class="sidebar_inner_shadow"></div>
935 </div>
947 </div>
936 </div>
948 </div>
937
949
938 % if diffset:
950 % if diffset:
939 %if diffset.limited_diff:
951 %if diffset.limited_diff:
940 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
952 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
941 %else:
953 %else:
942 <% file_placeholder = h.literal(_ungettext('%(num)s file changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>', '%(num)s files changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>',
954 <% file_placeholder = h.literal(_ungettext('%(num)s file changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>', '%(num)s files changed: <span class="op-added">%(linesadd)s inserted</span>, <span class="op-deleted">%(linesdel)s deleted</span>',
943 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
955 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
944
956
945 %endif
957 %endif
946 ## case on range-diff placeholder needs to be updated
958 ## case on range-diff placeholder needs to be updated
947 % if range_diff_on is True:
959 % if range_diff_on is True:
948 <% file_placeholder = _('Disabled on range diff') %>
960 <% file_placeholder = _('Disabled on range diff') %>
949 % endif
961 % endif
950
962
951 <script type="text/javascript">
963 <script type="text/javascript">
952 var feedFilesOptions = function (query, initialData) {
964 var feedFilesOptions = function (query, initialData) {
953 var data = {results: []};
965 var data = {results: []};
954 var isQuery = typeof query.term !== 'undefined';
966 var isQuery = typeof query.term !== 'undefined';
955
967
956 var section = _gettext('Changed files');
968 var section = _gettext('Changed files');
957 var filteredData = [];
969 var filteredData = [];
958
970
959 //filter results
971 //filter results
960 $.each(initialData.results, function (idx, value) {
972 $.each(initialData.results, function (idx, value) {
961
973
962 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
974 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
963 filteredData.push({
975 filteredData.push({
964 'id': this.id,
976 'id': this.id,
965 'text': this.text,
977 'text': this.text,
966 "ops": this.ops,
978 "ops": this.ops,
967 })
979 })
968 }
980 }
969
981
970 });
982 });
971
983
972 data.results = filteredData;
984 data.results = filteredData;
973
985
974 query.callback(data);
986 query.callback(data);
975 };
987 };
976
988
977 var selectionFormatter = function(data, escapeMarkup) {
989 var selectionFormatter = function(data, escapeMarkup) {
978 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
990 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
979 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
991 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
980 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
992 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
981 '<span class="pill" op="added">{0}</span>' +
993 '<span class="pill" op="added">{0}</span>' +
982 '<span class="pill" op="deleted">{1}</span>' +
994 '<span class="pill" op="deleted">{1}</span>' +
983 '</div>'
995 '</div>'
984 ;
996 ;
985 var added = data['ops']['added'];
997 var added = data['ops']['added'];
986 if (added === 0) {
998 if (added === 0) {
987 // don't show +0
999 // don't show +0
988 added = 0;
1000 added = 0;
989 } else {
1001 } else {
990 added = '+' + added;
1002 added = '+' + added;
991 }
1003 }
992
1004
993 var deleted = -1*data['ops']['deleted'];
1005 var deleted = -1*data['ops']['deleted'];
994
1006
995 tmpl += pill.format(added, deleted);
1007 tmpl += pill.format(added, deleted);
996 return container.format(tmpl);
1008 return container.format(tmpl);
997 };
1009 };
998 var formatFileResult = function(result, container, query, escapeMarkup) {
1010 var formatFileResult = function(result, container, query, escapeMarkup) {
999 return selectionFormatter(result, escapeMarkup);
1011 return selectionFormatter(result, escapeMarkup);
1000 };
1012 };
1001
1013
1002 var formatSelection = function (data, container) {
1014 var formatSelection = function (data, container) {
1003 return '${file_placeholder}'
1015 return '${file_placeholder}'
1004 };
1016 };
1005
1017
1006 if (window.preloadFileFilterData === undefined) {
1018 if (window.preloadFileFilterData === undefined) {
1007 window.preloadFileFilterData = {}
1019 window.preloadFileFilterData = {}
1008 }
1020 }
1009
1021
1010 preloadFileFilterData["${diffset_container_id}"] = {
1022 preloadFileFilterData["${diffset_container_id}"] = {
1011 results: [
1023 results: [
1012 % for filediff in diffset.files:
1024 % for filediff in diffset.files:
1013 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
1025 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
1014 text:"${filediff.patch['filename']}",
1026 text:"${filediff.patch['filename']}",
1015 ops:${h.json.dumps(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
1027 ops:${h.json.dumps(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
1016 % endfor
1028 % endfor
1017 ]
1029 ]
1018 };
1030 };
1019
1031
1020 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
1032 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
1021 var diffFileFilter = $(diffFileFilterId).select2({
1033 var diffFileFilter = $(diffFileFilterId).select2({
1022 'dropdownAutoWidth': true,
1034 'dropdownAutoWidth': true,
1023 'width': 'auto',
1035 'width': 'auto',
1024
1036
1025 containerCssClass: "drop-menu",
1037 containerCssClass: "drop-menu",
1026 dropdownCssClass: "drop-menu-dropdown",
1038 dropdownCssClass: "drop-menu-dropdown",
1027 data: preloadFileFilterData["${diffset_container_id}"],
1039 data: preloadFileFilterData["${diffset_container_id}"],
1028 query: function(query) {
1040 query: function(query) {
1029 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
1041 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
1030 },
1042 },
1031 initSelection: function(element, callback) {
1043 initSelection: function(element, callback) {
1032 callback({'init': true});
1044 callback({'init': true});
1033 },
1045 },
1034 formatResult: formatFileResult,
1046 formatResult: formatFileResult,
1035 formatSelection: formatSelection
1047 formatSelection: formatSelection
1036 });
1048 });
1037
1049
1038 % if range_diff_on is True:
1050 % if range_diff_on is True:
1039 diffFileFilter.select2("enable", false);
1051 diffFileFilter.select2("enable", false);
1040 % endif
1052 % endif
1041
1053
1042 $(diffFileFilterId).on('select2-selecting', function (e) {
1054 $(diffFileFilterId).on('select2-selecting', function (e) {
1043 var idSelector = e.choice.id;
1055 var idSelector = e.choice.id;
1044
1056
1045 // expand the container if we quick-select the field
1057 // expand the container if we quick-select the field
1046 $('#'+idSelector).next().prop('checked', false);
1058 $('#'+idSelector).next().prop('checked', false);
1047 // hide the mast as we later do preventDefault()
1059 // hide the mast as we later do preventDefault()
1048 $("#select2-drop-mask").click();
1060 $("#select2-drop-mask").click();
1049
1061
1050 window.location.hash = '#'+idSelector;
1062 window.location.hash = '#'+idSelector;
1051 updateSticky();
1063 updateSticky();
1052
1064
1053 e.preventDefault();
1065 e.preventDefault();
1054 });
1066 });
1055
1067
1068 diffNavText = 'diff navigation:'
1069
1056 getCurrentChunk = function () {
1070 getCurrentChunk = function () {
1057
1071
1058 var chunksAll = $('.nav-chunk').filter(function () {
1072 var chunksAll = $('.nav-chunk').filter(function () {
1059 return $(this).parents('.filediff').prev().get(0).checked !== true
1073 return $(this).parents('.filediff').prev().get(0).checked !== true
1060 })
1074 })
1061 var chunkSelected = $('.nav-chunk.selected');
1075 var chunkSelected = $('.nav-chunk.selected');
1062 var initial = false;
1076 var initial = false;
1063
1077
1064 if (chunkSelected.length === 0) {
1078 if (chunkSelected.length === 0) {
1065 // no initial chunk selected, we pick first
1079 // no initial chunk selected, we pick first
1066 chunkSelected = $(chunksAll.get(0));
1080 chunkSelected = $(chunksAll.get(0));
1067 var initial = true;
1081 var initial = true;
1068 }
1082 }
1069
1083
1070 return {
1084 return {
1071 'all': chunksAll,
1085 'all': chunksAll,
1072 'selected': chunkSelected,
1086 'selected': chunkSelected,
1073 'initial': initial,
1087 'initial': initial,
1074 }
1088 }
1075 }
1089 }
1076
1090
1077 animateDiffNavText = function () {
1091 animateDiffNavText = function () {
1078 var $diffNav = $('#diff_nav')
1092 var $diffNav = $('#diff_nav')
1079
1093
1080 var callback = function () {
1094 var callback = function () {
1081 $diffNav.animate({'opacity': 1.00}, 200)
1095 $diffNav.animate({'opacity': 1.00}, 200)
1082 };
1096 };
1083 $diffNav.animate({'opacity': 0.15}, 200, callback);
1097 $diffNav.animate({'opacity': 0.15}, 200, callback);
1084 }
1098 }
1085
1099
1086 scrollToChunk = function (moveBy) {
1100 scrollToChunk = function (moveBy) {
1087 var chunk = getCurrentChunk();
1101 var chunk = getCurrentChunk();
1088 var all = chunk.all
1102 var all = chunk.all
1089 var selected = chunk.selected
1103 var selected = chunk.selected
1090
1104
1091 var curPos = all.index(selected);
1105 var curPos = all.index(selected);
1092 var newPos = curPos;
1106 var newPos = curPos;
1093 if (!chunk.initial) {
1107 if (!chunk.initial) {
1094 var newPos = curPos + moveBy;
1108 var newPos = curPos + moveBy;
1095 }
1109 }
1096
1110
1097 var curElem = all.get(newPos);
1111 var curElem = all.get(newPos);
1098
1112
1099 if (curElem === undefined) {
1113 if (curElem === undefined) {
1100 // end or back
1114 // end or back
1101 $('#diff_nav').html('No next diff element.')
1115 $('#diff_nav').html('no next diff element:')
1102 animateDiffNavText()
1116 animateDiffNavText()
1103 return
1117 return
1104 } else if (newPos < 0) {
1118 } else if (newPos < 0) {
1105 $('#diff_nav').html('No previous diff element.')
1119 $('#diff_nav').html('no previous diff element:')
1106 animateDiffNavText()
1120 animateDiffNavText()
1107 return
1121 return
1108 } else {
1122 } else {
1109 $('#diff_nav').html('Diff navigation:')
1123 $('#diff_nav').html(diffNavText)
1110 }
1124 }
1111
1125
1112 curElem = $(curElem)
1126 curElem = $(curElem)
1113 var offset = 100;
1127 var offset = 100;
1114 $(window).scrollTop(curElem.position().top - offset);
1128 $(window).scrollTop(curElem.position().top - offset);
1115
1129
1116 //clear selection
1130 //clear selection
1117 all.removeClass('selected')
1131 all.removeClass('selected')
1118 curElem.addClass('selected')
1132 curElem.addClass('selected')
1119 }
1133 }
1120
1134
1121 scrollToPrevChunk = function () {
1135 scrollToPrevChunk = function () {
1122 scrollToChunk(-1)
1136 scrollToChunk(-1)
1123 }
1137 }
1124 scrollToNextChunk = function () {
1138 scrollToNextChunk = function () {
1125 scrollToChunk(1)
1139 scrollToChunk(1)
1126 }
1140 }
1127
1141
1128 </script>
1142 </script>
1129 % endif
1143 % endif
1130
1144
1131 <script type="text/javascript">
1145 <script type="text/javascript">
1132 $('#diff_nav').html('loading diff...') // wait until whole page is loaded
1146 $('#diff_nav').html('loading diff...') // wait until whole page is loaded
1133
1147
1134 $(document).ready(function () {
1148 $(document).ready(function () {
1135
1149
1136 var contextPrefix = _gettext('Context file: ');
1150 var contextPrefix = _gettext('Context file: ');
1137 ## sticky sidebar
1151 ## sticky sidebar
1138 var sidebarElement = document.getElementById('diff-file-sticky');
1152 var sidebarElement = document.getElementById('diff-file-sticky');
1139 sidebar = new StickySidebar(sidebarElement, {
1153 sidebar = new StickySidebar(sidebarElement, {
1140 topSpacing: 0,
1154 topSpacing: 0,
1141 bottomSpacing: 0,
1155 bottomSpacing: 0,
1142 innerWrapperSelector: '.sidebar__inner'
1156 innerWrapperSelector: '.sidebar__inner'
1143 });
1157 });
1144 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1158 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1145 // reset our file so it's not holding new value
1159 // reset our file so it's not holding new value
1146 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1160 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1147 });
1161 });
1148
1162
1149 updateSticky = function () {
1163 updateSticky = function () {
1150 sidebar.updateSticky();
1164 sidebar.updateSticky();
1151 Waypoint.refreshAll();
1165 Waypoint.refreshAll();
1152 };
1166 };
1153
1167
1154 var animateText = function (fPath, anchorId) {
1168 var animateText = function (fPath, anchorId) {
1155 fPath = Select2.util.escapeMarkup(fPath);
1169 fPath = Select2.util.escapeMarkup(fPath);
1156 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1170 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1157 };
1171 };
1158
1172
1159 ## dynamic file waypoints
1173 ## dynamic file waypoints
1160 var setFPathInfo = function(fPath, anchorId){
1174 var setFPathInfo = function(fPath, anchorId){
1161 animateText(fPath, anchorId)
1175 animateText(fPath, anchorId)
1162 };
1176 };
1163
1177
1164 var codeBlock = $('.filediff');
1178 var codeBlock = $('.filediff');
1165
1179
1166 // forward waypoint
1180 // forward waypoint
1167 codeBlock.waypoint(
1181 codeBlock.waypoint(
1168 function(direction) {
1182 function(direction) {
1169 if (direction === "down"){
1183 if (direction === "down"){
1170 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1184 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1171 }
1185 }
1172 }, {
1186 }, {
1173 offset: function () {
1187 offset: function () {
1174 return 70;
1188 return 70;
1175 },
1189 },
1176 context: '.fpath-placeholder'
1190 context: '.fpath-placeholder'
1177 }
1191 }
1178 );
1192 );
1179
1193
1180 // backward waypoint
1194 // backward waypoint
1181 codeBlock.waypoint(
1195 codeBlock.waypoint(
1182 function(direction) {
1196 function(direction) {
1183 if (direction === "up"){
1197 if (direction === "up"){
1184 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1198 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1185 }
1199 }
1186 }, {
1200 }, {
1187 offset: function () {
1201 offset: function () {
1188 return -this.element.clientHeight + 90;
1202 return -this.element.clientHeight + 90;
1189 },
1203 },
1190 context: '.fpath-placeholder'
1204 context: '.fpath-placeholder'
1191 }
1205 }
1192 );
1206 );
1193
1207
1194 toggleWideDiff = function (el) {
1208 toggleWideDiff = function (el) {
1195 updateSticky();
1209 updateSticky();
1196 var wide = Rhodecode.comments.toggleWideMode(this);
1210 var wide = Rhodecode.comments.toggleWideMode(this);
1197 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1211 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1198 if (wide === true) {
1212 if (wide === true) {
1199 $(el).addClass('btn-active');
1213 $(el).addClass('btn-active');
1200 } else {
1214 } else {
1201 $(el).removeClass('btn-active');
1215 $(el).removeClass('btn-active');
1202 }
1216 }
1203 return null;
1217 return null;
1204 };
1218 };
1205
1219
1206 var preloadDiffMenuData = {
1220 var preloadDiffMenuData = {
1207 results: [
1221 results: [
1208
1222
1209 ## Whitespace change
1223 ## Whitespace change
1210 % if request.GET.get('ignorews', '') == '1':
1224 % if request.GET.get('ignorews', '') == '1':
1211 {
1225 {
1212 id: 2,
1226 id: 2,
1213 text: _gettext('Show whitespace changes'),
1227 text: _gettext('Show whitespace changes'),
1214 action: function () {},
1228 action: function () {},
1215 url: "${h.current_route_path(request, ignorews=0)|n}"
1229 url: "${h.current_route_path(request, ignorews=0)|n}"
1216 },
1230 },
1217 % else:
1231 % else:
1218 {
1232 {
1219 id: 2,
1233 id: 2,
1220 text: _gettext('Hide whitespace changes'),
1234 text: _gettext('Hide whitespace changes'),
1221 action: function () {},
1235 action: function () {},
1222 url: "${h.current_route_path(request, ignorews=1)|n}"
1236 url: "${h.current_route_path(request, ignorews=1)|n}"
1223 },
1237 },
1224 % endif
1238 % endif
1225
1239
1226 ## FULL CONTEXT
1240 ## FULL CONTEXT
1227 % if request.GET.get('fullcontext', '') == '1':
1241 % if request.GET.get('fullcontext', '') == '1':
1228 {
1242 {
1229 id: 3,
1243 id: 3,
1230 text: _gettext('Hide full context diff'),
1244 text: _gettext('Hide full context diff'),
1231 action: function () {},
1245 action: function () {},
1232 url: "${h.current_route_path(request, fullcontext=0)|n}"
1246 url: "${h.current_route_path(request, fullcontext=0)|n}"
1233 },
1247 },
1234 % else:
1248 % else:
1235 {
1249 {
1236 id: 3,
1250 id: 3,
1237 text: _gettext('Show full context diff'),
1251 text: _gettext('Show full context diff'),
1238 action: function () {},
1252 action: function () {},
1239 url: "${h.current_route_path(request, fullcontext=1)|n}"
1253 url: "${h.current_route_path(request, fullcontext=1)|n}"
1240 },
1254 },
1241 % endif
1255 % endif
1242
1256
1243 ]
1257 ]
1244 };
1258 };
1245
1259
1246 var diffMenuId = "#diff_menu_" + "${diffset_container_id}";
1260 var diffMenuId = "#diff_menu_" + "${diffset_container_id}";
1247 $(diffMenuId).select2({
1261 $(diffMenuId).select2({
1248 minimumResultsForSearch: -1,
1262 minimumResultsForSearch: -1,
1249 containerCssClass: "drop-menu-no-width",
1263 containerCssClass: "drop-menu-no-width",
1250 dropdownCssClass: "drop-menu-dropdown",
1264 dropdownCssClass: "drop-menu-dropdown",
1251 dropdownAutoWidth: true,
1265 dropdownAutoWidth: true,
1252 data: preloadDiffMenuData,
1266 data: preloadDiffMenuData,
1253 placeholder: "${_('...')}",
1267 placeholder: "${_('...')}",
1254 });
1268 });
1255 $(diffMenuId).on('select2-selecting', function (e) {
1269 $(diffMenuId).on('select2-selecting', function (e) {
1256 e.choice.action();
1270 e.choice.action();
1257 if (e.choice.url !== null) {
1271 if (e.choice.url !== null) {
1258 window.location = e.choice.url
1272 window.location = e.choice.url
1259 }
1273 }
1260 });
1274 });
1261 toggleExpand = function (el, diffsetEl) {
1275 toggleExpand = function (el, diffsetEl) {
1262 var el = $(el);
1276 var el = $(el);
1263 if (el.hasClass('collapsed')) {
1277 if (el.hasClass('collapsed')) {
1264 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1278 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1265 el.removeClass('collapsed');
1279 el.removeClass('collapsed');
1266 el.html(
1280 el.html(
1267 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1281 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1268 _gettext('Collapse all files'));
1282 _gettext('Collapse all files'));
1269 }
1283 }
1270 else {
1284 else {
1271 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1285 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1272 el.addClass('collapsed');
1286 el.addClass('collapsed');
1273 el.html(
1287 el.html(
1274 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1288 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1275 _gettext('Expand all files'));
1289 _gettext('Expand all files'));
1276 }
1290 }
1277 updateSticky()
1291 updateSticky()
1278 };
1292 };
1279
1293
1280 toggleCommitExpand = function (el) {
1294 toggleCommitExpand = function (el) {
1281 var $el = $(el);
1295 var $el = $(el);
1282 var commits = $el.data('toggleCommitsCnt');
1296 var commits = $el.data('toggleCommitsCnt');
1283 var collapseMsg = _ngettext('Collapse {0} commit', 'Collapse {0} commits', commits).format(commits);
1297 var collapseMsg = _ngettext('Collapse {0} commit', 'Collapse {0} commits', commits).format(commits);
1284 var expandMsg = _ngettext('Expand {0} commit', 'Expand {0} commits', commits).format(commits);
1298 var expandMsg = _ngettext('Expand {0} commit', 'Expand {0} commits', commits).format(commits);
1285
1299
1286 if ($el.hasClass('collapsed')) {
1300 if ($el.hasClass('collapsed')) {
1287 $('.compare_select').show();
1301 $('.compare_select').show();
1288 $('.compare_select_hidden').hide();
1302 $('.compare_select_hidden').hide();
1289
1303
1290 $el.removeClass('collapsed');
1304 $el.removeClass('collapsed');
1291 $el.html(
1305 $el.html(
1292 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1306 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1293 collapseMsg);
1307 collapseMsg);
1294 }
1308 }
1295 else {
1309 else {
1296 $('.compare_select').hide();
1310 $('.compare_select').hide();
1297 $('.compare_select_hidden').show();
1311 $('.compare_select_hidden').show();
1298 $el.addClass('collapsed');
1312 $el.addClass('collapsed');
1299 $el.html(
1313 $el.html(
1300 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1314 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1301 expandMsg);
1315 expandMsg);
1302 }
1316 }
1303 updateSticky();
1317 updateSticky();
1304 };
1318 };
1305
1319
1306 // get stored diff mode and pre-enable it
1320 // get stored diff mode and pre-enable it
1307 if (templateContext.session_attrs.wide_diff_mode === "true") {
1321 if (templateContext.session_attrs.wide_diff_mode === "true") {
1308 Rhodecode.comments.toggleWideMode(null);
1322 Rhodecode.comments.toggleWideMode(null);
1309 $('.toggle-wide-diff').addClass('btn-active');
1323 $('.toggle-wide-diff').addClass('btn-active');
1310 updateSticky();
1324 updateSticky();
1311 }
1325 }
1312
1326
1313 // DIFF NAV //
1327 // DIFF NAV //
1314
1328
1315 // element to detect scroll direction of
1329 // element to detect scroll direction of
1316 var $window = $(window);
1330 var $window = $(window);
1317
1331
1318 // initialize last scroll position
1332 // initialize last scroll position
1319 var lastScrollY = $window.scrollTop();
1333 var lastScrollY = $window.scrollTop();
1320
1334
1321 $window.on('resize scrollstop', {latency: 350}, function () {
1335 $window.on('resize scrollstop', {latency: 350}, function () {
1322 var visibleChunks = $('.nav-chunk').withinviewport({top: 75});
1336 var visibleChunks = $('.nav-chunk').withinviewport({top: 75});
1323
1337
1324 // get current scroll position
1338 // get current scroll position
1325 var currentScrollY = $window.scrollTop();
1339 var currentScrollY = $window.scrollTop();
1326
1340
1327 // determine current scroll direction
1341 // determine current scroll direction
1328 if (currentScrollY > lastScrollY) {
1342 if (currentScrollY > lastScrollY) {
1329 var y = 'down'
1343 var y = 'down'
1330 } else if (currentScrollY !== lastScrollY) {
1344 } else if (currentScrollY !== lastScrollY) {
1331 var y = 'up';
1345 var y = 'up';
1332 }
1346 }
1333
1347
1334 var pos = -1; // by default we use last element in viewport
1348 var pos = -1; // by default we use last element in viewport
1335 if (y === 'down') {
1349 if (y === 'down') {
1336 pos = -1;
1350 pos = -1;
1337 } else if (y === 'up') {
1351 } else if (y === 'up') {
1338 pos = 0;
1352 pos = 0;
1339 }
1353 }
1340
1354
1341 if (visibleChunks.length > 0) {
1355 if (visibleChunks.length > 0) {
1342 $('.nav-chunk').removeClass('selected');
1356 $('.nav-chunk').removeClass('selected');
1343 $(visibleChunks.get(pos)).addClass('selected');
1357 $(visibleChunks.get(pos)).addClass('selected');
1344 }
1358 }
1345
1359
1346 // update last scroll position to current position
1360 // update last scroll position to current position
1347 lastScrollY = currentScrollY;
1361 lastScrollY = currentScrollY;
1348
1362
1349 });
1363 });
1350 $('#diff_nav').html('Diff navigation:')
1364 $('#diff_nav').html(diffNavText);
1351
1365
1352 });
1366 });
1353 </script>
1367 </script>
1354
1368
1355 </%def>
1369 </%def>
@@ -1,920 +1,921 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)}
6 ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)}
7 %if c.rhodecode_name:
7 %if c.rhodecode_name:
8 &middot; ${h.branding(c.rhodecode_name)}
8 &middot; ${h.branding(c.rhodecode_name)}
9 %endif
9 %endif
10 </%def>
10 </%def>
11
11
12 <%def name="breadcrumbs_links()">
12 <%def name="breadcrumbs_links()">
13
13
14 </%def>
14 </%def>
15
15
16 <%def name="menu_bar_nav()">
16 <%def name="menu_bar_nav()">
17 ${self.menu_items(active='repositories')}
17 ${self.menu_items(active='repositories')}
18 </%def>
18 </%def>
19
19
20 <%def name="menu_bar_subnav()">
20 <%def name="menu_bar_subnav()">
21 ${self.repo_menu(active='showpullrequest')}
21 ${self.repo_menu(active='showpullrequest')}
22 </%def>
22 </%def>
23
23
24 <%def name="main()">
24 <%def name="main()">
25
25
26 <script type="text/javascript">
26 <script type="text/javascript">
27 // TODO: marcink switch this to pyroutes
27 // TODO: marcink switch this to pyroutes
28 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__')}";
28 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__')}";
29 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
29 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
30 </script>
30 </script>
31
31
32 <div class="box">
32 <div class="box">
33
33
34 <div class="box pr-summary">
34 <div class="box pr-summary">
35
35
36 <div class="summary-details block-left">
36 <div class="summary-details block-left">
37 <div id="pr-title">
37 <div id="pr-title">
38 % if c.pull_request.is_closed():
38 % if c.pull_request.is_closed():
39 <span class="pr-title-closed-tag tag">${_('Closed')}</span>
39 <span class="pr-title-closed-tag tag">${_('Closed')}</span>
40 % endif
40 % endif
41 <input class="pr-title-input large disabled" disabled="disabled" name="pullrequest_title" type="text" value="${c.pull_request.title}">
41 <input class="pr-title-input large disabled" disabled="disabled" name="pullrequest_title" type="text" value="${c.pull_request.title}">
42 </div>
42 </div>
43 <div id="pr-title-edit" class="input" style="display: none;">
43 <div id="pr-title-edit" class="input" style="display: none;">
44 <input class="pr-title-input large" id="pr-title-input" name="pullrequest_title" type="text" value="${c.pull_request.title}">
44 <input class="pr-title-input large" id="pr-title-input" name="pullrequest_title" type="text" value="${c.pull_request.title}">
45 </div>
45 </div>
46
46
47 <% summary = lambda n:{False:'summary-short'}.get(n) %>
47 <% summary = lambda n:{False:'summary-short'}.get(n) %>
48 <div class="pr-details-title">
48 <div class="pr-details-title">
49 <div class="pull-left">
49 <div class="pull-left">
50 <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>
50 <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>
51 ${_('Created on')}
51 ${_('Created on')}
52 <span class="tooltip" title="${_('Last updated on')} ${h.format_date(c.pull_request.updated_on)}">${h.format_date(c.pull_request.created_on)},</span>
52 <span class="tooltip" title="${_('Last updated on')} ${h.format_date(c.pull_request.updated_on)}">${h.format_date(c.pull_request.created_on)},</span>
53 <span class="pr-details-title-author-pref">${_('by')}</span>
53 <span class="pr-details-title-author-pref">${_('by')}</span>
54 </div>
54 </div>
55
55
56 <div class="pull-left">
56 <div class="pull-left">
57 ${self.gravatar_with_user(c.pull_request.author.email, 16, tooltip=True)}
57 ${self.gravatar_with_user(c.pull_request.author.email, 16, tooltip=True)}
58 </div>
58 </div>
59
59
60 %if c.allowed_to_update:
60 %if c.allowed_to_update:
61 <div class="pull-right">
61 <div class="pull-right">
62 <div id="edit_pull_request" class="action_button pr-save" style="display: none;">${_('Update title & description')}</div>
62 <div id="edit_pull_request" class="action_button pr-save" style="display: none;">${_('Update title & description')}</div>
63 <div id="delete_pullrequest" class="action_button pr-save ${('' if c.allowed_to_delete else 'disabled' )}" style="display: none;">
63 <div id="delete_pullrequest" class="action_button pr-save ${('' if c.allowed_to_delete else 'disabled' )}" style="display: none;">
64 % if c.allowed_to_delete:
64 % if c.allowed_to_delete:
65 ${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)}
65 ${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)}
66 <input class="btn btn-link btn-danger no-margin" id="remove_${c.pull_request.pull_request_id}" name="remove_${c.pull_request.pull_request_id}"
66 <input class="btn btn-link btn-danger no-margin" id="remove_${c.pull_request.pull_request_id}" name="remove_${c.pull_request.pull_request_id}"
67 onclick="submitConfirm(event, this, _gettext('Confirm to delete this pull request'), _gettext('Delete'), '${'!{}'.format(c.pull_request.pull_request_id)}')"
67 onclick="submitConfirm(event, this, _gettext('Confirm to delete this pull request'), _gettext('Delete'), '${'!{}'.format(c.pull_request.pull_request_id)}')"
68 type="submit" value="${_('Delete pull request')}">
68 type="submit" value="${_('Delete pull request')}">
69 ${h.end_form()}
69 ${h.end_form()}
70 % else:
70 % else:
71 <span class="tooltip" title="${_('Not allowed to delete this pull request')}">${_('Delete pull request')}</span>
71 <span class="tooltip" title="${_('Not allowed to delete this pull request')}">${_('Delete pull request')}</span>
72 % endif
72 % endif
73 </div>
73 </div>
74 <div id="open_edit_pullrequest" class="action_button">${_('Edit')}</div>
74 <div id="open_edit_pullrequest" class="action_button">${_('Edit')}</div>
75 <div id="close_edit_pullrequest" class="action_button" style="display: none;">${_('Cancel')}</div>
75 <div id="close_edit_pullrequest" class="action_button" style="display: none;">${_('Cancel')}</div>
76 </div>
76 </div>
77
77
78 %endif
78 %endif
79 </div>
79 </div>
80
80
81 <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}">
81 <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}">
82 ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)}
82 ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)}
83 </div>
83 </div>
84
84
85 <div id="pr-desc-edit" class="input textarea" style="display: none;">
85 <div id="pr-desc-edit" class="input textarea" style="display: none;">
86 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
86 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
87 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
87 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
88 </div>
88 </div>
89
89
90 <div id="summary" class="fields pr-details-content">
90 <div id="summary" class="fields pr-details-content">
91
91
92 ## review
92 ## review
93 <div class="field">
93 <div class="field">
94 <div class="label-pr-detail">
94 <div class="label-pr-detail">
95 <label>${_('Review status')}:</label>
95 <label>${_('Review status')}:</label>
96 </div>
96 </div>
97 <div class="input">
97 <div class="input">
98 %if c.pull_request_review_status:
98 %if c.pull_request_review_status:
99 <div class="tag status-tag-${c.pull_request_review_status}">
99 <div class="tag status-tag-${c.pull_request_review_status}">
100 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
100 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
101 <span class="changeset-status-lbl">
101 <span class="changeset-status-lbl">
102 %if c.pull_request.is_closed():
102 %if c.pull_request.is_closed():
103 ${_('Closed')},
103 ${_('Closed')},
104 %endif
104 %endif
105
105
106 ${h.commit_status_lbl(c.pull_request_review_status)}
106 ${h.commit_status_lbl(c.pull_request_review_status)}
107
107
108 </span>
108 </span>
109 </div>
109 </div>
110 - ${_ungettext('calculated based on {} reviewer vote', 'calculated based on {} reviewers votes', len(c.pull_request_reviewers)).format(len(c.pull_request_reviewers))}
110 - ${_ungettext('calculated based on {} reviewer vote', 'calculated based on {} reviewers votes', len(c.pull_request_reviewers)).format(len(c.pull_request_reviewers))}
111 %endif
111 %endif
112 </div>
112 </div>
113 </div>
113 </div>
114
114
115 ## source
115 ## source
116 <div class="field">
116 <div class="field">
117 <div class="label-pr-detail">
117 <div class="label-pr-detail">
118 <label>${_('Commit flow')}:</label>
118 <label>${_('Commit flow')}:</label>
119 </div>
119 </div>
120 <div class="input">
120 <div class="input">
121 <div class="pr-commit-flow">
121 <div class="pr-commit-flow">
122 ## Source
122 ## Source
123 %if c.pull_request.source_ref_parts.type == 'branch':
123 %if c.pull_request.source_ref_parts.type == 'branch':
124 <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>
124 <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>
125 %else:
125 %else:
126 <code class="pr-source-info">${'{}:{}'.format(c.pull_request.source_ref_parts.type, c.pull_request.source_ref_parts.name)}</code>
126 <code class="pr-source-info">${'{}:{}'.format(c.pull_request.source_ref_parts.type, c.pull_request.source_ref_parts.name)}</code>
127 %endif
127 %endif
128 ${_('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>
128 ${_('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>
129 &rarr;
129 &rarr;
130 ## Target
130 ## Target
131 %if c.pull_request.target_ref_parts.type == 'branch':
131 %if c.pull_request.target_ref_parts.type == 'branch':
132 <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>
132 <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>
133 %else:
133 %else:
134 <code class="pr-target-info">${'{}:{}'.format(c.pull_request.target_ref_parts.type, c.pull_request.target_ref_parts.name)}</code>
134 <code class="pr-target-info">${'{}:{}'.format(c.pull_request.target_ref_parts.type, c.pull_request.target_ref_parts.name)}</code>
135 %endif
135 %endif
136
136
137 ${_('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>
137 ${_('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>
138
138
139 <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>'>
139 <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>'>
140 <i class="icon-angle-down">more details</i>
140 <i class="icon-angle-down">more details</i>
141 </a>
141 </a>
142
142
143 </div>
143 </div>
144
144
145 <div class="source-details" style="display: none">
145 <div class="source-details" style="display: none">
146
146
147 <ul>
147 <ul>
148
148
149 ## common ancestor
149 ## common ancestor
150 <li>
150 <li>
151 ${_('Common ancestor')}:
151 ${_('Common ancestor')}:
152 % if c.ancestor_commit:
152 % if c.ancestor_commit:
153 <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>
153 <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>
154 % else:
154 % else:
155 ${_('not available')}
155 ${_('not available')}
156 % endif
156 % endif
157 </li>
157 </li>
158
158
159 ## pull url
159 ## pull url
160 <li>
160 <li>
161 %if h.is_hg(c.pull_request.source_repo):
161 %if h.is_hg(c.pull_request.source_repo):
162 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
162 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
163 %elif h.is_git(c.pull_request.source_repo):
163 %elif h.is_git(c.pull_request.source_repo):
164 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
164 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
165 %endif
165 %endif
166
166
167 <span>${_('Pull changes from source')}</span>: <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
167 <span>${_('Pull changes from source')}</span>: <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
168 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
168 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
169 </li>
169 </li>
170
170
171 ## Shadow repo
171 ## Shadow repo
172 <li>
172 <li>
173 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
173 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
174 %if h.is_hg(c.pull_request.target_repo):
174 %if h.is_hg(c.pull_request.target_repo):
175 <% 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) %>
175 <% 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) %>
176 %elif h.is_git(c.pull_request.target_repo):
176 %elif h.is_git(c.pull_request.target_repo):
177 <% 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) %>
177 <% 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) %>
178 %endif
178 %endif
179
179
180 <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">
180 <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">
181 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
181 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
182
182
183 % else:
183 % else:
184 <div class="">
184 <div class="">
185 ${_('Shadow repository data not available')}.
185 ${_('Shadow repository data not available')}.
186 </div>
186 </div>
187 % endif
187 % endif
188 </li>
188 </li>
189
189
190 </ul>
190 </ul>
191
191
192 </div>
192 </div>
193
193
194 </div>
194 </div>
195
195
196 </div>
196 </div>
197
197
198 ## versions
198 ## versions
199 <div class="field">
199 <div class="field">
200 <div class="label-pr-detail">
200 <div class="label-pr-detail">
201 <label>${_('Versions')}:</label>
201 <label>${_('Versions')}:</label>
202 </div>
202 </div>
203
203
204 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
204 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
205 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
205 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
206
206
207 <div class="pr-versions">
207 <div class="pr-versions">
208 % if c.show_version_changes:
208 % if c.show_version_changes:
209 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
209 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
210 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
210 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
211 ${_ungettext('{} version available for this pull request, ', '{} versions available for this pull request, ', len(c.versions)).format(len(c.versions))}
211 ${_ungettext('{} version available for this pull request, ', '{} versions available for this pull request, ', len(c.versions)).format(len(c.versions))}
212 <a id="show-pr-versions" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
212 <a id="show-pr-versions" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
213 data-toggle-on="${_('show versions')}."
213 data-toggle-on="${_('show versions')}."
214 data-toggle-off="${_('hide versions')}.">
214 data-toggle-off="${_('hide versions')}.">
215 ${_('show versions')}.
215 ${_('show versions')}.
216 </a>
216 </a>
217 <table>
217 <table>
218 ## SHOW ALL VERSIONS OF PR
218 ## SHOW ALL VERSIONS OF PR
219 <% ver_pr = None %>
219 <% ver_pr = None %>
220
220
221 % for data in reversed(list(enumerate(c.versions, 1))):
221 % for data in reversed(list(enumerate(c.versions, 1))):
222 <% ver_pos = data[0] %>
222 <% ver_pos = data[0] %>
223 <% ver = data[1] %>
223 <% ver = data[1] %>
224 <% ver_pr = ver.pull_request_version_id %>
224 <% ver_pr = ver.pull_request_version_id %>
225 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
225 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
226
226
227 <tr class="version-pr" style="display: ${display_row}">
227 <tr class="version-pr" style="display: ${display_row}">
228 <td>
228 <td>
229 <code>
229 <code>
230 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
230 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
231 </code>
231 </code>
232 </td>
232 </td>
233 <td>
233 <td>
234 <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}"/>
234 <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}"/>
235 <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}"/>
235 <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}"/>
236 </td>
236 </td>
237 <td>
237 <td>
238 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
238 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
239 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
239 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
240
240
241 </td>
241 </td>
242 <td>
242 <td>
243 % if c.at_version_num != ver_pr:
243 % if c.at_version_num != ver_pr:
244 <i class="tooltip icon-comment" title="${_('Comments from pull request version v{0}').format(ver_pos)}"></i>
244 <i class="tooltip icon-comment" title="${_('Comments from pull request version v{0}').format(ver_pos)}"></i>
245 <code>
245 <code>
246 General:${len(c.comment_versions[ver_pr]['at'])} / Inline:${len(c.inline_versions[ver_pr]['at'])}
246 General:${len(c.comment_versions[ver_pr]['at'])} / Inline:${len(c.inline_versions[ver_pr]['at'])}
247 </code>
247 </code>
248 % endif
248 % endif
249 </td>
249 </td>
250 <td>
250 <td>
251 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
251 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
252 </td>
252 </td>
253 <td>
253 <td>
254 <code>${h.age_component(ver.updated_on, time_is_local=True, tooltip=False)}</code>
254 <code>${h.age_component(ver.updated_on, time_is_local=True, tooltip=False)}</code>
255 </td>
255 </td>
256 </tr>
256 </tr>
257 % endfor
257 % endfor
258
258
259 <tr>
259 <tr>
260 <td colspan="6">
260 <td colspan="6">
261 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
261 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
262 data-label-text-locked="${_('select versions to show changes')}"
262 data-label-text-locked="${_('select versions to show changes')}"
263 data-label-text-diff="${_('show changes between versions')}"
263 data-label-text-diff="${_('show changes between versions')}"
264 data-label-text-show="${_('show pull request for this version')}"
264 data-label-text-show="${_('show pull request for this version')}"
265 >
265 >
266 ${_('select versions to show changes')}
266 ${_('select versions to show changes')}
267 </button>
267 </button>
268 </td>
268 </td>
269 </tr>
269 </tr>
270 </table>
270 </table>
271 % else:
271 % else:
272 <div>
272 <div>
273 ${_('Pull request versions not available')}.
273 ${_('Pull request versions not available')}.
274 </div>
274 </div>
275 % endif
275 % endif
276 </div>
276 </div>
277 </div>
277 </div>
278
278
279 </div>
279 </div>
280
280
281 </div>
281 </div>
282
282
283 ## REVIEW RULES
283 ## REVIEW RULES
284 <div id="review_rules" style="display: none" class="reviewers-title block-right">
284 <div id="review_rules" style="display: none" class="reviewers-title block-right">
285 <div class="pr-details-title">
285 <div class="pr-details-title">
286 ${_('Reviewer rules')}
286 ${_('Reviewer rules')}
287 %if c.allowed_to_update:
287 %if c.allowed_to_update:
288 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
288 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
289 %endif
289 %endif
290 </div>
290 </div>
291 <div class="pr-reviewer-rules">
291 <div class="pr-reviewer-rules">
292 ## review rules will be appended here, by default reviewers logic
292 ## review rules will be appended here, by default reviewers logic
293 </div>
293 </div>
294 <input id="review_data" type="hidden" name="review_data" value="">
294 <input id="review_data" type="hidden" name="review_data" value="">
295 </div>
295 </div>
296
296
297 ## REVIEWERS
297 ## REVIEWERS
298 <div class="reviewers-title first-panel block-right">
298 <div class="reviewers-title first-panel block-right">
299 <div class="pr-details-title">
299 <div class="pr-details-title">
300 ${_('Pull request reviewers')}
300 ${_('Pull request reviewers')}
301 %if c.allowed_to_update:
301 %if c.allowed_to_update:
302 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
302 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
303 %endif
303 %endif
304 </div>
304 </div>
305 </div>
305 </div>
306 <div id="reviewers" class="block-right pr-details-content reviewers">
306 <div id="reviewers" class="block-right pr-details-content reviewers">
307
307
308 ## members redering block
308 ## members redering block
309 <input type="hidden" name="__start__" value="review_members:sequence">
309 <input type="hidden" name="__start__" value="review_members:sequence">
310 <ul id="review_members" class="group_members">
310 <ul id="review_members" class="group_members">
311
311
312 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
312 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
313 <script>
313 <script>
314 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
314 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
315 var status = "${(status[0][1].status if status else 'not_reviewed')}";
315 var status = "${(status[0][1].status if status else 'not_reviewed')}";
316 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
316 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
317 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
317 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
318
318
319 var entry = renderTemplate('reviewMemberEntry', {
319 var entry = renderTemplate('reviewMemberEntry', {
320 'member': member,
320 'member': member,
321 'mandatory': member.mandatory,
321 'mandatory': member.mandatory,
322 'reasons': member.reasons,
322 'reasons': member.reasons,
323 'allowed_to_update': allowed_to_update,
323 'allowed_to_update': allowed_to_update,
324 'review_status': status,
324 'review_status': status,
325 'review_status_label': status_lbl,
325 'review_status_label': status_lbl,
326 'user_group': member.user_group,
326 'user_group': member.user_group,
327 'create': false
327 'create': false
328 });
328 });
329 $('#review_members').append(entry)
329 $('#review_members').append(entry)
330 </script>
330 </script>
331
331
332 % endfor
332 % endfor
333
333
334 </ul>
334 </ul>
335
335
336 <input type="hidden" name="__end__" value="review_members:sequence">
336 <input type="hidden" name="__end__" value="review_members:sequence">
337 ## end members redering block
337 ## end members redering block
338
338
339 %if not c.pull_request.is_closed():
339 %if not c.pull_request.is_closed():
340 <div id="add_reviewer" class="ac" style="display: none;">
340 <div id="add_reviewer" class="ac" style="display: none;">
341 %if c.allowed_to_update:
341 %if c.allowed_to_update:
342 % if not c.forbid_adding_reviewers:
342 % if not c.forbid_adding_reviewers:
343 <div id="add_reviewer_input" class="reviewer_ac">
343 <div id="add_reviewer_input" class="reviewer_ac">
344 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
344 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
345 <div id="reviewers_container"></div>
345 <div id="reviewers_container"></div>
346 </div>
346 </div>
347 % endif
347 % endif
348 <div class="pull-right">
348 <div class="pull-right">
349 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
349 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
350 </div>
350 </div>
351 %endif
351 %endif
352 </div>
352 </div>
353 %endif
353 %endif
354 </div>
354 </div>
355
355
356 ## TODOs will be listed here
356 ## TODOs will be listed here
357 <div class="reviewers-title block-right">
357 <div class="reviewers-title block-right">
358 <div class="pr-details-title">
358 <div class="pr-details-title">
359 ## Only show unresolved, that is only what matters
359 ## Only show unresolved, that is only what matters
360 TODO Comments - ${len(c.unresolved_comments)} / ${(len(c.unresolved_comments) + len(c.resolved_comments))}
360 TODO Comments - ${len(c.unresolved_comments)} / ${(len(c.unresolved_comments) + len(c.resolved_comments))}
361
361
362 % if not c.at_version:
362 % if not c.at_version:
363 % if c.resolved_comments:
363 % if c.resolved_comments:
364 <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return versionController.toggleElement(this, '.unresolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span>
364 <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return versionController.toggleElement(this, '.unresolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span>
365 % else:
365 % else:
366 <span class="block-right last-item noselect">Show resolved</span>
366 <span class="block-right last-item noselect">Show resolved</span>
367 % endif
367 % endif
368 % endif
368 % endif
369 </div>
369 </div>
370 </div>
370 </div>
371 <div class="block-right pr-details-content reviewers">
371 <div class="block-right pr-details-content reviewers">
372
372
373 <table class="todo-table">
373 <table class="todo-table">
374 <%
374 <%
375 def sorter(entry):
375 def sorter(entry):
376 user_id = entry.author.user_id
376 user_id = entry.author.user_id
377 resolved = '1' if entry.resolved else '0'
377 resolved = '1' if entry.resolved else '0'
378 if user_id == c.rhodecode_user.user_id:
378 if user_id == c.rhodecode_user.user_id:
379 # own comments first
379 # own comments first
380 user_id = 0
380 user_id = 0
381 return '{}_{}_{}'.format(resolved, user_id, str(entry.comment_id).zfill(100))
381 return '{}_{}_{}'.format(resolved, user_id, str(entry.comment_id).zfill(100))
382 %>
382 %>
383
383
384 % if c.at_version:
384 % if c.at_version:
385 <tr>
385 <tr>
386 <td class="unresolved-todo-text">${_('unresolved TODOs unavailable in this view')}.</td>
386 <td class="unresolved-todo-text">${_('unresolved TODOs unavailable in this view')}.</td>
387 </tr>
387 </tr>
388 % else:
388 % else:
389 % for todo_comment in sorted(c.unresolved_comments + c.resolved_comments, key=sorter):
389 % for todo_comment in sorted(c.unresolved_comments + c.resolved_comments, key=sorter):
390 <% resolved = todo_comment.resolved %>
390 <% resolved = todo_comment.resolved %>
391 % if inline:
391 % if inline:
392 <% outdated_at_ver = todo_comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
392 <% outdated_at_ver = todo_comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
393 % else:
393 % else:
394 <% outdated_at_ver = todo_comment.older_than_version(getattr(c, 'at_version_num', None)) %>
394 <% outdated_at_ver = todo_comment.older_than_version(getattr(c, 'at_version_num', None)) %>
395 % endif
395 % endif
396
396
397 <tr ${('class="unresolved-todo" style="display: none"' if resolved else '') |n}>
397 <tr ${('class="unresolved-todo" style="display: none"' if resolved else '') |n}>
398
398
399 <td class="td-todo-number">
399 <td class="td-todo-number">
400 % if resolved:
400 % if resolved:
401 <a class="permalink todo-resolved tooltip" title="${_('Resolved by comment #{}').format(todo_comment.resolved.comment_id)}" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
401 <a class="permalink todo-resolved tooltip" title="${_('Resolved by comment #{}').format(todo_comment.resolved.comment_id)}" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
402 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
402 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
403 % else:
403 % else:
404 <a class="permalink" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
404 <a class="permalink" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
405 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
405 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
406 % endif
406 % endif
407 </td>
407 </td>
408 <td class="td-todo-gravatar">
408 <td class="td-todo-gravatar">
409 ${base.gravatar(todo_comment.author.email, 16, user=todo_comment.author, tooltip=True, extra_class=['no-margin'])}
409 ${base.gravatar(todo_comment.author.email, 16, user=todo_comment.author, tooltip=True, extra_class=['no-margin'])}
410 </td>
410 </td>
411 <td class="todo-comment-text-wrapper">
411 <td class="todo-comment-text-wrapper">
412 <div class="todo-comment-text">
412 <div class="todo-comment-text">
413 <code>${h.chop_at_smart(todo_comment.text, '\n', suffix_if_chopped='...')}</code>
413 <code>${h.chop_at_smart(todo_comment.text, '\n', suffix_if_chopped='...')}</code>
414 </div>
414 </div>
415 </td>
415 </td>
416
416
417 </tr>
417 </tr>
418 % endfor
418 % endfor
419
419
420 % if len(c.unresolved_comments) == 0:
420 % if len(c.unresolved_comments) == 0:
421 <tr>
421 <tr>
422 <td class="unresolved-todo-text">${_('No unresolved TODOs')}.</td>
422 <td class="unresolved-todo-text">${_('No unresolved TODOs')}.</td>
423 </tr>
423 </tr>
424 % endif
424 % endif
425
425
426 % endif
426 % endif
427
427
428 </table>
428 </table>
429
429
430 </div>
430 </div>
431 </div>
431 </div>
432
432
433 </div>
433 </div>
434
434
435 <div class="box">
435 <div class="box">
436
436
437 % if c.state_progressing:
437 % if c.state_progressing:
438
438
439 <h2 style="text-align: center">
439 <h2 style="text-align: center">
440 ${_('Cannot show diff when pull request state is changing. Current progress state')}: <span class="tag tag-merge-state-${c.pull_request.state}">${c.pull_request.state}</span>
440 ${_('Cannot show diff when pull request state is changing. Current progress state')}: <span class="tag tag-merge-state-${c.pull_request.state}">${c.pull_request.state}</span>
441
441
442 % if c.is_super_admin:
442 % if c.is_super_admin:
443 <br/>
443 <br/>
444 If you think this is an error try <a href="${h.current_route_path(request, force_state='created')}">forced state reset</a> to <span class="tag tag-merge-state-created">created</span> state.
444 If you think this is an error try <a href="${h.current_route_path(request, force_state='created')}">forced state reset</a> to <span class="tag tag-merge-state-created">created</span> state.
445 % endif
445 % endif
446 </h2>
446 </h2>
447
447
448 % else:
448 % else:
449
449
450 ## Diffs rendered here
450 ## Diffs rendered here
451 <div class="table" >
451 <div class="table" >
452 <div id="changeset_compare_view_content">
452 <div id="changeset_compare_view_content">
453 ##CS
453 ##CS
454 % if c.missing_requirements:
454 % if c.missing_requirements:
455 <div class="box">
455 <div class="box">
456 <div class="alert alert-warning">
456 <div class="alert alert-warning">
457 <div>
457 <div>
458 <strong>${_('Missing requirements:')}</strong>
458 <strong>${_('Missing requirements:')}</strong>
459 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
459 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
460 </div>
460 </div>
461 </div>
461 </div>
462 </div>
462 </div>
463 % elif c.missing_commits:
463 % elif c.missing_commits:
464 <div class="box">
464 <div class="box">
465 <div class="alert alert-warning">
465 <div class="alert alert-warning">
466 <div>
466 <div>
467 <strong>${_('Missing commits')}:</strong>
467 <strong>${_('Missing commits')}:</strong>
468 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
468 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
469 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
469 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
470 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
470 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
471 </div>
471 </div>
472 </div>
472 </div>
473 </div>
473 </div>
474 % elif c.pr_merge_source_commit.changed and not c.pull_request.is_closed():
474 % elif c.pr_merge_source_commit.changed and not c.pull_request.is_closed():
475 <div class="box">
475 <div class="box">
476 <div class="alert alert-info">
476 <div class="alert alert-info">
477 <div>
477 <div>
478 <strong>${_('There are new changes for `{}:{}` in source repository, please consider updating this pull request.').format(c.pr_merge_source_commit.ref_spec.type, c.pr_merge_source_commit.ref_spec.name)}</strong>
478 <strong>${_('There are new changes for `{}:{}` in source repository, please consider updating this pull request.').format(c.pr_merge_source_commit.ref_spec.type, c.pr_merge_source_commit.ref_spec.name)}</strong>
479 </div>
479 </div>
480 </div>
480 </div>
481 </div>
481 </div>
482 % endif
482 % endif
483
483
484 <div class="compare_view_commits_title">
484 <div class="compare_view_commits_title">
485 % if not c.compare_mode:
485 % if not c.compare_mode:
486
486
487 % if c.at_version_pos:
487 % if c.at_version_pos:
488 <h4>
488 <h4>
489 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
489 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
490 </h4>
490 </h4>
491 % endif
491 % endif
492
492
493 <div class="pull-left">
493 <div class="pull-left">
494 <div class="btn-group">
494 <div class="btn-group">
495 <a class="${('collapsed' if c.collapse_all_commits else '')}" href="#expand-commits" onclick="toggleCommitExpand(this); return false" data-toggle-commits-cnt=${len(c.commit_ranges)} >
495 <a class="${('collapsed' if c.collapse_all_commits else '')}" href="#expand-commits" onclick="toggleCommitExpand(this); return false" data-toggle-commits-cnt=${len(c.commit_ranges)} >
496 % if c.collapse_all_commits:
496 % if c.collapse_all_commits:
497 <i class="icon-plus-squared-alt icon-no-margin"></i>
497 <i class="icon-plus-squared-alt icon-no-margin"></i>
498 ${_ungettext('Expand {} commit', 'Expand {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
498 ${_ungettext('Expand {} commit', 'Expand {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
499 % else:
499 % else:
500 <i class="icon-minus-squared-alt icon-no-margin"></i>
500 <i class="icon-minus-squared-alt icon-no-margin"></i>
501 ${_ungettext('Collapse {} commit', 'Collapse {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
501 ${_ungettext('Collapse {} commit', 'Collapse {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
502 % endif
502 % endif
503 </a>
503 </a>
504 </div>
504 </div>
505 </div>
505 </div>
506
506
507 <div class="pull-right">
507 <div class="pull-right">
508 % if c.allowed_to_update and not c.pull_request.is_closed():
508 % if c.allowed_to_update and not c.pull_request.is_closed():
509
509
510 <div class="btn-group btn-group-actions">
510 <div class="btn-group btn-group-actions">
511 <a id="update_commits" class="btn btn-primary no-margin" onclick="updateController.updateCommits(this); return false">
511 <a id="update_commits" class="btn btn-primary no-margin" onclick="updateController.updateCommits(this); return false">
512 ${_('Update commits')}
512 ${_('Update commits')}
513 </a>
513 </a>
514
514
515 <a id="update_commits_switcher" class="tooltip btn btn-primary" style="margin-left: -1px" data-toggle="dropdown" aria-pressed="false" role="button" title="${_('more update options')}">
515 <a id="update_commits_switcher" class="tooltip btn btn-primary" style="margin-left: -1px" data-toggle="dropdown" aria-pressed="false" role="button" title="${_('more update options')}">
516 <i class="icon-down"></i>
516 <i class="icon-down"></i>
517 </a>
517 </a>
518
518
519 <div class="btn-action-switcher-container" id="update-commits-switcher">
519 <div class="btn-action-switcher-container" id="update-commits-switcher">
520 <ul class="btn-action-switcher" role="menu">
520 <ul class="btn-action-switcher" role="menu">
521 <li>
521 <li>
522 <a href="#forceUpdate" onclick="updateController.forceUpdateCommits(this); return false">
522 <a href="#forceUpdate" onclick="updateController.forceUpdateCommits(this); return false">
523 ${_('Force update commits')}
523 ${_('Force update commits')}
524 </a>
524 </a>
525 <div class="action-help-block">
525 <div class="action-help-block">
526 ${_('Update commits and force refresh this pull request.')}
526 ${_('Update commits and force refresh this pull request.')}
527 </div>
527 </div>
528 </li>
528 </li>
529 </ul>
529 </ul>
530 </div>
530 </div>
531 </div>
531 </div>
532
532
533 % else:
533 % else:
534 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
534 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
535 % endif
535 % endif
536
536
537 </div>
537 </div>
538 % endif
538 % endif
539 </div>
539 </div>
540
540
541 % if not c.missing_commits:
541 % if not c.missing_commits:
542 % if c.compare_mode:
542 % if c.compare_mode:
543 % if c.at_version:
543 % if c.at_version:
544 <h4>
544 <h4>
545 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
545 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
546 </h4>
546 </h4>
547
547
548 <div class="subtitle-compare">
548 <div class="subtitle-compare">
549 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
549 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
550 </div>
550 </div>
551
551
552 <div class="container">
552 <div class="container">
553 <table class="rctable compare_view_commits">
553 <table class="rctable compare_view_commits">
554 <tr>
554 <tr>
555 <th></th>
555 <th></th>
556 <th>${_('Time')}</th>
556 <th>${_('Time')}</th>
557 <th>${_('Author')}</th>
557 <th>${_('Author')}</th>
558 <th>${_('Commit')}</th>
558 <th>${_('Commit')}</th>
559 <th></th>
559 <th></th>
560 <th>${_('Description')}</th>
560 <th>${_('Description')}</th>
561 </tr>
561 </tr>
562
562
563 % for c_type, commit in c.commit_changes:
563 % for c_type, commit in c.commit_changes:
564 % if c_type in ['a', 'r']:
564 % if c_type in ['a', 'r']:
565 <%
565 <%
566 if c_type == 'a':
566 if c_type == 'a':
567 cc_title = _('Commit added in displayed changes')
567 cc_title = _('Commit added in displayed changes')
568 elif c_type == 'r':
568 elif c_type == 'r':
569 cc_title = _('Commit removed in displayed changes')
569 cc_title = _('Commit removed in displayed changes')
570 else:
570 else:
571 cc_title = ''
571 cc_title = ''
572 %>
572 %>
573 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
573 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
574 <td>
574 <td>
575 <div class="commit-change-indicator color-${c_type}-border">
575 <div class="commit-change-indicator color-${c_type}-border">
576 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
576 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
577 ${c_type.upper()}
577 ${c_type.upper()}
578 </div>
578 </div>
579 </div>
579 </div>
580 </td>
580 </td>
581 <td class="td-time">
581 <td class="td-time">
582 ${h.age_component(commit.date)}
582 ${h.age_component(commit.date)}
583 </td>
583 </td>
584 <td class="td-user">
584 <td class="td-user">
585 ${base.gravatar_with_user(commit.author, 16, tooltip=True)}
585 ${base.gravatar_with_user(commit.author, 16, tooltip=True)}
586 </td>
586 </td>
587 <td class="td-hash">
587 <td class="td-hash">
588 <code>
588 <code>
589 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
589 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
590 r${commit.idx}:${h.short_id(commit.raw_id)}
590 r${commit.idx}:${h.short_id(commit.raw_id)}
591 </a>
591 </a>
592 ${h.hidden('revisions', commit.raw_id)}
592 ${h.hidden('revisions', commit.raw_id)}
593 </code>
593 </code>
594 </td>
594 </td>
595 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
595 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
596 <i class="icon-expand-linked"></i>
596 <i class="icon-expand-linked"></i>
597 </td>
597 </td>
598 <td class="mid td-description">
598 <td class="mid td-description">
599 <div class="log-container truncate-wrap">
599 <div class="log-container truncate-wrap">
600 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
600 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
601 </div>
601 </div>
602 </td>
602 </td>
603 </tr>
603 </tr>
604 % endif
604 % endif
605 % endfor
605 % endfor
606 </table>
606 </table>
607 </div>
607 </div>
608
608
609 % endif
609 % endif
610
610
611 % else:
611 % else:
612 <%include file="/compare/compare_commits.mako" />
612 <%include file="/compare/compare_commits.mako" />
613 % endif
613 % endif
614
614
615 <div class="cs_files">
615 <div class="cs_files">
616 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
616 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
617 % if c.at_version:
617 % if c.at_version:
618 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['display']) %>
618 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['display']) %>
619 <% c.comments = c.comment_versions[c.at_version_num]['display'] %>
619 <% c.comments = c.comment_versions[c.at_version_num]['display'] %>
620 % else:
620 % else:
621 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['until']) %>
621 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['until']) %>
622 <% c.comments = c.comment_versions[c.at_version_num]['until'] %>
622 <% c.comments = c.comment_versions[c.at_version_num]['until'] %>
623 % endif
623 % endif
624
624
625 <%
625 <%
626 pr_menu_data = {
626 pr_menu_data = {
627 'outdated_comm_count_ver': outdated_comm_count_ver
627 'outdated_comm_count_ver': outdated_comm_count_ver,
628 'pull_request': c.pull_request
628 }
629 }
629 %>
630 %>
630
631
631 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
632 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on, pull_request_menu=pr_menu_data)}
632
633
633 % if c.range_diff_on:
634 % if c.range_diff_on:
634 % for commit in c.commit_ranges:
635 % for commit in c.commit_ranges:
635 ${cbdiffs.render_diffset(
636 ${cbdiffs.render_diffset(
636 c.changes[commit.raw_id],
637 c.changes[commit.raw_id],
637 commit=commit, use_comments=True,
638 commit=commit, use_comments=True,
638 collapse_when_files_over=5,
639 collapse_when_files_over=5,
639 disable_new_comments=True,
640 disable_new_comments=True,
640 deleted_files_comments=c.deleted_files_comments,
641 deleted_files_comments=c.deleted_files_comments,
641 inline_comments=c.inline_comments,
642 inline_comments=c.inline_comments,
642 pull_request_menu=pr_menu_data, show_todos=False)}
643 pull_request_menu=pr_menu_data, show_todos=False)}
643 % endfor
644 % endfor
644 % else:
645 % else:
645 ${cbdiffs.render_diffset(
646 ${cbdiffs.render_diffset(
646 c.diffset, use_comments=True,
647 c.diffset, use_comments=True,
647 collapse_when_files_over=30,
648 collapse_when_files_over=30,
648 disable_new_comments=not c.allowed_to_comment,
649 disable_new_comments=not c.allowed_to_comment,
649 deleted_files_comments=c.deleted_files_comments,
650 deleted_files_comments=c.deleted_files_comments,
650 inline_comments=c.inline_comments,
651 inline_comments=c.inline_comments,
651 pull_request_menu=pr_menu_data, show_todos=False)}
652 pull_request_menu=pr_menu_data, show_todos=False)}
652 % endif
653 % endif
653
654
654 </div>
655 </div>
655 % else:
656 % else:
656 ## skipping commits we need to clear the view for missing commits
657 ## skipping commits we need to clear the view for missing commits
657 <div style="clear:both;"></div>
658 <div style="clear:both;"></div>
658 % endif
659 % endif
659
660
660 </div>
661 </div>
661 </div>
662 </div>
662
663
663 ## template for inline comment form
664 ## template for inline comment form
664 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
665 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
665
666
666 ## comments heading with count
667 ## comments heading with count
667 <div class="comments-heading">
668 <div class="comments-heading">
668 <i class="icon-comment"></i>
669 <i class="icon-comment"></i>
669 ${_('Comments')} ${len(c.comments)}
670 ${_('Comments')} ${len(c.comments)}
670 </div>
671 </div>
671
672
672 ## render general comments
673 ## render general comments
673 <div id="comment-tr-show">
674 <div id="comment-tr-show">
674 % if general_outdated_comm_count_ver:
675 % if general_outdated_comm_count_ver:
675 <div class="info-box">
676 <div class="info-box">
676 % if general_outdated_comm_count_ver == 1:
677 % if general_outdated_comm_count_ver == 1:
677 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
678 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
678 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
679 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
679 % else:
680 % else:
680 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
681 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
681 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
682 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
682 % endif
683 % endif
683 </div>
684 </div>
684 % endif
685 % endif
685 </div>
686 </div>
686
687
687 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
688 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
688
689
689 % if not c.pull_request.is_closed():
690 % if not c.pull_request.is_closed():
690 ## main comment form and it status
691 ## main comment form and it status
691 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
692 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
692 pull_request_id=c.pull_request.pull_request_id),
693 pull_request_id=c.pull_request.pull_request_id),
693 c.pull_request_review_status,
694 c.pull_request_review_status,
694 is_pull_request=True, change_status=c.allowed_to_change_status)}
695 is_pull_request=True, change_status=c.allowed_to_change_status)}
695
696
696 ## merge status, and merge action
697 ## merge status, and merge action
697 <div class="pull-request-merge">
698 <div class="pull-request-merge">
698 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
699 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
699 </div>
700 </div>
700
701
701 %endif
702 %endif
702
703
703 % endif
704 % endif
704 </div>
705 </div>
705
706
706 <script type="text/javascript">
707 <script type="text/javascript">
707
708
708 versionController = new VersionController();
709 versionController = new VersionController();
709 versionController.init();
710 versionController.init();
710
711
711 reviewersController = new ReviewersController();
712 reviewersController = new ReviewersController();
712 commitsController = new CommitsController();
713 commitsController = new CommitsController();
713
714
714 updateController = new UpdatePrController();
715 updateController = new UpdatePrController();
715
716
716 $(function () {
717 $(function () {
717
718
718 // custom code mirror
719 // custom code mirror
719 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
720 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
720
721
721 var PRDetails = {
722 var PRDetails = {
722 editButton: $('#open_edit_pullrequest'),
723 editButton: $('#open_edit_pullrequest'),
723 closeButton: $('#close_edit_pullrequest'),
724 closeButton: $('#close_edit_pullrequest'),
724 deleteButton: $('#delete_pullrequest'),
725 deleteButton: $('#delete_pullrequest'),
725 viewFields: $('#pr-desc, #pr-title'),
726 viewFields: $('#pr-desc, #pr-title'),
726 editFields: $('#pr-desc-edit, #pr-title-edit, .pr-save'),
727 editFields: $('#pr-desc-edit, #pr-title-edit, .pr-save'),
727
728
728 init: function () {
729 init: function () {
729 var that = this;
730 var that = this;
730 this.editButton.on('click', function (e) {
731 this.editButton.on('click', function (e) {
731 that.edit();
732 that.edit();
732 });
733 });
733 this.closeButton.on('click', function (e) {
734 this.closeButton.on('click', function (e) {
734 that.view();
735 that.view();
735 });
736 });
736 },
737 },
737
738
738 edit: function (event) {
739 edit: function (event) {
739 this.viewFields.hide();
740 this.viewFields.hide();
740 this.editButton.hide();
741 this.editButton.hide();
741 this.deleteButton.hide();
742 this.deleteButton.hide();
742 this.closeButton.show();
743 this.closeButton.show();
743 this.editFields.show();
744 this.editFields.show();
744 codeMirrorInstance.refresh();
745 codeMirrorInstance.refresh();
745 },
746 },
746
747
747 view: function (event) {
748 view: function (event) {
748 this.editButton.show();
749 this.editButton.show();
749 this.deleteButton.show();
750 this.deleteButton.show();
750 this.editFields.hide();
751 this.editFields.hide();
751 this.closeButton.hide();
752 this.closeButton.hide();
752 this.viewFields.show();
753 this.viewFields.show();
753 }
754 }
754 };
755 };
755
756
756 var ReviewersPanel = {
757 var ReviewersPanel = {
757 editButton: $('#open_edit_reviewers'),
758 editButton: $('#open_edit_reviewers'),
758 closeButton: $('#close_edit_reviewers'),
759 closeButton: $('#close_edit_reviewers'),
759 addButton: $('#add_reviewer'),
760 addButton: $('#add_reviewer'),
760 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
761 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
761
762
762 init: function () {
763 init: function () {
763 var self = this;
764 var self = this;
764 this.editButton.on('click', function (e) {
765 this.editButton.on('click', function (e) {
765 self.edit();
766 self.edit();
766 });
767 });
767 this.closeButton.on('click', function (e) {
768 this.closeButton.on('click', function (e) {
768 self.close();
769 self.close();
769 });
770 });
770 },
771 },
771
772
772 edit: function (event) {
773 edit: function (event) {
773 this.editButton.hide();
774 this.editButton.hide();
774 this.closeButton.show();
775 this.closeButton.show();
775 this.addButton.show();
776 this.addButton.show();
776 this.removeButtons.css('visibility', 'visible');
777 this.removeButtons.css('visibility', 'visible');
777 // review rules
778 // review rules
778 reviewersController.loadReviewRules(
779 reviewersController.loadReviewRules(
779 ${c.pull_request.reviewer_data_json | n});
780 ${c.pull_request.reviewer_data_json | n});
780 },
781 },
781
782
782 close: function (event) {
783 close: function (event) {
783 this.editButton.show();
784 this.editButton.show();
784 this.closeButton.hide();
785 this.closeButton.hide();
785 this.addButton.hide();
786 this.addButton.hide();
786 this.removeButtons.css('visibility', 'hidden');
787 this.removeButtons.css('visibility', 'hidden');
787 // hide review rules
788 // hide review rules
788 reviewersController.hideReviewRules()
789 reviewersController.hideReviewRules()
789 }
790 }
790 };
791 };
791
792
792 PRDetails.init();
793 PRDetails.init();
793 ReviewersPanel.init();
794 ReviewersPanel.init();
794
795
795 showOutdated = function (self) {
796 showOutdated = function (self) {
796 $('.comment-inline.comment-outdated').show();
797 $('.comment-inline.comment-outdated').show();
797 $('.filediff-outdated').show();
798 $('.filediff-outdated').show();
798 $('.showOutdatedComments').hide();
799 $('.showOutdatedComments').hide();
799 $('.hideOutdatedComments').show();
800 $('.hideOutdatedComments').show();
800 };
801 };
801
802
802 hideOutdated = function (self) {
803 hideOutdated = function (self) {
803 $('.comment-inline.comment-outdated').hide();
804 $('.comment-inline.comment-outdated').hide();
804 $('.filediff-outdated').hide();
805 $('.filediff-outdated').hide();
805 $('.hideOutdatedComments').hide();
806 $('.hideOutdatedComments').hide();
806 $('.showOutdatedComments').show();
807 $('.showOutdatedComments').show();
807 };
808 };
808
809
809 refreshMergeChecks = function () {
810 refreshMergeChecks = function () {
810 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
811 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
811 $('.pull-request-merge').css('opacity', 0.3);
812 $('.pull-request-merge').css('opacity', 0.3);
812 $('.action-buttons-extra').css('opacity', 0.3);
813 $('.action-buttons-extra').css('opacity', 0.3);
813
814
814 $('.pull-request-merge').load(
815 $('.pull-request-merge').load(
815 loadUrl, function () {
816 loadUrl, function () {
816 $('.pull-request-merge').css('opacity', 1);
817 $('.pull-request-merge').css('opacity', 1);
817
818
818 $('.action-buttons-extra').css('opacity', 1);
819 $('.action-buttons-extra').css('opacity', 1);
819 }
820 }
820 );
821 );
821 };
822 };
822
823
823 closePullRequest = function (status) {
824 closePullRequest = function (status) {
824 if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) {
825 if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) {
825 return false;
826 return false;
826 }
827 }
827 // inject closing flag
828 // inject closing flag
828 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
829 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
829 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
830 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
830 $(generalCommentForm.submitForm).submit();
831 $(generalCommentForm.submitForm).submit();
831 };
832 };
832
833
833 $('#show-outdated-comments').on('click', function (e) {
834 $('#show-outdated-comments').on('click', function (e) {
834 var button = $(this);
835 var button = $(this);
835 var outdated = $('.comment-outdated');
836 var outdated = $('.comment-outdated');
836
837
837 if (button.html() === "(Show)") {
838 if (button.html() === "(Show)") {
838 button.html("(Hide)");
839 button.html("(Hide)");
839 outdated.show();
840 outdated.show();
840 } else {
841 } else {
841 button.html("(Show)");
842 button.html("(Show)");
842 outdated.hide();
843 outdated.hide();
843 }
844 }
844 });
845 });
845
846
846 $('.show-inline-comments').on('change', function (e) {
847 $('.show-inline-comments').on('change', function (e) {
847 var show = 'none';
848 var show = 'none';
848 var target = e.currentTarget;
849 var target = e.currentTarget;
849 if (target.checked) {
850 if (target.checked) {
850 show = ''
851 show = ''
851 }
852 }
852 var boxid = $(target).attr('id_for');
853 var boxid = $(target).attr('id_for');
853 var comments = $('#{0} .inline-comments'.format(boxid));
854 var comments = $('#{0} .inline-comments'.format(boxid));
854 var fn_display = function (idx) {
855 var fn_display = function (idx) {
855 $(this).css('display', show);
856 $(this).css('display', show);
856 };
857 };
857 $(comments).each(fn_display);
858 $(comments).each(fn_display);
858 var btns = $('#{0} .inline-comments-button'.format(boxid));
859 var btns = $('#{0} .inline-comments-button'.format(boxid));
859 $(btns).each(fn_display);
860 $(btns).each(fn_display);
860 });
861 });
861
862
862 $('#merge_pull_request_form').submit(function () {
863 $('#merge_pull_request_form').submit(function () {
863 if (!$('#merge_pull_request').attr('disabled')) {
864 if (!$('#merge_pull_request').attr('disabled')) {
864 $('#merge_pull_request').attr('disabled', 'disabled');
865 $('#merge_pull_request').attr('disabled', 'disabled');
865 }
866 }
866 return true;
867 return true;
867 });
868 });
868
869
869 $('#edit_pull_request').on('click', function (e) {
870 $('#edit_pull_request').on('click', function (e) {
870 var title = $('#pr-title-input').val();
871 var title = $('#pr-title-input').val();
871 var description = codeMirrorInstance.getValue();
872 var description = codeMirrorInstance.getValue();
872 var renderer = $('#pr-renderer-input').val();
873 var renderer = $('#pr-renderer-input').val();
873 editPullRequest(
874 editPullRequest(
874 "${c.repo_name}", "${c.pull_request.pull_request_id}",
875 "${c.repo_name}", "${c.pull_request.pull_request_id}",
875 title, description, renderer);
876 title, description, renderer);
876 });
877 });
877
878
878 $('#update_pull_request').on('click', function (e) {
879 $('#update_pull_request').on('click', function (e) {
879 $(this).attr('disabled', 'disabled');
880 $(this).attr('disabled', 'disabled');
880 $(this).addClass('disabled');
881 $(this).addClass('disabled');
881 $(this).html(_gettext('Saving...'));
882 $(this).html(_gettext('Saving...'));
882 reviewersController.updateReviewers(
883 reviewersController.updateReviewers(
883 "${c.repo_name}", "${c.pull_request.pull_request_id}");
884 "${c.repo_name}", "${c.pull_request.pull_request_id}");
884 });
885 });
885
886
886
887
887 // fixing issue with caches on firefox
888 // fixing issue with caches on firefox
888 $('#update_commits').removeAttr("disabled");
889 $('#update_commits').removeAttr("disabled");
889
890
890 $('.show-inline-comments').on('click', function (e) {
891 $('.show-inline-comments').on('click', function (e) {
891 var boxid = $(this).attr('data-comment-id');
892 var boxid = $(this).attr('data-comment-id');
892 var button = $(this);
893 var button = $(this);
893
894
894 if (button.hasClass("comments-visible")) {
895 if (button.hasClass("comments-visible")) {
895 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
896 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
896 $(this).hide();
897 $(this).hide();
897 });
898 });
898 button.removeClass("comments-visible");
899 button.removeClass("comments-visible");
899 } else {
900 } else {
900 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
901 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
901 $(this).show();
902 $(this).show();
902 });
903 });
903 button.addClass("comments-visible");
904 button.addClass("comments-visible");
904 }
905 }
905 });
906 });
906
907
907 // register submit callback on commentForm form to track TODOs
908 // register submit callback on commentForm form to track TODOs
908 window.commentFormGlobalSubmitSuccessCallback = function () {
909 window.commentFormGlobalSubmitSuccessCallback = function () {
909 refreshMergeChecks();
910 refreshMergeChecks();
910 };
911 };
911
912
912 ReviewerAutoComplete('#user');
913 ReviewerAutoComplete('#user');
913
914
914 })
915 })
915
916
916 </script>
917 </script>
917
918
918 </div>
919 </div>
919
920
920 </%def>
921 </%def>
General Comments 0
You need to be logged in to leave comments. Login now