##// END OF EJS Templates
fixed paragraphs wrapping for ultralong commit messages. Disabled tooltips for new repos without a last commit message. ie. when tooltip_title is empty (there is a strange bug on empty tooltip_title)
marcink -
r284:c4caeca9 default
parent child Browse files
Show More
@@ -1,231 +1,238 b''
1 """Helper functions
1 """Helper functions
2
2
3 Consists of functions to typically be used within templates, but also
3 Consists of functions to typically be used within templates, but also
4 available to Controllers. This module is available to both as 'h'.
4 available to Controllers. This module is available to both as 'h'.
5 """
5 """
6 from pygments.formatters import HtmlFormatter
6 from pygments.formatters import HtmlFormatter
7 from pygments import highlight as code_highlight
7 from pygments import highlight as code_highlight
8 from pylons import url, app_globals as g
8 from pylons import url, app_globals as g
9 from pylons.i18n.translation import _, ungettext
9 from pylons.i18n.translation import _, ungettext
10 from vcs.utils.annotate import annotate_highlight
10 from vcs.utils.annotate import annotate_highlight
11 from webhelpers.html import literal, HTML, escape
11 from webhelpers.html import literal, HTML, escape
12 from webhelpers.html.tools import *
12 from webhelpers.html.tools import *
13 from webhelpers.html.builder import make_tag
13 from webhelpers.html.builder import make_tag
14 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
14 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
15 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
15 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
16 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
16 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
17 password, textarea, title, ul, xml_declaration, radio
17 password, textarea, title, ul, xml_declaration, radio
18 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
18 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
19 mail_to, strip_links, strip_tags, tag_re
19 mail_to, strip_links, strip_tags, tag_re
20 from webhelpers.number import format_byte_size, format_bit_size
20 from webhelpers.number import format_byte_size, format_bit_size
21 from webhelpers.pylonslib import Flash as _Flash
21 from webhelpers.pylonslib import Flash as _Flash
22 from webhelpers.pylonslib.secure_form import secure_form
22 from webhelpers.pylonslib.secure_form import secure_form
23 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
23 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
24 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
24 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
25 replace_whitespace, urlify, truncate, wrap_paragraphs
25 replace_whitespace, urlify, truncate, wrap_paragraphs
26
26
27
27
28 #Custom helpers here :)
28 #Custom helpers here :)
29 class _Link(object):
29 class _Link(object):
30 '''
30 '''
31 Make a url based on label and url with help of url_for
31 Make a url based on label and url with help of url_for
32 @param label:name of link if not defined url is used
32 @param label:name of link if not defined url is used
33 @param url: the url for link
33 @param url: the url for link
34 '''
34 '''
35
35
36 def __call__(self, label='', *url_, **urlargs):
36 def __call__(self, label='', *url_, **urlargs):
37 if label is None or '':
37 if label is None or '':
38 label = url
38 label = url
39 link_fn = link_to(label, url(*url_, **urlargs))
39 link_fn = link_to(label, url(*url_, **urlargs))
40 return link_fn
40 return link_fn
41
41
42 link = _Link()
42 link = _Link()
43
43
44 class _GetError(object):
44 class _GetError(object):
45
45
46 def __call__(self, field_name, form_errors):
46 def __call__(self, field_name, form_errors):
47 tmpl = """<span class="error_msg">%s</span>"""
47 tmpl = """<span class="error_msg">%s</span>"""
48 if form_errors and form_errors.has_key(field_name):
48 if form_errors and form_errors.has_key(field_name):
49 return literal(tmpl % form_errors.get(field_name))
49 return literal(tmpl % form_errors.get(field_name))
50
50
51 get_error = _GetError()
51 get_error = _GetError()
52
52
53 def recursive_replace(str, replace=' '):
53 def recursive_replace(str, replace=' '):
54 """
54 """
55 Recursive replace of given sign to just one instance
55 Recursive replace of given sign to just one instance
56 @param str: given string
56 @param str: given string
57 @param replace:char to find and replace multiple instances
57 @param replace:char to find and replace multiple instances
58
58
59 Examples::
59 Examples::
60 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
60 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
61 'Mighty-Mighty-Bo-sstones'
61 'Mighty-Mighty-Bo-sstones'
62 """
62 """
63
63
64 if str.find(replace * 2) == -1:
64 if str.find(replace * 2) == -1:
65 return str
65 return str
66 else:
66 else:
67 str = str.replace(replace * 2, replace)
67 str = str.replace(replace * 2, replace)
68 return recursive_replace(str, replace)
68 return recursive_replace(str, replace)
69
69
70 class _ToolTip(object):
70 class _ToolTip(object):
71
71
72 def __call__(self, tooltip_title, trim_at=50):
72 def __call__(self, tooltip_title, trim_at=50):
73 """
73 """
74 Special function just to wrap our text into nice formatted autowrapped
74 Special function just to wrap our text into nice formatted autowrapped
75 text
75 text
76 @param tooltip_title:
76 @param tooltip_title:
77 """
77 """
78
78
79 return literal(wrap_paragraphs(tooltip_title, trim_at)\
79 return literal(wrap_paragraphs(tooltip_title, trim_at)\
80 .replace('\n', '<br/>'))
80 .replace('\n', '<br/>'))
81
81
82 def activate(self):
82 def activate(self):
83 """
83 """
84 Adds tooltip mechanism to the given Html all tooltips have to have
84 Adds tooltip mechanism to the given Html all tooltips have to have
85 set class tooltip and set attribute tooltip_title.
85 set class tooltip and set attribute tooltip_title.
86 Then a tooltip will be generated based on that
86 Then a tooltip will be generated based on that
87 All with yui js tooltip
87 All with yui js tooltip
88 """
88 """
89
89
90 js = '''
90 js = '''
91 YAHOO.util.Event.onDOMReady(function(){
91 YAHOO.util.Event.onDOMReady(function(){
92 function toolTipsId(){
92 function toolTipsId(){
93 var ids = [];
93 var ids = [];
94 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
94 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
95
95
96 for (var i = 0; i < tts.length; i++) {
96 for (var i = 0; i < tts.length; i++) {
97 //if element doesn not have and id autgenerate one for tooltip
97 //if element doesn not have and id autgenerate one for tooltip
98
98
99 if (!tts[i].id){
99 if (!tts[i].id){
100 tts[i].id='tt'+i*100;
100 tts[i].id='tt'+i*100;
101 }
101 }
102 ids.push(tts[i].id);
102 ids.push(tts[i].id);
103 }
103 }
104 return ids
104 return ids
105 };
105 };
106 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
106 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
107 context: toolTipsId(),
107 context: toolTipsId(),
108 monitorresize:false,
108 monitorresize:false,
109 xyoffset :[0,0],
109 xyoffset :[0,0],
110 autodismissdelay:300000,
110 autodismissdelay:300000,
111 hidedelay:5,
111 hidedelay:5,
112 showdelay:20,
112 showdelay:20,
113 });
113 });
114
114
115 //Mouse subscribe optional arguments
115 //Mouse Over event disabled for new repositories since they dont
116 //have last commit message
116 myToolTips.contextMouseOverEvent.subscribe(
117 myToolTips.contextMouseOverEvent.subscribe(
117 function(type, args) {
118 function(type, args) {
118 var context = args[0];
119 var context = args[0];
119 return true;
120 var txt = context.getAttribute('tooltip_title');
121 if(txt){
122 return true;
123 }
124 else{
125 return false;
126 }
120 });
127 });
121
128
122 // Set the text for the tooltip just before we display it. Lazy method
129 // Set the text for the tooltip just before we display it. Lazy method
123 myToolTips.contextTriggerEvent.subscribe(
130 myToolTips.contextTriggerEvent.subscribe(
124 function(type, args) {
131 function(type, args) {
125 var context = args[0];
132 var context = args[0];
126 var txt = context.getAttribute('tooltip_title');
133 var txt = context.getAttribute('tooltip_title');
127 this.cfg.setProperty("text", txt);
134 this.cfg.setProperty("text", txt);
128 });
135 });
129 });
136 });
130 '''
137 '''
131 return literal(js)
138 return literal(js)
132
139
133 tooltip = _ToolTip()
140 tooltip = _ToolTip()
134
141
135 class _FilesBreadCrumbs(object):
142 class _FilesBreadCrumbs(object):
136
143
137 def __call__(self, repo_name, rev, paths):
144 def __call__(self, repo_name, rev, paths):
138 url_l = [link_to(repo_name, url('files_home', repo_name=repo_name, revision=rev, f_path=''))]
145 url_l = [link_to(repo_name, url('files_home', repo_name=repo_name, revision=rev, f_path=''))]
139 paths_l = paths.split(' / ')
146 paths_l = paths.split(' / ')
140
147
141 for cnt, p in enumerate(paths_l, 1):
148 for cnt, p in enumerate(paths_l, 1):
142 if p != '':
149 if p != '':
143 url_l.append(link_to(p, url('files_home', repo_name=repo_name, revision=rev, f_path=' / '.join(paths_l[:cnt]))))
150 url_l.append(link_to(p, url('files_home', repo_name=repo_name, revision=rev, f_path=' / '.join(paths_l[:cnt]))))
144
151
145 return literal(' / '.join(url_l))
152 return literal(' / '.join(url_l))
146
153
147 files_breadcrumbs = _FilesBreadCrumbs()
154 files_breadcrumbs = _FilesBreadCrumbs()
148
155
149 def pygmentize(filenode, **kwargs):
156 def pygmentize(filenode, **kwargs):
150 """
157 """
151 pygmentize function using pygments
158 pygmentize function using pygments
152 @param filenode:
159 @param filenode:
153 """
160 """
154 return literal(code_highlight(filenode.content, filenode.lexer, HtmlFormatter(**kwargs)))
161 return literal(code_highlight(filenode.content, filenode.lexer, HtmlFormatter(**kwargs)))
155
162
156 def pygmentize_annotation(filenode, **kwargs):
163 def pygmentize_annotation(filenode, **kwargs):
157 """
164 """
158 pygmentize function for annotation
165 pygmentize function for annotation
159 @param filenode:
166 @param filenode:
160 """
167 """
161
168
162 color_dict = g.changeset_annotation_colors
169 color_dict = g.changeset_annotation_colors
163 def gen_color():
170 def gen_color():
164 import random
171 import random
165 return [str(random.randrange(10, 235)) for _ in xrange(3)]
172 return [str(random.randrange(10, 235)) for _ in xrange(3)]
166 def get_color_string(cs):
173 def get_color_string(cs):
167 if color_dict.has_key(cs):
174 if color_dict.has_key(cs):
168 col = color_dict[cs]
175 col = color_dict[cs]
169 else:
176 else:
170 color_dict[cs] = gen_color()
177 color_dict[cs] = gen_color()
171 col = color_dict[cs]
178 col = color_dict[cs]
172 return "color: rgb(%s) ! important;" % (', '.join(col))
179 return "color: rgb(%s) ! important;" % (', '.join(col))
173
180
174 def url_func(changeset):
181 def url_func(changeset):
175 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b> %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
182 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b> %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
176
183
177 tooltip_html = tooltip_html % (changeset.author,
184 tooltip_html = tooltip_html % (changeset.author,
178 changeset.date,
185 changeset.date,
179 tooltip(changeset.message))
186 tooltip(changeset.message))
180 lnk_format = 'r%s:%s' % (changeset.revision,
187 lnk_format = 'r%s:%s' % (changeset.revision,
181 changeset.raw_id)
188 changeset.raw_id)
182 uri = link_to(
189 uri = link_to(
183 lnk_format,
190 lnk_format,
184 url('changeset_home', repo_name='test',
191 url('changeset_home', repo_name='test',
185 revision=changeset.raw_id),
192 revision=changeset.raw_id),
186 style=get_color_string(changeset.raw_id),
193 style=get_color_string(changeset.raw_id),
187 class_='tooltip',
194 class_='tooltip',
188 tooltip_title=tooltip_html
195 tooltip_title=tooltip_html
189 )
196 )
190
197
191 uri += '\n'
198 uri += '\n'
192 return uri
199 return uri
193 return literal(annotate_highlight(filenode, url_func, **kwargs))
200 return literal(annotate_highlight(filenode, url_func, **kwargs))
194
201
195 def repo_name_slug(value):
202 def repo_name_slug(value):
196 """
203 """
197 Return slug of name of repository
204 Return slug of name of repository
198 """
205 """
199 slug = urlify(value)
206 slug = urlify(value)
200 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|:""":
207 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|:""":
201 slug = slug.replace(c, '-')
208 slug = slug.replace(c, '-')
202 slug = recursive_replace(slug, '-')
209 slug = recursive_replace(slug, '-')
203 return slug
210 return slug
204
211
205 flash = _Flash()
212 flash = _Flash()
206
213
207
214
208 #===============================================================================
215 #===============================================================================
209 # MERCURIAL FILTERS available via h.
216 # MERCURIAL FILTERS available via h.
210 #===============================================================================
217 #===============================================================================
211
218
212
219
213 from mercurial import util
220 from mercurial import util
214 from mercurial.templatefilters import age as _age, person as _person
221 from mercurial.templatefilters import age as _age, person as _person
215
222
216 age = lambda x:_age(x)
223 age = lambda x:_age(x)
217 capitalize = lambda x: x.capitalize()
224 capitalize = lambda x: x.capitalize()
218 date = lambda x: util.datestr(x)
225 date = lambda x: util.datestr(x)
219 email = util.email
226 email = util.email
220 person = lambda x: _person(x)
227 person = lambda x: _person(x)
221 hgdate = lambda x: "%d %d" % x
228 hgdate = lambda x: "%d %d" % x
222 isodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2')
229 isodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2')
223 isodatesec = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2')
230 isodatesec = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2')
224 localdate = lambda x: (x[0], util.makedate()[1])
231 localdate = lambda x: (x[0], util.makedate()[1])
225 rfc822date = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2")
232 rfc822date = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2")
226 rfc3339date = lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2")
233 rfc3339date = lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2")
227 time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2")
234 time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2")
228
235
229
236
230
237
231
238
@@ -1,96 +1,95 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${_('Changelog - %s') % c.repo_name}
4 ${_('Changelog - %s') % c.repo_name}
5 </%def>
5 </%def>
6 <%def name="breadcrumbs()">
6 <%def name="breadcrumbs()">
7 ${h.link_to(u'Home',h.url('/'))}
7 ${h.link_to(u'Home',h.url('/'))}
8 /
8 /
9 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
9 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
10 /
10 /
11 ${_('changelog')}
11 ${_('changelog')}
12 </%def>
12 </%def>
13 <%def name="page_nav()">
13 <%def name="page_nav()">
14 ${self.menu('changelog')}
14 ${self.menu('changelog')}
15 </%def>
15 </%def>
16
16
17 <%def name="main()">
17 <%def name="main()">
18
18
19 <h2 class="no-link no-border">${_('Changelog')} - ${_('showing ')}
19 <h2 class="no-link no-border">${_('Changelog')} - ${_('showing ')}
20 ${c.size if c.size <= c.total_cs else c.total_cs}
20 ${c.size if c.size <= c.total_cs else c.total_cs}
21 ${_('out of')} ${c.total_cs} ${_('revisions')}
21 ${_('out of')} ${c.total_cs} ${_('revisions')}
22 </h2>
22 </h2>
23 <noscript>${_('The revision graph only works with JavaScript-enabled browsers.')}</noscript>
23 <noscript>${_('The revision graph only works with JavaScript-enabled browsers.')}</noscript>
24 % if c.pagination:
24 % if c.pagination:
25
25
26 <div id="graph">
26 <div id="graph">
27 ##<div id="graph_nodes" style="height:1000px">
27 ##<div id="graph_nodes" style="height:1000px">
28 ## <canvas id="graph" width="160"></canvas>
28 ## <canvas id="graph" width="160"></canvas>
29 ##</div>
29 ##</div>
30 <div id="graph_content">
30 <div id="graph_content">
31 <div class="container_header">
31 <div class="container_header">
32 ${h.form(h.url.current(),method='get')}
32 ${h.form(h.url.current(),method='get')}
33 ${_('Show')}: ${h.text('size',size=2,value=c.size)} ${_('revisions')}
33 ${_('Show')}: ${h.text('size',size=2,value=c.size)} ${_('revisions')}
34 ${h.submit('','set')}
34 ${h.submit('','set')}
35 ${h.end_form()}
35 ${h.end_form()}
36 </div>
36 </div>
37 %for cnt,cs in enumerate(c.pagination):
37 %for cnt,cs in enumerate(c.pagination):
38 <div class="container">
38 <div class="container">
39 <div class="left">
39 <div class="left">
40 <div class="date">${_('commit')} ${cs.revision}: ${cs.raw_id}@${cs.date}</div>
40 <div class="date">${_('commit')} ${cs.revision}: ${cs.raw_id}@${cs.date}</div>
41 <div class="author">${cs.author}</div>
41 <div class="author">${cs.author}</div>
42 <div id="chg_${cnt}" class="message">
42 <div id="chg_${cnt}" class="message">
43 ${h.link_to(cs.message,
43 ${h.link_to(h.wrap_paragraphs(cs.message),
44 h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
44 h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
45 title=cs.message)}
46 </div>
45 </div>
47 <span class="logtags">
46 <span class="logtags">
48 <span class="branchtag">${cs.branch}</span>
47 <span class="branchtag">${cs.branch}</span>
49 %for tag in cs.tags:
48 %for tag in cs.tags:
50 <span class="tagtag">${tag}</span>
49 <span class="tagtag">${tag}</span>
51 %endfor
50 %endfor
52 </span>
51 </span>
53 </div>
52 </div>
54 <div class="right">
53 <div class="right">
55 <div class="changes">
54 <div class="changes">
56 <span class="removed" title="${_('removed')}">${len(cs.removed)}</span>
55 <span class="removed" title="${_('removed')}">${len(cs.removed)}</span>
57 <span class="changed" title="${_('changed')}">${len(cs.changed)}</span>
56 <span class="changed" title="${_('changed')}">${len(cs.changed)}</span>
58 <span class="added" title="${_('added')}">${len(cs.added)}</span>
57 <span class="added" title="${_('added')}">${len(cs.added)}</span>
59 </div>
58 </div>
60 %if len(cs.parents)>1:
59 %if len(cs.parents)>1:
61 <div class="merge">
60 <div class="merge">
62 ${_('merge')}<img alt="merge" src="/images/icons/arrow_join.png">
61 ${_('merge')}<img alt="merge" src="/images/icons/arrow_join.png">
63 </div>
62 </div>
64 %endif
63 %endif
65 %for p_cs in reversed(cs.parents):
64 %for p_cs in reversed(cs.parents):
66 <div class="parent">${_('Parent')} ${p_cs.revision}: ${h.link_to(p_cs.raw_id,
65 <div class="parent">${_('Parent')} ${p_cs.revision}: ${h.link_to(p_cs.raw_id,
67 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}
66 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}
68 </div>
67 </div>
69 %endfor
68 %endfor
70 </div>
69 </div>
71 </div>
70 </div>
72
71
73 %endfor
72 %endfor
74 </div>
73 </div>
75 </div>
74 </div>
76
75
77 ##<script type="text/javascript" src="/js/graph2.js"></script>
76 ##<script type="text/javascript" src="/js/graph2.js"></script>
78 ##<script type="text/javascript" src="http://bitbucket-assets.s3.amazonaws.com/js/lib/bundle.160310Mar.js"></script>
77 ##<script type="text/javascript" src="http://bitbucket-assets.s3.amazonaws.com/js/lib/bundle.160310Mar.js"></script>
79 ##
78 ##
80 ##<script>
79 ##<script>
81 ##<!-- hide script content
80 ##<!-- hide script content
82 ##
81 ##
83 ##var jsdata = ${c.jsdata|n};
82 ##var jsdata = ${c.jsdata|n};
84 ##var r = new BranchRenderer();
83 ##var r = new BranchRenderer();
85 ##r.render(jsdata);
84 ##r.render(jsdata);
86
85
87 ##// stop hiding script -->
86 ##// stop hiding script -->
88 ##</script>
87 ##</script>
89
88
90 <div>
89 <div>
91 <h2>${c.pagination.pager('$link_previous ~2~ $link_next')}</h2>
90 <h2>${c.pagination.pager('$link_previous ~2~ $link_next')}</h2>
92 </div>
91 </div>
93 %else:
92 %else:
94 ${_('There are no changes yet')}
93 ${_('There are no changes yet')}
95 %endif
94 %endif
96 </%def> No newline at end of file
95 </%def>
General Comments 0
You need to be logged in to leave comments. Login now