##// END OF EJS Templates
added tooltip into changelog files affected
added tooltip into changelog files affected

File last commit:

r790:0142dac6 beta
r805:26602c8a beta
Show More
helpers.py
512 lines | 17.9 KiB | text/x-python | PythonLexer
renamed project to rhodecode
r547 """Helper functions
Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
implemented user dashboards, and following system.
r734 import random
import hashlib
renamed project to rhodecode
r547 from pygments.formatters import HtmlFormatter
from pygments import highlight as code_highlight
from pylons import url, app_globals as g
from pylons.i18n.translation import _, ungettext
from vcs.utils.annotate import annotate_highlight
from webhelpers.html import literal, HTML, escape
from webhelpers.html.tools import *
from webhelpers.html.builder import make_tag
from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
password, textarea, title, ul, xml_declaration, radio
from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
mail_to, strip_links, strip_tags, tag_re
from webhelpers.number import format_byte_size, format_bit_size
from webhelpers.pylonslib import Flash as _Flash
from webhelpers.pylonslib.secure_form import secure_form
from webhelpers.text import chop_at, collapse, convert_accented_entities, \
convert_misc_entities, lchop, plural, rchop, remove_formatting, \
replace_whitespace, urlify, truncate, wrap_paragraphs
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 from webhelpers.date import time_ago_in_words
renamed project to rhodecode
r547
fixes #65, Added reset buttons to edit forms
r698 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
implemented user dashboards, and following system.
r734
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]
renamed project to rhodecode
r547 #Custom helpers here :)
class _Link(object):
'''
Make a url based on label and url with help of url_for
fixed @repo into :repo for docs...
r604 :param label:name of link if not defined url is used
:param url: the url for link
renamed project to rhodecode
r547 '''
def __call__(self, label='', *url_, **urlargs):
if label is None or '':
label = url
link_fn = link_to(label, url(*url_, **urlargs))
return link_fn
link = _Link()
class _GetError(object):
def __call__(self, field_name, form_errors):
tmpl = """<span class="error_msg">%s</span>"""
if form_errors and form_errors.has_key(field_name):
return literal(tmpl % form_errors.get(field_name))
get_error = _GetError()
def recursive_replace(str, replace=' '):
"""
Recursive replace of given sign to just one instance
fixed @repo into :repo for docs...
r604 :param str: given string
:param replace:char to find and replace multiple instances
renamed project to rhodecode
r547
Examples::
>>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
'Mighty-Mighty-Bo-sstones'
"""
if str.find(replace * 2) == -1:
return str
else:
str = str.replace(replace * 2, replace)
Hacking for git support,and new faster repo scan
r631 return recursive_replace(str, replace)
renamed project to rhodecode
r547
class _ToolTip(object):
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def __call__(self, tooltip_title, trim_at=50):
"""
Special function just to wrap our text into nice formatted autowrapped
text
fixed @repo into :repo for docs...
r604 :param tooltip_title:
renamed project to rhodecode
r547 """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 return wrap_paragraphs(escape(tooltip_title), trim_at)\
.replace('\n', '<br/>')
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def activate(self):
"""
Adds tooltip mechanism to the given Html all tooltips have to have
set class tooltip and set attribute tooltip_title.
Then a tooltip will be generated based on that
All with yui js tooltip
"""
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 js = '''
YAHOO.util.Event.onDOMReady(function(){
function toolTipsId(){
var ids = [];
var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
for (var i = 0; i < tts.length; i++) {
fixed deletion of repository on filesystem, works based on scm type for git and hg....
r668 //if element doesn't not have and id autgenerate one for tooltip
renamed project to rhodecode
r547
if (!tts[i].id){
tts[i].id='tt'+i*100;
}
ids.push(tts[i].id);
}
return ids
};
var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
context: toolTipsId(),
monitorresize:false,
xyoffset :[0,0],
autodismissdelay:300000,
hidedelay:5,
showdelay:20,
});
fixed deletion of repository on filesystem, works based on scm type for git and hg....
r668 //Mouse Over event disabled for new repositories since they don't
renamed project to rhodecode
r547 //have last commit message
myToolTips.contextMouseOverEvent.subscribe(
function(type, args) {
var context = args[0];
var txt = context.getAttribute('tooltip_title');
if(txt){
return true;
}
else{
return false;
}
});
// Set the text for the tooltip just before we display it. Lazy method
myToolTips.contextTriggerEvent.subscribe(
function(type, args) {
var context = args[0];
var txt = context.getAttribute('tooltip_title');
this.cfg.setProperty("text", txt);
// positioning of tooltip
var tt_w = this.element.clientWidth;
var tt_h = this.element.clientHeight;
var context_w = context.offsetWidth;
var context_h = context.offsetHeight;
var pos_x = YAHOO.util.Dom.getX(context);
var pos_y = YAHOO.util.Dom.getY(context);
var display_strategy = 'top';
var xy_pos = [0,0];
switch (display_strategy){
case 'top':
var cur_x = (pos_x+context_w/2)-(tt_w/2);
var cur_y = pos_y-tt_h-4;
xy_pos = [cur_x,cur_y];
break;
case 'bottom':
var cur_x = (pos_x+context_w/2)-(tt_w/2);
var cur_y = pos_y+context_h+4;
xy_pos = [cur_x,cur_y];
break;
case 'left':
var cur_x = (pos_x-tt_w-4);
var cur_y = pos_y-((tt_h/2)-context_h/2);
xy_pos = [cur_x,cur_y];
break;
case 'right':
var cur_x = (pos_x+context_w+4);
var cur_y = pos_y-((tt_h/2)-context_h/2);
xy_pos = [cur_x,cur_y];
break;
default:
var cur_x = (pos_x+context_w/2)-(tt_w/2);
var cur_y = pos_y-tt_h-4;
xy_pos = [cur_x,cur_y];
break;
}
this.cfg.setProperty("xy",xy_pos);
});
//Mouse out
myToolTips.contextMouseOutEvent.subscribe(
function(type, args) {
var context = args[0];
});
});
Hacking for git support,and new faster repo scan
r631 '''
renamed project to rhodecode
r547 return literal(js)
tooltip = _ToolTip()
class _FilesBreadCrumbs(object):
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def __call__(self, repo_name, rev, paths):
url_l = [link_to(repo_name, url('files_home',
repo_name=repo_name,
revision=rev, f_path=''))]
paths_l = paths.split('/')
Hacking for git support,and new faster repo scan
r631
fixed python2.5 incompatible enumerate calls
r740 for cnt, p in enumerate(paths_l):
renamed project to rhodecode
r547 if p != '':
url_l.append(link_to(p, url('files_home',
repo_name=repo_name,
revision=rev,
fixed python2.5 incompatible enumerate calls
r740 f_path='/'.join(paths_l[:cnt + 1]))))
renamed project to rhodecode
r547
return literal('/'.join(url_l))
files_breadcrumbs = _FilesBreadCrumbs()
class CodeHtmlFormatter(HtmlFormatter):
def wrap(self, source, outfile):
return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
def _wrap_code(self, source):
fixed python2.5 incompatible enumerate calls
r740 for cnt, it in enumerate(source):
renamed project to rhodecode
r547 i, t = it
fixed python2.5 incompatible enumerate calls
r740 t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
renamed project to rhodecode
r547 yield i, t
def pygmentize(filenode, **kwargs):
"""
pygmentize function using pygments
fixed @repo into :repo for docs...
r604 :param filenode:
renamed project to rhodecode
r547 """
return literal(code_highlight(filenode.content,
filenode.lexer, CodeHtmlFormatter(**kwargs)))
def pygmentize_annotation(filenode, **kwargs):
"""
pygmentize function for annotation
fixed @repo into :repo for docs...
r604 :param filenode:
renamed project to rhodecode
r547 """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 color_dict = {}
def gen_color():
"""generator for getting 10k of evenly distibuted colors using hsv color
and golden ratio.
Hacking for git support,and new faster repo scan
r631 """
renamed project to rhodecode
r547 import colorsys
n = 10000
golden_ratio = 0.618033988749895
h = 0.22717784590367374
#generate 10k nice web friendly colors in the same order
for c in xrange(n):
h += golden_ratio
h %= 1
HSV_tuple = [h, 0.95, 0.95]
RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
Hacking for git support,and new faster repo scan
r631 yield map(lambda x:str(int(x * 256)), RGB_tuple)
renamed project to rhodecode
r547
cgenerator = gen_color()
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def get_color_string(cs):
if color_dict.has_key(cs):
col = color_dict[cs]
else:
col = color_dict[cs] = cgenerator.next()
return "color: rgb(%s)! important;" % (', '.join(col))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def url_func(changeset):
tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
Hacking for git support,and new faster repo scan
r631 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
renamed project to rhodecode
r547 tooltip_html = tooltip_html % (changeset.author,
changeset.date,
tooltip(changeset.message))
fixed annotation bug, added history to annotation....
r662 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
short_id(changeset.raw_id))
renamed project to rhodecode
r547 uri = link_to(
lnk_format,
url('changeset_home', repo_name=changeset.repository.name,
Fixes for raw_id, needed for git...
r636 revision=changeset.raw_id),
style=get_color_string(changeset.raw_id),
renamed project to rhodecode
r547 class_='tooltip',
tooltip_title=tooltip_html
)
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 uri += '\n'
Hacking for git support,and new faster repo scan
r631 return uri
renamed project to rhodecode
r547 return literal(annotate_highlight(filenode, url_func, **kwargs))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 def repo_name_slug(value):
"""Return slug of name of repository
This function is called on each creation/modification
of repository to prevent bad names in repo
"""
slug = remove_formatting(value)
slug = strip_tags(slug)
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
slug = slug.replace(c, '-')
slug = recursive_replace(slug, '-')
slug = collapse(slug, '-')
return slug
def get_changeset_safe(repo, rev):
from vcs.backends.base import BaseRepository
from vcs.exceptions import RepositoryError
if not isinstance(repo, BaseRepository):
raise Exception('You must pass an Repository '
'object as first argument got %s', type(repo))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 try:
cs = repo.get_changeset(rev)
except RepositoryError:
from rhodecode.lib.utils import EmptyChangeset
cs = EmptyChangeset()
return cs
flash = _Flash()
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 # MERCURIAL FILTERS available via h.
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 from mercurial import util
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 from mercurial.templatefilters import person as _person
def _age(curdate):
"""turns a datetime into an age string."""
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
updated setup for all newest versions...
r643 if not curdate:
return ''
renamed project to rhodecode
r547
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 from datetime import timedelta, datetime
updated setup for all newest versions...
r643
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 agescales = [("year", 3600 * 24 * 365),
fixed a bug when age of last change is less than one minute
r653 ("month", 3600 * 24 * 30),
("day", 3600 * 24),
("hour", 3600),
("minute", 60),
("second", 1), ]
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635
age = datetime.now() - curdate
age_seconds = (age.days * agescales[2][1]) + age.seconds
pos = 1
for scale in agescales:
if scale[1] <= age_seconds:
fixed a bug when age of last change is less than one minute
r653 if pos == 6:pos = 5
fixed deletion of repository on filesystem, works based on scm type for git and hg....
r668 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 pos += 1
fixed deletion of repository on filesystem, works based on scm type for git and hg....
r668 return _('just now')
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 age = lambda x:_age(x)
renamed project to rhodecode
r547 capitalize = lambda x: x.capitalize()
email = util.email
email_or_none = lambda x: util.email(x) if util.email(x) != x else None
person = lambda x: _person(x)
Fixes for raw_id, needed for git...
r636 short_id = lambda x: x[:12]
renamed project to rhodecode
r547
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712 def bool2icon(value):
"""
Returns True/False values represented as small html image of true/false
icons
:param value: bool value
"""
if value is True:
html w3c fixes
r714 return HTML.tag('img', src="/images/icons/accept.png", alt=_('True'))
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712
if value is False:
html w3c fixes
r714 return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False'))
Added ldap info on admin users, added bool2icon helper for nicer representation of...
r712
return value
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660 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 = None
x = action.split(':')
if len(x) > 1:
action, action_params = x
Added fork name to journal...
r718 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:
html_tmpl = '<span title="%s"> %s </span>'
cs_links += html_tmpl % (', '.join(r for r in revs[revs_limit:]),
_('and %s more revisions') \
% (len(revs) - revs_limit))
implemented user dashboards, and following system.
r734
fixed journal helper, little test update,...
r790 return cs_links
Added fork name to journal...
r718 return ''
implemented user dashboards, and following system.
r734
Added fork name to journal...
r718 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 ''
some stylings to journal
r764 map = {'user_deleted_repo':_('User [deleted] repository'),
'user_created_repo':_('User [created] repository'),
fixed journal helper, little test update,...
r790 'user_forked_repo':_('User [forked] repository as: %s') % get_fork_name(),
some stylings to journal
r764 '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'),
fixed journal helper, little test update,...
r790 'push':_('[Pushed] %s') % get_cs_links(),
css update for journal
r788 'pull':_('[Pulled]'),
some stylings to journal
r764 'started_following_repo':_('User [started following] repository'),
'stopped_following_repo':_('User [stopped following] repository'),
added action loggers to following repositories,...
r735 }
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
some stylings to journal
r764 action_str = map.get(action, action)
css update for journal
r788 return literal(action_str.replace('[', '<span class="journal_highlight">').replace(']', '</span>'))
#48 rewrote action logger, translated action logger messages, added some extra messages. Linked and showed pushed revisions in logs
r660
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 # PERMS
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
HasRepoPermissionAny, HasRepoPermissionAll
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 # GRAVATAR URL
Fixed age, for new vcs implementation. Removed all obsolete date formatters...
r635 #==============================================================================
renamed project to rhodecode
r547 import hashlib
import urllib
from pylons import request
def gravatar_url(email_address, size=30):
ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
default = 'identicon'
baseurl_nossl = "http://www.gravatar.com/avatar/"
baseurl_ssl = "https://secure.gravatar.com/avatar/"
baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 # construct the url
gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
return gravatar_url
def safe_unicode(str):
"""safe unicode function. In case of UnicodeDecode error we try to return
unicode with errors replace, if this failes we return unicode with
string_escape decoding """
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 try:
u_str = unicode(str)
except UnicodeDecodeError:
try:
u_str = unicode(str, 'utf-8', 'replace')
except UnicodeDecodeError:
#incase we have a decode error just represent as byte string
u_str = unicode(str(str).encode('string_escape'))
Hacking for git support,and new faster repo scan
r631
renamed project to rhodecode
r547 return u_str