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