##// END OF EJS Templates
rhodecode release 1.1.3 changes part2
marcink -
r1058:4fa80e04 rhodecode-0.0.1.1.3 default
parent child Browse files
Show More
@@ -1,179 +1,177 b''
1 1 .. _changelog:
2 2
3 3 Changelog
4 4 =========
5 5
6 1.1.3 (**2011-02-15**)
6 1.1.3 (**2011-02-16**)
7 7 ======================
8 8
9 9 news
10 10 ----
11 11
12 - implemented #102 allowing '.' in username
12 - implemented #102 allowing the '.' character in username
13 13 - added option to access repository just by entering http://server/<repo_name>
14 14 - celery task ignores result for better performance
15 15
16 16 fixes
17 17 -----
18 18
19 19 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
20 20 apollo13 and Johan Walles
21 21 - small fixes in journal
22 22 - fixed problems with getting setting for celery from .ini files
23 23 - registration, password reset and login boxes share the same title as main
24 24 application now
25 25 - fixed #113: to high permissions to fork repository
26 26 - fixed problem with '[' chars in commit messages in journal
27 27 - removed issue with space inside renamed repository after deletion
28 28 - db transaction fixes when filesystem repository creation failed
29 29 - fixed #106 relation issues on databases different than sqlite
30
31 30 - fixed static files paths links to use of url() method
32 31
33 32
34
35 33 1.1.2 (**2011-01-12**)
36 34 ======================
37 35
38 36 news
39 37 ----
40 38
41 39
42 40 fixes
43 41 -----
44 42
45 43 - fixes #98 protection against float division of percentage stats
46 44 - fixed graph bug
47 45 - forced webhelpers version since it was making troubles during installation
48 46
49 47 1.1.1 (**2011-01-06**)
50 48 ======================
51 49
52 50 news
53 51 ----
54 52
55 53 - added force https option into ini files for easier https usage (no need to
56 54 set server headers with this options)
57 55 - small css updates
58 56
59 57 fixes
60 58 -----
61 59
62 60 - fixed #96 redirect loop on files view on repositories without changesets
63 61 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
64 62 and server crashed with errors
65 63 - fixed large tooltips problems on main page
66 64 - fixed #92 whoosh indexer is more error proof
67 65
68 66 1.1.0 (**2010-12-18**)
69 67 ======================
70 68
71 69 news
72 70 ----
73 71
74 72 - rewrite of internals for vcs >=0.1.10
75 73 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
76 74 with older clients
77 75 - anonymous access, authentication via ldap
78 76 - performance upgrade for cached repos list - each repository has it's own
79 77 cache that's invalidated when needed.
80 78 - performance upgrades on repositories with large amount of commits (20K+)
81 79 - main page quick filter for filtering repositories
82 80 - user dashboards with ability to follow chosen repositories actions
83 81 - sends email to admin on new user registration
84 82 - added cache/statistics reset options into repository settings
85 83 - more detailed action logger (based on hooks) with pushed changesets lists
86 84 and options to disable those hooks from admin panel
87 85 - introduced new enhanced changelog for merges that shows more accurate results
88 86 - new improved and faster code stats (based on pygments lexers mapping tables,
89 87 showing up to 10 trending sources for each repository. Additionally stats
90 88 can be disabled in repository settings.
91 89 - gui optimizations, fixed application width to 1024px
92 90 - added cut off (for large files/changesets) limit into config files
93 91 - whoosh, celeryd, upgrade moved to paster command
94 92 - other than sqlite database backends can be used
95 93
96 94 fixes
97 95 -----
98 96
99 97 - fixes #61 forked repo was showing only after cache expired
100 98 - fixes #76 no confirmation on user deletes
101 99 - fixes #66 Name field misspelled
102 100 - fixes #72 block user removal when he owns repositories
103 101 - fixes #69 added password confirmation fields
104 102 - fixes #87 RhodeCode crashes occasionally on updating repository owner
105 103 - fixes #82 broken annotations on files with more than 1 blank line at the end
106 104 - a lot of fixes and tweaks for file browser
107 105 - fixed detached session issues
108 106 - fixed when user had no repos he would see all repos listed in my account
109 107 - fixed ui() instance bug when global hgrc settings was loaded for server
110 108 instance and all hgrc options were merged with our db ui() object
111 109 - numerous small bugfixes
112 110
113 111 (special thanks for TkSoh for detailed feedback)
114 112
115 113
116 114 1.0.2 (**2010-11-12**)
117 115 ======================
118 116
119 117 news
120 118 ----
121 119
122 120 - tested under python2.7
123 121 - bumped sqlalchemy and celery versions
124 122
125 123 fixes
126 124 -----
127 125
128 126 - fixed #59 missing graph.js
129 127 - fixed repo_size crash when repository had broken symlinks
130 128 - fixed python2.5 crashes.
131 129
132 130
133 131 1.0.1 (**2010-11-10**)
134 132 ======================
135 133
136 134 news
137 135 ----
138 136
139 137 - small css updated
140 138
141 139 fixes
142 140 -----
143 141
144 142 - fixed #53 python2.5 incompatible enumerate calls
145 143 - fixed #52 disable mercurial extension for web
146 144 - fixed #51 deleting repositories don't delete it's dependent objects
147 145
148 146
149 147 1.0.0 (**2010-11-02**)
150 148 ======================
151 149
152 150 - security bugfix simplehg wasn't checking for permissions on commands
153 151 other than pull or push.
154 152 - fixed doubled messages after push or pull in admin journal
155 153 - templating and css corrections, fixed repo switcher on chrome, updated titles
156 154 - admin menu accessible from options menu on repository view
157 155 - permissions cached queries
158 156
159 157 1.0.0rc4 (**2010-10-12**)
160 158 ==========================
161 159
162 160 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
163 161 - removed cache_manager settings from sqlalchemy meta
164 162 - added sqlalchemy cache settings to ini files
165 163 - validated password length and added second try of failure on paster setup-app
166 164 - fixed setup database destroy prompt even when there was no db
167 165
168 166
169 167 1.0.0rc3 (**2010-10-11**)
170 168 =========================
171 169
172 170 - fixed i18n during installation.
173 171
174 172 1.0.0rc2 (**2010-10-11**)
175 173 =========================
176 174
177 175 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
178 176 occure. After vcs is fixed it'll be put back again.
179 177 - templating/css rewrites, optimized css. No newline at end of file
@@ -1,557 +1,557 b''
1 1 """Helper functions
2 2
3 3 Consists of functions to typically be used within templates, but also
4 4 available to Controllers. This module is available to both as 'h'.
5 5 """
6 6 import random
7 7 import hashlib
8 8 from pygments.formatters import HtmlFormatter
9 9 from pygments import highlight as code_highlight
10 10 from pylons import url, app_globals as g
11 11 from pylons.i18n.translation import _, ungettext
12 12 from vcs.utils.annotate import annotate_highlight
13 13 from webhelpers.html import literal, HTML, escape
14 14 from webhelpers.html.tools import *
15 15 from webhelpers.html.builder import make_tag
16 16 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
17 17 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
18 18 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
19 19 password, textarea, title, ul, xml_declaration, radio
20 20 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
21 21 mail_to, strip_links, strip_tags, tag_re
22 22 from webhelpers.number import format_byte_size, format_bit_size
23 23 from webhelpers.pylonslib import Flash as _Flash
24 24 from webhelpers.pylonslib.secure_form import secure_form
25 25 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
26 26 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
27 27 replace_whitespace, urlify, truncate, wrap_paragraphs
28 28 from webhelpers.date import time_ago_in_words
29 29
30 30 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
31 31 convert_boolean_attrs, NotGiven
32 32
33 33 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
34 34 _set_input_attrs(attrs, type, name, value)
35 35 _set_id_attr(attrs, id, name)
36 36 convert_boolean_attrs(attrs, ["disabled"])
37 37 return HTML.input(**attrs)
38 38
39 39 reset = _reset
40 40
41 41
42 42 def get_token():
43 43 """Return the current authentication token, creating one if one doesn't
44 44 already exist.
45 45 """
46 46 token_key = "_authentication_token"
47 47 from pylons import session
48 48 if not token_key in session:
49 49 try:
50 50 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
51 51 except AttributeError: # Python < 2.4
52 52 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
53 53 session[token_key] = token
54 54 if hasattr(session, 'save'):
55 55 session.save()
56 56 return session[token_key]
57 57
58 58
59 59 #Custom helpers here :)
60 60 class _Link(object):
61 61 '''
62 62 Make a url based on label and url with help of url_for
63 63 :param label:name of link if not defined url is used
64 64 :param url: the url for link
65 65 '''
66 66
67 67 def __call__(self, label='', *url_, **urlargs):
68 68 if label is None or '':
69 69 label = url
70 70 link_fn = link_to(label, url(*url_, **urlargs))
71 71 return link_fn
72 72
73 73 link = _Link()
74 74
75 75 class _GetError(object):
76 76
77 77 def __call__(self, field_name, form_errors):
78 78 tmpl = """<span class="error_msg">%s</span>"""
79 79 if form_errors and form_errors.has_key(field_name):
80 80 return literal(tmpl % form_errors.get(field_name))
81 81
82 82 get_error = _GetError()
83 83
84 84 def recursive_replace(str, replace=' '):
85 85 """
86 86 Recursive replace of given sign to just one instance
87 87 :param str: given string
88 88 :param replace:char to find and replace multiple instances
89 89
90 90 Examples::
91 91 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
92 92 'Mighty-Mighty-Bo-sstones'
93 93 """
94 94
95 95 if str.find(replace * 2) == -1:
96 96 return str
97 97 else:
98 98 str = str.replace(replace * 2, replace)
99 99 return recursive_replace(str, replace)
100 100
101 101 class _ToolTip(object):
102 102
103 103 def __call__(self, tooltip_title, trim_at=50):
104 104 """
105 105 Special function just to wrap our text into nice formatted autowrapped
106 106 text
107 107 :param tooltip_title:
108 108 """
109 109
110 110 return wrap_paragraphs(escape(tooltip_title), trim_at)\
111 111 .replace('\n', '<br/>')
112 112
113 113 def activate(self):
114 114 """
115 115 Adds tooltip mechanism to the given Html all tooltips have to have
116 116 set class tooltip and set attribute tooltip_title.
117 117 Then a tooltip will be generated based on that
118 118 All with yui js tooltip
119 119 """
120 120
121 121 js = '''
122 122 YAHOO.util.Event.onDOMReady(function(){
123 123 function toolTipsId(){
124 124 var ids = [];
125 125 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
126 126
127 127 for (var i = 0; i < tts.length; i++) {
128 128 //if element doesn't not have and id autogenerate one for tooltip
129 129
130 130 if (!tts[i].id){
131 131 tts[i].id='tt'+i*100;
132 132 }
133 133 ids.push(tts[i].id);
134 134 }
135 135 return ids
136 136 };
137 137 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
138 138 context: toolTipsId(),
139 139 monitorresize:false,
140 140 xyoffset :[0,0],
141 141 autodismissdelay:300000,
142 142 hidedelay:5,
143 143 showdelay:20,
144 144 });
145 145
146 146 //Mouse Over event disabled for new repositories since they don't
147 147 //have last commit message
148 148 myToolTips.contextMouseOverEvent.subscribe(
149 149 function(type, args) {
150 150 var context = args[0];
151 151 var txt = context.getAttribute('tooltip_title');
152 152 if(txt){
153 153 return true;
154 154 }
155 155 else{
156 156 return false;
157 157 }
158 158 });
159 159
160 160
161 161 // Set the text for the tooltip just before we display it. Lazy method
162 162 myToolTips.contextTriggerEvent.subscribe(
163 163 function(type, args) {
164 164
165 165
166 166 var context = args[0];
167 167
168 168 var txt = context.getAttribute('tooltip_title');
169 169 this.cfg.setProperty("text", txt);
170 170
171 171
172 172 // positioning of tooltip
173 173 var tt_w = this.element.clientWidth;
174 174 var tt_h = this.element.clientHeight;
175 175
176 176 var context_w = context.offsetWidth;
177 177 var context_h = context.offsetHeight;
178 178
179 179 var pos_x = YAHOO.util.Dom.getX(context);
180 180 var pos_y = YAHOO.util.Dom.getY(context);
181 181
182 182 var display_strategy = 'top';
183 183 var xy_pos = [0,0];
184 184 switch (display_strategy){
185 185
186 186 case 'top':
187 187 var cur_x = (pos_x+context_w/2)-(tt_w/2);
188 188 var cur_y = (pos_y-tt_h-4);
189 189 xy_pos = [cur_x,cur_y];
190 190 break;
191 191 case 'bottom':
192 192 var cur_x = (pos_x+context_w/2)-(tt_w/2);
193 193 var cur_y = pos_y+context_h+4;
194 194 xy_pos = [cur_x,cur_y];
195 195 break;
196 196 case 'left':
197 197 var cur_x = (pos_x-tt_w-4);
198 198 var cur_y = pos_y-((tt_h/2)-context_h/2);
199 199 xy_pos = [cur_x,cur_y];
200 200 break;
201 201 case 'right':
202 202 var cur_x = (pos_x+context_w+4);
203 203 var cur_y = pos_y-((tt_h/2)-context_h/2);
204 204 xy_pos = [cur_x,cur_y];
205 205 break;
206 206 default:
207 207 var cur_x = (pos_x+context_w/2)-(tt_w/2);
208 208 var cur_y = pos_y-tt_h-4;
209 209 xy_pos = [cur_x,cur_y];
210 210 break;
211 211
212 212 }
213 213
214 214 this.cfg.setProperty("xy",xy_pos);
215 215
216 216 });
217 217
218 218 //Mouse out
219 219 myToolTips.contextMouseOutEvent.subscribe(
220 220 function(type, args) {
221 221 var context = args[0];
222 222
223 223 });
224 224 });
225 225 '''
226 226 return literal(js)
227 227
228 228 tooltip = _ToolTip()
229 229
230 230 class _FilesBreadCrumbs(object):
231 231
232 232 def __call__(self, repo_name, rev, paths):
233 233 url_l = [link_to(repo_name, url('files_home',
234 234 repo_name=repo_name,
235 235 revision=rev, f_path=''))]
236 236 paths_l = paths.split('/')
237 237
238 238 for cnt, p in enumerate(paths_l):
239 239 if p != '':
240 240 url_l.append(link_to(p, url('files_home',
241 241 repo_name=repo_name,
242 242 revision=rev,
243 243 f_path='/'.join(paths_l[:cnt + 1]))))
244 244
245 245 return literal('/'.join(url_l))
246 246
247 247 files_breadcrumbs = _FilesBreadCrumbs()
248 248 class CodeHtmlFormatter(HtmlFormatter):
249 249
250 250 def wrap(self, source, outfile):
251 251 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
252 252
253 253 def _wrap_code(self, source):
254 254 for cnt, it in enumerate(source):
255 255 i, t = it
256 256 t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
257 257 yield i, t
258 258 def pygmentize(filenode, **kwargs):
259 259 """
260 260 pygmentize function using pygments
261 261 :param filenode:
262 262 """
263 263 return literal(code_highlight(filenode.content,
264 264 filenode.lexer, CodeHtmlFormatter(**kwargs)))
265 265
266 266 def pygmentize_annotation(filenode, **kwargs):
267 267 """
268 268 pygmentize function for annotation
269 269 :param filenode:
270 270 """
271 271
272 272 color_dict = {}
273 273 def gen_color():
274 274 """generator for getting 10k of evenly distibuted colors using hsv color
275 275 and golden ratio.
276 276 """
277 277 import colorsys
278 278 n = 10000
279 279 golden_ratio = 0.618033988749895
280 280 h = 0.22717784590367374
281 281 #generate 10k nice web friendly colors in the same order
282 282 for c in xrange(n):
283 283 h += golden_ratio
284 284 h %= 1
285 285 HSV_tuple = [h, 0.95, 0.95]
286 286 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
287 287 yield map(lambda x:str(int(x * 256)), RGB_tuple)
288 288
289 289 cgenerator = gen_color()
290 290
291 291 def get_color_string(cs):
292 292 if color_dict.has_key(cs):
293 293 col = color_dict[cs]
294 294 else:
295 295 col = color_dict[cs] = cgenerator.next()
296 296 return "color: rgb(%s)! important;" % (', '.join(col))
297 297
298 298 def url_func(changeset):
299 299 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
300 300 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
301 301
302 302 tooltip_html = tooltip_html % (changeset.author,
303 303 changeset.date,
304 304 tooltip(changeset.message))
305 305 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
306 306 short_id(changeset.raw_id))
307 307 uri = link_to(
308 308 lnk_format,
309 309 url('changeset_home', repo_name=changeset.repository.name,
310 310 revision=changeset.raw_id),
311 311 style=get_color_string(changeset.raw_id),
312 312 class_='tooltip',
313 313 tooltip_title=tooltip_html
314 314 )
315 315
316 316 uri += '\n'
317 317 return uri
318 318 return literal(annotate_highlight(filenode, url_func, **kwargs))
319 319
320 320 def repo_name_slug(value):
321 321 """Return slug of name of repository
322 322 This function is called on each creation/modification
323 323 of repository to prevent bad names in repo
324 324 """
325 325 slug = remove_formatting(value)
326 326 slug = strip_tags(slug)
327 327
328 328 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
329 329 slug = slug.replace(c, '-')
330 330 slug = recursive_replace(slug, '-')
331 331 slug = collapse(slug, '-')
332 332 return slug
333 333
334 334 def get_changeset_safe(repo, rev):
335 335 from vcs.backends.base import BaseRepository
336 336 from vcs.exceptions import RepositoryError
337 337 if not isinstance(repo, BaseRepository):
338 338 raise Exception('You must pass an Repository '
339 339 'object as first argument got %s', type(repo))
340 340
341 341 try:
342 342 cs = repo.get_changeset(rev)
343 343 except RepositoryError:
344 344 from rhodecode.lib.utils import EmptyChangeset
345 345 cs = EmptyChangeset()
346 346 return cs
347 347
348 348
349 349 flash = _Flash()
350 350
351 351
352 352 #==============================================================================
353 353 # MERCURIAL FILTERS available via h.
354 354 #==============================================================================
355 355 from mercurial import util
356 356 from mercurial.templatefilters import person as _person
357 357
358 358
359 359
360 360 def _age(curdate):
361 361 """turns a datetime into an age string."""
362 362
363 363 if not curdate:
364 364 return ''
365 365
366 366 from datetime import timedelta, datetime
367 367
368 368 agescales = [("year", 3600 * 24 * 365),
369 369 ("month", 3600 * 24 * 30),
370 370 ("day", 3600 * 24),
371 371 ("hour", 3600),
372 372 ("minute", 60),
373 373 ("second", 1), ]
374 374
375 375 age = datetime.now() - curdate
376 376 age_seconds = (age.days * agescales[2][1]) + age.seconds
377 377 pos = 1
378 378 for scale in agescales:
379 379 if scale[1] <= age_seconds:
380 380 if pos == 6:pos = 5
381 381 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
382 382 pos += 1
383 383
384 384 return _('just now')
385 385
386 386 age = lambda x:_age(x)
387 387 capitalize = lambda x: x.capitalize()
388 388 email = util.email
389 389 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
390 390 person = lambda x: _person(x)
391 391 short_id = lambda x: x[:12]
392 392
393 393
394 394 def bool2icon(value):
395 395 """
396 396 Returns True/False values represented as small html image of true/false
397 397 icons
398 398 :param value: bool value
399 399 """
400 400
401 401 if value is True:
402 return HTML.tag('img', src="/images/icons/accept.png", alt=_('True'))
402 return HTML.tag('img', src=url("/images/icons/accept.png"), alt=_('True'))
403 403
404 404 if value is False:
405 return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False'))
405 return HTML.tag('img', src=url("/images/icons/cancel.png"), alt=_('False'))
406 406
407 407 return value
408 408
409 409
410 410 def action_parser(user_log):
411 411 """
412 412 This helper will map the specified string action into translated
413 413 fancy names with icons and links
414 414
415 415 @param action:
416 416 """
417 417 action = user_log.action
418 418 action_params = ' '
419 419
420 420 x = action.split(':')
421 421
422 422 if len(x) > 1:
423 423 action, action_params = x
424 424
425 425 def get_cs_links():
426 426 if action == 'push':
427 427 revs_limit = 5
428 428 revs = action_params.split(',')
429 429 cs_links = " " + ', '.join ([link(rev,
430 430 url('changeset_home',
431 431 repo_name=user_log.repository.repo_name,
432 432 revision=rev)) for rev in revs[:revs_limit] ])
433 433 if len(revs) > revs_limit:
434 434 uniq_id = revs[0]
435 435 html_tmpl = ('<span> %s '
436 436 '<a class="show_more" id="_%s" href="#">%s</a> '
437 437 '%s</span>')
438 438 cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
439 439 % (len(revs) - revs_limit),
440 440 _('revisions'))
441 441
442 442 html_tmpl = '<span id="%s" style="display:none"> %s </span>'
443 443 cs_links += html_tmpl % (uniq_id, ', '.join([link(rev,
444 444 url('changeset_home',
445 445 repo_name=user_log.repository.repo_name,
446 446 revision=rev)) for rev in revs[revs_limit:] ]))
447 447
448 448 return cs_links
449 449 return ''
450 450
451 451 def get_fork_name():
452 452 repo_name = action_params
453 453 return str(link_to(action_params, url('summary_home',
454 454 repo_name=repo_name,)))
455
455
456 456 map = {'user_deleted_repo':(_('[deleted] repository'), None),
457 457 'user_created_repo':(_('[created] repository'), None),
458 458 'user_forked_repo':(_('[forked] repository'), get_fork_name),
459 459 'user_updated_repo':(_('[updated] repository'), None),
460 460 'admin_deleted_repo':(_('[delete] repository'), None),
461 461 'admin_created_repo':(_('[created] repository'), None),
462 462 'admin_forked_repo':(_('[forked] repository'), None),
463 463 'admin_updated_repo':(_('[updated] repository'), None),
464 464 'push':(_('[pushed] into'), get_cs_links),
465 465 'pull':(_('[pulled] from'), None),
466 466 'started_following_repo':(_('[started following] repository'), None),
467 467 'stopped_following_repo':(_('[stopped following] repository'), None),
468 468 }
469 469
470 470 action_str = map.get(action, action)
471 471 action = action_str[0].replace('[', '<span class="journal_highlight">')\
472 472 .replace(']', '</span>')
473 473 action_params_func = lambda :""
474 474
475 475 if action_str[1] is not None:
476 476 action_params_func = action_str[1]
477 477
478 return literal(action +" "+ action_params_func())
478 return literal(action + " " + action_params_func())
479 479
480 480 def action_parser_icon(user_log):
481 481 action = user_log.action
482 482 action_params = None
483 483 x = action.split(':')
484 484
485 485 if len(x) > 1:
486 486 action, action_params = x
487 487
488 488 tmpl = """<img src="%s/%s" alt="%s"/>"""
489 489 map = {'user_deleted_repo':'database_delete.png',
490 490 'user_created_repo':'database_add.png',
491 491 'user_forked_repo':'arrow_divide.png',
492 492 'user_updated_repo':'database_edit.png',
493 493 'admin_deleted_repo':'database_delete.png',
494 494 'admin_created_repo':'database_add.png',
495 495 'admin_forked_repo':'arrow_divide.png',
496 496 'admin_updated_repo':'database_edit.png',
497 497 'push':'script_add.png',
498 498 'pull':'down_16.png',
499 499 'started_following_repo':'heart_add.png',
500 500 'stopped_following_repo':'heart_delete.png',
501 501 }
502 502 return literal(tmpl % ((url('/images/icons/')),
503 503 map.get(action, action), action))
504 504
505 505
506 506 #==============================================================================
507 507 # PERMS
508 508 #==============================================================================
509 509 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
510 510 HasRepoPermissionAny, HasRepoPermissionAll
511 511
512 512 #==============================================================================
513 513 # GRAVATAR URL
514 514 #==============================================================================
515 515 import hashlib
516 516 import urllib
517 517 from pylons import request
518 518
519 519 def gravatar_url(email_address, size=30):
520 520 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
521 521 default = 'identicon'
522 522 baseurl_nossl = "http://www.gravatar.com/avatar/"
523 523 baseurl_ssl = "https://secure.gravatar.com/avatar/"
524 524 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
525 525
526 526
527 527 # construct the url
528 528 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
529 529 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
530 530
531 531 return gravatar_url
532 532
533 533 def safe_unicode(str):
534 534 """safe unicode function. In case of UnicodeDecode error we try to return
535 535 unicode with errors replace, if this failes we return unicode with
536 536 string_escape decoding """
537 537
538 538 try:
539 539 u_str = unicode(str)
540 540 except UnicodeDecodeError:
541 541 try:
542 542 u_str = unicode(str, 'utf-8', 'replace')
543 543 except UnicodeDecodeError:
544 544 #incase we have a decode error just represent as byte string
545 545 u_str = unicode(str(str).encode('string_escape'))
546 546
547 547 return u_str
548 548
549 549 def changed_tooltip(nodes):
550 550 if nodes:
551 551 pref = ': <br/> '
552 552 suf = ''
553 553 if len(nodes) > 30:
554 554 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
555 555 return literal(pref + '<br/> '.join([x.path for x in nodes[:30]]) + suf)
556 556 else:
557 557 return ': ' + _('No Files')
@@ -1,88 +1,88 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Repositories administration')} - ${c.rhodecode_name}
6 6 </%def>
7 7
8 8
9 9 <%def name="breadcrumbs_links()">
10 10 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Repositories')}
11 11 </%def>
12 12 <%def name="page_nav()">
13 13 ${self.menu('admin')}
14 14 </%def>
15 15 <%def name="main()">
16 16 <div class="box">
17 17 <!-- box / title -->
18 18 <div class="title">
19 19 ${self.breadcrumbs()}
20 20 <ul class="links">
21 21 <li>
22 22 <span>${h.link_to(u'ADD NEW REPOSITORY',h.url('new_repo'))}</span>
23 23 </li>
24 24 </ul>
25 25 </div>
26 26 <!-- end box / title -->
27 27 <div class="table">
28 28 <table class="table_disp">
29 29 <tr class="header">
30 30 <th class="left">${_('Name')}</th>
31 31 <th class="left">${_('Description')}</th>
32 32 <th class="left">${_('Last change')}</th>
33 33 <th class="left">${_('Tip')}</th>
34 34 <th class="left">${_('Contact')}</th>
35 35 <th class="left">${_('action')}</th>
36 36 </tr>
37 37 %for cnt,repo in enumerate(c.repos_list):
38 38 <tr class="parity${cnt%2}">
39 39 <td>
40 40 ## TYPE OF REPO
41 41 %if repo['repo'].dbrepo.repo_type =='hg':
42 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
42 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
43 43 %elif repo['repo'].dbrepo.repo_type =='git':
44 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
44 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
45 45 %else:
46 46
47 47 %endif
48 48
49 49 ## PRIVATE/PUBLIC REPO
50 50 %if repo['repo'].dbrepo.private:
51 <img alt="${_('private')}" src="/images/icons/lock.png"/>
51 <img alt="${_('private')}" src="${h.url("/images/icons/lock.png")}"/>
52 52 %else:
53 <img alt="${_('public')}" src="/images/icons/lock_open.png"/>
53 <img alt="${_('public')}" src="${h.url("/images/icons/lock_open.png")}"/>
54 54 %endif
55 55 ${h.link_to(repo['name'],h.url('edit_repo',repo_name=repo['name']))}
56 56
57 57 %if repo['repo'].dbrepo.fork:
58 58 <a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
59 59 <img class="icon" alt="${_('public')}"
60 60 title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}"
61 src="/images/icons/arrow_divide.png"/></a>
61 src="${h.url("/images/icons/arrow_divide.png")}"/></a>
62 62 %endif
63 63 </td>
64 64 <td title="${repo['description']}">${h.truncate(repo['description'],60)}</td>
65 65 <td>${h.age(repo['last_change'])}</td>
66 66 <td>
67 67 %if repo['rev']>=0:
68 68 ${h.link_to('r%s:%s' % (repo['rev'],h.short_id(repo['tip'])),
69 69 h.url('changeset_home',repo_name=repo['name'],revision=repo['tip']),
70 70 class_="tooltip",
71 71 tooltip_title=h.tooltip(repo['last_msg']))}
72 72 %else:
73 73 ${_('No changesets yet')}
74 74 %endif
75 75 </td>
76 76 <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
77 77 <td>
78 78 ${h.form(url('repo', repo_name=repo['name']),method='delete')}
79 79 ${h.submit('remove_%s' % repo['name'],'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
80 80 ${h.end_form()}
81 81 </td>
82 82 </tr>
83 83 %endfor
84 84 </table>
85 85 </div>
86 86 </div>
87 87
88 88 </%def>
@@ -1,210 +1,210 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('My account')} ${c.rhodecode_user.username} - ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 9 ${_('My Account')}
10 10 </%def>
11 11
12 12 <%def name="page_nav()">
13 13 ${self.menu('admin')}
14 14 </%def>
15 15
16 16 <%def name="main()">
17 17
18 18 <div class="box box-left">
19 19 <!-- box / title -->
20 20 <div class="title">
21 21 ${self.breadcrumbs()}
22 22 </div>
23 23 <!-- end box / title -->
24 24 <div class="ui-tabs-panel ui-widget-content ui-corner-bottom">
25 25 ${h.form(url('admin_settings_my_account_update'),method='put')}
26 26 <div class="form">
27 27
28 28 <div class="field">
29 29 <div class="gravatar_box">
30 30 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
31 31 <p>
32 32 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
33 33 ${_('Using')} ${c.user.email}
34 34 </p>
35 35 </div>
36 36 </div>
37 37
38 38 <div class="fields">
39 39 <div class="field">
40 40 <div class="label">
41 41 <label for="username">${_('Username')}:</label>
42 42 </div>
43 43 <div class="input">
44 44 ${h.text('username',class_="medium")}
45 45 </div>
46 46 </div>
47 47
48 48 <div class="field">
49 49 <div class="label">
50 50 <label for="new_password">${_('New password')}:</label>
51 51 </div>
52 52 <div class="input">
53 53 ${h.password('new_password',class_="medium")}
54 54 </div>
55 55 </div>
56 56
57 57 <div class="field">
58 58 <div class="label">
59 59 <label for="name">${_('First Name')}:</label>
60 60 </div>
61 61 <div class="input">
62 62 ${h.text('name',class_="medium")}
63 63 </div>
64 64 </div>
65 65
66 66 <div class="field">
67 67 <div class="label">
68 68 <label for="lastname">${_('Last Name')}:</label>
69 69 </div>
70 70 <div class="input">
71 71 ${h.text('lastname',class_="medium")}
72 72 </div>
73 73 </div>
74 74
75 75 <div class="field">
76 76 <div class="label">
77 77 <label for="email">${_('Email')}:</label>
78 78 </div>
79 79 <div class="input">
80 80 ${h.text('email',class_="medium")}
81 81 </div>
82 82 </div>
83 83
84 84 <div class="buttons">
85 85 ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
86 86 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
87 87
88 88
89 89
90 90 </div>
91 91 </div>
92 92 </div>
93 93 ${h.end_form()}
94 94 </div>
95 95 </div>
96 96
97 97 <div class="box box-right">
98 98 <!-- box / title -->
99 99 <div class="title">
100 100 <h5>${_('My repositories')}
101 101 <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
102 102 </h5>
103 103 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
104 104 <ul class="links">
105 105 <li>
106 106 <span>${h.link_to(_('ADD REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
107 107 </li>
108 108 </ul>
109 109 %endif
110 110 </div>
111 111 <!-- end box / title -->
112 112 <div class="table">
113 113 <table>
114 114 <thead>
115 115 <tr>
116 116 <th class="left">${_('Name')}</th>
117 117 <th class="left">${_('revision')}</th>
118 118 <th colspan="2" class="left">${_('action')}</th>
119 119 </thead>
120 120 <tbody>
121 121 %if c.user_repos:
122 122 %for repo in c.user_repos:
123 123 <tr>
124 124 <td>
125 125 %if repo['repo'].dbrepo.repo_type =='hg':
126 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
126 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
127 127 %elif repo['repo'].dbrepo.repo_type =='git':
128 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
128 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
129 129 %else:
130 130
131 131 %endif
132 132 %if repo['repo'].dbrepo.private:
133 <img class="icon" alt="${_('private')}" src="/images/icons/lock.png"/>
133 <img class="icon" alt="${_('private')}" src="${h.url("/images/icons/lock.png")}"/>
134 134 %else:
135 <img class="icon" alt="${_('public')}" src="/images/icons/lock_open.png"/>
135 <img class="icon" alt="${_('public')}" src="${h.url("/images/icons/lock_open.png")}"/>
136 136 %endif
137 137
138 138 ${h.link_to(repo['repo'].name, h.url('summary_home',repo_name=repo['repo'].name),class_="repo_name")}
139 139 %if repo['repo'].dbrepo.fork:
140 140 <a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
141 141 <img class="icon" alt="${_('public')}"
142 142 title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}"
143 src="/images/icons/arrow_divide.png"/></a>
143 src="${h.url("/images/icons/arrow_divide.png")}"/></a>
144 144 %endif
145 145 </td>
146 146 <td><span class="tooltip" tooltip_title="${repo['repo'].last_change}">${("r%s:%s") % (h.get_changeset_safe(repo['repo'],'tip').revision,h.short_id(h.get_changeset_safe(repo['repo'],'tip').raw_id))}</span></td>
147 <td><a href="${h.url('repo_settings_home',repo_name=repo['repo'].name)}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="/images/icons/application_form_edit.png"/></a></td>
147 <td><a href="${h.url('repo_settings_home',repo_name=repo['repo'].name)}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url("/images/icons/application_form_edit.png")}"/></a></td>
148 148 <td>
149 149 ${h.form(url('repo_settings_delete', repo_name=repo['repo'].name),method='delete')}
150 150 ${h.submit('remove_%s' % repo['repo'].name,'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
151 151 ${h.end_form()}
152 152 </td>
153 153 </tr>
154 154 %endfor
155 155 %else:
156 156 ${_('No repositories yet')}
157 157 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
158 158 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
159 159 %endif
160 160 %endif
161 161 </tbody>
162 162 </table>
163 163 </div>
164 164
165 165 </div>
166 166 <script type="text/javascript">
167 167 var D = YAHOO.util.Dom;
168 168 var E = YAHOO.util.Event;
169 169 var S = YAHOO.util.Selector;
170 170
171 171 var q_filter = D.get('q_filter');
172 172 var F = YAHOO.namespace('q_filter');
173 173
174 174 E.on(q_filter,'click',function(){
175 175 q_filter.value = '';
176 176 });
177 177
178 178 F.filterTimeout = null;
179 179
180 180 F.updateFilter = function() {
181 181 // Reset timeout
182 182 F.filterTimeout = null;
183 183
184 184 var obsolete = [];
185 185 var nodes = S.query('div.table tr td a.repo_name');
186 186 var req = D.get('q_filter').value;
187 187 for (n in nodes){
188 188 D.setStyle(nodes[n].parentNode.parentNode,'display','')
189 189 }
190 190 if (req){
191 191 for (n in nodes){
192 192 if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
193 193 obsolete.push(nodes[n]);
194 194 }
195 195 }
196 196 if(obsolete){
197 197 for (n in obsolete){
198 198 D.setStyle(obsolete[n].parentNode.parentNode,'display','none');
199 199 }
200 200 }
201 201 }
202 202 }
203 203
204 204 E.on(q_filter,'keyup',function(e){
205 205 clearTimeout(F.filterTimeout);
206 206 setTimeout(F.updateFilter,600);
207 207 });
208 208
209 209 </script>
210 210 </%def> No newline at end of file
@@ -1,375 +1,375 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
4 4 <head>
5 5 <title>${next.title()}</title>
6 6 <link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
7 7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 8 <meta name="robots" content="index, nofollow"/>
9 9 <!-- stylesheets -->
10 10 ${self.css()}
11 11 <!-- scripts -->
12 12 ${self.js()}
13 13 </head>
14 14 <body>
15 15 <!-- header -->
16 16 <div id="header">
17 17 <!-- user -->
18 18 <ul id="logged-user">
19 19 <li class="first">
20 20 <div class="gravatar">
21 21 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,20)}" />
22 22 </div>
23 23 <div class="account">
24 24 %if c.rhodecode_user.username == 'default':
25 25 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
26 26 ${h.link_to('anonymous',h.url('register'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
27 27 %else:
28 28 ${h.link_to('anonymous',h.url('#'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
29 29 %endif
30 30
31 31 %else:
32 32 ${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
33 33 %endif
34 34 </div>
35 35 </li>
36 36 <li>
37 37 <a href="${h.url('home')}">${_('Home')}</a>
38 38 </li>
39 39 %if c.rhodecode_user.username != 'default':
40 40 <li>
41 41 <a href="${h.url('journal')}">${_('Journal')}</a>
42 42 ##(${c.unread_journal})</a>
43 43 </li>
44 44 %endif
45 45 %if c.rhodecode_user.username == 'default':
46 46 <li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
47 47 %else:
48 48 <li class="last highlight">${h.link_to(u'Log Out',h.url('logout_home'))}</li>
49 49 %endif
50 50 </ul>
51 51 <!-- end user -->
52 52 <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
53 53 <!-- logo -->
54 54 <div id="logo">
55 55 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
56 56 </div>
57 57 <!-- end logo -->
58 58 <!-- menu -->
59 59 ${self.page_nav()}
60 60 <!-- quick -->
61 61 </div>
62 62 </div>
63 63 <!-- end header -->
64 64
65 65 <!-- CONTENT -->
66 66 <div id="content">
67 67 <div class="flash_msg">
68 68 <% messages = h.flash.pop_messages() %>
69 69 % if messages:
70 70 <ul id="flash-messages">
71 71 % for message in messages:
72 72 <li class="${message.category}_msg">${message}</li>
73 73 % endfor
74 74 </ul>
75 75 % endif
76 76 </div>
77 77 <div id="main">
78 78 ${next.main()}
79 79 </div>
80 80 </div>
81 81 <!-- END CONTENT -->
82 82
83 83 <!-- footer -->
84 84 <div id="footer">
85 85 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
86 86 <div>
87 87 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
88 88 <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
89 89 <p>RhodeCode ${c.rhodecode_version} &copy; 2010-2011 by Marcin Kuzminski</p>
90 90 </div>
91 91 </div>
92 92 <script type="text/javascript">
93 93 function tooltip_activate(){
94 94 ${h.tooltip.activate()}
95 95 }
96 96 tooltip_activate();
97 97 </script>
98 98 </div>
99 99 <!-- end footer -->
100 100 </body>
101 101
102 102 </html>
103 103
104 104 ### MAKO DEFS ###
105 105 <%def name="page_nav()">
106 106 ${self.menu()}
107 107 </%def>
108 108
109 109 <%def name="menu(current=None)">
110 110 <%
111 111 def is_current(selected):
112 112 if selected == current:
113 113 return h.literal('class="current"')
114 114 %>
115 115 %if current not in ['home','admin']:
116 116 ##REGULAR MENU
117 117 <ul id="quick">
118 118 <!-- repo switcher -->
119 119 <li>
120 120 <a id="repo_switcher" title="${_('Switch repository')}" href="#">
121 121 <span class="icon">
122 122 <img src="${h.url("/images/icons/database.png")}" alt="${_('Products')}" />
123 123 </span>
124 124 <span>&darr;</span>
125 125 </a>
126 126 <ul class="repo_switcher">
127 127 %for repo in c.cached_repo_list:
128 128
129 129 %if repo['repo'].dbrepo.private:
130 <li><img src="/images/icons/lock.png" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
130 <li><img src="${h.url("/images/icons/lock.png")}" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
131 131 %else:
132 132 <li><img src="${h.url("/images/icons/lock_open.png")}" alt="${_('Public repository')}" class="repo_switcher_type" />${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
133 133 %endif
134 134 %endfor
135 135 </ul>
136 136 </li>
137 137
138 138 <li ${is_current('summary')}>
139 139 <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
140 140 <span class="icon">
141 141 <img src="${h.url("/images/icons/clipboard_16.png")}" alt="${_('Summary')}" />
142 142 </span>
143 143 <span>${_('Summary')}</span>
144 144 </a>
145 145 </li>
146 146 ##<li ${is_current('shortlog')}>
147 147 ## <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
148 148 ## <span class="icon">
149 149 ## <img src="${h.url("/images/icons/application_view_list.png")}" alt="${_('Shortlog')}" />
150 150 ## </span>
151 151 ## <span>${_('Shortlog')}</span>
152 152 ## </a>
153 153 ##</li>
154 154 <li ${is_current('changelog')}>
155 155 <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
156 156 <span class="icon">
157 157 <img src="${h.url("/images/icons/time.png")}" alt="${_('Changelog')}" />
158 158 </span>
159 159 <span>${_('Changelog')}</span>
160 160 </a>
161 161 </li>
162 162
163 163 <li ${is_current('switch_to')}>
164 164 <a title="${_('Switch to')}" href="#">
165 165 <span class="icon">
166 166 <img src="${h.url("/images/icons/arrow_switch.png")}" alt="${_('Switch to')}" />
167 167 </span>
168 168 <span>${_('Switch to')}</span>
169 169 </a>
170 170 <ul>
171 171 <li>
172 172 ${h.link_to('%s (%s)' % (_('branches'),len(c.repository_branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
173 173 <ul>
174 174 %if c.repository_branches.values():
175 175 %for cnt,branch in enumerate(c.repository_branches.items()):
176 176 <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
177 177 %endfor
178 178 %else:
179 179 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
180 180 %endif
181 181 </ul>
182 182 </li>
183 183 <li>
184 184 ${h.link_to('%s (%s)' % (_('tags'),len(c.repository_tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
185 185 <ul>
186 186 %if c.repository_tags.values():
187 187 %for cnt,tag in enumerate(c.repository_tags.items()):
188 188 <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
189 189 %endfor
190 190 %else:
191 191 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
192 192 %endif
193 193 </ul>
194 194 </li>
195 195 </ul>
196 196 </li>
197 197 <li ${is_current('files')}>
198 198 <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
199 199 <span class="icon">
200 200 <img src="${h.url("/images/icons/file.png")}" alt="${_('Files')}" />
201 201 </span>
202 202 <span>${_('Files')}</span>
203 203 </a>
204 204 </li>
205 205
206 206 <li ${is_current('options')}>
207 207 <a title="${_('Options')}" href="#">
208 208 <span class="icon">
209 209 <img src="${h.url("/images/icons/table_gear.png")}" alt="${_('Admin')}" />
210 210 </span>
211 211 <span>${_('Options')}</span>
212 212 </a>
213 213 <ul>
214 214 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
215 215 %if h.HasPermissionAll('hg.admin')('access settings on repository'):
216 216 <li>${h.link_to(_('settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
217 217 %else:
218 218 <li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
219 219 %endif
220 220 %endif
221 221 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
222 222 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
223 223
224 224 %if h.HasPermissionAll('hg.admin')('access admin main page'):
225 225 <li>
226 226 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
227 227 <%def name="admin_menu()">
228 228 <ul>
229 229 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
230 230 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
231 231 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
232 232 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
233 233 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
234 234 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
235 235 </ul>
236 236 </%def>
237 237
238 238 ${admin_menu()}
239 239 </li>
240 240 %endif
241 241
242 242 </ul>
243 243 </li>
244 244
245 245 <li>
246 246 <a title="${_('Followers')}" href="#">
247 247 <span class="icon_short">
248 248 <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
249 249 </span>
250 250 <span class="short">${c.repository_followers}</span>
251 251 </a>
252 252 </li>
253 253 <li>
254 254 <a title="${_('Forks')}" href="#">
255 255 <span class="icon_short">
256 256 <img src="${h.url("/images/icons/arrow_divide.png")}" alt="${_('Forks')}" />
257 257 </span>
258 258 <span class="short">${c.repository_forks}</span>
259 259 </a>
260 260 </li>
261 261
262 262
263 263
264 264 </ul>
265 265 %else:
266 266 ##ROOT MENU
267 267 <ul id="quick">
268 268 <li>
269 269 <a title="${_('Home')}" href="${h.url('home')}">
270 270 <span class="icon">
271 271 <img src="${h.url("/images/icons/home_16.png")}" alt="${_('Home')}" />
272 272 </span>
273 273 <span>${_('Home')}</span>
274 274 </a>
275 275 </li>
276 276 %if c.rhodecode_user.username != 'default':
277 277 <li>
278 278 <a title="${_('Journal')}" href="${h.url('journal')}">
279 279 <span class="icon">
280 280 <img src="${h.url("/images/icons/book.png")}" alt="${_('Journal')}" />
281 281 </span>
282 282 <span>${_('Journal')}</span>
283 283 </a>
284 284 </li>
285 285 %endif
286 286 <li>
287 287 <a title="${_('Search')}" href="${h.url('search')}">
288 288 <span class="icon">
289 289 <img src="${h.url("/images/icons/search_16.png")}" alt="${_('Search')}" />
290 290 </span>
291 291 <span>${_('Search')}</span>
292 292 </a>
293 293 </li>
294 294
295 295 %if h.HasPermissionAll('hg.admin')('access admin main page'):
296 296 <li ${is_current('admin')}>
297 297 <a title="${_('Admin')}" href="${h.url('admin_home')}">
298 298 <span class="icon">
299 299 <img src="${h.url("/images/icons/cog_edit.png")}" alt="${_('Admin')}" />
300 300 </span>
301 301 <span>${_('Admin')}</span>
302 302 </a>
303 303 ${admin_menu()}
304 304 </li>
305 305 %endif
306 306 </ul>
307 307 %endif
308 308 </%def>
309 309
310 310
311 311 <%def name="css()">
312 312 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
313 313 <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css')}" />
314 314 <link rel="stylesheet" type="text/css" href="${h.url('/css/diff.css')}" />
315 315 </%def>
316 316
317 317 <%def name="js()">
318 318 ##<script type="text/javascript" src="${h.url('/js/yui/utilities/utilities.js')}"></script>
319 319 ##<script type="text/javascript" src="${h.url('/js/yui/container/container.js')}"></script>
320 320 ##<script type="text/javascript" src="${h.url('/js/yui/datasource/datasource.js')}"></script>
321 321 ##<script type="text/javascript" src="${h.url('/js/yui/autocomplete/autocomplete.js')}"></script>
322 322 ##<script type="text/javascript" src="${h.url('/js/yui/selector/selector-min.js')}"></script>
323 323
324 324 <script type="text/javascript" src="${h.url('/js/yui2a.js')}"></script>
325 325 <!--[if IE]><script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script><![endif]-->
326 326 <script type="text/javascript" src="${h.url('/js/yui.flot.js')}"></script>
327 327
328 328 <script type="text/javascript">
329 329 var base_url = "${h.url('toggle_following')}";
330 330 var YUC = YAHOO.util.Connect;
331 331 var YUD = YAHOO.util.Dom;
332 332 var YUE = YAHOO.util.Event;
333 333
334 334 function onSuccess(target){
335 335
336 336 var f = YUD.get(target.id);
337 337 if(f.getAttribute('class')=='follow'){
338 338 f.setAttribute('class','following');
339 339 f.setAttribute('title',"${_('Stop following this repository')}");
340 340 }
341 341 else{
342 342 f.setAttribute('class','follow');
343 343 f.setAttribute('title',"${_('Start following this repository')}");
344 344 }
345 345 }
346 346
347 347 function toggleFollowingUser(fallows_user_id,token){
348 348 args = 'follows_user_id='+fallows_user_id;
349 349 args+= '&amp;auth_token='+token;
350 350 YUC.asyncRequest('POST',base_url,{
351 351 success:function(o){
352 352 onSuccess();
353 353 }
354 354 },args); return false;
355 355 }
356 356
357 357 function toggleFollowingRepo(target,fallows_repo_id,token){
358 358
359 359 args = 'follows_repo_id='+fallows_repo_id;
360 360 args+= '&amp;auth_token='+token;
361 361 YUC.asyncRequest('POST',base_url,{
362 362 success:function(o){
363 363 onSuccess(target);
364 364 }
365 365 },args); return false;
366 366 }
367 367 </script>
368 368
369 369 </%def>
370 370
371 371 <%def name="breadcrumbs()">
372 372 <div class="breadcrumbs">
373 373 ${self.breadcrumbs_links()}
374 374 </div>
375 375 </%def> No newline at end of file
@@ -1,136 +1,136 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} ${_('Changelog')} - ${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 ${_('Changelog')} - ${_('showing ')} ${c.size if c.size <= c.total_cs else c.total_cs} ${_('out of')} ${c.total_cs} ${_('revisions')}
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 % if c.pagination:
29 29 <div id="graph">
30 30 <div id="graph_nodes">
31 31 <canvas id="graph_canvas"></canvas>
32 32 </div>
33 33 <div id="graph_content">
34 34 <div class="container_header">
35 35
36 36 ${h.form(h.url.current(),method='get')}
37 37 <div class="info_box">
38 38 <span>${_('Show')}:</span>
39 39 ${h.text('size',size=1,value=c.size)}
40 40 <span>${_('revisions')}</span>
41 41 ${h.submit('set',_('set'))}
42 42 </div>
43 43 ${h.end_form()}
44 44
45 45 </div>
46 46 %for cnt,cs in enumerate(c.pagination):
47 47 <div id="chg_${cnt+1}" class="container">
48 48 <div class="left">
49 49 <div class="date">${_('commit')} ${cs.revision}: ${h.short_id(cs.raw_id)}@${cs.date}</div>
50 50 <div class="author">
51 51 <div class="gravatar">
52 52 <img alt="gravatar" src="${h.gravatar_url(h.email(cs.author),20)}"/>
53 53 </div>
54 54 <span>${h.person(cs.author)}</span><br/>
55 55 <span><a href="mailto:${h.email_or_none(cs.author)}">${h.email_or_none(cs.author)}</a></span><br/>
56 56 </div>
57 57 <div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
58 58 </div>
59 59 <div class="right">
60 60 <div class="changes">
61 61
62 62 <%
63 63 def changed_tooltip(cs):
64 64 if cs:
65 65 pref = ': '
66 66 suf = ''
67 67 if len(cs) > 30:
68 68 suf='<br/>'+_(' and %s more') % (len(cs) - 30)
69 69 return pref+'<br/> '.join([x.path for x in cs[:30]]) + suf
70 70 else:
71 71 return ': '+_('No Files')
72 72 %>
73 73
74 74 <span class="removed tooltip" tooltip_title="${_('removed')}${h.literal(changed_tooltip(cs.removed))}">${len(cs.removed)}</span>
75 75 <span class="changed tooltip" tooltip_title="${_('changed')}${h.literal(changed_tooltip(cs.changed))}">${len(cs.changed)}</span>
76 76 <span class="added tooltip" tooltip_title="${_('added')}${h.literal(changed_tooltip(cs.added))}">${len(cs.added)}</span>
77 77 </div>
78 78 %if len(cs.parents)>1:
79 79 <div class="merge">
80 ${_('merge')}<img alt="merge" src="/images/icons/arrow_join.png"/>
80 ${_('merge')}<img alt="merge" src="${h.url("/images/icons/arrow_join.png")}"/>
81 81 </div>
82 82 %endif
83 83 %if cs.parents:
84 84 %for p_cs in reversed(cs.parents):
85 85 <div class="parent">${_('Parent')} ${p_cs.revision}: ${h.link_to(h.short_id(p_cs.raw_id),
86 86 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}
87 87 </div>
88 88 %endfor
89 89 %else:
90 90 <div class="parent">${_('No parents')}</div>
91 91 %endif
92 92
93 93 <span class="logtags">
94 94 %if cs.branch:
95 95 <span class="branchtag" title="${'%s %s' % (_('branch'),cs.branch)}">
96 96 ${h.link_to(cs.branch,h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span>
97 97 %endif
98 98 %for tag in cs.tags:
99 99 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
100 100 ${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span>
101 101 %endfor
102 102 </span>
103 103 </div>
104 104 </div>
105 105
106 106 %endfor
107 107 <div class="pagination-wh pagination-left">
108 108 ${c.pagination.pager('$link_previous ~2~ $link_next')}
109 109 </div>
110 110 </div>
111 111 </div>
112 112
113 113 <script type="text/javascript" src="${h.url("/js/graph.js")}"></script>
114 114 <script type="text/javascript">
115 115 YAHOO.util.Event.onDOMReady(function(){
116 116 function set_canvas() {
117 117 var c = document.getElementById('graph_nodes');
118 118 var t = document.getElementById('graph_content');
119 119 canvas = document.getElementById('graph_canvas');
120 120 var div_h = t.clientHeight;
121 121 c.style.height=div_h+'px';
122 122 canvas.setAttribute('height',div_h);
123 123 canvas.setAttribute('width',160);
124 124 };
125 125 set_canvas();
126 126 var jsdata = ${c.jsdata|n};
127 127 var r = new BranchRenderer();
128 128 r.render(jsdata);
129 129 });
130 130 </script>
131 131 %else:
132 132 ${_('There are no changes yet')}
133 133 %endif
134 134 </div>
135 135 </div>
136 136 </%def> No newline at end of file
@@ -1,124 +1,124 b''
1 1 <%inherit file="/base/base.html"/>
2 2
3 3 <%def name="title()">
4 4 ${c.repo_name} ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - ${c.rhodecode_name}
5 5 </%def>
6 6
7 7 <%def name="breadcrumbs_links()">
8 8 ${h.link_to(u'Home',h.url('/'))}
9 9 &raquo;
10 10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 11 &raquo;
12 12 ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
13 13 </%def>
14 14
15 15 <%def name="page_nav()">
16 16 ${self.menu('changelog')}
17 17 </%def>
18 18
19 19 <%def name="main()">
20 20 <div class="box">
21 21 <!-- box / title -->
22 22 <div class="title">
23 23 ${self.breadcrumbs()}
24 24 </div>
25 25 <div class="table">
26 26 <div id="body" class="diffblock">
27 27 <div class="code-header">
28 28 <div>
29 29 ${_('Changeset')} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}
30 30 &raquo; <span>${h.link_to(_('raw diff'),
31 31 h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
32 32 &raquo; <span>${h.link_to(_('download diff'),
33 33 h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
34 34 </div>
35 35 </div>
36 36 </div>
37 37 <div id="changeset_content">
38 38 <div class="container">
39 39 <div class="left">
40 40 <div class="date">${_('commit')} ${c.changeset.revision}: ${h.short_id(c.changeset.raw_id)}@${c.changeset.date}</div>
41 41 <div class="author">
42 42 <div class="gravatar">
43 43 <img alt="gravatar" src="${h.gravatar_url(h.email(c.changeset.author),20)}"/>
44 44 </div>
45 45 <span>${h.person(c.changeset.author)}</span><br/>
46 46 <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
47 47 </div>
48 48 <div class="message">${h.link_to(h.wrap_paragraphs(c.changeset.message),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</div>
49 49 </div>
50 50 <div class="right">
51 51 <div class="changes">
52 52 <span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span>
53 53 <span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span>
54 54 <span class="added" title="${_('added')}">${len(c.changeset.added)}</span>
55 55 </div>
56 56 %if len(c.changeset.parents)>1:
57 57 <div class="merge">
58 ${_('merge')}<img alt="merge" src="/images/icons/arrow_join.png"/>
58 ${_('merge')}<img alt="merge" src="${h.url("/images/icons/arrow_join.png")}"/>
59 59 </div>
60 60 %endif
61 61
62 62 %if c.changeset.parents:
63 63 %for p_cs in reversed(c.changeset.parents):
64 64 <div class="parent">${_('Parent')} ${p_cs.revision}: ${h.link_to(h.short_id(p_cs.raw_id),
65 65 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}
66 66 </div>
67 67 %endfor
68 68 %else:
69 69 <div class="parent">${_('No parents')}</div>
70 70 %endif
71 71 <span class="logtags">
72 72 <span class="branchtag" title="${'%s %s' % (_('branch'),c.changeset.branch)}">
73 73 ${h.link_to(c.changeset.branch,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
74 74 %for tag in c.changeset.tags:
75 75 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
76 76 ${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
77 77 %endfor
78 78 </span>
79 79 </div>
80 80 </div>
81 81 <span style="font-size:1.1em;font-weight: bold">${_('Files affected')}</span>
82 82 <div class="cs_files">
83 83 %for change,filenode,diff,cs1,cs2 in c.changes:
84 84 <div class="cs_${change}">${h.link_to(filenode.path,h.url.current(anchor='CHANGE-%s'%filenode.path))}</div>
85 85 %endfor
86 86 </div>
87 87 </div>
88 88
89 89 </div>
90 90
91 91 %for change,filenode,diff,cs1,cs2 in c.changes:
92 92 %if change !='removed':
93 93 <div style="clear:both;height:10px"></div>
94 94 <div id="body" class="diffblock">
95 95 <div id="${'CHANGE-%s'%filenode.path}" class="code-header">
96 96 <div class="changeset_header">
97 97 <span class="changeset_file">
98 98 ${h.link_to_if(change!='removed',filenode.path,h.url('files_home',repo_name=c.repo_name,
99 99 revision=filenode.changeset.raw_id,f_path=filenode.path))}
100 100 </span>
101 101 %if 1:
102 102 &raquo; <span>${h.link_to(_('diff'),
103 103 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='diff'))}</span>
104 104 &raquo; <span>${h.link_to(_('raw diff'),
105 105 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='raw'))}</span>
106 106 &raquo; <span>${h.link_to(_('download diff'),
107 107 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='download'))}</span>
108 108 %endif
109 109 </div>
110 110 </div>
111 111 <div class="code-body">
112 112 %if diff:
113 113 ${diff|n}
114 114 %else:
115 115 ${_('No changes in this file')}
116 116 %endif
117 117 </div>
118 118 </div>
119 119 %endif
120 120 %endfor
121 121 </div>
122 122 </div>
123 123
124 124 </%def> No newline at end of file
@@ -1,168 +1,168 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/base.html"/>
3 3 <%def name="title()">
4 4 ${_('Dashboard')} - ${c.rhodecode_name}
5 5 </%def>
6 6 <%def name="breadcrumbs()">
7 7 ${c.rhodecode_name}
8 8 </%def>
9 9 <%def name="page_nav()">
10 10 ${self.menu('home')}
11 11 </%def>
12 12 <%def name="main()">
13 13 <%def name="get_sort(name)">
14 14 <%name_slug = name.lower().replace(' ','_') %>
15 15
16 16 %if name_slug == c.sort_slug:
17 17 %if c.sort_by.startswith('-'):
18 18 <a href="?sort=${name_slug}">${name}&uarr;</a>
19 19 %else:
20 20 <a href="?sort=-${name_slug}">${name}&darr;</a>
21 21 %endif:
22 22 %else:
23 23 <a href="?sort=${name_slug}">${name}</a>
24 24 %endif
25 25 </%def>
26 26
27 27 <div class="box">
28 28 <!-- box / title -->
29 29 <div class="title">
30 30 <h5>${_('Dashboard')}
31 31 <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
32 32 </h5>
33 33 %if c.rhodecode_user.username != 'default':
34 34 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
35 35 <ul class="links">
36 36 <li>
37 37 <span>${h.link_to(_('ADD NEW REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
38 38 </li>
39 39 </ul>
40 40 %endif
41 41 %endif
42 42 </div>
43 43 <!-- end box / title -->
44 44 <div class="table">
45 45 <table>
46 46 <thead>
47 47 <tr>
48 48 <th class="left">${get_sort(_('Name'))}</th>
49 49 <th class="left">${get_sort(_('Description'))}</th>
50 50 <th class="left">${get_sort(_('Last change'))}</th>
51 51 <th class="left">${get_sort(_('Tip'))}</th>
52 52 <th class="left">${get_sort(_('Owner'))}</th>
53 53 <th class="left">${_('RSS')}</th>
54 54 <th class="left">${_('Atom')}</th>
55 55 </tr>
56 56 </thead>
57 57 <tbody>
58 58 %for cnt,repo in enumerate(c.repos_list):
59 59 <tr class="parity${cnt%2}">
60 60 <td>
61 61 <div style="white-space: nowrap">
62 62 ## TYPE OF REPO
63 63 %if repo['repo'].dbrepo.repo_type =='hg':
64 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
64 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
65 65 %elif repo['repo'].dbrepo.repo_type =='git':
66 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
66 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
67 67 %else:
68 68
69 69 %endif
70 70
71 71 ##PRIVATE/PUBLIC
72 72 %if repo['repo'].dbrepo.private:
73 <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
73 <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
74 74 %else:
75 <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
75 <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
76 76 %endif
77 77
78 78 ##NAME
79 79 ${h.link_to(repo['name'],
80 80 h.url('summary_home',repo_name=repo['name']),class_="repo_name")}
81 81 %if repo['repo'].dbrepo.fork:
82 82 <a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
83 83 <img class="icon" alt="${_('fork')}"
84 84 title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}"
85 src="/images/icons/arrow_divide.png"/></a>
85 src="${h.url("/images/icons/arrow_divide.png")}"/></a>
86 86 %endif
87 87 </div>
88 88 </td>
89 89 ##DESCRIPTION
90 90 <td><span class="tooltip" tooltip_title="${h.tooltip(repo['description'])}">
91 91 ${h.truncate(repo['description'],60)}</span>
92 92 </td>
93 93 ##LAST CHANGE
94 94 <td>
95 95 <span class="tooltip" tooltip_title="${repo['last_change']}">
96 96 ${h.age(repo['last_change'])}</span>
97 97 </td>
98 98 <td>
99 99 %if repo['rev']>=0:
100 100 ${h.link_to('r%s:%s' % (repo['rev'],h.short_id(repo['tip'])),
101 101 h.url('changeset_home',repo_name=repo['name'],revision=repo['tip']),
102 102 class_="tooltip",
103 103 tooltip_title=h.tooltip(repo['last_msg']))}
104 104 %else:
105 105 ${_('No changesets yet')}
106 106 %endif
107 107 </td>
108 108 <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
109 109 <td>
110 110 <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon" href="${h.url('rss_feed_home',repo_name=repo['name'])}"></a>
111 111 </td>
112 112 <td>
113 113 <a title="${_('Subscribe to %s atom feed')%repo['name']}" class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'])}"></a>
114 114 </td>
115 115 </tr>
116 116 %endfor
117 117 </tbody>
118 118 </table>
119 119 </div>
120 120 </div>
121 121
122 122
123 123 <script type="text/javascript">
124 124 var D = YAHOO.util.Dom;
125 125 var E = YAHOO.util.Event;
126 126 var S = YAHOO.util.Selector;
127 127
128 128 var q_filter = D.get('q_filter');
129 129 var F = YAHOO.namespace('q_filter');
130 130
131 131 E.on(q_filter,'click',function(){
132 132 q_filter.value = '';
133 133 });
134 134
135 135 F.filterTimeout = null;
136 136
137 137 F.updateFilter = function() {
138 138 // Reset timeout
139 139 F.filterTimeout = null;
140 140
141 141 var obsolete = [];
142 142 var nodes = S.query('div.table tr td div a.repo_name');
143 143 var req = D.get('q_filter').value;
144 144 for (n in nodes){
145 145 D.setStyle(nodes[n].parentNode.parentNode.parentNode,'display','')
146 146 }
147 147 if (req){
148 148 for (n in nodes){
149 149 if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
150 150 obsolete.push(nodes[n]);
151 151 }
152 152 }
153 153 if(obsolete){
154 154 for (n in obsolete){
155 155 D.setStyle(obsolete[n].parentNode.parentNode.parentNode,'display','none');
156 156 }
157 157 }
158 158 }
159 159 }
160 160
161 161 E.on(q_filter,'keyup',function(e){
162 162 clearTimeout(F.filterTimeout);
163 163 setTimeout(F.updateFilter,600);
164 164 });
165 165
166 166 </script>
167 167
168 168 </%def>
@@ -1,92 +1,92 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/base.html"/>
3 3 <%def name="title()">
4 4 ${_('Journal')} - ${c.rhodecode_name}
5 5 </%def>
6 6 <%def name="breadcrumbs()">
7 7 ${c.rhodecode_name}
8 8 </%def>
9 9 <%def name="page_nav()">
10 10 ${self.menu('home')}
11 11 </%def>
12 12 <%def name="main()">
13 13
14 14 <div class="box box-left">
15 15 <!-- box / title -->
16 16 <div class="title">
17 17 <h5>${_('Journal')}</h5>
18 18 </div>
19 19 <div>
20 20 %if c.journal:
21 21 %for entry in c.journal:
22 22 <div style="padding:10px">
23 23 <div class="gravatar">
24 24 <img alt="gravatar" src="${h.gravatar_url(entry.user.email)}"/>
25 25 </div>
26 26 <div>${entry.user.name} ${entry.user.lastname}</div>
27 27 <div style="padding-left: 45px;padding-top:5px;min-height:20px">${h.action_parser(entry)}</div>
28 28 <div style="float: left; padding-top: 8px;padding-left:18px">
29 29 ${h.action_parser_icon(entry)}
30 30 </div>
31 31 <div style="margin-left: 45px;padding-top: 10px">
32 32 <span style="font-weight: bold;font-size: 1.1em">
33 33 %if entry.repository:
34 34 ${h.link_to(entry.repository.repo_name,
35 35 h.url('summary_home',repo_name=entry.repository.repo_name))}
36 36 %else:
37 37 ${entry.repository_name}
38 38 %endif
39 39 </span> - <span title="${entry.action_date}">${h.age(entry.action_date)}</span>
40 40 </div>
41 41 </div>
42 42 <div style="clear:both;border-bottom:1px dashed #DDD;padding:3px 3px;margin:0px 10px 0px 10px"></div>
43 43 %endfor
44 44 %else:
45 45 ${_('No entries yet')}
46 46 %endif
47 47 </div>
48 48 </div>
49 49
50 50 <div class="box box-right">
51 51 <!-- box / title -->
52 52 <div class="title">
53 53 <h5>${_('Following')}</h5>
54 54 </div>
55 55 <div>
56 56 %if c.following:
57 57 %for entry in c.following:
58 58 <div class="currently_following">
59 59 %if entry.follows_user_id:
60 <img title="${_('following user')}" alt="${_('user')}" src="/images/icons/user.png"/>
60 <img title="${_('following user')}" alt="${_('user')}" src="${h.url("/images/icons/user.png")}"/>
61 61 ${entry.follows_user.full_contact}
62 62 %endif
63 63
64 64 %if entry.follows_repo_id:
65 65
66 66 %if entry.follows_repository.private:
67 <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
67 <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
68 68 %else:
69 <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
69 <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
70 70 %endif
71 71
72 72 ${h.link_to(entry.follows_repository.repo_name,h.url('summary_home',
73 73 repo_name=entry.follows_repository.repo_name))}
74 74
75 75 %endif
76 76 </div>
77 77 %endfor
78 78 %else:
79 79 ${_('You are not following any users or repositories')}
80 80 %endif
81 81 </div>
82 82 </div>
83 83
84 84 <script type="text/javascript">
85 85 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
86 86 var el = e.target;
87 87 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
88 88 YUD.setStyle(el.parentNode,'display','none');
89 89 });
90 90 </script>
91 91
92 92 </%def>
@@ -1,643 +1,643 b''
1 1 <%inherit file="/base/base.html"/>
2 2
3 3 <%def name="title()">
4 4 ${c.repo_name} ${_('Summary')} - ${c.rhodecode_name}
5 5 </%def>
6 6
7 7 <%def name="breadcrumbs_links()">
8 8 ${h.link_to(u'Home',h.url('/'))}
9 9 &raquo;
10 10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 11 &raquo;
12 12 ${_('summary')}
13 13 </%def>
14 14
15 15 <%def name="page_nav()">
16 16 ${self.menu('summary')}
17 17 </%def>
18 18
19 19 <%def name="main()">
20 20 <div class="box box-left">
21 21 <!-- box / title -->
22 22 <div class="title">
23 23 ${self.breadcrumbs()}
24 24 </div>
25 25 <!-- end box / title -->
26 26 <div class="form">
27 27 <div class="fields">
28 28
29 29 <div class="field">
30 30 <div class="label">
31 31 <label>${_('Name')}:</label>
32 32 </div>
33 33 <div class="input-short">
34 34 %if c.repo_info.dbrepo.repo_type =='hg':
35 <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
35 <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
36 36 %endif
37 37 %if c.repo_info.dbrepo.repo_type =='git':
38 <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
38 <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
39 39 %endif
40 40
41 41 %if c.repo_info.dbrepo.private:
42 <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
42 <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url("/images/icons/lock.png")}"/>
43 43 %else:
44 <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
44 <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url("/images/icons/lock_open.png")}"/>
45 45 %endif
46 46 <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
47 47 %if c.rhodecode_user.username != 'default':
48 48 %if c.following:
49 49 <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
50 50 onclick="javascript:toggleFollowingRepo(this,${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
51 51 </span>
52 52 %else:
53 53 <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
54 54 onclick="javascript:toggleFollowingRepo(this,${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
55 55 </span>
56 56 %endif
57 57 %endif:
58 58 <br/>
59 59 %if c.repo_info.dbrepo.fork:
60 60 <span style="margin-top:5px">
61 61 <a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
62 62 <img class="icon" alt="${_('public')}"
63 63 title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}"
64 64 src="${h.url("/images/icons/arrow_divide.png")}"/>
65 65 ${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
66 66 </a>
67 67 </span>
68 68 %endif
69 69 </div>
70 70 </div>
71 71
72 72
73 73 <div class="field">
74 74 <div class="label">
75 75 <label>${_('Description')}:</label>
76 76 </div>
77 77 <div class="input-short">
78 78 ${c.repo_info.dbrepo.description}
79 79 </div>
80 80 </div>
81 81
82 82
83 83 <div class="field">
84 84 <div class="label">
85 85 <label>${_('Contact')}:</label>
86 86 </div>
87 87 <div class="input-short">
88 88 <div class="gravatar">
89 89 <img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
90 90 </div>
91 91 ${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
92 92 ${_('Name')}: ${c.repo_info.dbrepo.user.name} ${c.repo_info.dbrepo.user.lastname}<br/>
93 93 ${_('Email')}: <a href="mailto:${c.repo_info.dbrepo.user.email}">${c.repo_info.dbrepo.user.email}</a>
94 94 </div>
95 95 </div>
96 96
97 97 <div class="field">
98 98 <div class="label">
99 99 <label>${_('Last change')}:</label>
100 100 </div>
101 101 <div class="input-short">
102 102 ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change}
103 103 ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author}
104 104
105 105 </div>
106 106 </div>
107 107
108 108 <div class="field">
109 109 <div class="label">
110 110 <label>${_('Clone url')}:</label>
111 111 </div>
112 112 <div class="input-short">
113 113 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
114 114 </div>
115 115 </div>
116 116
117 117 <div class="field">
118 118 <div class="label">
119 119 <label>${_('Trending source files')}:</label>
120 120 </div>
121 121 <div class="input-short">
122 122 <div id="lang_stats">
123 123
124 124 </div>
125 125 <script type="text/javascript">
126 126 YUE.onDOMReady(function(e){
127 127 id = 'clone_url';
128 128 YUE.on(id,'click',function(e){
129 129 YUD.get('clone_url').select();
130 130 })
131 131 })
132 132 var data = ${c.trending_languages|n};
133 133 var total = 0;
134 134 var no_data = true;
135 135 for (k in data){
136 136 total += data[k];
137 137 no_data = false;
138 138 }
139 139 var tbl = document.createElement('table');
140 140 tbl.setAttribute('class','trending_language_tbl');
141 141 var cnt =0;
142 142 for (k in data){
143 143 cnt+=1;
144 144 var hide = cnt>2;
145 145 var tr = document.createElement('tr');
146 146 if (hide){
147 147 tr.setAttribute('style','display:none');
148 148 tr.setAttribute('class','stats_hidden');
149 149 }
150 150 var percentage = Math.round((data[k]/total*100),2);
151 151 var value = data[k];
152 152 var td1 = document.createElement('td');
153 153 td1.width=150;
154 154 var trending_language_label = document.createElement('div');
155 155 trending_language_label.innerHTML = k;
156 156 td1.appendChild(trending_language_label);
157 157
158 158 var td2 = document.createElement('td');
159 159 td2.setAttribute('style','padding-right:14px !important');
160 160 var trending_language = document.createElement('div');
161 161 var nr_files = value+" ${_('files')}";
162 162
163 163 trending_language.title = k+" "+nr_files;
164 164
165 165 if (percentage>20){
166 166 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
167 167 }
168 168 else{
169 169 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
170 170 }
171 171
172 172 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
173 173 trending_language.style.width=percentage+"%";
174 174 td2.appendChild(trending_language);
175 175
176 176 tr.appendChild(td1);
177 177 tr.appendChild(td2);
178 178 tbl.appendChild(tr);
179 179 if(cnt == 2){
180 180 var show_more = document.createElement('tr');
181 181 var td=document.createElement('td');
182 182 lnk = document.createElement('a');
183 183 lnk.href='#';
184 184 lnk.innerHTML = "${_("show more")}";
185 185 lnk.id='code_stats_show_more';
186 186 td.appendChild(lnk);
187 187 show_more.appendChild(td);
188 188 show_more.appendChild(document.createElement('td'));
189 189 tbl.appendChild(show_more);
190 190 }
191 191
192 192 }
193 193 if(no_data){
194 194 var tr = document.createElement('tr');
195 195 var td1 = document.createElement('td');
196 196 td1.innerHTML = "${c.no_data_msg}";
197 197 tr.appendChild(td1);
198 198 tbl.appendChild(tr);
199 199 }
200 200 YUD.get('lang_stats').appendChild(tbl);
201 201 YUE.on('code_stats_show_more','click',function(){
202 202 l = YUD.getElementsByClassName('stats_hidden')
203 203 for (e in l){
204 204 YUD.setStyle(l[e],'display','');
205 205 };
206 206 YUD.setStyle(YUD.get('code_stats_show_more'),
207 207 'display','none');
208 208 })
209 209
210 210 </script>
211 211
212 212 </div>
213 213 </div>
214 214
215 215 <div class="field">
216 216 <div class="label">
217 217 <label>${_('Download')}:</label>
218 218 </div>
219 219 <div class="input-short">
220 220 %for cnt,archive in enumerate(c.repo_info._get_archives()):
221 221 %if cnt >=1:
222 222 |
223 223 %endif
224 224 ${h.link_to(c.repo_info.name+'.'+archive['type'],
225 225 h.url('files_archive_home',repo_name=c.repo_info.name,
226 226 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
227 227 %endfor
228 228 </div>
229 229 </div>
230 230
231 231 <div class="field">
232 232 <div class="label">
233 233 <label>${_('Feeds')}:</label>
234 234 </div>
235 235 <div class="input-short">
236 236 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
237 237 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
238 238 </div>
239 239 </div>
240 240 </div>
241 241 </div>
242 242 </div>
243 243
244 244 <div class="box box-right" style="min-height:455px">
245 245 <!-- box / title -->
246 246 <div class="title">
247 247 <h5>${_('Commit activity by day / author')}</h5>
248 248 </div>
249 249
250 250 <div class="table">
251 251
252 252 %if c.no_data:
253 253 <div style="padding:0 10px 10px 15px;font-size: 1.2em;">${c.no_data_msg}</div>
254 254 %endif:
255 255 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
256 256 <div style="clear: both;height: 10px"></div>
257 257 <div id="overview" style="width:460px;height:100px;float:left"></div>
258 258
259 259 <div id="legend_data" style="clear:both;margin-top:10px;">
260 260 <div id="legend_container"></div>
261 261 <div id="legend_choices">
262 262 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
263 263 </div>
264 264 </div>
265 265 <script type="text/javascript">
266 266 /**
267 267 * Plots summary graph
268 268 *
269 269 * @class SummaryPlot
270 270 * @param {from} initial from for detailed graph
271 271 * @param {to} initial to for detailed graph
272 272 * @param {dataset}
273 273 * @param {overview_dataset}
274 274 */
275 275 function SummaryPlot(from,to,dataset,overview_dataset) {
276 276 var initial_ranges = {
277 277 "xaxis":{
278 278 "from":from,
279 279 "to":to,
280 280 },
281 281 };
282 282 var dataset = dataset;
283 283 var overview_dataset = [overview_dataset];
284 284 var choiceContainer = YUD.get("legend_choices");
285 285 var choiceContainerTable = YUD.get("legend_choices_tables");
286 286 var plotContainer = YUD.get('commit_history');
287 287 var overviewContainer = YUD.get('overview');
288 288
289 289 var plot_options = {
290 290 bars: {show:true,align:'center',lineWidth:4},
291 291 legend: {show:true, container:"legend_container"},
292 292 points: {show:true,radius:0,fill:false},
293 293 yaxis: {tickDecimals:0,},
294 294 xaxis: {
295 295 mode: "time",
296 296 timeformat: "%d/%m",
297 297 min:from,
298 298 max:to,
299 299 },
300 300 grid: {
301 301 hoverable: true,
302 302 clickable: true,
303 303 autoHighlight:true,
304 304 color: "#999"
305 305 },
306 306 //selection: {mode: "x"}
307 307 };
308 308 var overview_options = {
309 309 legend:{show:false},
310 310 bars: {show:true,barWidth: 2,},
311 311 shadowSize: 0,
312 312 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
313 313 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
314 314 grid: {color: "#999",},
315 315 selection: {mode: "x"}
316 316 };
317 317
318 318 /**
319 319 *get dummy data needed in few places
320 320 */
321 321 function getDummyData(label){
322 322 return {"label":label,
323 323 "data":[{"time":0,
324 324 "commits":0,
325 325 "added":0,
326 326 "changed":0,
327 327 "removed":0,
328 328 }],
329 329 "schema":["commits"],
330 330 "color":'#ffffff',
331 331 }
332 332 }
333 333
334 334 /**
335 335 * generate checkboxes accordindly to data
336 336 * @param keys
337 337 * @returns
338 338 */
339 339 function generateCheckboxes(data) {
340 340 //append checkboxes
341 341 var i = 0;
342 342 choiceContainerTable.innerHTML = '';
343 343 for(var pos in data) {
344 344
345 345 data[pos].color = i;
346 346 i++;
347 347 if(data[pos].label != ''){
348 348 choiceContainerTable.innerHTML += '<tr><td>'+
349 349 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
350 350 +data[pos].label+
351 351 '</td></tr>';
352 352 }
353 353 }
354 354 }
355 355
356 356 /**
357 357 * ToolTip show
358 358 */
359 359 function showTooltip(x, y, contents) {
360 360 var div=document.getElementById('tooltip');
361 361 if(!div) {
362 362 div = document.createElement('div');
363 363 div.id="tooltip";
364 364 div.style.position="absolute";
365 365 div.style.border='1px solid #fdd';
366 366 div.style.padding='2px';
367 367 div.style.backgroundColor='#fee';
368 368 document.body.appendChild(div);
369 369 }
370 370 YUD.setStyle(div, 'opacity', 0);
371 371 div.innerHTML = contents;
372 372 div.style.top=(y + 5) + "px";
373 373 div.style.left=(x + 5) + "px";
374 374
375 375 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
376 376 anim.animate();
377 377 }
378 378
379 379 /**
380 380 * This function will detect if selected period has some changesets
381 381 for this user if it does this data is then pushed for displaying
382 382 Additionally it will only display users that are selected by the checkbox
383 383 */
384 384 function getDataAccordingToRanges(ranges) {
385 385
386 386 var data = [];
387 387 var keys = [];
388 388 for(var key in dataset){
389 389 var push = false;
390 390
391 391 //method1 slow !!
392 392 //*
393 393 for(var ds in dataset[key].data){
394 394 commit_data = dataset[key].data[ds];
395 395 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
396 396 push = true;
397 397 break;
398 398 }
399 399 }
400 400 //*/
401 401
402 402 /*//method2 sorted commit data !!!
403 403
404 404 var first_commit = dataset[key].data[0].time;
405 405 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
406 406
407 407 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
408 408 push = true;
409 409 }
410 410 //*/
411 411
412 412 if(push){
413 413 data.push(dataset[key]);
414 414 }
415 415 }
416 416 if(data.length >= 1){
417 417 return data;
418 418 }
419 419 else{
420 420 //just return dummy data for graph to plot itself
421 421 return [getDummyData('')];
422 422 }
423 423
424 424 }
425 425
426 426 /**
427 427 * redraw using new checkbox data
428 428 */
429 429 function plotchoiced(e,args){
430 430 var cur_data = args[0];
431 431 var cur_ranges = args[1];
432 432
433 433 var new_data = [];
434 434 var inputs = choiceContainer.getElementsByTagName("input");
435 435
436 436 //show only checked labels
437 437 for(var i=0; i<inputs.length; i++) {
438 438 var checkbox_key = inputs[i].name;
439 439
440 440 if(inputs[i].checked){
441 441 for(var d in cur_data){
442 442 if(cur_data[d].label == checkbox_key){
443 443 new_data.push(cur_data[d]);
444 444 }
445 445 }
446 446 }
447 447 else{
448 448 //push dummy data to not hide the label
449 449 new_data.push(getDummyData(checkbox_key));
450 450 }
451 451 }
452 452
453 453 var new_options = YAHOO.lang.merge(plot_options, {
454 454 xaxis: {
455 455 min: cur_ranges.xaxis.from,
456 456 max: cur_ranges.xaxis.to,
457 457 mode:"time",
458 458 timeformat: "%d/%m",
459 459 },
460 460 });
461 461 if (!new_data){
462 462 new_data = [[0,1]];
463 463 }
464 464 // do the zooming
465 465 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
466 466
467 467 plot.subscribe("plotselected", plotselected);
468 468
469 469 //resubscribe plothover
470 470 plot.subscribe("plothover", plothover);
471 471
472 472 // don't fire event on the overview to prevent eternal loop
473 473 overview.setSelection(cur_ranges, true);
474 474
475 475 }
476 476
477 477 /**
478 478 * plot only selected items from overview
479 479 * @param ranges
480 480 * @returns
481 481 */
482 482 function plotselected(ranges,cur_data) {
483 483 //updates the data for new plot
484 484 data = getDataAccordingToRanges(ranges);
485 485 generateCheckboxes(data);
486 486
487 487 var new_options = YAHOO.lang.merge(plot_options, {
488 488 xaxis: {
489 489 min: ranges.xaxis.from,
490 490 max: ranges.xaxis.to,
491 491 mode:"time",
492 492 timeformat: "%d/%m",
493 493 },
494 494 yaxis: {
495 495 min: ranges.yaxis.from,
496 496 max: ranges.yaxis.to,
497 497 },
498 498
499 499 });
500 500 // do the zooming
501 501 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
502 502
503 503 plot.subscribe("plotselected", plotselected);
504 504
505 505 //resubscribe plothover
506 506 plot.subscribe("plothover", plothover);
507 507
508 508 // don't fire event on the overview to prevent eternal loop
509 509 overview.setSelection(ranges, true);
510 510
511 511 //resubscribe choiced
512 512 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
513 513 }
514 514
515 515 var previousPoint = null;
516 516
517 517 function plothover(o) {
518 518 var pos = o.pos;
519 519 var item = o.item;
520 520
521 521 //YUD.get("x").innerHTML = pos.x.toFixed(2);
522 522 //YUD.get("y").innerHTML = pos.y.toFixed(2);
523 523 if (item) {
524 524 if (previousPoint != item.datapoint) {
525 525 previousPoint = item.datapoint;
526 526
527 527 var tooltip = YUD.get("tooltip");
528 528 if(tooltip) {
529 529 tooltip.parentNode.removeChild(tooltip);
530 530 }
531 531 var x = item.datapoint.x.toFixed(2);
532 532 var y = item.datapoint.y.toFixed(2);
533 533
534 534 if (!item.series.label){
535 535 item.series.label = 'commits';
536 536 }
537 537 var d = new Date(x*1000);
538 538 var fd = d.toDateString()
539 539 var nr_commits = parseInt(y);
540 540
541 541 var cur_data = dataset[item.series.label].data[item.dataIndex];
542 542 var added = cur_data.added;
543 543 var changed = cur_data.changed;
544 544 var removed = cur_data.removed;
545 545
546 546 var nr_commits_suffix = " ${_('commits')} ";
547 547 var added_suffix = " ${_('files added')} ";
548 548 var changed_suffix = " ${_('files changed')} ";
549 549 var removed_suffix = " ${_('files removed')} ";
550 550
551 551
552 552 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
553 553 if(added==1){added_suffix=" ${_('file added')} ";}
554 554 if(changed==1){changed_suffix=" ${_('file changed')} ";}
555 555 if(removed==1){removed_suffix=" ${_('file removed')} ";}
556 556
557 557 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
558 558 +'<br/>'+
559 559 nr_commits + nr_commits_suffix+'<br/>'+
560 560 added + added_suffix +'<br/>'+
561 561 changed + changed_suffix + '<br/>'+
562 562 removed + removed_suffix + '<br/>');
563 563 }
564 564 }
565 565 else {
566 566 var tooltip = YUD.get("tooltip");
567 567
568 568 if(tooltip) {
569 569 tooltip.parentNode.removeChild(tooltip);
570 570 }
571 571 previousPoint = null;
572 572 }
573 573 }
574 574
575 575 /**
576 576 * MAIN EXECUTION
577 577 */
578 578
579 579 var data = getDataAccordingToRanges(initial_ranges);
580 580 generateCheckboxes(data);
581 581
582 582 //main plot
583 583 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
584 584
585 585 //overview
586 586 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
587 587
588 588 //show initial selection on overview
589 589 overview.setSelection(initial_ranges);
590 590
591 591 plot.subscribe("plotselected", plotselected);
592 592
593 593 overview.subscribe("plotselected", function (ranges) {
594 594 plot.setSelection(ranges);
595 595 });
596 596
597 597 plot.subscribe("plothover", plothover);
598 598
599 599 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
600 600 }
601 601 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
602 602 </script>
603 603
604 604 </div>
605 605 </div>
606 606
607 607 <div class="box">
608 608 <div class="title">
609 609 <div class="breadcrumbs">${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
610 610 </div>
611 611 <div class="table">
612 612 <div id="shortlog_data">
613 613 <%include file='../shortlog/shortlog_data.html'/>
614 614 </div>
615 615 ##%if c.repo_changesets:
616 616 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
617 617 ##%endif
618 618 </div>
619 619 </div>
620 620 <div class="box">
621 621 <div class="title">
622 622 <div class="breadcrumbs">${h.link_to(_('Tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
623 623 </div>
624 624 <div class="table">
625 625 <%include file='../tags/tags_data.html'/>
626 626 %if c.repo_changesets:
627 627 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
628 628 %endif
629 629 </div>
630 630 </div>
631 631 <div class="box">
632 632 <div class="title">
633 633 <div class="breadcrumbs">${h.link_to(_('Branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
634 634 </div>
635 635 <div class="table">
636 636 <%include file='../branches/branches_data.html'/>
637 637 %if c.repo_changesets:
638 638 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
639 639 %endif
640 640 </div>
641 641 </div>
642 642
643 643 </%def>
General Comments 0
You need to be logged in to leave comments. Login now