##// END OF EJS Templates
changeset: replace diff/whitespace/context popup menu with icons
Aras Pranckevicius -
r1859:929fc8d9 beta
parent child Browse files
Show More
@@ -1,365 +1,367 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.changeset
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 changeset controller for pylons showoing changes beetween
7 7 revisions
8 8
9 9 :created_on: Apr 25, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26 import logging
27 27 import traceback
28 28 from collections import defaultdict
29 29 from webob.exc import HTTPForbidden
30 30
31 31 from pylons import tmpl_context as c, url, request, response
32 32 from pylons.i18n.translation import _
33 33 from pylons.controllers.util import redirect
34 34 from pylons.decorators import jsonify
35 35
36 36 from vcs.exceptions import RepositoryError, ChangesetError, \
37 37 ChangesetDoesNotExistError
38 38 from vcs.nodes import FileNode
39 39
40 40 import rhodecode.lib.helpers as h
41 41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
42 42 from rhodecode.lib.base import BaseRepoController, render
43 43 from rhodecode.lib.utils import EmptyChangeset
44 44 from rhodecode.lib.compat import OrderedDict
45 45 from rhodecode.lib import diffs
46 46 from rhodecode.model.db import ChangesetComment
47 47 from rhodecode.model.comment import ChangesetCommentsModel
48 48 from rhodecode.model.meta import Session
49 49 from rhodecode.lib.diffs import wrapped_diff
50 50
51 51 log = logging.getLogger(__name__)
52 52
53 53
54 54 def anchor_url(revision, path):
55 55 fid = h.FID(revision, path)
56 56 return h.url.current(anchor=fid, **request.GET)
57 57
58 58
59 59 def get_ignore_ws(fid, GET):
60 60 ig_ws_global = request.GET.get('ignorews')
61 61 ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid))
62 62 if ig_ws:
63 63 try:
64 64 return int(ig_ws[0].split(':')[-1])
65 65 except:
66 66 pass
67 67 return ig_ws_global
68 68
69 69
70 70 def _ignorews_url(fileid=None):
71 71
72 72 params = defaultdict(list)
73 73 lbl = _('show white space')
74 74 ig_ws = get_ignore_ws(fileid, request.GET)
75 75 ln_ctx = get_line_ctx(fileid, request.GET)
76 76 # global option
77 77 if fileid is None:
78 78 if ig_ws is None:
79 79 params['ignorews'] += [1]
80 80 lbl = _('ignore white space')
81 81 ctx_key = 'context'
82 82 ctx_val = ln_ctx
83 83 # per file options
84 84 else:
85 85 if ig_ws is None:
86 86 params[fileid] += ['WS:1']
87 87 lbl = _('ignore white space')
88 88
89 89 ctx_key = fileid
90 90 ctx_val = 'C:%s' % ln_ctx
91 91 # if we have passed in ln_ctx pass it along to our params
92 92 if ln_ctx:
93 93 params[ctx_key] += [ctx_val]
94 94
95 95 params['anchor'] = fileid
96 return h.link_to(lbl, h.url.current(**params))
96 img = h.image('/images/icons/text_strikethrough.png', lbl, class_='icon')
97 return h.link_to(img, h.url.current(**params), title=lbl)
97 98
98 99
99 100 def get_line_ctx(fid, GET):
100 101 ln_ctx_global = request.GET.get('context')
101 102 ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid))
102 103
103 104 if ln_ctx:
104 105 retval = ln_ctx[0].split(':')[-1]
105 106 else:
106 107 retval = ln_ctx_global
107 108
108 109 try:
109 110 return int(retval)
110 111 except:
111 112 return
112 113
113 114
114 115 def _context_url(fileid=None):
115 116 """
116 117 Generates url for context lines
117 118
118 119 :param fileid:
119 120 """
120 121 ig_ws = get_ignore_ws(fileid, request.GET)
121 122 ln_ctx = (get_line_ctx(fileid, request.GET) or 3) * 2
122 123
123 124 params = defaultdict(list)
124 125
125 126 # global option
126 127 if fileid is None:
127 128 if ln_ctx > 0:
128 129 params['context'] += [ln_ctx]
129 130
130 131 if ig_ws:
131 132 ig_ws_key = 'ignorews'
132 133 ig_ws_val = 1
133 134
134 135 # per file option
135 136 else:
136 137 params[fileid] += ['C:%s' % ln_ctx]
137 138 ig_ws_key = fileid
138 139 ig_ws_val = 'WS:%s' % 1
139 140
140 141 if ig_ws:
141 142 params[ig_ws_key] += [ig_ws_val]
142 143
143 144 lbl = _('%s line context') % ln_ctx
144 145
145 146 params['anchor'] = fileid
146 return h.link_to(lbl, h.url.current(**params))
147 img = h.image('/images/icons/table_add.png', lbl, class_='icon')
148 return h.link_to(img, h.url.current(**params), title=lbl)
147 149
148 150
149 151 class ChangesetController(BaseRepoController):
150 152
151 153 @LoginRequired()
152 154 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
153 155 'repository.admin')
154 156 def __before__(self):
155 157 super(ChangesetController, self).__before__()
156 158 c.affected_files_cut_off = 60
157 159
158 160 def index(self, revision):
159 161
160 162 c.anchor_url = anchor_url
161 163 c.ignorews_url = _ignorews_url
162 164 c.context_url = _context_url
163 165
164 166 #get ranges of revisions if preset
165 167 rev_range = revision.split('...')[:2]
166 168 enable_comments = True
167 169 try:
168 170 if len(rev_range) == 2:
169 171 enable_comments = False
170 172 rev_start = rev_range[0]
171 173 rev_end = rev_range[1]
172 174 rev_ranges = c.rhodecode_repo.get_changesets(start=rev_start,
173 175 end=rev_end)
174 176 else:
175 177 rev_ranges = [c.rhodecode_repo.get_changeset(revision)]
176 178
177 179 c.cs_ranges = list(rev_ranges)
178 180 if not c.cs_ranges:
179 181 raise RepositoryError('Changeset range returned empty result')
180 182
181 183 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
182 184 log.error(traceback.format_exc())
183 185 h.flash(str(e), category='warning')
184 186 return redirect(url('home'))
185 187
186 188 c.changes = OrderedDict()
187 189
188 190 c.lines_added = 0 # count of lines added
189 191 c.lines_deleted = 0 # count of lines removes
190 192
191 193 cumulative_diff = 0
192 194 c.cut_off = False # defines if cut off limit is reached
193 195
194 196 c.comments = []
195 197 c.inline_comments = []
196 198 c.inline_cnt = 0
197 199 # Iterate over ranges (default changeset view is always one changeset)
198 200 for changeset in c.cs_ranges:
199 201 c.comments.extend(ChangesetCommentsModel()\
200 202 .get_comments(c.rhodecode_db_repo.repo_id,
201 203 changeset.raw_id))
202 204 inlines = ChangesetCommentsModel()\
203 205 .get_inline_comments(c.rhodecode_db_repo.repo_id,
204 206 changeset.raw_id)
205 207 c.inline_comments.extend(inlines)
206 208 c.changes[changeset.raw_id] = []
207 209 try:
208 210 changeset_parent = changeset.parents[0]
209 211 except IndexError:
210 212 changeset_parent = None
211 213
212 214 #==================================================================
213 215 # ADDED FILES
214 216 #==================================================================
215 217 for node in changeset.added:
216 218 fid = h.FID(revision, node.path)
217 219 line_context_lcl = get_line_ctx(fid, request.GET)
218 220 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
219 221 lim = self.cut_off_limit
220 222 if cumulative_diff > self.cut_off_limit:
221 223 lim = -1
222 224 size, cs1, cs2, diff, st = wrapped_diff(filenode_old=None,
223 225 filenode_new=node,
224 226 cut_off_limit=lim,
225 227 ignore_whitespace=ign_whitespace_lcl,
226 228 line_context=line_context_lcl,
227 229 enable_comments=enable_comments)
228 230 cumulative_diff += size
229 231 c.lines_added += st[0]
230 232 c.lines_deleted += st[1]
231 233 c.changes[changeset.raw_id].append(('added', node, diff,
232 234 cs1, cs2, st))
233 235
234 236 #==================================================================
235 237 # CHANGED FILES
236 238 #==================================================================
237 239 for node in changeset.changed:
238 240 try:
239 241 filenode_old = changeset_parent.get_node(node.path)
240 242 except ChangesetError:
241 243 log.warning('Unable to fetch parent node for diff')
242 244 filenode_old = FileNode(node.path, '', EmptyChangeset())
243 245
244 246 fid = h.FID(revision, node.path)
245 247 line_context_lcl = get_line_ctx(fid, request.GET)
246 248 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
247 249 lim = self.cut_off_limit
248 250 if cumulative_diff > self.cut_off_limit:
249 251 lim = -1
250 252 size, cs1, cs2, diff, st = wrapped_diff(filenode_old=filenode_old,
251 253 filenode_new=node,
252 254 cut_off_limit=lim,
253 255 ignore_whitespace=ign_whitespace_lcl,
254 256 line_context=line_context_lcl,
255 257 enable_comments=enable_comments)
256 258 cumulative_diff += size
257 259 c.lines_added += st[0]
258 260 c.lines_deleted += st[1]
259 261 c.changes[changeset.raw_id].append(('changed', node, diff,
260 262 cs1, cs2, st))
261 263
262 264 #==================================================================
263 265 # REMOVED FILES
264 266 #==================================================================
265 267 for node in changeset.removed:
266 268 c.changes[changeset.raw_id].append(('removed', node, None,
267 269 None, None, (0, 0)))
268 270
269 271 # count inline comments
270 272 for path, lines in c.inline_comments:
271 273 for comments in lines.values():
272 274 c.inline_cnt += len(comments)
273 275
274 276 if len(c.cs_ranges) == 1:
275 277 c.changeset = c.cs_ranges[0]
276 278 c.changes = c.changes[c.changeset.raw_id]
277 279
278 280 return render('changeset/changeset.html')
279 281 else:
280 282 return render('changeset/changeset_range.html')
281 283
282 284 def raw_changeset(self, revision):
283 285
284 286 method = request.GET.get('diff', 'show')
285 287 ignore_whitespace = request.GET.get('ignorews') == '1'
286 288 line_context = request.GET.get('context', 3)
287 289 try:
288 290 c.scm_type = c.rhodecode_repo.alias
289 291 c.changeset = c.rhodecode_repo.get_changeset(revision)
290 292 except RepositoryError:
291 293 log.error(traceback.format_exc())
292 294 return redirect(url('home'))
293 295 else:
294 296 try:
295 297 c.changeset_parent = c.changeset.parents[0]
296 298 except IndexError:
297 299 c.changeset_parent = None
298 300 c.changes = []
299 301
300 302 for node in c.changeset.added:
301 303 filenode_old = FileNode(node.path, '')
302 304 if filenode_old.is_binary or node.is_binary:
303 305 diff = _('binary file') + '\n'
304 306 else:
305 307 f_gitdiff = diffs.get_gitdiff(filenode_old, node,
306 308 ignore_whitespace=ignore_whitespace,
307 309 context=line_context)
308 310 diff = diffs.DiffProcessor(f_gitdiff,
309 311 format='gitdiff').raw_diff()
310 312
311 313 cs1 = None
312 314 cs2 = node.last_changeset.raw_id
313 315 c.changes.append(('added', node, diff, cs1, cs2))
314 316
315 317 for node in c.changeset.changed:
316 318 filenode_old = c.changeset_parent.get_node(node.path)
317 319 if filenode_old.is_binary or node.is_binary:
318 320 diff = _('binary file')
319 321 else:
320 322 f_gitdiff = diffs.get_gitdiff(filenode_old, node,
321 323 ignore_whitespace=ignore_whitespace,
322 324 context=line_context)
323 325 diff = diffs.DiffProcessor(f_gitdiff,
324 326 format='gitdiff').raw_diff()
325 327
326 328 cs1 = filenode_old.last_changeset.raw_id
327 329 cs2 = node.last_changeset.raw_id
328 330 c.changes.append(('changed', node, diff, cs1, cs2))
329 331
330 332 response.content_type = 'text/plain'
331 333
332 334 if method == 'download':
333 335 response.content_disposition = 'attachment; filename=%s.patch' \
334 336 % revision
335 337
336 338 c.parent_tmpl = ''.join(['# Parent %s\n' % x.raw_id for x in
337 339 c.changeset.parents])
338 340
339 341 c.diffs = ''
340 342 for x in c.changes:
341 343 c.diffs += x[2]
342 344
343 345 return render('changeset/raw_changeset.html')
344 346
345 347 def comment(self, repo_name, revision):
346 348 ChangesetCommentsModel().create(text=request.POST.get('text'),
347 349 repo_id=c.rhodecode_db_repo.repo_id,
348 350 user_id=c.rhodecode_user.user_id,
349 351 revision=revision,
350 352 f_path=request.POST.get('f_path'),
351 353 line_no=request.POST.get('line'))
352 354 Session.commit()
353 355 return redirect(h.url('changeset_home', repo_name=repo_name,
354 356 revision=revision))
355 357
356 358 @jsonify
357 359 def delete_comment(self, repo_name, comment_id):
358 360 co = ChangesetComment.get(comment_id)
359 361 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
360 362 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
361 363 ChangesetCommentsModel().delete(comment=co)
362 364 Session.commit()
363 365 return True
364 366 else:
365 367 raise HTTPForbidden()
@@ -1,206 +1,189 b''
1 1 ## -*- coding: utf-8 -*-
2 2
3 3 <%inherit file="/base/base.html"/>
4 4
5 5 <%def name="title()">
6 6 ${c.repo_name} ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - ${c.rhodecode_name}
7 7 </%def>
8 8
9 9 <%def name="breadcrumbs_links()">
10 10 ${h.link_to(u'Home',h.url('/'))}
11 11 &raquo;
12 12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
13 13 &raquo;
14 14 ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
15 15 </%def>
16 16
17 17 <%def name="page_nav()">
18 18 ${self.menu('changelog')}
19 19 </%def>
20 20
21 21 <%def name="main()">
22 22 <div class="box">
23 23 <!-- box / title -->
24 24 <div class="title">
25 25 ${self.breadcrumbs()}
26 26 </div>
27 27 <div class="table">
28 28 <div class="diffblock">
29 29 <div class="code-header">
30 30 <div class="date">${c.changeset.revision}:
31 31 ${h.link_to(h.short_id(c.changeset.raw_id),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}
32 32 ${c.changeset.date}</div>
33 <div class="diff-menu-wrapper">
34 <img class="diff-menu-activate" style="cursor: pointer" alt="diff-menu" src="${h.url('/images/icons/script_gear.png')}" />
35 <div class="diff-menu" style="display:none">
36 <ul>
37 <li>${h.link_to(_('raw diff'),h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</li>
38 <li>${h.link_to(_('download diff'),h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</li>
39 <li>${c.ignorews_url()}</li>
40 <li>${c.context_url()}</li>
41 </ul>
42 </div>
43 </div>
33 <span class="diff-actions">
34 <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show')}" title="${_('raw diff')}"><img class="icon" src="${h.url('/images/icons/page_white_text.png')}"/></a>
35 <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download')}" title="${_('download diff')}"><img class="icon" src="${h.url('/images/icons/down_16.png')}"/></a>
36 ${c.ignorews_url()}
37 ${c.context_url()}
38 </span>
44 39 <div class="comments-number" style="float:right;padding-right:5px">${len(c.comments)} comment(s) (${c.inline_cnt} ${_('inline')})</div>
45 40 </div>
46 41 </div>
47 42 <div id="changeset_content">
48 43 <div class="container">
49 44 <div class="left">
50 45 <div class="author">
51 46 <div class="gravatar">
52 47 <img alt="gravatar" src="${h.gravatar_url(h.email(c.changeset.author),20)}"/>
53 48 </div>
54 49 <span>${h.person(c.changeset.author)}</span><br/>
55 50 <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
56 51 </div>
57 52 <div class="message">${h.wrap_paragraphs(c.changeset.message)}</div>
58 53 </div>
59 54 <div class="right">
60 55 <div class="changes">
61 56 % if len(c.changeset.affected_files) <= c.affected_files_cut_off:
62 57 <span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span>
63 58 <span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span>
64 59 <span class="added" title="${_('added')}">${len(c.changeset.added)}</span>
65 60 % else:
66 61 <span class="removed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
67 62 <span class="changed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
68 63 <span class="added" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span>
69 64 % endif
70 65 </div>
71 66
72 67 %if c.changeset.parents:
73 68 %for p_cs in reversed(c.changeset.parents):
74 69 <div class="parent">${_('Parent')}
75 70 <span class="changeset_id">${p_cs.revision}:<span class="changeset_hash">${h.link_to(h.short_id(p_cs.raw_id),
76 71 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}</span></span>
77 72 </div>
78 73 %endfor
79 74 %else:
80 75 <div class="parent">${_('No parents')}</div>
81 76 %endif
82 77 <span class="logtags">
83 78 %if len(c.changeset.parents)>1:
84 79 <span class="merge">${_('merge')}</span>
85 80 %endif
86 81 <span class="branchtag" title="${'%s %s' % (_('branch'),c.changeset.branch)}">
87 82 ${h.link_to(c.changeset.branch,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
88 83 %for tag in c.changeset.tags:
89 84 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
90 85 ${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
91 86 %endfor
92 87 </span>
93 88 </div>
94 89 </div>
95 90 <span>
96 91 ${_('%s files affected with %s additions and %s deletions:') % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}
97 92 </span>
98 93 <div class="cs_files">
99 94 %for change,filenode,diff,cs1,cs2,stat in c.changes:
100 95 <div class="cs_${change}">
101 96 <div class="node">
102 97 %if change != 'removed':
103 98 ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path))}
104 99 %else:
105 100 ${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
106 101 %endif
107 102 </div>
108 103 <div class="changes">${h.fancy_file_stats(stat)}</div>
109 104 </div>
110 105 %endfor
111 106 % if c.cut_off:
112 107 ${_('Changeset was too big and was cut off...')}
113 108 % endif
114 109 </div>
115 110 </div>
116 111
117 112 </div>
118 113
119 114 ## diff block
120 115 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
121 116 ${diff_block.diff_block(c.changes)}
122 117
123 118 ## template for inline comment form
124 119 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
125 120 ${comment.comment_inline_form(c.changeset)}
126 121
127 122 ${comment.comments(c.changeset)}
128 123
129 124 <script type="text/javascript">
130 125 var deleteComment = function(comment_id){
131 126
132 127 var url = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}".replace('__COMMENT_ID__',comment_id);
133 128 var postData = '_method=delete';
134 129 var success = function(o){
135 130 var n = YUD.get('comment-'+comment_id);
136 131 n.parentNode.removeChild(n);
137 132 }
138 133 ajaxPOST(url,postData,success);
139 134 }
140 135
141 136 YUE.onDOMReady(function(){
142 137
143 YUE.on(YUQ('.diff-menu-activate'),'click',function(e){
144 var act = e.currentTarget.nextElementSibling;
145
146 if(YUD.hasClass(act,'active')){
147 YUD.removeClass(act,'active');
148 YUD.setStyle(act,'display','none');
149 }else{
150 YUD.addClass(act,'active');
151 YUD.setStyle(act,'display','');
152 }
153 });
154
155 138 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
156 139 var show = 'none';
157 140 var target = e.currentTarget;
158 141 if(target.checked){
159 142 var show = ''
160 143 }
161 144 var boxid = YUD.getAttribute(target,'id_for');
162 145 var comments = YUQ('#{0} .inline-comments'.format(boxid));
163 146 for(c in comments){
164 147 YUD.setStyle(comments[c],'display',show);
165 148 }
166 149 var btns = YUQ('#{0} .inline-comments-button'.format(boxid));
167 150 for(c in btns){
168 151 YUD.setStyle(btns[c],'display',show);
169 152 }
170 153 })
171 154
172 155 YUE.on(YUQ('.line'),'click',function(e){
173 156 var tr = e.currentTarget;
174 157 injectInlineForm(tr);
175 158 });
176 159
177 160 // inject comments into they proper positions
178 161 var file_comments = YUQ('.inline-comment-placeholder');
179 162
180 163 for (f in file_comments){
181 164 var box = file_comments[f];
182 165 var inlines = box.children;
183 166 for(var i=0; i<inlines.length; i++){
184 167 try{
185 168
186 169 var inline = inlines[i];
187 170 var lineno = YUD.getAttribute(inlines[i],'line');
188 171 var lineid = "{0}_{1}".format(YUD.getAttribute(inline,'target_id'),lineno);
189 172 var target_line = YUD.get(lineid);
190 173
191 174 var add = createInlineAddButton(target_line.parentNode,'${_("add another comment")}');
192 175 YUD.insertAfter(add,target_line.parentNode);
193 176
194 177 var comment = new YAHOO.util.Element(tableTr('inline-comments',inline.innerHTML))
195 178 YUD.insertAfter(comment,target_line.parentNode);
196 179 }catch(e){
197 180 console.log(e);
198 181 }
199 182 }
200 183 }
201 184 })
202 185
203 186 </script>
204 187
205 188 </div>
206 189 </%def>
@@ -1,46 +1,41 b''
1 1 ## -*- coding: utf-8 -*-
2 2 ##usage:
3 3 ## <%namespace name="diff_block" file="/changeset/diff_block.html"/>
4 4 ## ${diff_block.diff_block(changes)}
5 5 ##
6 6 <%def name="diff_block(changes)">
7 7
8 8 %for change,filenode,diff,cs1,cs2,stat in changes:
9 9 %if change !='removed':
10 10 <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" style="clear:both;height:90px;margin-top:-60px"></div>
11 11 <div class="diffblock margined comm">
12 12 <div class="code-header">
13 13 <div class="changeset_header">
14 14 <div class="changeset_file">
15 15 ${h.link_to_if(change!='removed',h.safe_unicode(filenode.path),h.url('files_home',repo_name=c.repo_name,
16 16 revision=filenode.changeset.raw_id,f_path=h.safe_unicode(filenode.path)))}
17 17 </div>
18 <div class="diff-menu-wrapper">
19 <img class="diff-menu-activate" style="margin-bottom:-6px;cursor: pointer" alt="diff-menu" src="${h.url('/images/icons/script_gear.png')}" />
20 <div class="diff-menu" style="display:none">
21 <ul>
22 <li>${h.link_to(_('diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff',fulldiff=1))}</li>
23 <li>${h.link_to(_('raw diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw'))}</li>
24 <li>${h.link_to(_('download diff'),h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download'))}</li>
25 <li>${c.ignorews_url(h.FID(filenode.changeset.raw_id,filenode.path))}</li>
26 <li>${c.context_url(h.FID(filenode.changeset.raw_id,filenode.path))}</li>
27 </ul>
28 </div>
29 </div>
18 <span class="diff-actions">
19 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff',fulldiff=1)}" title="${_('diff')}"><img class="icon" src="${h.url('/images/icons/page_white_text.png')}"/></a>
20 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw')}" title="${_('raw diff')}"><img class="icon" src="${h.url('/images/icons/page_white_text.png')}"/></a>
21 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download')}" title="${_('download diff')}"><img class="icon" src="${h.url('/images/icons/down_16.png')}"/></a>
22 ${c.ignorews_url(h.FID(filenode.changeset.raw_id,filenode.path))}
23 ${c.context_url(h.FID(filenode.changeset.raw_id,filenode.path))}
24 </span>
30 25 <span style="float:right;margin-top:-3px">
31 26 <label>
32 27 ${_('show inline comments')}
33 28 ${h.checkbox('',checked="checked",class_="show-inline-comments",id_for=h.FID(filenode.changeset.raw_id,filenode.path))}
34 29 </label>
35 30 </span>
36 31 </div>
37 32 </div>
38 33 <div class="code-body">
39 34 <div class="full_f_path" path="${h.safe_unicode(filenode.path)}"></div>
40 35 ${diff|n}
41 36 </div>
42 37 </div>
43 38 %endif
44 39 %endfor
45 40
46 41 </%def> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now