##// END OF EJS Templates
diffs: expose per-file comment counts.
marcink -
r4380:2d4194c7 stable
parent child Browse files
Show More
@@ -1,1193 +1,1215 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 <%
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]
259 %>
256 <div class="filediff-collapse-indicator icon-"></div>
260 <div class="filediff-collapse-indicator icon-"></div>
261 <span class="pill-group pull-right" >
262 <span class="pill"><i class="icon-comment"></i> ${len(total_file_comments)}</span>
263 </span>
257 ${diff_ops(filediff)}
264 ${diff_ops(filediff)}
265
258 </label>
266 </label>
259
267
260 ${diff_menu(filediff, use_comments=use_comments)}
268 ${diff_menu(filediff, use_comments=use_comments)}
261 <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 '')}">
262
270
263 ## new/deleted/empty content case
271 ## new/deleted/empty content case
264 % if not filediff.hunks:
272 % if not filediff.hunks:
265 ## 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
266 ${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)}
267 % endif
275 % endif
268
276
269 %if filediff.limited_diff:
277 %if filediff.limited_diff:
270 <tr class="cb-warning cb-collapser">
278 <tr class="cb-warning cb-collapser">
271 <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')}>
272 ${_('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>
273 </td>
281 </td>
274 </tr>
282 </tr>
275 %else:
283 %else:
276 %if over_lines_changed_limit:
284 %if over_lines_changed_limit:
277 <tr class="cb-warning cb-collapser">
285 <tr class="cb-warning cb-collapser">
278 <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')}>
279 ${_('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)}
280 <a href="#" class="cb-expand"
288 <a href="#" class="cb-expand"
281 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')}
282 </a>
290 </a>
283 <a href="#" class="cb-collapse"
291 <a href="#" class="cb-collapse"
284 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')}
285 </a>
293 </a>
286 </td>
294 </td>
287 </tr>
295 </tr>
288 %endif
296 %endif
289 %endif
297 %endif
290
298
291 % for hunk in filediff.hunks:
299 % for hunk in filediff.hunks:
292 <tr class="cb-hunk">
300 <tr class="cb-hunk">
293 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
301 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
294 ## TODO: dan: add ajax loading of more context here
302 ## TODO: dan: add ajax loading of more context here
295 ## <a href="#">
303 ## <a href="#">
296 <i class="icon-more"></i>
304 <i class="icon-more"></i>
297 ## </a>
305 ## </a>
298 </td>
306 </td>
299 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
307 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
300 @@
308 @@
301 -${hunk.source_start},${hunk.source_length}
309 -${hunk.source_start},${hunk.source_length}
302 +${hunk.target_start},${hunk.target_length}
310 +${hunk.target_start},${hunk.target_length}
303 ${hunk.section_header}
311 ${hunk.section_header}
304 </td>
312 </td>
305 </tr>
313 </tr>
306 ${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)}
307 % endfor
315 % endfor
308
316
309 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
317 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
310
318
311 ## outdated comments that do not fit into currently displayed lines
319 ## outdated comments that do not fit into currently displayed lines
312 % for lineno, comments in unmatched_comments.items():
320 % for lineno, comments in unmatched_comments.items():
313
321
314 %if c.user_session_attrs["diffmode"] == 'unified':
322 %if c.user_session_attrs["diffmode"] == 'unified':
315 % if loop.index == 0:
323 % if loop.index == 0:
316 <tr class="cb-hunk">
324 <tr class="cb-hunk">
317 <td colspan="3"></td>
325 <td colspan="3"></td>
318 <td>
326 <td>
319 <div>
327 <div>
320 ${_('Unmatched/outdated inline comments below')}
328 ${_('Unmatched/outdated inline comments below')}
321 </div>
329 </div>
322 </td>
330 </td>
323 </tr>
331 </tr>
324 % endif
332 % endif
325 <tr class="cb-line">
333 <tr class="cb-line">
326 <td class="cb-data cb-context"></td>
334 <td class="cb-data cb-context"></td>
327 <td class="cb-lineno cb-context"></td>
335 <td class="cb-lineno cb-context"></td>
328 <td class="cb-lineno cb-context"></td>
336 <td class="cb-lineno cb-context"></td>
329 <td class="cb-content cb-context">
337 <td class="cb-content cb-context">
330 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
338 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
331 </td>
339 </td>
332 </tr>
340 </tr>
333 %elif c.user_session_attrs["diffmode"] == 'sideside':
341 %elif c.user_session_attrs["diffmode"] == 'sideside':
334 % if loop.index == 0:
342 % if loop.index == 0:
335 <tr class="cb-comment-info">
343 <tr class="cb-comment-info">
336 <td colspan="2"></td>
344 <td colspan="2"></td>
337 <td class="cb-line">
345 <td class="cb-line">
338 <div>
346 <div>
339 ${_('Unmatched/outdated inline comments below')}
347 ${_('Unmatched/outdated inline comments below')}
340 </div>
348 </div>
341 </td>
349 </td>
342 <td colspan="2"></td>
350 <td colspan="2"></td>
343 <td class="cb-line">
351 <td class="cb-line">
344 <div>
352 <div>
345 ${_('Unmatched/outdated comments below')}
353 ${_('Unmatched/outdated comments below')}
346 </div>
354 </div>
347 </td>
355 </td>
348 </tr>
356 </tr>
349 % endif
357 % endif
350 <tr class="cb-line">
358 <tr class="cb-line">
351 <td class="cb-data cb-context"></td>
359 <td class="cb-data cb-context"></td>
352 <td class="cb-lineno cb-context"></td>
360 <td class="cb-lineno cb-context"></td>
353 <td class="cb-content cb-context">
361 <td class="cb-content cb-context">
354 % if lineno.startswith('o'):
362 % if lineno.startswith('o'):
355 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
363 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
356 % endif
364 % endif
357 </td>
365 </td>
358
366
359 <td class="cb-data cb-context"></td>
367 <td class="cb-data cb-context"></td>
360 <td class="cb-lineno cb-context"></td>
368 <td class="cb-lineno cb-context"></td>
361 <td class="cb-content cb-context">
369 <td class="cb-content cb-context">
362 % if lineno.startswith('n'):
370 % if lineno.startswith('n'):
363 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
371 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
364 % endif
372 % endif
365 </td>
373 </td>
366 </tr>
374 </tr>
367 %endif
375 %endif
368
376
369 % endfor
377 % endfor
370
378
371 </table>
379 </table>
372 </div>
380 </div>
373 %endfor
381 %endfor
374
382
375 ## 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
376 % for filename, comments_dict in (deleted_files_comments or {}).items():
384 % for filename, comments_dict in (deleted_files_comments or {}).items():
377
385
378 <%
386 <%
379 display_state = 'display: none'
387 display_state = 'display: none'
380 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]
381 if open_comments_in_file:
389 if open_comments_in_file:
382 display_state = ''
390 display_state = ''
383 fid = str(id(filename))
391 fid = str(id(filename))
384 %>
392 %>
385 <div class="filediffs filediff-outdated" style="${display_state}">
393 <div class="filediffs filediff-outdated" style="${display_state}">
386 <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();">
387 <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)}">
388 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
396 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
389 <div class="filediff-collapse-indicator icon-"></div>
397 <div class="filediff-collapse-indicator icon-"></div>
390
398
391 <span class="pill">
399 <span class="pill">
392 ## file was deleted
400 ## file was deleted
393 ${filename}
401 ${filename}
394 </span>
402 </span>
395 <span class="pill-group pull-left" >
403 <span class="pill-group pull-left" >
396 ## file op, doesn't need translation
404 ## file op, doesn't need translation
397 <span class="pill" op="removed">unresolved comments</span>
405 <span class="pill" op="removed">unresolved comments</span>
398 </span>
406 </span>
399 <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>
400 <span class="pill-group pull-right">
408 <span class="pill-group pull-right">
401 <span class="pill" op="deleted">
409 <span class="pill" op="deleted">
402 % if comments_dict['stats'] >0:
410 % if comments_dict['stats'] >0:
403 -${comments_dict['stats']}
411 -${comments_dict['stats']}
404 % else:
412 % else:
405 ${comments_dict['stats']}
413 ${comments_dict['stats']}
406 % endif
414 % endif
407 </span>
415 </span>
408 </span>
416 </span>
409 </label>
417 </label>
410
418
411 <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 '')}">
412 <tr>
420 <tr>
413 % if c.user_session_attrs["diffmode"] == 'unified':
421 % if c.user_session_attrs["diffmode"] == 'unified':
414 <td></td>
422 <td></td>
415 %endif
423 %endif
416
424
417 <td></td>
425 <td></td>
418 <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')}>
419 <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/>
420 ${_('There are still outdated/unresolved comments attached to it.')}
428 ${_('There are still outdated/unresolved comments attached to it.')}
421 </td>
429 </td>
422 </tr>
430 </tr>
423 %if c.user_session_attrs["diffmode"] == 'unified':
431 %if c.user_session_attrs["diffmode"] == 'unified':
424 <tr class="cb-line">
432 <tr class="cb-line">
425 <td class="cb-data cb-context"></td>
433 <td class="cb-data cb-context"></td>
426 <td class="cb-lineno cb-context"></td>
434 <td class="cb-lineno cb-context"></td>
427 <td class="cb-lineno cb-context"></td>
435 <td class="cb-lineno cb-context"></td>
428 <td class="cb-content cb-context">
436 <td class="cb-content cb-context">
429 ${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)}
430 </td>
438 </td>
431 </tr>
439 </tr>
432 %elif c.user_session_attrs["diffmode"] == 'sideside':
440 %elif c.user_session_attrs["diffmode"] == 'sideside':
433 <tr class="cb-line">
441 <tr class="cb-line">
434 <td class="cb-data cb-context"></td>
442 <td class="cb-data cb-context"></td>
435 <td class="cb-lineno cb-context"></td>
443 <td class="cb-lineno cb-context"></td>
436 <td class="cb-content cb-context"></td>
444 <td class="cb-content cb-context"></td>
437
445
438 <td class="cb-data cb-context"></td>
446 <td class="cb-data cb-context"></td>
439 <td class="cb-lineno cb-context"></td>
447 <td class="cb-lineno cb-context"></td>
440 <td class="cb-content cb-context">
448 <td class="cb-content cb-context">
441 ${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)}
442 </td>
450 </td>
443 </tr>
451 </tr>
444 %endif
452 %endif
445 </table>
453 </table>
446 </div>
454 </div>
447 </div>
455 </div>
448 % endfor
456 % endfor
449
457
450 </div>
458 </div>
451 </div>
459 </div>
452 </%def>
460 </%def>
453
461
454 <%def name="diff_ops(filediff)">
462 <%def name="diff_ops(filediff)">
455 <%
463 <%
456 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
464 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
457 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
465 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
458 %>
466 %>
459 <span class="pill">
467 <span class="pill">
460 <i class="icon-file-text"></i>
468 <i class="icon-file-text"></i>
461 %if filediff.source_file_path and filediff.target_file_path:
469 %if filediff.source_file_path and filediff.target_file_path:
462 %if filediff.source_file_path != filediff.target_file_path:
470 %if filediff.source_file_path != filediff.target_file_path:
463 ## file was renamed, or copied
471 ## file was renamed, or copied
464 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
472 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
465 ${filediff.target_file_path} β¬… <del>${filediff.source_file_path}</del>
473 ${filediff.target_file_path} β¬… <del>${filediff.source_file_path}</del>
466 <% final_path = filediff.target_file_path %>
474 <% final_path = filediff.target_file_path %>
467 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
475 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
468 ${filediff.target_file_path} β¬… ${filediff.source_file_path}
476 ${filediff.target_file_path} β¬… ${filediff.source_file_path}
469 <% final_path = filediff.target_file_path %>
477 <% final_path = filediff.target_file_path %>
470 %endif
478 %endif
471 %else:
479 %else:
472 ## file was modified
480 ## file was modified
473 ${filediff.source_file_path}
481 ${filediff.source_file_path}
474 <% final_path = filediff.source_file_path %>
482 <% final_path = filediff.source_file_path %>
475 %endif
483 %endif
476 %else:
484 %else:
477 %if filediff.source_file_path:
485 %if filediff.source_file_path:
478 ## file was deleted
486 ## file was deleted
479 ${filediff.source_file_path}
487 ${filediff.source_file_path}
480 <% final_path = filediff.source_file_path %>
488 <% final_path = filediff.source_file_path %>
481 %else:
489 %else:
482 ## file was added
490 ## file was added
483 ${filediff.target_file_path}
491 ${filediff.target_file_path}
484 <% final_path = filediff.target_file_path %>
492 <% final_path = filediff.target_file_path %>
485 %endif
493 %endif
486 %endif
494 %endif
487 <i style="color: #aaa" class="tooltip 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>
488 </span>
496 </span>
489 ## anchor link
497 ## anchor link
490 <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>
491
499
492 <span class="pill-group pull-right">
500 <span class="pill-group pull-right">
493
501
494 ## ops pills
502 ## ops pills
495 %if filediff.limited_diff:
503 %if filediff.limited_diff:
496 <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>
497 %endif
505 %endif
498
506
499 %if NEW_FILENODE in filediff.patch['stats']['ops']:
507 %if NEW_FILENODE in filediff.patch['stats']['ops']:
500 <span class="pill" op="created">created</span>
508 <span class="pill" op="created">created</span>
501 %if filediff['target_mode'].startswith('120'):
509 %if filediff['target_mode'].startswith('120'):
502 <span class="pill" op="symlink">symlink</span>
510 <span class="pill" op="symlink">symlink</span>
503 %else:
511 %else:
504 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
512 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
505 %endif
513 %endif
506 %endif
514 %endif
507
515
508 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
516 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
509 <span class="pill" op="renamed">renamed</span>
517 <span class="pill" op="renamed">renamed</span>
510 %endif
518 %endif
511
519
512 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
520 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
513 <span class="pill" op="copied">copied</span>
521 <span class="pill" op="copied">copied</span>
514 %endif
522 %endif
515
523
516 %if DEL_FILENODE in filediff.patch['stats']['ops']:
524 %if DEL_FILENODE in filediff.patch['stats']['ops']:
517 <span class="pill" op="removed">removed</span>
525 <span class="pill" op="removed">removed</span>
518 %endif
526 %endif
519
527
520 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
528 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
521 <span class="pill" op="mode">
529 <span class="pill" op="mode">
522 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
530 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
523 </span>
531 </span>
524 %endif
532 %endif
525
533
526 %if BIN_FILENODE in filediff.patch['stats']['ops']:
534 %if BIN_FILENODE in filediff.patch['stats']['ops']:
527 <span class="pill" op="binary">binary</span>
535 <span class="pill" op="binary">binary</span>
528 %if MOD_FILENODE in filediff.patch['stats']['ops']:
536 %if MOD_FILENODE in filediff.patch['stats']['ops']:
529 <span class="pill" op="modified">modified</span>
537 <span class="pill" op="modified">modified</span>
530 %endif
538 %endif
531 %endif
539 %endif
532
540
533 <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>
534 <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>
535
543
536 </span>
544 </span>
537
545
538 </%def>
546 </%def>
539
547
540 <%def name="nice_mode(filemode)">
548 <%def name="nice_mode(filemode)">
541 ${(filemode.startswith('100') and filemode[3:] or filemode)}
549 ${(filemode.startswith('100') and filemode[3:] or filemode)}
542 </%def>
550 </%def>
543
551
544 <%def name="diff_menu(filediff, use_comments=False)">
552 <%def name="diff_menu(filediff, use_comments=False)">
545 <div class="filediff-menu">
553 <div class="filediff-menu">
546
554
547 %if filediff.diffset.source_ref:
555 %if filediff.diffset.source_ref:
548
556
549 ## FILE BEFORE CHANGES
557 ## FILE BEFORE CHANGES
550 %if filediff.operation in ['D', 'M']:
558 %if filediff.operation in ['D', 'M']:
551 <a
559 <a
552 class="tooltip"
560 class="tooltip"
553 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)}"
561 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)}"
554 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
562 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
555 >
563 >
556 ${_('Show file before')}
564 ${_('Show file before')}
557 </a> |
565 </a> |
558 %else:
566 %else:
559 <span
567 <span
560 class="tooltip"
568 class="tooltip"
561 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
569 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
562 >
570 >
563 ${_('Show file before')}
571 ${_('Show file before')}
564 </span> |
572 </span> |
565 %endif
573 %endif
566
574
567 ## FILE AFTER CHANGES
575 ## FILE AFTER CHANGES
568 %if filediff.operation in ['A', 'M']:
576 %if filediff.operation in ['A', 'M']:
569 <a
577 <a
570 class="tooltip"
578 class="tooltip"
571 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)}"
579 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)}"
572 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
580 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
573 >
581 >
574 ${_('Show file after')}
582 ${_('Show file after')}
575 </a>
583 </a>
576 %else:
584 %else:
577 <span
585 <span
578 class="tooltip"
586 class="tooltip"
579 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
587 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
580 >
588 >
581 ${_('Show file after')}
589 ${_('Show file after')}
582 </span>
590 </span>
583 %endif
591 %endif
584
592
585 % if use_comments:
593 % if use_comments:
586 |
594 |
587 <a href="#" onclick="return Rhodecode.comments.toggleComments(this);">
595 <a href="#" onclick="return Rhodecode.comments.toggleComments(this);">
588 <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span>
596 <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span>
589 </a>
597 </a>
590 % endif
598 % endif
591
599
592 %endif
600 %endif
593
601
594 </div>
602 </div>
595 </%def>
603 </%def>
596
604
597
605
598 <%def name="inline_comments_container(comments, active_pattern_entries=None)">
606 <%def name="inline_comments_container(comments, active_pattern_entries=None)">
599
607
600 <div class="inline-comments">
608 <div class="inline-comments">
601 %for comment in comments:
609 %for comment in comments:
602 ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)}
610 ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)}
603 %endfor
611 %endfor
604 % if comments and comments[-1].outdated:
612 % if comments and comments[-1].outdated:
605 <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}">
613 <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}">
606 ${_('Add another comment')}
614 ${_('Add another comment')}
607 </span>
615 </span>
608 % else:
616 % else:
609 <span onclick="return Rhodecode.comments.createComment(this)" class="btn btn-secondary cb-comment-add-button">
617 <span onclick="return Rhodecode.comments.createComment(this)" class="btn btn-secondary cb-comment-add-button">
610 ${_('Add another comment')}
618 ${_('Add another comment')}
611 </span>
619 </span>
612 % endif
620 % endif
613
621
614 </div>
622 </div>
615 </%def>
623 </%def>
616
624
617 <%!
625 <%!
626
627 def get_inline_comments(comments, filename):
628 if hasattr(filename, 'unicode_path'):
629 filename = filename.unicode_path
630
631 if not isinstance(filename, (unicode, str)):
632 return None
633
634 if comments and filename in comments:
635 return comments[filename]
636
637 return None
638
618 def get_comments_for(diff_type, comments, filename, line_version, line_number):
639 def get_comments_for(diff_type, comments, filename, line_version, line_number):
619 if hasattr(filename, 'unicode_path'):
640 if hasattr(filename, 'unicode_path'):
620 filename = filename.unicode_path
641 filename = filename.unicode_path
621
642
622 if not isinstance(filename, (unicode, str)):
643 if not isinstance(filename, (unicode, str)):
623 return None
644 return None
624
645
625 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
646 file_comments = get_inline_comments(comments, filename)
647 if file_comments is None:
648 return None
626
649
627 if comments and filename in comments:
650 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
628 file_comments = comments[filename]
651 if line_key in file_comments:
629 if line_key in file_comments:
652 data = file_comments.pop(line_key)
630 data = file_comments.pop(line_key)
653 return data
631 return data
632 %>
654 %>
633
655
634 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
656 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
635 %for i, line in enumerate(hunk.sideside):
657 %for i, line in enumerate(hunk.sideside):
636 <%
658 <%
637 old_line_anchor, new_line_anchor = None, None
659 old_line_anchor, new_line_anchor = None, None
638
660
639 if line.original.lineno:
661 if line.original.lineno:
640 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
662 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
641 if line.modified.lineno:
663 if line.modified.lineno:
642 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
664 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
643 %>
665 %>
644
666
645 <tr class="cb-line">
667 <tr class="cb-line">
646 <td class="cb-data ${action_class(line.original.action)}"
668 <td class="cb-data ${action_class(line.original.action)}"
647 data-line-no="${line.original.lineno}"
669 data-line-no="${line.original.lineno}"
648 >
670 >
649 <div>
671 <div>
650
672
651 <% line_old_comments = None %>
673 <% line_old_comments = None %>
652 %if line.original.get_comment_args:
674 %if line.original.get_comment_args:
653 <% line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args) %>
675 <% line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args) %>
654 %endif
676 %endif
655 %if line_old_comments:
677 %if line_old_comments:
656 <% has_outdated = any([x.outdated for x in line_old_comments]) %>
678 <% has_outdated = any([x.outdated for x in line_old_comments]) %>
657 % if has_outdated:
679 % if has_outdated:
658 <i title="${_('comments including outdated')}:${len(line_old_comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
680 <i title="${_('comments including outdated')}:${len(line_old_comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
659 % else:
681 % else:
660 <i title="${_('comments')}: ${len(line_old_comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
682 <i title="${_('comments')}: ${len(line_old_comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
661 % endif
683 % endif
662 %endif
684 %endif
663 </div>
685 </div>
664 </td>
686 </td>
665 <td class="cb-lineno ${action_class(line.original.action)}"
687 <td class="cb-lineno ${action_class(line.original.action)}"
666 data-line-no="${line.original.lineno}"
688 data-line-no="${line.original.lineno}"
667 %if old_line_anchor:
689 %if old_line_anchor:
668 id="${old_line_anchor}"
690 id="${old_line_anchor}"
669 %endif
691 %endif
670 >
692 >
671 %if line.original.lineno:
693 %if line.original.lineno:
672 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
694 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
673 %endif
695 %endif
674 </td>
696 </td>
675 <td class="cb-content ${action_class(line.original.action)}"
697 <td class="cb-content ${action_class(line.original.action)}"
676 data-line-no="o${line.original.lineno}"
698 data-line-no="o${line.original.lineno}"
677 >
699 >
678 %if use_comments and line.original.lineno:
700 %if use_comments and line.original.lineno:
679 ${render_add_comment_button()}
701 ${render_add_comment_button()}
680 %endif
702 %endif
681 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
703 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
682
704
683 %if use_comments and line.original.lineno and line_old_comments:
705 %if use_comments and line.original.lineno and line_old_comments:
684 ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries)}
706 ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries)}
685 %endif
707 %endif
686
708
687 </td>
709 </td>
688 <td class="cb-data ${action_class(line.modified.action)}"
710 <td class="cb-data ${action_class(line.modified.action)}"
689 data-line-no="${line.modified.lineno}"
711 data-line-no="${line.modified.lineno}"
690 >
712 >
691 <div>
713 <div>
692
714
693 %if line.modified.get_comment_args:
715 %if line.modified.get_comment_args:
694 <% line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args) %>
716 <% line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args) %>
695 %else:
717 %else:
696 <% line_new_comments = None%>
718 <% line_new_comments = None%>
697 %endif
719 %endif
698 %if line_new_comments:
720 %if line_new_comments:
699 <% has_outdated = any([x.outdated for x in line_new_comments]) %>
721 <% has_outdated = any([x.outdated for x in line_new_comments]) %>
700 % if has_outdated:
722 % if has_outdated:
701 <i title="${_('comments including outdated')}:${len(line_new_comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
723 <i title="${_('comments including outdated')}:${len(line_new_comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
702 % else:
724 % else:
703 <i title="${_('comments')}: ${len(line_new_comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
725 <i title="${_('comments')}: ${len(line_new_comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
704 % endif
726 % endif
705 %endif
727 %endif
706 </div>
728 </div>
707 </td>
729 </td>
708 <td class="cb-lineno ${action_class(line.modified.action)}"
730 <td class="cb-lineno ${action_class(line.modified.action)}"
709 data-line-no="${line.modified.lineno}"
731 data-line-no="${line.modified.lineno}"
710 %if new_line_anchor:
732 %if new_line_anchor:
711 id="${new_line_anchor}"
733 id="${new_line_anchor}"
712 %endif
734 %endif
713 >
735 >
714 %if line.modified.lineno:
736 %if line.modified.lineno:
715 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
737 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
716 %endif
738 %endif
717 </td>
739 </td>
718 <td class="cb-content ${action_class(line.modified.action)}"
740 <td class="cb-content ${action_class(line.modified.action)}"
719 data-line-no="n${line.modified.lineno}"
741 data-line-no="n${line.modified.lineno}"
720 >
742 >
721 %if use_comments and line.modified.lineno:
743 %if use_comments and line.modified.lineno:
722 ${render_add_comment_button()}
744 ${render_add_comment_button()}
723 %endif
745 %endif
724 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
746 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
725 %if use_comments and line.modified.lineno and line_new_comments:
747 %if use_comments and line.modified.lineno and line_new_comments:
726 ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)}
748 ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)}
727 %endif
749 %endif
728 </td>
750 </td>
729 </tr>
751 </tr>
730 %endfor
752 %endfor
731 </%def>
753 </%def>
732
754
733
755
734 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
756 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)">
735 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
757 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
736
758
737 <%
759 <%
738 old_line_anchor, new_line_anchor = None, None
760 old_line_anchor, new_line_anchor = None, None
739 if old_line_no:
761 if old_line_no:
740 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
762 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
741 if new_line_no:
763 if new_line_no:
742 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
764 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
743 %>
765 %>
744 <tr class="cb-line">
766 <tr class="cb-line">
745 <td class="cb-data ${action_class(action)}">
767 <td class="cb-data ${action_class(action)}">
746 <div>
768 <div>
747
769
748 %if comments_args:
770 %if comments_args:
749 <% comments = get_comments_for('unified', inline_comments, *comments_args) %>
771 <% comments = get_comments_for('unified', inline_comments, *comments_args) %>
750 %else:
772 %else:
751 <% comments = None %>
773 <% comments = None %>
752 %endif
774 %endif
753
775
754 % if comments:
776 % if comments:
755 <% has_outdated = any([x.outdated for x in comments]) %>
777 <% has_outdated = any([x.outdated for x in comments]) %>
756 % if has_outdated:
778 % if has_outdated:
757 <i title="${_('comments including outdated')}:${len(comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
779 <i title="${_('comments including outdated')}:${len(comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
758 % else:
780 % else:
759 <i title="${_('comments')}: ${len(comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
781 <i title="${_('comments')}: ${len(comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
760 % endif
782 % endif
761 % endif
783 % endif
762 </div>
784 </div>
763 </td>
785 </td>
764 <td class="cb-lineno ${action_class(action)}"
786 <td class="cb-lineno ${action_class(action)}"
765 data-line-no="${old_line_no}"
787 data-line-no="${old_line_no}"
766 %if old_line_anchor:
788 %if old_line_anchor:
767 id="${old_line_anchor}"
789 id="${old_line_anchor}"
768 %endif
790 %endif
769 >
791 >
770 %if old_line_anchor:
792 %if old_line_anchor:
771 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
793 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
772 %endif
794 %endif
773 </td>
795 </td>
774 <td class="cb-lineno ${action_class(action)}"
796 <td class="cb-lineno ${action_class(action)}"
775 data-line-no="${new_line_no}"
797 data-line-no="${new_line_no}"
776 %if new_line_anchor:
798 %if new_line_anchor:
777 id="${new_line_anchor}"
799 id="${new_line_anchor}"
778 %endif
800 %endif
779 >
801 >
780 %if new_line_anchor:
802 %if new_line_anchor:
781 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
803 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
782 %endif
804 %endif
783 </td>
805 </td>
784 <td class="cb-content ${action_class(action)}"
806 <td class="cb-content ${action_class(action)}"
785 data-line-no="${(new_line_no and 'n' or 'o')}${(new_line_no or old_line_no)}"
807 data-line-no="${(new_line_no and 'n' or 'o')}${(new_line_no or old_line_no)}"
786 >
808 >
787 %if use_comments:
809 %if use_comments:
788 ${render_add_comment_button()}
810 ${render_add_comment_button()}
789 %endif
811 %endif
790 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
812 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
791 %if use_comments and comments:
813 %if use_comments and comments:
792 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
814 ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)}
793 %endif
815 %endif
794 </td>
816 </td>
795 </tr>
817 </tr>
796 %endfor
818 %endfor
797 </%def>
819 </%def>
798
820
799
821
800 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)">
822 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)">
801 % if diff_mode == 'unified':
823 % if diff_mode == 'unified':
802 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
824 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
803 % elif diff_mode == 'sideside':
825 % elif diff_mode == 'sideside':
804 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
826 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)}
805 % else:
827 % else:
806 <tr class="cb-line">
828 <tr class="cb-line">
807 <td>unknown diff mode</td>
829 <td>unknown diff mode</td>
808 </tr>
830 </tr>
809 % endif
831 % endif
810 </%def>file changes
832 </%def>file changes
811
833
812
834
813 <%def name="render_add_comment_button()">
835 <%def name="render_add_comment_button()">
814 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)">
836 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)">
815 <span><i class="icon-comment"></i></span>
837 <span><i class="icon-comment"></i></span>
816 </button>
838 </button>
817 </%def>
839 </%def>
818
840
819 <%def name="render_diffset_menu(diffset, range_diff_on=None)">
841 <%def name="render_diffset_menu(diffset, range_diff_on=None)">
820 <% diffset_container_id = h.md5(diffset.target_ref) %>
842 <% diffset_container_id = h.md5(diffset.target_ref) %>
821
843
822 <div id="diff-file-sticky" class="diffset-menu clearinner">
844 <div id="diff-file-sticky" class="diffset-menu clearinner">
823 ## auto adjustable
845 ## auto adjustable
824 <div class="sidebar__inner">
846 <div class="sidebar__inner">
825 <div class="sidebar__bar">
847 <div class="sidebar__bar">
826 <div class="pull-right">
848 <div class="pull-right">
827 <div class="btn-group">
849 <div class="btn-group">
828 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
850 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
829 <i class="icon-wide-mode"></i>
851 <i class="icon-wide-mode"></i>
830 </a>
852 </a>
831 </div>
853 </div>
832 <div class="btn-group">
854 <div class="btn-group">
833
855
834 <a
856 <a
835 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
857 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
836 title="${h.tooltip(_('View diff as side by side'))}"
858 title="${h.tooltip(_('View diff as side by side'))}"
837 href="${h.current_route_path(request, diffmode='sideside')}">
859 href="${h.current_route_path(request, diffmode='sideside')}">
838 <span>${_('Side by Side')}</span>
860 <span>${_('Side by Side')}</span>
839 </a>
861 </a>
840
862
841 <a
863 <a
842 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
864 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
843 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
865 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
844 <span>${_('Unified')}</span>
866 <span>${_('Unified')}</span>
845 </a>
867 </a>
846
868
847 % if range_diff_on is True:
869 % if range_diff_on is True:
848 <a
870 <a
849 title="${_('Turn off: Show the diff as commit range')}"
871 title="${_('Turn off: Show the diff as commit range')}"
850 class="btn btn-primary"
872 class="btn btn-primary"
851 href="${h.current_route_path(request, **{"range-diff":"0"})}">
873 href="${h.current_route_path(request, **{"range-diff":"0"})}">
852 <span>${_('Range Diff')}</span>
874 <span>${_('Range Diff')}</span>
853 </a>
875 </a>
854 % elif range_diff_on is False:
876 % elif range_diff_on is False:
855 <a
877 <a
856 title="${_('Show the diff as commit range')}"
878 title="${_('Show the diff as commit range')}"
857 class="btn"
879 class="btn"
858 href="${h.current_route_path(request, **{"range-diff":"1"})}">
880 href="${h.current_route_path(request, **{"range-diff":"1"})}">
859 <span>${_('Range Diff')}</span>
881 <span>${_('Range Diff')}</span>
860 </a>
882 </a>
861 % endif
883 % endif
862 </div>
884 </div>
863 <div class="btn-group">
885 <div class="btn-group">
864
886
865 <div class="pull-left">
887 <div class="pull-left">
866 ${h.hidden('diff_menu_{}'.format(diffset_container_id))}
888 ${h.hidden('diff_menu_{}'.format(diffset_container_id))}
867 </div>
889 </div>
868
890
869 </div>
891 </div>
870 </div>
892 </div>
871 <div class="pull-left">
893 <div class="pull-left">
872 <div class="btn-group">
894 <div class="btn-group">
873 <div class="pull-left">
895 <div class="pull-left">
874 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
896 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
875 </div>
897 </div>
876
898
877 </div>
899 </div>
878 </div>
900 </div>
879 </div>
901 </div>
880 <div class="fpath-placeholder">
902 <div class="fpath-placeholder">
881 <i class="icon-file-text"></i>
903 <i class="icon-file-text"></i>
882 <strong class="fpath-placeholder-text">
904 <strong class="fpath-placeholder-text">
883 Context file:
905 Context file:
884 </strong>
906 </strong>
885 </div>
907 </div>
886 <div class="sidebar_inner_shadow"></div>
908 <div class="sidebar_inner_shadow"></div>
887 </div>
909 </div>
888 </div>
910 </div>
889
911
890 % if diffset:
912 % if diffset:
891 %if diffset.limited_diff:
913 %if diffset.limited_diff:
892 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
914 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
893 %else:
915 %else:
894 <% 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>',
916 <% 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>',
895 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
917 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
896
918
897 %endif
919 %endif
898 ## case on range-diff placeholder needs to be updated
920 ## case on range-diff placeholder needs to be updated
899 % if range_diff_on is True:
921 % if range_diff_on is True:
900 <% file_placeholder = _('Disabled on range diff') %>
922 <% file_placeholder = _('Disabled on range diff') %>
901 % endif
923 % endif
902
924
903 <script type="text/javascript">
925 <script type="text/javascript">
904 var feedFilesOptions = function (query, initialData) {
926 var feedFilesOptions = function (query, initialData) {
905 var data = {results: []};
927 var data = {results: []};
906 var isQuery = typeof query.term !== 'undefined';
928 var isQuery = typeof query.term !== 'undefined';
907
929
908 var section = _gettext('Changed files');
930 var section = _gettext('Changed files');
909 var filteredData = [];
931 var filteredData = [];
910
932
911 //filter results
933 //filter results
912 $.each(initialData.results, function (idx, value) {
934 $.each(initialData.results, function (idx, value) {
913
935
914 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
936 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
915 filteredData.push({
937 filteredData.push({
916 'id': this.id,
938 'id': this.id,
917 'text': this.text,
939 'text': this.text,
918 "ops": this.ops,
940 "ops": this.ops,
919 })
941 })
920 }
942 }
921
943
922 });
944 });
923
945
924 data.results = filteredData;
946 data.results = filteredData;
925
947
926 query.callback(data);
948 query.callback(data);
927 };
949 };
928
950
929 var selectionFormatter = function(data, escapeMarkup) {
951 var selectionFormatter = function(data, escapeMarkup) {
930 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
952 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
931 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
953 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
932 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
954 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
933 '<span class="pill" op="added">{0}</span>' +
955 '<span class="pill" op="added">{0}</span>' +
934 '<span class="pill" op="deleted">{1}</span>' +
956 '<span class="pill" op="deleted">{1}</span>' +
935 '</div>'
957 '</div>'
936 ;
958 ;
937 var added = data['ops']['added'];
959 var added = data['ops']['added'];
938 if (added === 0) {
960 if (added === 0) {
939 // don't show +0
961 // don't show +0
940 added = 0;
962 added = 0;
941 } else {
963 } else {
942 added = '+' + added;
964 added = '+' + added;
943 }
965 }
944
966
945 var deleted = -1*data['ops']['deleted'];
967 var deleted = -1*data['ops']['deleted'];
946
968
947 tmpl += pill.format(added, deleted);
969 tmpl += pill.format(added, deleted);
948 return container.format(tmpl);
970 return container.format(tmpl);
949 };
971 };
950 var formatFileResult = function(result, container, query, escapeMarkup) {
972 var formatFileResult = function(result, container, query, escapeMarkup) {
951 return selectionFormatter(result, escapeMarkup);
973 return selectionFormatter(result, escapeMarkup);
952 };
974 };
953
975
954 var formatSelection = function (data, container) {
976 var formatSelection = function (data, container) {
955 return '${file_placeholder}'
977 return '${file_placeholder}'
956 };
978 };
957
979
958 if (window.preloadFileFilterData === undefined) {
980 if (window.preloadFileFilterData === undefined) {
959 window.preloadFileFilterData = {}
981 window.preloadFileFilterData = {}
960 }
982 }
961
983
962 preloadFileFilterData["${diffset_container_id}"] = {
984 preloadFileFilterData["${diffset_container_id}"] = {
963 results: [
985 results: [
964 % for filediff in diffset.files:
986 % for filediff in diffset.files:
965 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
987 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
966 text:"${filediff.patch['filename']}",
988 text:"${filediff.patch['filename']}",
967 ops:${h.json.dumps(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
989 ops:${h.json.dumps(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
968 % endfor
990 % endfor
969 ]
991 ]
970 };
992 };
971
993
972 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
994 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
973 var diffFileFilter = $(diffFileFilterId).select2({
995 var diffFileFilter = $(diffFileFilterId).select2({
974 'dropdownAutoWidth': true,
996 'dropdownAutoWidth': true,
975 'width': 'auto',
997 'width': 'auto',
976
998
977 containerCssClass: "drop-menu",
999 containerCssClass: "drop-menu",
978 dropdownCssClass: "drop-menu-dropdown",
1000 dropdownCssClass: "drop-menu-dropdown",
979 data: preloadFileFilterData["${diffset_container_id}"],
1001 data: preloadFileFilterData["${diffset_container_id}"],
980 query: function(query) {
1002 query: function(query) {
981 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
1003 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
982 },
1004 },
983 initSelection: function(element, callback) {
1005 initSelection: function(element, callback) {
984 callback({'init': true});
1006 callback({'init': true});
985 },
1007 },
986 formatResult: formatFileResult,
1008 formatResult: formatFileResult,
987 formatSelection: formatSelection
1009 formatSelection: formatSelection
988 });
1010 });
989
1011
990 % if range_diff_on is True:
1012 % if range_diff_on is True:
991 diffFileFilter.select2("enable", false);
1013 diffFileFilter.select2("enable", false);
992 % endif
1014 % endif
993
1015
994 $(diffFileFilterId).on('select2-selecting', function (e) {
1016 $(diffFileFilterId).on('select2-selecting', function (e) {
995 var idSelector = e.choice.id;
1017 var idSelector = e.choice.id;
996
1018
997 // expand the container if we quick-select the field
1019 // expand the container if we quick-select the field
998 $('#'+idSelector).next().prop('checked', false);
1020 $('#'+idSelector).next().prop('checked', false);
999 // hide the mast as we later do preventDefault()
1021 // hide the mast as we later do preventDefault()
1000 $("#select2-drop-mask").click();
1022 $("#select2-drop-mask").click();
1001
1023
1002 window.location.hash = '#'+idSelector;
1024 window.location.hash = '#'+idSelector;
1003 updateSticky();
1025 updateSticky();
1004
1026
1005 e.preventDefault();
1027 e.preventDefault();
1006 });
1028 });
1007
1029
1008 </script>
1030 </script>
1009 % endif
1031 % endif
1010
1032
1011 <script type="text/javascript">
1033 <script type="text/javascript">
1012 $(document).ready(function () {
1034 $(document).ready(function () {
1013
1035
1014 var contextPrefix = _gettext('Context file: ');
1036 var contextPrefix = _gettext('Context file: ');
1015 ## sticky sidebar
1037 ## sticky sidebar
1016 var sidebarElement = document.getElementById('diff-file-sticky');
1038 var sidebarElement = document.getElementById('diff-file-sticky');
1017 sidebar = new StickySidebar(sidebarElement, {
1039 sidebar = new StickySidebar(sidebarElement, {
1018 topSpacing: 0,
1040 topSpacing: 0,
1019 bottomSpacing: 0,
1041 bottomSpacing: 0,
1020 innerWrapperSelector: '.sidebar__inner'
1042 innerWrapperSelector: '.sidebar__inner'
1021 });
1043 });
1022 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1044 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1023 // reset our file so it's not holding new value
1045 // reset our file so it's not holding new value
1024 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1046 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1025 });
1047 });
1026
1048
1027 updateSticky = function () {
1049 updateSticky = function () {
1028 sidebar.updateSticky();
1050 sidebar.updateSticky();
1029 Waypoint.refreshAll();
1051 Waypoint.refreshAll();
1030 };
1052 };
1031
1053
1032 var animateText = function (fPath, anchorId) {
1054 var animateText = function (fPath, anchorId) {
1033 fPath = Select2.util.escapeMarkup(fPath);
1055 fPath = Select2.util.escapeMarkup(fPath);
1034 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1056 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1035 };
1057 };
1036
1058
1037 ## dynamic file waypoints
1059 ## dynamic file waypoints
1038 var setFPathInfo = function(fPath, anchorId){
1060 var setFPathInfo = function(fPath, anchorId){
1039 animateText(fPath, anchorId)
1061 animateText(fPath, anchorId)
1040 };
1062 };
1041
1063
1042 var codeBlock = $('.filediff');
1064 var codeBlock = $('.filediff');
1043
1065
1044 // forward waypoint
1066 // forward waypoint
1045 codeBlock.waypoint(
1067 codeBlock.waypoint(
1046 function(direction) {
1068 function(direction) {
1047 if (direction === "down"){
1069 if (direction === "down"){
1048 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1070 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1049 }
1071 }
1050 }, {
1072 }, {
1051 offset: function () {
1073 offset: function () {
1052 return 70;
1074 return 70;
1053 },
1075 },
1054 context: '.fpath-placeholder'
1076 context: '.fpath-placeholder'
1055 }
1077 }
1056 );
1078 );
1057
1079
1058 // backward waypoint
1080 // backward waypoint
1059 codeBlock.waypoint(
1081 codeBlock.waypoint(
1060 function(direction) {
1082 function(direction) {
1061 if (direction === "up"){
1083 if (direction === "up"){
1062 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1084 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1063 }
1085 }
1064 }, {
1086 }, {
1065 offset: function () {
1087 offset: function () {
1066 return -this.element.clientHeight + 90;
1088 return -this.element.clientHeight + 90;
1067 },
1089 },
1068 context: '.fpath-placeholder'
1090 context: '.fpath-placeholder'
1069 }
1091 }
1070 );
1092 );
1071
1093
1072 toggleWideDiff = function (el) {
1094 toggleWideDiff = function (el) {
1073 updateSticky();
1095 updateSticky();
1074 var wide = Rhodecode.comments.toggleWideMode(this);
1096 var wide = Rhodecode.comments.toggleWideMode(this);
1075 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1097 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1076 if (wide === true) {
1098 if (wide === true) {
1077 $(el).addClass('btn-active');
1099 $(el).addClass('btn-active');
1078 } else {
1100 } else {
1079 $(el).removeClass('btn-active');
1101 $(el).removeClass('btn-active');
1080 }
1102 }
1081 return null;
1103 return null;
1082 };
1104 };
1083
1105
1084 var preloadDiffMenuData = {
1106 var preloadDiffMenuData = {
1085 results: [
1107 results: [
1086
1108
1087 ## Whitespace change
1109 ## Whitespace change
1088 % if request.GET.get('ignorews', '') == '1':
1110 % if request.GET.get('ignorews', '') == '1':
1089 {
1111 {
1090 id: 2,
1112 id: 2,
1091 text: _gettext('Show whitespace changes'),
1113 text: _gettext('Show whitespace changes'),
1092 action: function () {},
1114 action: function () {},
1093 url: "${h.current_route_path(request, ignorews=0)|n}"
1115 url: "${h.current_route_path(request, ignorews=0)|n}"
1094 },
1116 },
1095 % else:
1117 % else:
1096 {
1118 {
1097 id: 2,
1119 id: 2,
1098 text: _gettext('Hide whitespace changes'),
1120 text: _gettext('Hide whitespace changes'),
1099 action: function () {},
1121 action: function () {},
1100 url: "${h.current_route_path(request, ignorews=1)|n}"
1122 url: "${h.current_route_path(request, ignorews=1)|n}"
1101 },
1123 },
1102 % endif
1124 % endif
1103
1125
1104 ## FULL CONTEXT
1126 ## FULL CONTEXT
1105 % if request.GET.get('fullcontext', '') == '1':
1127 % if request.GET.get('fullcontext', '') == '1':
1106 {
1128 {
1107 id: 3,
1129 id: 3,
1108 text: _gettext('Hide full context diff'),
1130 text: _gettext('Hide full context diff'),
1109 action: function () {},
1131 action: function () {},
1110 url: "${h.current_route_path(request, fullcontext=0)|n}"
1132 url: "${h.current_route_path(request, fullcontext=0)|n}"
1111 },
1133 },
1112 % else:
1134 % else:
1113 {
1135 {
1114 id: 3,
1136 id: 3,
1115 text: _gettext('Show full context diff'),
1137 text: _gettext('Show full context diff'),
1116 action: function () {},
1138 action: function () {},
1117 url: "${h.current_route_path(request, fullcontext=1)|n}"
1139 url: "${h.current_route_path(request, fullcontext=1)|n}"
1118 },
1140 },
1119 % endif
1141 % endif
1120
1142
1121 ]
1143 ]
1122 };
1144 };
1123
1145
1124 var diffMenuId = "#diff_menu_" + "${diffset_container_id}";
1146 var diffMenuId = "#diff_menu_" + "${diffset_container_id}";
1125 $(diffMenuId).select2({
1147 $(diffMenuId).select2({
1126 minimumResultsForSearch: -1,
1148 minimumResultsForSearch: -1,
1127 containerCssClass: "drop-menu-no-width",
1149 containerCssClass: "drop-menu-no-width",
1128 dropdownCssClass: "drop-menu-dropdown",
1150 dropdownCssClass: "drop-menu-dropdown",
1129 dropdownAutoWidth: true,
1151 dropdownAutoWidth: true,
1130 data: preloadDiffMenuData,
1152 data: preloadDiffMenuData,
1131 placeholder: "${_('...')}",
1153 placeholder: "${_('...')}",
1132 });
1154 });
1133 $(diffMenuId).on('select2-selecting', function (e) {
1155 $(diffMenuId).on('select2-selecting', function (e) {
1134 e.choice.action();
1156 e.choice.action();
1135 if (e.choice.url !== null) {
1157 if (e.choice.url !== null) {
1136 window.location = e.choice.url
1158 window.location = e.choice.url
1137 }
1159 }
1138 });
1160 });
1139 toggleExpand = function (el, diffsetEl) {
1161 toggleExpand = function (el, diffsetEl) {
1140 var el = $(el);
1162 var el = $(el);
1141 if (el.hasClass('collapsed')) {
1163 if (el.hasClass('collapsed')) {
1142 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1164 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1143 el.removeClass('collapsed');
1165 el.removeClass('collapsed');
1144 el.html(
1166 el.html(
1145 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1167 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1146 _gettext('Collapse all files'));
1168 _gettext('Collapse all files'));
1147 }
1169 }
1148 else {
1170 else {
1149 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1171 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1150 el.addClass('collapsed');
1172 el.addClass('collapsed');
1151 el.html(
1173 el.html(
1152 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1174 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1153 _gettext('Expand all files'));
1175 _gettext('Expand all files'));
1154 }
1176 }
1155 updateSticky()
1177 updateSticky()
1156 };
1178 };
1157
1179
1158 toggleCommitExpand = function (el) {
1180 toggleCommitExpand = function (el) {
1159 var $el = $(el);
1181 var $el = $(el);
1160 var commits = $el.data('toggleCommitsCnt');
1182 var commits = $el.data('toggleCommitsCnt');
1161 var collapseMsg = _ngettext('Collapse {0} commit', 'Collapse {0} commits', commits).format(commits);
1183 var collapseMsg = _ngettext('Collapse {0} commit', 'Collapse {0} commits', commits).format(commits);
1162 var expandMsg = _ngettext('Expand {0} commit', 'Expand {0} commits', commits).format(commits);
1184 var expandMsg = _ngettext('Expand {0} commit', 'Expand {0} commits', commits).format(commits);
1163
1185
1164 if ($el.hasClass('collapsed')) {
1186 if ($el.hasClass('collapsed')) {
1165 $('.compare_select').show();
1187 $('.compare_select').show();
1166 $('.compare_select_hidden').hide();
1188 $('.compare_select_hidden').hide();
1167
1189
1168 $el.removeClass('collapsed');
1190 $el.removeClass('collapsed');
1169 $el.html(
1191 $el.html(
1170 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1192 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1171 collapseMsg);
1193 collapseMsg);
1172 }
1194 }
1173 else {
1195 else {
1174 $('.compare_select').hide();
1196 $('.compare_select').hide();
1175 $('.compare_select_hidden').show();
1197 $('.compare_select_hidden').show();
1176 $el.addClass('collapsed');
1198 $el.addClass('collapsed');
1177 $el.html(
1199 $el.html(
1178 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1200 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1179 expandMsg);
1201 expandMsg);
1180 }
1202 }
1181 updateSticky();
1203 updateSticky();
1182 };
1204 };
1183
1205
1184 // get stored diff mode and pre-enable it
1206 // get stored diff mode and pre-enable it
1185 if (templateContext.session_attrs.wide_diff_mode === "true") {
1207 if (templateContext.session_attrs.wide_diff_mode === "true") {
1186 Rhodecode.comments.toggleWideMode(null);
1208 Rhodecode.comments.toggleWideMode(null);
1187 $('.toggle-wide-diff').addClass('btn-active');
1209 $('.toggle-wide-diff').addClass('btn-active');
1188 updateSticky();
1210 updateSticky();
1189 }
1211 }
1190 });
1212 });
1191 </script>
1213 </script>
1192
1214
1193 </%def>
1215 </%def>
General Comments 0
You need to be logged in to leave comments. Login now