##// END OF EJS Templates
diffs: toggle race condition on sticky vs wide-diff-mode that caused some display artifacts
marcink -
r4037:077904b2 default
parent child Browse files
Show More
@@ -1,1151 +1,1152 b''
1 1 <%namespace name="commentblock" file="/changeset/changeset_file_comment.mako"/>
2 2
3 3 <%def name="diff_line_anchor(commit, filename, line, type)"><%
4 4 return '%s_%s_%i' % (h.md5_safe(commit+filename), type, line)
5 5 %></%def>
6 6
7 7 <%def name="action_class(action)">
8 8 <%
9 9 return {
10 10 '-': 'cb-deletion',
11 11 '+': 'cb-addition',
12 12 ' ': 'cb-context',
13 13 }.get(action, 'cb-empty')
14 14 %>
15 15 </%def>
16 16
17 17 <%def name="op_class(op_id)">
18 18 <%
19 19 return {
20 20 DEL_FILENODE: 'deletion', # file deleted
21 21 BIN_FILENODE: 'warning' # binary diff hidden
22 22 }.get(op_id, 'addition')
23 23 %>
24 24 </%def>
25 25
26 26
27 27
28 28 <%def name="render_diffset(diffset, commit=None,
29 29
30 30 # collapse all file diff entries when there are more than this amount of files in the diff
31 31 collapse_when_files_over=20,
32 32
33 33 # collapse lines in the diff when more than this amount of lines changed in the file diff
34 34 lines_changed_limit=500,
35 35
36 36 # add a ruler at to the output
37 37 ruler_at_chars=0,
38 38
39 39 # show inline comments
40 40 use_comments=False,
41 41
42 42 # disable new comments
43 43 disable_new_comments=False,
44 44
45 45 # special file-comments that were deleted in previous versions
46 46 # it's used for showing outdated comments for deleted files in a PR
47 47 deleted_files_comments=None,
48 48
49 49 # for cache purpose
50 50 inline_comments=None,
51 51
52 52 # additional menu for PRs
53 53 pull_request_menu=None
54 54
55 55 )">
56 56
57 57 <%
58 58 diffset_container_id = h.md5(diffset.target_ref)
59 59 collapse_all = len(diffset.files) > collapse_when_files_over
60 60 %>
61 61
62 62 %if use_comments:
63 63 <div id="cb-comments-inline-container-template" class="js-template">
64 64 ${inline_comments_container([], inline_comments)}
65 65 </div>
66 66 <div class="js-template" id="cb-comment-inline-form-template">
67 67 <div class="comment-inline-form ac">
68 68
69 69 %if c.rhodecode_user.username != h.DEFAULT_USER:
70 70 ## render template for inline comments
71 71 ${commentblock.comment_form(form_type='inline')}
72 72 %else:
73 73 ${h.form('', class_='inline-form comment-form-login', method='get')}
74 74 <div class="pull-left">
75 75 <div class="comment-help pull-right">
76 76 ${_('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>
77 77 </div>
78 78 </div>
79 79 <div class="comment-button pull-right">
80 80 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
81 81 ${_('Cancel')}
82 82 </button>
83 83 </div>
84 84 <div class="clearfix"></div>
85 85 ${h.end_form()}
86 86 %endif
87 87 </div>
88 88 </div>
89 89
90 90 %endif
91 91
92 92 %if c.user_session_attrs["diffmode"] == 'sideside':
93 93 <style>
94 94 .wrapper {
95 95 max-width: 1600px !important;
96 96 }
97 97 </style>
98 98 %endif
99 99
100 100 %if ruler_at_chars:
101 101 <style>
102 102 .diff table.cb .cb-content:after {
103 103 content: "";
104 104 border-left: 1px solid blue;
105 105 position: absolute;
106 106 top: 0;
107 107 height: 18px;
108 108 opacity: .2;
109 109 z-index: 10;
110 110 //## +5 to account for diff action (+/-)
111 111 left: ${ruler_at_chars + 5}ch;
112 112 </style>
113 113 %endif
114 114
115 115 <div class="diffset ${disable_new_comments and 'diffset-comments-disabled'}">
116 116
117 117 <div style="height: 20px; line-height: 20px">
118 118 ## expand/collapse action
119 119 <div class="pull-left">
120 120 <a class="${'collapsed' if collapse_all else ''}" href="#expand-files" onclick="toggleExpand(this, '${diffset_container_id}'); return false">
121 121 % if collapse_all:
122 122 <i class="icon-plus-squared-alt icon-no-margin"></i>${_('Expand all files')}
123 123 % else:
124 124 <i class="icon-minus-squared-alt icon-no-margin"></i>${_('Collapse all files')}
125 125 % endif
126 126 </a>
127 127
128 128 </div>
129 129
130 130 ## todos
131 131 % if getattr(c, 'at_version', None):
132 132 <div class="pull-right">
133 133 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
134 134 ${_('not available in this view')}
135 135 </div>
136 136 % else:
137 137 <div class="pull-right">
138 138 <div class="comments-number" style="padding-left: 10px">
139 139 % if hasattr(c, 'unresolved_comments') and hasattr(c, 'resolved_comments'):
140 140 <i class="icon-flag-filled" style="color: #949494">TODOs:</i>
141 141 % if c.unresolved_comments:
142 142 <a href="#show-todos" onclick="$('#todo-box').toggle(); return false">
143 143 ${_('{} unresolved').format(len(c.unresolved_comments))}
144 144 </a>
145 145 % else:
146 146 ${_('0 unresolved')}
147 147 % endif
148 148
149 149 ${_('{} Resolved').format(len(c.resolved_comments))}
150 150 % endif
151 151 </div>
152 152 </div>
153 153 % endif
154 154
155 155 ## comments
156 156 <div class="pull-right">
157 157 <div class="comments-number" style="padding-left: 10px">
158 158 % if hasattr(c, 'comments') and hasattr(c, 'inline_cnt'):
159 159 <i class="icon-comment" style="color: #949494">COMMENTS:</i>
160 160 % if c.comments:
161 161 <a href="#comments">${_ungettext("{} General", "{} General", len(c.comments)).format(len(c.comments))}</a>,
162 162 % else:
163 163 ${_('0 General')}
164 164 % endif
165 165
166 166 % if c.inline_cnt:
167 167 <a href="#" onclick="return Rhodecode.comments.nextComment();"
168 168 id="inline-comments-counter">${_ungettext("{} Inline", "{} Inline", c.inline_cnt).format(c.inline_cnt)}
169 169 </a>
170 170 % else:
171 171 ${_('0 Inline')}
172 172 % endif
173 173 % endif
174 174
175 175 % if pull_request_menu:
176 176 <%
177 177 outdated_comm_count_ver = pull_request_menu['outdated_comm_count_ver']
178 178 %>
179 179
180 180 % if outdated_comm_count_ver:
181 181 <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">
182 182 (${_("{} Outdated").format(outdated_comm_count_ver)})
183 183 </a>
184 184 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated')}</a>
185 185 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated')}</a>
186 186 % else:
187 187 (${_("{} Outdated").format(outdated_comm_count_ver)})
188 188 % endif
189 189
190 190 % endif
191 191
192 192 </div>
193 193 </div>
194 194
195 195 </div>
196 196
197 197 % if diffset.limited_diff:
198 198 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
199 199 <h2 class="clearinner">
200 200 ${_('The requested changes are too big and content was truncated.')}
201 201 <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>
202 202 </h2>
203 203 </div>
204 204 ## commit range header for each individual diff
205 205 % elif commit and hasattr(c, 'commit_ranges') and len(c.commit_ranges) > 1:
206 206 <div class="diffset-heading ${(diffset.limited_diff and 'diffset-heading-warning' or '')}">
207 207 <div class="clearinner">
208 208 <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>
209 209 </div>
210 210 </div>
211 211 % endif
212 212
213 213 <div id="todo-box">
214 214 % if hasattr(c, 'unresolved_comments') and c.unresolved_comments:
215 215 % for co in c.unresolved_comments:
216 216 <a class="permalink" href="#comment-${co.comment_id}"
217 217 onclick="Rhodecode.comments.scrollToComment($('#comment-${co.comment_id}'))">
218 218 <i class="icon-flag-filled-red"></i>
219 219 ${co.comment_id}</a>${('' if loop.last else ',')}
220 220 % endfor
221 221 % endif
222 222 </div>
223 223 %if diffset.has_hidden_changes:
224 224 <p class="empty_data">${_('Some changes may be hidden')}</p>
225 225 %elif not diffset.files:
226 226 <p class="empty_data">${_('No files')}</p>
227 227 %endif
228 228
229 229 <div class="filediffs">
230 230
231 231 ## initial value could be marked as False later on
232 232 <% over_lines_changed_limit = False %>
233 233 %for i, filediff in enumerate(diffset.files):
234 234
235 235 <%
236 236 lines_changed = filediff.patch['stats']['added'] + filediff.patch['stats']['deleted']
237 237 over_lines_changed_limit = lines_changed > lines_changed_limit
238 238 %>
239 239 ## anchor with support of sticky header
240 240 <div class="anchor" id="a_${h.FID(filediff.raw_id, filediff.patch['filename'])}"></div>
241 241
242 242 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filediff)}" type="checkbox" onchange="updateSticky();">
243 243 <div
244 244 class="filediff"
245 245 data-f-path="${filediff.patch['filename']}"
246 246 data-anchor-id="${h.FID(filediff.raw_id, filediff.patch['filename'])}"
247 247 >
248 248 <label for="filediff-collapse-${id(filediff)}" class="filediff-heading">
249 249 <div class="filediff-collapse-indicator icon-"></div>
250 250 ${diff_ops(filediff)}
251 251 </label>
252 252
253 253 ${diff_menu(filediff, use_comments=use_comments)}
254 254 <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 '')}">
255 255
256 256 ## new/deleted/empty content case
257 257 % if not filediff.hunks:
258 258 ## Comment container, on "fakes" hunk that contains all data to render comments
259 259 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments)}
260 260 % endif
261 261
262 262 %if filediff.limited_diff:
263 263 <tr class="cb-warning cb-collapser">
264 264 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
265 265 ${_('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>
266 266 </td>
267 267 </tr>
268 268 %else:
269 269 %if over_lines_changed_limit:
270 270 <tr class="cb-warning cb-collapser">
271 271 <td class="cb-text" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=6')}>
272 272 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
273 273 <a href="#" class="cb-expand"
274 274 onclick="$(this).closest('table').removeClass('cb-collapsed'); updateSticky(); return false;">${_('Show them')}
275 275 </a>
276 276 <a href="#" class="cb-collapse"
277 277 onclick="$(this).closest('table').addClass('cb-collapsed'); updateSticky(); return false;">${_('Hide them')}
278 278 </a>
279 279 </td>
280 280 </tr>
281 281 %endif
282 282 %endif
283 283
284 284 % for hunk in filediff.hunks:
285 285 <tr class="cb-hunk">
286 286 <td ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=3' or '')}>
287 287 ## TODO: dan: add ajax loading of more context here
288 288 ## <a href="#">
289 289 <i class="icon-more"></i>
290 290 ## </a>
291 291 </td>
292 292 <td ${(c.user_session_attrs["diffmode"] == 'sideside' and 'colspan=5' or '')}>
293 293 @@
294 294 -${hunk.source_start},${hunk.source_length}
295 295 +${hunk.target_start},${hunk.target_length}
296 296 ${hunk.section_header}
297 297 </td>
298 298 </tr>
299 299 ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments)}
300 300 % endfor
301 301
302 302 <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %>
303 303
304 304 ## outdated comments that do not fit into currently displayed lines
305 305 % for lineno, comments in unmatched_comments.items():
306 306
307 307 %if c.user_session_attrs["diffmode"] == 'unified':
308 308 % if loop.index == 0:
309 309 <tr class="cb-hunk">
310 310 <td colspan="3"></td>
311 311 <td>
312 312 <div>
313 313 ${_('Unmatched inline comments below')}
314 314 </div>
315 315 </td>
316 316 </tr>
317 317 % endif
318 318 <tr class="cb-line">
319 319 <td class="cb-data cb-context"></td>
320 320 <td class="cb-lineno cb-context"></td>
321 321 <td class="cb-lineno cb-context"></td>
322 322 <td class="cb-content cb-context">
323 323 ${inline_comments_container(comments, inline_comments)}
324 324 </td>
325 325 </tr>
326 326 %elif c.user_session_attrs["diffmode"] == 'sideside':
327 327 % if loop.index == 0:
328 328 <tr class="cb-comment-info">
329 329 <td colspan="2"></td>
330 330 <td class="cb-line">
331 331 <div>
332 332 ${_('Unmatched inline comments below')}
333 333 </div>
334 334 </td>
335 335 <td colspan="2"></td>
336 336 <td class="cb-line">
337 337 <div>
338 338 ${_('Unmatched comments below')}
339 339 </div>
340 340 </td>
341 341 </tr>
342 342 % endif
343 343 <tr class="cb-line">
344 344 <td class="cb-data cb-context"></td>
345 345 <td class="cb-lineno cb-context"></td>
346 346 <td class="cb-content cb-context">
347 347 % if lineno.startswith('o'):
348 348 ${inline_comments_container(comments, inline_comments)}
349 349 % endif
350 350 </td>
351 351
352 352 <td class="cb-data cb-context"></td>
353 353 <td class="cb-lineno cb-context"></td>
354 354 <td class="cb-content cb-context">
355 355 % if lineno.startswith('n'):
356 356 ${inline_comments_container(comments, inline_comments)}
357 357 % endif
358 358 </td>
359 359 </tr>
360 360 %endif
361 361
362 362 % endfor
363 363
364 364 </table>
365 365 </div>
366 366 %endfor
367 367
368 368 ## outdated comments that are made for a file that has been deleted
369 369 % for filename, comments_dict in (deleted_files_comments or {}).items():
370 370
371 371 <%
372 372 display_state = 'display: none'
373 373 open_comments_in_file = [x for x in comments_dict['comments'] if x.outdated is False]
374 374 if open_comments_in_file:
375 375 display_state = ''
376 376 fid = str(id(filename))
377 377 %>
378 378 <div class="filediffs filediff-outdated" style="${display_state}">
379 379 <input ${(collapse_all and 'checked' or '')} class="filediff-collapse-state collapse-${diffset_container_id}" id="filediff-collapse-${id(filename)}" type="checkbox" onchange="updateSticky();">
380 380 <div class="filediff" data-f-path="${filename}" id="a_${h.FID(fid, filename)}">
381 381 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
382 382 <div class="filediff-collapse-indicator icon-"></div>
383 383
384 384 <span class="pill">
385 385 ## file was deleted
386 386 ${filename}
387 387 </span>
388 388 <span class="pill-group pull-left" >
389 389 ## file op, doesn't need translation
390 390 <span class="pill" op="removed">removed in this version</span>
391 391 </span>
392 392 <a class="pill filediff-anchor" href="#a_${h.FID(fid, filename)}">ΒΆ</a>
393 393 <span class="pill-group pull-right">
394 394 <span class="pill" op="deleted">-${comments_dict['stats']}</span>
395 395 </span>
396 396 </label>
397 397
398 398 <table class="cb cb-diff-${c.user_session_attrs["diffmode"]} code-highlight ${(over_lines_changed_limit and 'cb-collapsed' or '')}">
399 399 <tr>
400 400 % if c.user_session_attrs["diffmode"] == 'unified':
401 401 <td></td>
402 402 %endif
403 403
404 404 <td></td>
405 405 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${(c.user_session_attrs["diffmode"] == 'unified' and 'colspan=4' or 'colspan=5')}>
406 406 ${_('File was deleted in this version. There are still outdated/unresolved comments attached to it.')}
407 407 </td>
408 408 </tr>
409 409 %if c.user_session_attrs["diffmode"] == 'unified':
410 410 <tr class="cb-line">
411 411 <td class="cb-data cb-context"></td>
412 412 <td class="cb-lineno cb-context"></td>
413 413 <td class="cb-lineno cb-context"></td>
414 414 <td class="cb-content cb-context">
415 415 ${inline_comments_container(comments_dict['comments'], inline_comments)}
416 416 </td>
417 417 </tr>
418 418 %elif c.user_session_attrs["diffmode"] == 'sideside':
419 419 <tr class="cb-line">
420 420 <td class="cb-data cb-context"></td>
421 421 <td class="cb-lineno cb-context"></td>
422 422 <td class="cb-content cb-context"></td>
423 423
424 424 <td class="cb-data cb-context"></td>
425 425 <td class="cb-lineno cb-context"></td>
426 426 <td class="cb-content cb-context">
427 427 ${inline_comments_container(comments_dict['comments'], inline_comments)}
428 428 </td>
429 429 </tr>
430 430 %endif
431 431 </table>
432 432 </div>
433 433 </div>
434 434 % endfor
435 435
436 436 </div>
437 437 </div>
438 438 </%def>
439 439
440 440 <%def name="diff_ops(filediff)">
441 441 <%
442 442 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
443 443 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
444 444 %>
445 445 <span class="pill">
446 446 <i class="icon-file-text"></i>
447 447 %if filediff.source_file_path and filediff.target_file_path:
448 448 %if filediff.source_file_path != filediff.target_file_path:
449 449 ## file was renamed, or copied
450 450 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
451 451 ${filediff.target_file_path} β¬… <del>${filediff.source_file_path}</del>
452 452 <% final_path = filediff.target_file_path %>
453 453 %elif COPIED_FILENODE in filediff.patch['stats']['ops']:
454 454 ${filediff.target_file_path} β¬… ${filediff.source_file_path}
455 455 <% final_path = filediff.target_file_path %>
456 456 %endif
457 457 %else:
458 458 ## file was modified
459 459 ${filediff.source_file_path}
460 460 <% final_path = filediff.source_file_path %>
461 461 %endif
462 462 %else:
463 463 %if filediff.source_file_path:
464 464 ## file was deleted
465 465 ${filediff.source_file_path}
466 466 <% final_path = filediff.source_file_path %>
467 467 %else:
468 468 ## file was added
469 469 ${filediff.target_file_path}
470 470 <% final_path = filediff.target_file_path %>
471 471 %endif
472 472 %endif
473 473 <i style="color: #aaa" class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${final_path}" title="${_('Copy the full path')}" onclick="return false;"></i>
474 474 </span>
475 475 ## anchor link
476 476 <a class="pill filediff-anchor" href="#a_${h.FID(filediff.raw_id, filediff.patch['filename'])}">ΒΆ</a>
477 477
478 478 <span class="pill-group pull-right">
479 479
480 480 ## ops pills
481 481 %if filediff.limited_diff:
482 482 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
483 483 %endif
484 484
485 485 %if NEW_FILENODE in filediff.patch['stats']['ops']:
486 486 <span class="pill" op="created">created</span>
487 487 %if filediff['target_mode'].startswith('120'):
488 488 <span class="pill" op="symlink">symlink</span>
489 489 %else:
490 490 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
491 491 %endif
492 492 %endif
493 493
494 494 %if RENAMED_FILENODE in filediff.patch['stats']['ops']:
495 495 <span class="pill" op="renamed">renamed</span>
496 496 %endif
497 497
498 498 %if COPIED_FILENODE in filediff.patch['stats']['ops']:
499 499 <span class="pill" op="copied">copied</span>
500 500 %endif
501 501
502 502 %if DEL_FILENODE in filediff.patch['stats']['ops']:
503 503 <span class="pill" op="removed">removed</span>
504 504 %endif
505 505
506 506 %if CHMOD_FILENODE in filediff.patch['stats']['ops']:
507 507 <span class="pill" op="mode">
508 508 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
509 509 </span>
510 510 %endif
511 511
512 512 %if BIN_FILENODE in filediff.patch['stats']['ops']:
513 513 <span class="pill" op="binary">binary</span>
514 514 %if MOD_FILENODE in filediff.patch['stats']['ops']:
515 515 <span class="pill" op="modified">modified</span>
516 516 %endif
517 517 %endif
518 518
519 519 <span class="pill" op="added">${('+' if filediff.patch['stats']['added'] else '')}${filediff.patch['stats']['added']}</span>
520 520 <span class="pill" op="deleted">${((h.safe_int(filediff.patch['stats']['deleted']) or 0) * -1)}</span>
521 521
522 522 </span>
523 523
524 524 </%def>
525 525
526 526 <%def name="nice_mode(filemode)">
527 527 ${(filemode.startswith('100') and filemode[3:] or filemode)}
528 528 </%def>
529 529
530 530 <%def name="diff_menu(filediff, use_comments=False)">
531 531 <div class="filediff-menu">
532 532
533 533 %if filediff.diffset.source_ref:
534 534
535 535 ## FILE BEFORE CHANGES
536 536 %if filediff.operation in ['D', 'M']:
537 537 <a
538 538 class="tooltip"
539 539 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)}"
540 540 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
541 541 >
542 542 ${_('Show file before')}
543 543 </a> |
544 544 %else:
545 545 <span
546 546 class="tooltip"
547 547 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
548 548 >
549 549 ${_('Show file before')}
550 550 </span> |
551 551 %endif
552 552
553 553 ## FILE AFTER CHANGES
554 554 %if filediff.operation in ['A', 'M']:
555 555 <a
556 556 class="tooltip"
557 557 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)}"
558 558 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
559 559 >
560 560 ${_('Show file after')}
561 561 </a>
562 562 %else:
563 563 <span
564 564 class="tooltip"
565 565 title="${h.tooltip(_('File not present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
566 566 >
567 567 ${_('Show file after')}
568 568 </span>
569 569 %endif
570 570
571 571 % if use_comments:
572 572 |
573 573 <a href="#" onclick="return Rhodecode.comments.toggleComments(this);">
574 574 <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span>
575 575 </a>
576 576 % endif
577 577
578 578 %endif
579 579
580 580 </div>
581 581 </%def>
582 582
583 583
584 584 <%def name="inline_comments_container(comments, inline_comments)">
585 585 <div class="inline-comments">
586 586 %for comment in comments:
587 587 ${commentblock.comment_block(comment, inline=True)}
588 588 %endfor
589 589 % if comments and comments[-1].outdated:
590 590 <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}">
591 591 ${_('Add another comment')}
592 592 </span>
593 593 % else:
594 594 <span onclick="return Rhodecode.comments.createComment(this)" class="btn btn-secondary cb-comment-add-button">
595 595 ${_('Add another comment')}
596 596 </span>
597 597 % endif
598 598
599 599 </div>
600 600 </%def>
601 601
602 602 <%!
603 603 def get_comments_for(diff_type, comments, filename, line_version, line_number):
604 604 if hasattr(filename, 'unicode_path'):
605 605 filename = filename.unicode_path
606 606
607 607 if not isinstance(filename, (unicode, str)):
608 608 return None
609 609
610 610 line_key = '{}{}'.format(line_version, line_number) ## e.g o37, n12
611 611
612 612 if comments and filename in comments:
613 613 file_comments = comments[filename]
614 614 if line_key in file_comments:
615 615 data = file_comments.pop(line_key)
616 616 return data
617 617 %>
618 618
619 619 <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None)">
620 620 %for i, line in enumerate(hunk.sideside):
621 621 <%
622 622 old_line_anchor, new_line_anchor = None, None
623 623
624 624 if line.original.lineno:
625 625 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o')
626 626 if line.modified.lineno:
627 627 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n')
628 628 %>
629 629
630 630 <tr class="cb-line">
631 631 <td class="cb-data ${action_class(line.original.action)}"
632 632 data-line-no="${line.original.lineno}"
633 633 >
634 634 <div>
635 635
636 636 <% line_old_comments = None %>
637 637 %if line.original.get_comment_args:
638 638 <% line_old_comments = get_comments_for('side-by-side', inline_comments, *line.original.get_comment_args) %>
639 639 %endif
640 640 %if line_old_comments:
641 641 <% has_outdated = any([x.outdated for x in line_old_comments]) %>
642 642 % if has_outdated:
643 643 <i title="${_('comments including outdated')}:${len(line_old_comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
644 644 % else:
645 645 <i title="${_('comments')}: ${len(line_old_comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
646 646 % endif
647 647 %endif
648 648 </div>
649 649 </td>
650 650 <td class="cb-lineno ${action_class(line.original.action)}"
651 651 data-line-no="${line.original.lineno}"
652 652 %if old_line_anchor:
653 653 id="${old_line_anchor}"
654 654 %endif
655 655 >
656 656 %if line.original.lineno:
657 657 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
658 658 %endif
659 659 </td>
660 660 <td class="cb-content ${action_class(line.original.action)}"
661 661 data-line-no="o${line.original.lineno}"
662 662 >
663 663 %if use_comments and line.original.lineno:
664 664 ${render_add_comment_button()}
665 665 %endif
666 666 <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span>
667 667
668 668 %if use_comments and line.original.lineno and line_old_comments:
669 669 ${inline_comments_container(line_old_comments, inline_comments)}
670 670 %endif
671 671
672 672 </td>
673 673 <td class="cb-data ${action_class(line.modified.action)}"
674 674 data-line-no="${line.modified.lineno}"
675 675 >
676 676 <div>
677 677
678 678 %if line.modified.get_comment_args:
679 679 <% line_new_comments = get_comments_for('side-by-side', inline_comments, *line.modified.get_comment_args) %>
680 680 %else:
681 681 <% line_new_comments = None%>
682 682 %endif
683 683 %if line_new_comments:
684 684 <% has_outdated = any([x.outdated for x in line_new_comments]) %>
685 685 % if has_outdated:
686 686 <i title="${_('comments including outdated')}:${len(line_new_comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
687 687 % else:
688 688 <i title="${_('comments')}: ${len(line_new_comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
689 689 % endif
690 690 %endif
691 691 </div>
692 692 </td>
693 693 <td class="cb-lineno ${action_class(line.modified.action)}"
694 694 data-line-no="${line.modified.lineno}"
695 695 %if new_line_anchor:
696 696 id="${new_line_anchor}"
697 697 %endif
698 698 >
699 699 %if line.modified.lineno:
700 700 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
701 701 %endif
702 702 </td>
703 703 <td class="cb-content ${action_class(line.modified.action)}"
704 704 data-line-no="n${line.modified.lineno}"
705 705 >
706 706 %if use_comments and line.modified.lineno:
707 707 ${render_add_comment_button()}
708 708 %endif
709 709 <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span>
710 710 %if use_comments and line.modified.lineno and line_new_comments:
711 711 ${inline_comments_container(line_new_comments, inline_comments)}
712 712 %endif
713 713 </td>
714 714 </tr>
715 715 %endfor
716 716 </%def>
717 717
718 718
719 719 <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None)">
720 720 %for old_line_no, new_line_no, action, content, comments_args in hunk.unified:
721 721
722 722 <%
723 723 old_line_anchor, new_line_anchor = None, None
724 724 if old_line_no:
725 725 old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, old_line_no, 'o')
726 726 if new_line_no:
727 727 new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, new_line_no, 'n')
728 728 %>
729 729 <tr class="cb-line">
730 730 <td class="cb-data ${action_class(action)}">
731 731 <div>
732 732
733 733 %if comments_args:
734 734 <% comments = get_comments_for('unified', inline_comments, *comments_args) %>
735 735 %else:
736 736 <% comments = None %>
737 737 %endif
738 738
739 739 % if comments:
740 740 <% has_outdated = any([x.outdated for x in comments]) %>
741 741 % if has_outdated:
742 742 <i title="${_('comments including outdated')}:${len(comments)}" class="icon-comment-toggle" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
743 743 % else:
744 744 <i title="${_('comments')}: ${len(comments)}" class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
745 745 % endif
746 746 % endif
747 747 </div>
748 748 </td>
749 749 <td class="cb-lineno ${action_class(action)}"
750 750 data-line-no="${old_line_no}"
751 751 %if old_line_anchor:
752 752 id="${old_line_anchor}"
753 753 %endif
754 754 >
755 755 %if old_line_anchor:
756 756 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
757 757 %endif
758 758 </td>
759 759 <td class="cb-lineno ${action_class(action)}"
760 760 data-line-no="${new_line_no}"
761 761 %if new_line_anchor:
762 762 id="${new_line_anchor}"
763 763 %endif
764 764 >
765 765 %if new_line_anchor:
766 766 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
767 767 %endif
768 768 </td>
769 769 <td class="cb-content ${action_class(action)}"
770 770 data-line-no="${(new_line_no and 'n' or 'o')}${(new_line_no or old_line_no)}"
771 771 >
772 772 %if use_comments:
773 773 ${render_add_comment_button()}
774 774 %endif
775 775 <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span>
776 776 %if use_comments and comments:
777 777 ${inline_comments_container(comments, inline_comments)}
778 778 %endif
779 779 </td>
780 780 </tr>
781 781 %endfor
782 782 </%def>
783 783
784 784
785 785 <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments)">
786 786 % if diff_mode == 'unified':
787 787 ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments)}
788 788 % elif diff_mode == 'sideside':
789 789 ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments)}
790 790 % else:
791 791 <tr class="cb-line">
792 792 <td>unknown diff mode</td>
793 793 </tr>
794 794 % endif
795 795 </%def>file changes
796 796
797 797
798 798 <%def name="render_add_comment_button()">
799 799 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)">
800 800 <span><i class="icon-comment"></i></span>
801 801 </button>
802 802 </%def>
803 803
804 804 <%def name="render_diffset_menu(diffset, range_diff_on=None)">
805 805 <% diffset_container_id = h.md5(diffset.target_ref) %>
806 806
807 807 <div id="diff-file-sticky" class="diffset-menu clearinner">
808 808 ## auto adjustable
809 809 <div class="sidebar__inner">
810 810 <div class="sidebar__bar">
811 811 <div class="pull-right">
812 812 <div class="btn-group">
813 813 <a class="btn tooltip toggle-wide-diff" href="#toggle-wide-diff" onclick="toggleWideDiff(this); return false" title="${h.tooltip(_('Toggle wide diff'))}">
814 814 <i class="icon-wide-mode"></i>
815 815 </a>
816 816 </div>
817 817 <div class="btn-group">
818 818
819 819 <a
820 820 class="btn ${(c.user_session_attrs["diffmode"] == 'sideside' and 'btn-active')} tooltip"
821 821 title="${h.tooltip(_('View diff as side by side'))}"
822 822 href="${h.current_route_path(request, diffmode='sideside')}">
823 823 <span>${_('Side by Side')}</span>
824 824 </a>
825 825
826 826 <a
827 827 class="btn ${(c.user_session_attrs["diffmode"] == 'unified' and 'btn-active')} tooltip"
828 828 title="${h.tooltip(_('View diff as unified'))}" href="${h.current_route_path(request, diffmode='unified')}">
829 829 <span>${_('Unified')}</span>
830 830 </a>
831 831
832 832 % if range_diff_on is True:
833 833 <a
834 834 title="${_('Turn off: Show the diff as commit range')}"
835 835 class="btn btn-primary"
836 836 href="${h.current_route_path(request, **{"range-diff":"0"})}">
837 837 <span>${_('Range Diff')}</span>
838 838 </a>
839 839 % elif range_diff_on is False:
840 840 <a
841 841 title="${_('Show the diff as commit range')}"
842 842 class="btn"
843 843 href="${h.current_route_path(request, **{"range-diff":"1"})}">
844 844 <span>${_('Range Diff')}</span>
845 845 </a>
846 846 % endif
847 847 </div>
848 848 <div class="btn-group">
849 849
850 850 <div class="pull-left">
851 851 ${h.hidden('diff_menu_{}'.format(diffset_container_id))}
852 852 </div>
853 853
854 854 </div>
855 855 </div>
856 856 <div class="pull-left">
857 857 <div class="btn-group">
858 858 <div class="pull-left">
859 859 ${h.hidden('file_filter_{}'.format(diffset_container_id))}
860 860 </div>
861 861
862 862 </div>
863 863 </div>
864 864 </div>
865 865 <div class="fpath-placeholder">
866 866 <i class="icon-file-text"></i>
867 867 <strong class="fpath-placeholder-text">
868 868 Context file:
869 869 </strong>
870 870 </div>
871 871 <div class="sidebar_inner_shadow"></div>
872 872 </div>
873 873 </div>
874 874
875 875 % if diffset:
876 876 %if diffset.limited_diff:
877 877 <% file_placeholder = _ungettext('%(num)s file changed', '%(num)s files changed', diffset.changed_files) % {'num': diffset.changed_files} %>
878 878 %else:
879 879 <% 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>',
880 880 diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}) %>
881 881
882 882 %endif
883 883 ## case on range-diff placeholder needs to be updated
884 884 % if range_diff_on is True:
885 885 <% file_placeholder = _('Disabled on range diff') %>
886 886 % endif
887 887
888 888 <script type="text/javascript">
889 889 var feedFilesOptions = function (query, initialData) {
890 890 var data = {results: []};
891 891 var isQuery = typeof query.term !== 'undefined';
892 892
893 893 var section = _gettext('Changed files');
894 894 var filteredData = [];
895 895
896 896 //filter results
897 897 $.each(initialData.results, function (idx, value) {
898 898
899 899 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
900 900 filteredData.push({
901 901 'id': this.id,
902 902 'text': this.text,
903 903 "ops": this.ops,
904 904 })
905 905 }
906 906
907 907 });
908 908
909 909 data.results = filteredData;
910 910
911 911 query.callback(data);
912 912 };
913 913
914 914 var selectionFormatter = function(data, escapeMarkup) {
915 915 var container = '<div class="filelist" style="padding-right:100px">{0}</div>';
916 916 var tmpl = '<div><strong>{0}</strong></div>'.format(escapeMarkup(data['text']));
917 917 var pill = '<div class="pill-group" style="position: absolute; top:7px; right: 0">' +
918 918 '<span class="pill" op="added">{0}</span>' +
919 919 '<span class="pill" op="deleted">{1}</span>' +
920 920 '</div>'
921 921 ;
922 922 var added = data['ops']['added'];
923 923 if (added === 0) {
924 924 // don't show +0
925 925 added = 0;
926 926 } else {
927 927 added = '+' + added;
928 928 }
929 929
930 930 var deleted = -1*data['ops']['deleted'];
931 931
932 932 tmpl += pill.format(added, deleted);
933 933 return container.format(tmpl);
934 934 };
935 935 var formatFileResult = function(result, container, query, escapeMarkup) {
936 936 return selectionFormatter(result, escapeMarkup);
937 937 };
938 938
939 939 var formatSelection = function (data, container) {
940 940 return '${file_placeholder}'
941 941 };
942 942
943 943 if (window.preloadFileFilterData === undefined) {
944 944 window.preloadFileFilterData = {}
945 945 }
946 946
947 947 preloadFileFilterData["${diffset_container_id}"] = {
948 948 results: [
949 949 % for filediff in diffset.files:
950 950 {id:"a_${h.FID(filediff.raw_id, filediff.patch['filename'])}",
951 951 text:"${filediff.patch['filename']}",
952 952 ops:${h.json.dumps(filediff.patch['stats'])|n}}${('' if loop.last else ',')}
953 953 % endfor
954 954 ]
955 955 };
956 956
957 957 var diffFileFilterId = "#file_filter_" + "${diffset_container_id}";
958 958 var diffFileFilter = $(diffFileFilterId).select2({
959 959 'dropdownAutoWidth': true,
960 960 'width': 'auto',
961 961
962 962 containerCssClass: "drop-menu",
963 963 dropdownCssClass: "drop-menu-dropdown",
964 964 data: preloadFileFilterData["${diffset_container_id}"],
965 965 query: function(query) {
966 966 feedFilesOptions(query, preloadFileFilterData["${diffset_container_id}"]);
967 967 },
968 968 initSelection: function(element, callback) {
969 969 callback({'init': true});
970 970 },
971 971 formatResult: formatFileResult,
972 972 formatSelection: formatSelection
973 973 });
974 974
975 975 % if range_diff_on is True:
976 976 diffFileFilter.select2("enable", false);
977 977 % endif
978 978
979 979 $(diffFileFilterId).on('select2-selecting', function (e) {
980 980 var idSelector = e.choice.id;
981 981
982 982 // expand the container if we quick-select the field
983 983 $('#'+idSelector).next().prop('checked', false);
984 984 // hide the mast as we later do preventDefault()
985 985 $("#select2-drop-mask").click();
986 986
987 987 window.location.hash = '#'+idSelector;
988 988 updateSticky();
989 989
990 990 e.preventDefault();
991 991 });
992 992
993 993 </script>
994 994 % endif
995 995
996 996 <script type="text/javascript">
997 997 $(document).ready(function () {
998 998
999 999 var contextPrefix = _gettext('Context file: ');
1000 1000 ## sticky sidebar
1001 1001 var sidebarElement = document.getElementById('diff-file-sticky');
1002 1002 sidebar = new StickySidebar(sidebarElement, {
1003 1003 topSpacing: 0,
1004 1004 bottomSpacing: 0,
1005 1005 innerWrapperSelector: '.sidebar__inner'
1006 1006 });
1007 1007 sidebarElement.addEventListener('affixed.static.stickySidebar', function () {
1008 1008 // reset our file so it's not holding new value
1009 1009 $('.fpath-placeholder-text').html(contextPrefix + ' - ')
1010 1010 });
1011 1011
1012 1012 updateSticky = function () {
1013 1013 sidebar.updateSticky();
1014 1014 Waypoint.refreshAll();
1015 1015 };
1016 1016
1017 1017 var animateText = function (fPath, anchorId) {
1018 1018 fPath = Select2.util.escapeMarkup(fPath);
1019 1019 $('.fpath-placeholder-text').html(contextPrefix + '<a href="#a_' + anchorId + '">' + fPath + '</a>')
1020 1020 };
1021 1021
1022 1022 ## dynamic file waypoints
1023 1023 var setFPathInfo = function(fPath, anchorId){
1024 1024 animateText(fPath, anchorId)
1025 1025 };
1026 1026
1027 1027 var codeBlock = $('.filediff');
1028 1028
1029 1029 // forward waypoint
1030 1030 codeBlock.waypoint(
1031 1031 function(direction) {
1032 1032 if (direction === "down"){
1033 1033 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1034 1034 }
1035 1035 }, {
1036 1036 offset: function () {
1037 1037 return 70;
1038 1038 },
1039 1039 context: '.fpath-placeholder'
1040 1040 }
1041 1041 );
1042 1042
1043 1043 // backward waypoint
1044 1044 codeBlock.waypoint(
1045 1045 function(direction) {
1046 1046 if (direction === "up"){
1047 1047 setFPathInfo($(this.element).data('fPath'), $(this.element).data('anchorId'))
1048 1048 }
1049 1049 }, {
1050 1050 offset: function () {
1051 1051 return -this.element.clientHeight + 90;
1052 1052 },
1053 1053 context: '.fpath-placeholder'
1054 1054 }
1055 1055 );
1056 1056
1057 1057 toggleWideDiff = function (el) {
1058 1058 updateSticky();
1059 1059 var wide = Rhodecode.comments.toggleWideMode(this);
1060 1060 storeUserSessionAttr('rc_user_session_attr.wide_diff_mode', wide);
1061 1061 if (wide === true) {
1062 1062 $(el).addClass('btn-active');
1063 1063 } else {
1064 1064 $(el).removeClass('btn-active');
1065 1065 }
1066 1066 return null;
1067 1067 };
1068 1068
1069 1069 var preloadDiffMenuData = {
1070 1070 results: [
1071 1071
1072 1072 ## Whitespace change
1073 1073 % if request.GET.get('ignorews', '') == '1':
1074 1074 {
1075 1075 id: 2,
1076 1076 text: _gettext('Show whitespace changes'),
1077 1077 action: function () {},
1078 1078 url: "${h.current_route_path(request, ignorews=0)|n}"
1079 1079 },
1080 1080 % else:
1081 1081 {
1082 1082 id: 2,
1083 1083 text: _gettext('Hide whitespace changes'),
1084 1084 action: function () {},
1085 1085 url: "${h.current_route_path(request, ignorews=1)|n}"
1086 1086 },
1087 1087 % endif
1088 1088
1089 1089 ## FULL CONTEXT
1090 1090 % if request.GET.get('fullcontext', '') == '1':
1091 1091 {
1092 1092 id: 3,
1093 1093 text: _gettext('Hide full context diff'),
1094 1094 action: function () {},
1095 1095 url: "${h.current_route_path(request, fullcontext=0)|n}"
1096 1096 },
1097 1097 % else:
1098 1098 {
1099 1099 id: 3,
1100 1100 text: _gettext('Show full context diff'),
1101 1101 action: function () {},
1102 1102 url: "${h.current_route_path(request, fullcontext=1)|n}"
1103 1103 },
1104 1104 % endif
1105 1105
1106 1106 ]
1107 1107 };
1108 1108
1109 // get stored diff mode and pre-enable it
1110 if (templateContext.session_attrs.wide_diff_mode === "true") {
1111 Rhodecode.comments.toggleWideMode(null);
1112 $('.toggle-wide-diff').addClass('btn-active');
1113 }
1114
1115 1109 var diffMenuId = "#diff_menu_" + "${diffset_container_id}";
1116 1110 $(diffMenuId).select2({
1117 1111 minimumResultsForSearch: -1,
1118 1112 containerCssClass: "drop-menu-no-width",
1119 1113 dropdownCssClass: "drop-menu-dropdown",
1120 1114 dropdownAutoWidth: true,
1121 1115 data: preloadDiffMenuData,
1122 1116 placeholder: "${_('...')}",
1123 1117 });
1124 1118 $(diffMenuId).on('select2-selecting', function (e) {
1125 1119 e.choice.action();
1126 1120 if (e.choice.url !== null) {
1127 1121 window.location = e.choice.url
1128 1122 }
1129 1123 });
1130 1124 toggleExpand = function (el, diffsetEl) {
1131 1125 var el = $(el);
1132 1126 if (el.hasClass('collapsed')) {
1133 1127 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', false);
1134 1128 el.removeClass('collapsed');
1135 1129 el.html(
1136 1130 '<i class="icon-minus-squared-alt icon-no-margin"></i>' +
1137 1131 _gettext('Collapse all files'));
1138 1132 }
1139 1133 else {
1140 1134 $('.filediff-collapse-state.collapse-{0}'.format(diffsetEl)).prop('checked', true);
1141 1135 el.addClass('collapsed');
1142 1136 el.html(
1143 1137 '<i class="icon-plus-squared-alt icon-no-margin"></i>' +
1144 1138 _gettext('Expand all files'));
1145 1139 }
1146 1140 updateSticky()
1141 };
1142
1143 // get stored diff mode and pre-enable it
1144 if (templateContext.session_attrs.wide_diff_mode === "true") {
1145 Rhodecode.comments.toggleWideMode(null);
1146 $('.toggle-wide-diff').addClass('btn-active');
1147 updateSticky();
1147 1148 }
1148 1149 });
1149 1150 </script>
1150 1151
1151 1152 </%def>
General Comments 0
You need to be logged in to leave comments. Login now