##// END OF EJS Templates
comments: show nicer tooltip about outdated comments.
marcink -
r4382:b8cc803a stable
parent child
Show More
@@ -1,1215 +1,1215
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"><i class="icon-comment"></i> ${len(total_file_comments)}</span>
262 <span class="pill"><i class="icon-comment"></i> ${len(total_file_comments)}</span>
263 </span>
263 </span>
264 ${diff_ops(filediff)}
264 ${diff_ops(filediff)}
265
265
266 </label>
266 </label>
267
267
268 ${diff_menu(filediff, use_comments=use_comments)}
268 ${diff_menu(filediff, use_comments=use_comments)}
269 <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 '')}">
269 <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 '')}">
270
270
271 ## new/deleted/empty content case
271 ## new/deleted/empty content case
272 % if not filediff.hunks:
272 % if not filediff.hunks:
273 ## Comment container, on "fakes" hunk that contains all data to render comments
273 ## Comment container, on "fakes" hunk that contains all data to render comments
274 ${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)}
274 ${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)}
275 % endif
275 % endif
276
276
277 %if filediff.limited_diff:
277 %if filediff.limited_diff:
278 <tr class="cb-warning cb-collapser">
278 <tr class="cb-warning cb-collapser">
279 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
279 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
280 ${_('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>
280 ${_('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>
281 </td>
281 </td>
282 </tr>
282 </tr>
283 %else:
283 %else:
284 %if over_lines_changed_limit:
284 %if over_lines_changed_limit:
285 <tr class="cb-warning cb-collapser">
285 <tr class="cb-warning cb-collapser">
286 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
286 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
287 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
287 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
288 <a href="#" class="cb-expand"
288 <a href="#" class="cb-expand"
289 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
289 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
290 </a>
290 </a>
291 <a href="#" class="cb-collapse"
291 <a href="#" class="cb-collapse"
292 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
292 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
293 </a>
293 </a>
294 </td>
294 </td>
295 </tr>
295 </tr>
296 %endif
296 %endif
297 %endif
297 %endif
298
298
299 % for hunk in filediff.hunks:
299 % for hunk in filediff.hunks:
300 <tr class="cb-hunk">
300 <tr class="cb-hunk">
301 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
301 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
302 ## TODO: dan: add ajax loading of more context here
302 ## TODO: dan: add ajax loading of more context here
303 ## <a href="#">
303 ## <a href="#">
304 <i class="icon-more"></i>
304 <i class="icon-more"></i>
305 ## </a>
305 ## </a>
306 </td>
306 </td>
307 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
307 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
308 @@
308 @@
309 -${hunk.source_start},${hunk.source_length}
309 -${hunk.source_start},${hunk.source_length}
310 +${hunk.target_start},${hunk.target_length}
310 +${hunk.target_start},${hunk.target_length}
311 ${hunk.section_header}
311 ${hunk.section_header}
312 </td>
312 </td>
313 </tr>
313 </tr>
314 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
314 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
315 % endfor
315 % endfor
316
316
317 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
317 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
318
318
319 ## outdated comments that do not fit into currently displayed lines
319 ## outdated comments that do not fit into currently displayed lines
320 % for lineno, comments in unmatched_comments.items():
320 % for lineno, comments in unmatched_comments.items():
321
321
322 %if c.user_session_attrs["diffmode"] == 'unified':
322 %if c.user_session_attrs["diffmode"] == 'unified':
323 % if loop.index == 0:
323 % if loop.index == 0:
324 <tr class="cb-hunk">
324 <tr class="cb-hunk">
325 <td colspan="3"></td>
325 <td colspan="3"></td>
326 <td>
326 <td>
327 <div>
327 <div>
328 ${_('Unmatched/outdated inline comments below')}
328 ${_('Unmatched/outdated inline comments below')}
329 </div>
329 </div>
330 </td>
330 </td>
331 </tr>
331 </tr>
332 % endif
332 % endif
333 <tr class="cb-line">
333 <tr class="cb-line">
334 <td class="cb-data cb-context"></td>
334 <td class="cb-data cb-context"></td>
335 <td class="cb-lineno cb-context"></td>
335 <td class="cb-lineno cb-context"></td>
336 <td class="cb-lineno cb-context"></td>
336 <td class="cb-lineno cb-context"></td>
337 <td class="cb-content cb-context">
337 <td class="cb-content cb-context">
338 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
338 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
339 </td>
339 </td>
340 </tr>
340 </tr>
341 %elif c.user_session_attrs["diffmode"] == 'sideside':
341 %elif c.user_session_attrs["diffmode"] == 'sideside':
342 % if loop.index == 0:
342 % if loop.index == 0:
343 <tr class="cb-comment-info">
343 <tr class="cb-comment-info">
344 <td colspan="2"></td>
344 <td colspan="2"></td>
345 <td class="cb-line">
345 <td class="cb-line">
346 <div>
346 <div>
347 ${_('Unmatched/outdated inline comments below')}
347 ${_('Unmatched/outdated inline comments below')}
348 </div>
348 </div>
349 </td>
349 </td>
350 <td colspan="2"></td>
350 <td colspan="2"></td>
351 <td class="cb-line">
351 <td class="cb-line">
352 <div>
352 <div>
353 ${_('Unmatched/outdated comments below')}
353 ${_('Unmatched/outdated comments below')}
354 </div>
354 </div>
355 </td>
355 </td>
356 </tr>
356 </tr>
357 % endif
357 % endif
358 <tr class="cb-line">
358 <tr class="cb-line">
359 <td class="cb-data cb-context"></td>
359 <td class="cb-data cb-context"></td>
360 <td class="cb-lineno cb-context"></td>
360 <td class="cb-lineno cb-context"></td>
361 <td class="cb-content cb-context">
361 <td class="cb-content cb-context">
362 % if lineno.startswith('o'):
362 % if lineno.startswith('o'):
363 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
363 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
364 % endif
364 % endif
365 </td>
365 </td>
366
366
367 <td class="cb-data cb-context"></td>
367 <td class="cb-data cb-context"></td>
368 <td class="cb-lineno cb-context"></td>
368 <td class="cb-lineno cb-context"></td>
369 <td class="cb-content cb-context">
369 <td class="cb-content cb-context">
370 % if lineno.startswith('n'):
370 % if lineno.startswith('n'):
371 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
371 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
372 % endif
372 % endif
373 </td>
373 </td>
374 </tr>
374 </tr>
375 %endif
375 %endif
376
376
377 % endfor
377 % endfor
378
378
379 </table>
379 </table>
380 </div>
380 </div>
381 %endfor
381 %endfor
382
382
383 ## outdated comments that are made for a file that has been deleted
383 ## outdated comments that are made for a file that has been deleted
384 % for filename, comments_dict in (deleted_files_comments or {}).items():
384 % for filename, comments_dict in (deleted_files_comments or {}).items():
385
385
386 <%
386 <%
387 display_state = 'display: none'
387 display_state = 'display: none'
388 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
388 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
389 if open_comments_in_file:
389 if open_comments_in_file:
390 display_state = ''
390 display_state = ''
391 fid = str(id(filename))
391 fid = str(id(filename))
392 %>
392 %>
393 <div class="filediffs filediff-outdated" style="${display_state}">
393 <div class="filediffs filediff-outdated" style="${display_state}">
394 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
394 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
395 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
395 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
396 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
396 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
397 <div class="filediff-collapse-indicator icon-"></div>
397 <div class="filediff-collapse-indicator icon-"></div>
398
398
399 <span class="pill">
399 <span class="pill">
400 ## file was deleted
400 ## file was deleted
401 ${filename}
401 ${filename}
402 </span>
402 </span>
403 <span class="pill-group pull-left" >
403 <span class="pill-group pull-left" >
404 ## file op, doesn't need translation
404 ## file op, doesn't need translation
405 <span class="pill" op="removed">unresolved comments</span>
405 <span class="pill" op="removed">unresolved comments</span>
406 </span>
406 </span>
407 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}"></a>
407 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}"></a>
408 <span class="pill-group pull-right">
408 <span class="pill-group pull-right">
409 <span class="pill" op="deleted">
409 <span class="pill" op="deleted">
410 % if comments_dict['stats'] >0:
410 % if comments_dict['stats'] >0:
411 -${comments_dict['stats']}
411 -${comments_dict['stats']}
412 % else:
412 % else:
413 ${comments_dict['stats']}
413 ${comments_dict['stats']}
414 % endif
414 % endif
415 </span>
415 </span>
416 </span>
416 </span>
417 </label>
417 </label>
418
418
419 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
419 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
420 <tr>
420 <tr>
421 % if c.user_session_attrs["diffmode"] == 'unified':
421 % if c.user_session_attrs["diffmode"] == 'unified':
422 <td></td>
422 <td></td>
423 %endif
423 %endif
424
424
425 <td></td>
425 <td></td>
426 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
426 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
427 <strong>${_('This file was removed from diff during updates to this pull-request.')}</strong><br/>
427 <strong>${_('This file was removed from diff during updates to this pull-request.')}</strong><br/>
428 ${_('There are still outdated/unresolved comments attached to it.')}
428 ${_('There are still outdated/unresolved comments attached to it.')}
429 </td>
429 </td>
430 </tr>
430 </tr>
431 %if c.user_session_attrs["diffmode"] == 'unified':
431 %if c.user_session_attrs["diffmode"] == 'unified':
432 <tr class="cb-line">
432 <tr class="cb-line">
433 <td class="cb-data cb-context"></td>
433 <td class="cb-data cb-context"></td>
434 <td class="cb-lineno cb-context"></td>
434 <td class="cb-lineno cb-context"></td>
435 <td class="cb-lineno cb-context"></td>
435 <td class="cb-lineno cb-context"></td>
436 <td class="cb-content cb-context">
436 <td class="cb-content cb-context">
437 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
437 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
438 </td>
438 </td>
439 </tr>
439 </tr>
440 %elif c.user_session_attrs["diffmode"] == 'sideside':
440 %elif c.user_session_attrs["diffmode"] == 'sideside':
441 <tr class="cb-line">
441 <tr class="cb-line">
442 <td class="cb-data cb-context"></td>
442 <td class="cb-data cb-context"></td>
443 <td class="cb-lineno cb-context"></td>
443 <td class="cb-lineno cb-context"></td>
444 <td class="cb-content cb-context"></td>
444 <td class="cb-content cb-context"></td>
445
445
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">
448 <td class="cb-content cb-context">
449 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
449 ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)}
450 </td>
450 </td>
451 </tr>
451 </tr>
452 %endif
452 %endif
453 </table>
453 </table>
454 </div>
454 </div>
455 </div>
455 </div>
456 % endfor
456 % endfor
457
457
458 </div>
458 </div>
459 </div>
459 </div>
460 </%def>
460 </%def>
461
461
462 <%def name="diff_ops(filediff)">
462 <%def name="diff_ops(filediff)">
463 <%
463 <%
464 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
464 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
465 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
465 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
466 %>
466 %>
467 <span class="pill">
467 <span class="pill">
468 <i class="icon-file-text"></i>
468 <i class="icon-file-text"></i>
469 %if filediff.source_file_path and filediff.target_file_path:
469 %if filediff.source_file_path and filediff.target_file_path:
470 %if filediff.source_file_path != filediff.target_file_path:
470 %if filediff.source_file_path != filediff.target_file_path:
471 ## file was renamed, or copied
471 ## file was renamed, or copied
472 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
472 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
473 ${filediff.target_file_path}<del>${filediff.source_file_path}</del>
473 ${filediff.target_file_path}<del>${filediff.source_file_path}</del>
474 <% final_path = filediff.target_file_path %>
474 <% final_path = filediff.target_file_path %>
475 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
475 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
476 ${filediff.target_file_path}${filediff.source_file_path}
476 ${filediff.target_file_path}${filediff.source_file_path}
477 <% final_path = filediff.target_file_path %>
477 <% final_path = filediff.target_file_path %>
478 %endif
478 %endif
479 %else:
479 %else:
480 ## file was modified
480 ## file was modified
481 ${filediff.source_file_path}
481 ${filediff.source_file_path}
482 <% final_path = filediff.source_file_path %>
482 <% final_path = filediff.source_file_path %>
483 %endif
483 %endif
484 %else:
484 %else:
485 %if filediff.source_file_path:
485 %if filediff.source_file_path:
486 ## file was deleted
486 ## file was deleted
487 ${filediff.source_file_path}
487 ${filediff.source_file_path}
488 <% final_path = filediff.source_file_path %>
488 <% final_path = filediff.source_file_path %>
489 %else:
489 %else:
490 ## file was added
490 ## file was added
491 ${filediff.target_file_path}
491 ${filediff.target_file_path}
492 <% final_path = filediff.target_file_path %>
492 <% final_path = filediff.target_file_path %>
493 %endif
493 %endif
494 %endif
494 %endif
495 <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>
495 <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>
496 </span>
496 </span>
497 ## anchor link
497 ## anchor link
498 <a class="pill filediff-anchor" href="#a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></a>
498 <a class="pill filediff-anchor" href="#a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></a>
499
499
500 <span class="pill-group pull-right">
500 <span class="pill-group pull-right">
501
501
502 ## ops pills
502 ## ops pills
503 %if filediff.limited_diff:
503 %if filediff.limited_diff:
504 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
504 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
505 %endif
505 %endif
506
506
507 %if NEW_FILENODE in filediff.patch['stats']['ops']:
507 %if NEW_FILENODE in filediff.patch['stats']['ops']:
508 <span class="pill" op="created">created</span>
508 <span class="pill" op="created">created</span>
509 %if filediff['target_mode'].startswith('120'):
509 %if filediff['target_mode'].startswith('120'):
510 <span class="pill" op="symlink">symlink</span>
510 <span class="pill" op="symlink">symlink</span>
511 %else:
511 %else:
512 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
512 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
513 %endif
513 %endif
514 %endif
514 %endif
515
515
516 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
516 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
517 <span class="pill" op="renamed">renamed</span>
517 <span class="pill" op="renamed">renamed</span>
518 %endif
518 %endif
519
519
520 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
520 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
521 <span class="pill" op="copied">copied</span>
521 <span class="pill" op="copied">copied</span>
522 %endif
522 %endif
523
523
524 %if DEL_FILENODE in filediff.patch['stats']['ops']:
524 %if DEL_FILENODE in filediff.patch['stats']['ops']:
525 <span class="pill" op="removed">removed</span>
525 <span class="pill" op="removed">removed</span>
526 %endif
526 %endif
527
527
528 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
528 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
529 <span class="pill" op="mode">
529 <span class="pill" op="mode">
530 ${nice_mode(filediff['source_mode'])}${nice_mode(filediff['target_mode'])}
530 ${nice_mode(filediff['source_mode'])}${nice_mode(filediff['target_mode'])}
531 </span>
531 </span>
532 %endif
532 %endif
533
533
534 %if BIN_FILENODE in filediff.patch['stats']['ops']:
534 %if BIN_FILENODE in filediff.patch['stats']['ops']:
535 <span class="pill" op="binary">binary</span>
535 <span class="pill" op="binary">binary</span>
536 %if MOD_FILENODE in filediff.patch['stats']['ops']:
536 %if MOD_FILENODE in filediff.patch['stats']['ops']:
537 <span class="pill" op="modified">modified</span>
537 <span class="pill" op="modified">modified</span>
538 %endif
538 %endif
539 %endif
539 %endif
540
540
541 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
541 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
542 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
542 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
543
543
544 </span>
544 </span>
545
545
546 </%def>
546 </%def>
547
547
548 <%def name="nice_mode(filemode)">
548 <%def name="nice_mode(filemode)">
549 ${(filemode.startswith('100') and filemode[3:] or filemode)}
549 ${(filemode.startswith('100') and filemode[3:] or filemode)}
550 </%def>
550 </%def>
551
551
552 <%def name="diff_menu(filediff, use_comments=False)">
552 <%def name="diff_menu(filediff, use_comments=False)">
553 <div class="filediff-menu">
553 <div class="filediff-menu">
554
554