diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -3,6 +3,8 @@ Consists of functions to typically be used within templates, but also available to Controllers. This module is available to both as 'h'. """ +import random +import hashlib from pygments.formatters import HtmlFormatter from pygments import highlight as code_highlight from pylons import url, app_globals as g @@ -23,6 +25,36 @@ from webhelpers.pylonslib.secure_form im from webhelpers.text import chop_at, collapse, convert_accented_entities, \ convert_misc_entities, lchop, plural, rchop, remove_formatting, \ replace_whitespace, urlify, truncate, wrap_paragraphs +from webhelpers.date import time_ago_in_words + +from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \ + convert_boolean_attrs, NotGiven + +def _reset(name, value=None, id=NotGiven, type="reset", **attrs): + _set_input_attrs(attrs, type, name, value) + _set_id_attr(attrs, id, name) + convert_boolean_attrs(attrs, ["disabled"]) + return HTML.input(**attrs) + +reset = _reset + + +def get_token(): + """Return the current authentication token, creating one if one doesn't + already exist. + """ + token_key = "_authentication_token" + from pylons import session + if not token_key in session: + try: + token = hashlib.sha1(str(random.getrandbits(128))).hexdigest() + except AttributeError: # Python < 2.4 + token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest() + session[token_key] = token + if hasattr(session, 'save'): + session.save() + return session[token_key] + #Custom helpers here :) class _Link(object): @@ -93,7 +125,7 @@ class _ToolTip(object): var tts = YAHOO.util.Dom.getElementsByClassName('tooltip'); for (var i = 0; i < tts.length; i++) { - //if element doesn not have and id autgenerate one for tooltip + //if element doesn't not have and id autgenerate one for tooltip if (!tts[i].id){ tts[i].id='tt'+i*100; @@ -111,7 +143,7 @@ class _ToolTip(object): showdelay:20, }); - //Mouse Over event disabled for new repositories since they dont + //Mouse Over event disabled for new repositories since they don't //have last commit message myToolTips.contextMouseOverEvent.subscribe( function(type, args) { @@ -270,13 +302,13 @@ def pygmentize_annotation(filenode, **kw tooltip_html = tooltip_html % (changeset.author, changeset.date, tooltip(changeset.message)) - lnk_format = 'r%-5s:%s' % (changeset.revision, - changeset.short_id) + lnk_format = '%5s:%s' % ('r%s' % changeset.revision, + short_id(changeset.raw_id)) uri = link_to( lnk_format, url('changeset_home', repo_name=changeset.repository.name, - revision=changeset.short_id), - style=get_color_string(changeset.short_id), + revision=changeset.raw_id), + style=get_color_string(changeset.raw_id), class_='tooltip', tooltip_title=tooltip_html ) @@ -317,37 +349,168 @@ def get_changeset_safe(repo, rev): flash = _Flash() -#=============================================================================== +#============================================================================== # MERCURIAL FILTERS available via h. -#=============================================================================== +#============================================================================== from mercurial import util -from mercurial.templatefilters import age as _age, person as _person +from mercurial.templatefilters import person as _person + + + +def _age(curdate): + """turns a datetime into an age string.""" + + if not curdate: + return '' + + from datetime import timedelta, datetime + + agescales = [("year", 3600 * 24 * 365), + ("month", 3600 * 24 * 30), + ("day", 3600 * 24), + ("hour", 3600), + ("minute", 60), + ("second", 1), ] + + age = datetime.now() - curdate + age_seconds = (age.days * agescales[2][1]) + age.seconds + pos = 1 + for scale in agescales: + if scale[1] <= age_seconds: + if pos == 6:pos = 5 + return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago') + pos += 1 + + return _('just now') age = lambda x:_age(x) capitalize = lambda x: x.capitalize() -date = lambda x: util.datestr(x) email = util.email email_or_none = lambda x: util.email(x) if util.email(x) != x else None person = lambda x: _person(x) -hgdate = lambda x: "%d %d" % x -isodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2') -isodatesec = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2') -localdate = lambda x: (x[0], util.makedate()[1]) -rfc822date = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2") -rfc822date_notz = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S") -rfc3339date = lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2") -time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2") +short_id = lambda x: x[:12] + + +def bool2icon(value): + """ + Returns True/False values represented as small html image of true/false + icons + :param value: bool value + """ + + if value is True: + return HTML.tag('img', src="/images/icons/accept.png", alt=_('True')) + + if value is False: + return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False')) + + return value -#=============================================================================== +def action_parser(user_log): + """ + This helper will map the specified string action into translated + fancy names with icons and links + + @param action: + """ + action = user_log.action + action_params = ' ' + + x = action.split(':') + + if len(x) > 1: + action, action_params = x + + def get_cs_links(): + if action == 'push': + revs_limit = 5 + revs = action_params.split(',') + cs_links = " " + ', '.join ([link(rev, + url('changeset_home', + repo_name=user_log.repository.repo_name, + revision=rev)) for rev in revs[:revs_limit] ]) + if len(revs) > revs_limit: + uniq_id = revs[0] + html_tmpl = (' %s ' + '%s ' + '%s') + cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \ + % (len(revs) - revs_limit), + _('revisions')) + + html_tmpl = '' + cs_links += html_tmpl % (uniq_id, ', '.join([link(rev, + url('changeset_home', + repo_name=user_log.repository.repo_name, + revision=rev)) for rev in revs[:revs_limit] ])) + + return cs_links + return '' + + def get_fork_name(): + if action == 'user_forked_repo': + from rhodecode.model.scm import ScmModel + repo_name = action_params + repo = ScmModel().get(repo_name) + if repo is None: + return repo_name + return link_to(action_params, url('summary_home', + repo_name=repo.name,), + title=repo.dbrepo.description) + return '' + map = {'user_deleted_repo':_('User [deleted] repository'), + 'user_created_repo':_('User [created] repository'), + 'user_forked_repo':_('User [forked] repository as: %s') % get_fork_name(), + 'user_updated_repo':_('User [updated] repository'), + 'admin_deleted_repo':_('Admin [delete] repository'), + 'admin_created_repo':_('Admin [created] repository'), + 'admin_forked_repo':_('Admin [forked] repository'), + 'admin_updated_repo':_('Admin [updated] repository'), + 'push':_('[Pushed] %s') % get_cs_links(), + 'pull':_('[Pulled]'), + 'started_following_repo':_('User [started following] repository'), + 'stopped_following_repo':_('User [stopped following] repository'), + } + + action_str = map.get(action, action) + return literal(action_str.replace('[', '')\ + .replace(']', '')) + +def action_parser_icon(user_log): + action = user_log.action + action_params = None + x = action.split(':') + + if len(x) > 1: + action, action_params = x + + tmpl = """%s""" + map = {'user_deleted_repo':'database_delete.png', + 'user_created_repo':'database_add.png', + 'user_forked_repo':'arrow_divide.png', + 'user_updated_repo':'database_edit.png', + 'admin_deleted_repo':'database_delete.png', + 'admin_created_repo':'database_ddd.png', + 'admin_forked_repo':'arrow_divide.png', + 'admin_updated_repo':'database_edit.png', + 'push':'script_add.png', + 'pull':'down_16.png', + 'started_following_repo':'heart_add.png', + 'stopped_following_repo':'heart_delete.png', + } + return literal(tmpl % (map.get(action, action), action)) + + +#============================================================================== # PERMS -#=============================================================================== +#============================================================================== from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \ HasRepoPermissionAny, HasRepoPermissionAll -#=============================================================================== +#============================================================================== # GRAVATAR URL -#=============================================================================== +#============================================================================== import hashlib import urllib from pylons import request