##// END OF EJS Templates
fixes #65, Added reset buttons to edit forms
marcink -
r698:4cd0709b beta
parent child Browse files
Show More
@@ -1,447 +1,458 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 from webhelpers.date import time_ago_in_words
26 from webhelpers.date import time_ago_in_words
27
27
28 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
29 convert_boolean_attrs, NotGiven
30
31 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
32 _set_input_attrs(attrs, type, name, value)
33 _set_id_attr(attrs, id, name)
34 convert_boolean_attrs(attrs, ["disabled"])
35 return HTML.input(**attrs)
36
37 reset = _reset
38
28 #Custom helpers here :)
39 #Custom helpers here :)
29 class _Link(object):
40 class _Link(object):
30 '''
41 '''
31 Make a url based on label and url with help of url_for
42 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
43 :param label:name of link if not defined url is used
33 :param url: the url for link
44 :param url: the url for link
34 '''
45 '''
35
46
36 def __call__(self, label='', *url_, **urlargs):
47 def __call__(self, label='', *url_, **urlargs):
37 if label is None or '':
48 if label is None or '':
38 label = url
49 label = url
39 link_fn = link_to(label, url(*url_, **urlargs))
50 link_fn = link_to(label, url(*url_, **urlargs))
40 return link_fn
51 return link_fn
41
52
42 link = _Link()
53 link = _Link()
43
54
44 class _GetError(object):
55 class _GetError(object):
45
56
46 def __call__(self, field_name, form_errors):
57 def __call__(self, field_name, form_errors):
47 tmpl = """<span class="error_msg">%s</span>"""
58 tmpl = """<span class="error_msg">%s</span>"""
48 if form_errors and form_errors.has_key(field_name):
59 if form_errors and form_errors.has_key(field_name):
49 return literal(tmpl % form_errors.get(field_name))
60 return literal(tmpl % form_errors.get(field_name))
50
61
51 get_error = _GetError()
62 get_error = _GetError()
52
63
53 def recursive_replace(str, replace=' '):
64 def recursive_replace(str, replace=' '):
54 """
65 """
55 Recursive replace of given sign to just one instance
66 Recursive replace of given sign to just one instance
56 :param str: given string
67 :param str: given string
57 :param replace:char to find and replace multiple instances
68 :param replace:char to find and replace multiple instances
58
69
59 Examples::
70 Examples::
60 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
71 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
61 'Mighty-Mighty-Bo-sstones'
72 'Mighty-Mighty-Bo-sstones'
62 """
73 """
63
74
64 if str.find(replace * 2) == -1:
75 if str.find(replace * 2) == -1:
65 return str
76 return str
66 else:
77 else:
67 str = str.replace(replace * 2, replace)
78 str = str.replace(replace * 2, replace)
68 return recursive_replace(str, replace)
79 return recursive_replace(str, replace)
69
80
70 class _ToolTip(object):
81 class _ToolTip(object):
71
82
72 def __call__(self, tooltip_title, trim_at=50):
83 def __call__(self, tooltip_title, trim_at=50):
73 """
84 """
74 Special function just to wrap our text into nice formatted autowrapped
85 Special function just to wrap our text into nice formatted autowrapped
75 text
86 text
76 :param tooltip_title:
87 :param tooltip_title:
77 """
88 """
78
89
79 return wrap_paragraphs(escape(tooltip_title), trim_at)\
90 return wrap_paragraphs(escape(tooltip_title), trim_at)\
80 .replace('\n', '<br/>')
91 .replace('\n', '<br/>')
81
92
82 def activate(self):
93 def activate(self):
83 """
94 """
84 Adds tooltip mechanism to the given Html all tooltips have to have
95 Adds tooltip mechanism to the given Html all tooltips have to have
85 set class tooltip and set attribute tooltip_title.
96 set class tooltip and set attribute tooltip_title.
86 Then a tooltip will be generated based on that
97 Then a tooltip will be generated based on that
87 All with yui js tooltip
98 All with yui js tooltip
88 """
99 """
89
100
90 js = '''
101 js = '''
91 YAHOO.util.Event.onDOMReady(function(){
102 YAHOO.util.Event.onDOMReady(function(){
92 function toolTipsId(){
103 function toolTipsId(){
93 var ids = [];
104 var ids = [];
94 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
105 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
95
106
96 for (var i = 0; i < tts.length; i++) {
107 for (var i = 0; i < tts.length; i++) {
97 //if element doesn't not have and id autgenerate one for tooltip
108 //if element doesn't not have and id autgenerate one for tooltip
98
109
99 if (!tts[i].id){
110 if (!tts[i].id){
100 tts[i].id='tt'+i*100;
111 tts[i].id='tt'+i*100;
101 }
112 }
102 ids.push(tts[i].id);
113 ids.push(tts[i].id);
103 }
114 }
104 return ids
115 return ids
105 };
116 };
106 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
117 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
107 context: toolTipsId(),
118 context: toolTipsId(),
108 monitorresize:false,
119 monitorresize:false,
109 xyoffset :[0,0],
120 xyoffset :[0,0],
110 autodismissdelay:300000,
121 autodismissdelay:300000,
111 hidedelay:5,
122 hidedelay:5,
112 showdelay:20,
123 showdelay:20,
113 });
124 });
114
125
115 //Mouse Over event disabled for new repositories since they don't
126 //Mouse Over event disabled for new repositories since they don't
116 //have last commit message
127 //have last commit message
117 myToolTips.contextMouseOverEvent.subscribe(
128 myToolTips.contextMouseOverEvent.subscribe(
118 function(type, args) {
129 function(type, args) {
119 var context = args[0];
130 var context = args[0];
120 var txt = context.getAttribute('tooltip_title');
131 var txt = context.getAttribute('tooltip_title');
121 if(txt){
132 if(txt){
122 return true;
133 return true;
123 }
134 }
124 else{
135 else{
125 return false;
136 return false;
126 }
137 }
127 });
138 });
128
139
129
140
130 // Set the text for the tooltip just before we display it. Lazy method
141 // Set the text for the tooltip just before we display it. Lazy method
131 myToolTips.contextTriggerEvent.subscribe(
142 myToolTips.contextTriggerEvent.subscribe(
132 function(type, args) {
143 function(type, args) {
133
144
134
145
135 var context = args[0];
146 var context = args[0];
136
147
137 var txt = context.getAttribute('tooltip_title');
148 var txt = context.getAttribute('tooltip_title');
138 this.cfg.setProperty("text", txt);
149 this.cfg.setProperty("text", txt);
139
150
140
151
141 // positioning of tooltip
152 // positioning of tooltip
142 var tt_w = this.element.clientWidth;
153 var tt_w = this.element.clientWidth;
143 var tt_h = this.element.clientHeight;
154 var tt_h = this.element.clientHeight;
144
155
145 var context_w = context.offsetWidth;
156 var context_w = context.offsetWidth;
146 var context_h = context.offsetHeight;
157 var context_h = context.offsetHeight;
147
158
148 var pos_x = YAHOO.util.Dom.getX(context);
159 var pos_x = YAHOO.util.Dom.getX(context);
149 var pos_y = YAHOO.util.Dom.getY(context);
160 var pos_y = YAHOO.util.Dom.getY(context);
150
161
151 var display_strategy = 'top';
162 var display_strategy = 'top';
152 var xy_pos = [0,0];
163 var xy_pos = [0,0];
153 switch (display_strategy){
164 switch (display_strategy){
154
165
155 case 'top':
166 case 'top':
156 var cur_x = (pos_x+context_w/2)-(tt_w/2);
167 var cur_x = (pos_x+context_w/2)-(tt_w/2);
157 var cur_y = pos_y-tt_h-4;
168 var cur_y = pos_y-tt_h-4;
158 xy_pos = [cur_x,cur_y];
169 xy_pos = [cur_x,cur_y];
159 break;
170 break;
160 case 'bottom':
171 case 'bottom':
161 var cur_x = (pos_x+context_w/2)-(tt_w/2);
172 var cur_x = (pos_x+context_w/2)-(tt_w/2);
162 var cur_y = pos_y+context_h+4;
173 var cur_y = pos_y+context_h+4;
163 xy_pos = [cur_x,cur_y];
174 xy_pos = [cur_x,cur_y];
164 break;
175 break;
165 case 'left':
176 case 'left':
166 var cur_x = (pos_x-tt_w-4);
177 var cur_x = (pos_x-tt_w-4);
167 var cur_y = pos_y-((tt_h/2)-context_h/2);
178 var cur_y = pos_y-((tt_h/2)-context_h/2);
168 xy_pos = [cur_x,cur_y];
179 xy_pos = [cur_x,cur_y];
169 break;
180 break;
170 case 'right':
181 case 'right':
171 var cur_x = (pos_x+context_w+4);
182 var cur_x = (pos_x+context_w+4);
172 var cur_y = pos_y-((tt_h/2)-context_h/2);
183 var cur_y = pos_y-((tt_h/2)-context_h/2);
173 xy_pos = [cur_x,cur_y];
184 xy_pos = [cur_x,cur_y];
174 break;
185 break;
175 default:
186 default:
176 var cur_x = (pos_x+context_w/2)-(tt_w/2);
187 var cur_x = (pos_x+context_w/2)-(tt_w/2);
177 var cur_y = pos_y-tt_h-4;
188 var cur_y = pos_y-tt_h-4;
178 xy_pos = [cur_x,cur_y];
189 xy_pos = [cur_x,cur_y];
179 break;
190 break;
180
191
181 }
192 }
182
193
183 this.cfg.setProperty("xy",xy_pos);
194 this.cfg.setProperty("xy",xy_pos);
184
195
185 });
196 });
186
197
187 //Mouse out
198 //Mouse out
188 myToolTips.contextMouseOutEvent.subscribe(
199 myToolTips.contextMouseOutEvent.subscribe(
189 function(type, args) {
200 function(type, args) {
190 var context = args[0];
201 var context = args[0];
191
202
192 });
203 });
193 });
204 });
194 '''
205 '''
195 return literal(js)
206 return literal(js)
196
207
197 tooltip = _ToolTip()
208 tooltip = _ToolTip()
198
209
199 class _FilesBreadCrumbs(object):
210 class _FilesBreadCrumbs(object):
200
211
201 def __call__(self, repo_name, rev, paths):
212 def __call__(self, repo_name, rev, paths):
202 url_l = [link_to(repo_name, url('files_home',
213 url_l = [link_to(repo_name, url('files_home',
203 repo_name=repo_name,
214 repo_name=repo_name,
204 revision=rev, f_path=''))]
215 revision=rev, f_path=''))]
205 paths_l = paths.split('/')
216 paths_l = paths.split('/')
206
217
207 for cnt, p in enumerate(paths_l, 1):
218 for cnt, p in enumerate(paths_l, 1):
208 if p != '':
219 if p != '':
209 url_l.append(link_to(p, url('files_home',
220 url_l.append(link_to(p, url('files_home',
210 repo_name=repo_name,
221 repo_name=repo_name,
211 revision=rev,
222 revision=rev,
212 f_path='/'.join(paths_l[:cnt]))))
223 f_path='/'.join(paths_l[:cnt]))))
213
224
214 return literal('/'.join(url_l))
225 return literal('/'.join(url_l))
215
226
216 files_breadcrumbs = _FilesBreadCrumbs()
227 files_breadcrumbs = _FilesBreadCrumbs()
217 class CodeHtmlFormatter(HtmlFormatter):
228 class CodeHtmlFormatter(HtmlFormatter):
218
229
219 def wrap(self, source, outfile):
230 def wrap(self, source, outfile):
220 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
231 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
221
232
222 def _wrap_code(self, source):
233 def _wrap_code(self, source):
223 for cnt, it in enumerate(source, 1):
234 for cnt, it in enumerate(source, 1):
224 i, t = it
235 i, t = it
225 t = '<div id="#S-%s">%s</div>' % (cnt, t)
236 t = '<div id="#S-%s">%s</div>' % (cnt, t)
226 yield i, t
237 yield i, t
227 def pygmentize(filenode, **kwargs):
238 def pygmentize(filenode, **kwargs):
228 """
239 """
229 pygmentize function using pygments
240 pygmentize function using pygments
230 :param filenode:
241 :param filenode:
231 """
242 """
232 return literal(code_highlight(filenode.content,
243 return literal(code_highlight(filenode.content,
233 filenode.lexer, CodeHtmlFormatter(**kwargs)))
244 filenode.lexer, CodeHtmlFormatter(**kwargs)))
234
245
235 def pygmentize_annotation(filenode, **kwargs):
246 def pygmentize_annotation(filenode, **kwargs):
236 """
247 """
237 pygmentize function for annotation
248 pygmentize function for annotation
238 :param filenode:
249 :param filenode:
239 """
250 """
240
251
241 color_dict = {}
252 color_dict = {}
242 def gen_color():
253 def gen_color():
243 """generator for getting 10k of evenly distibuted colors using hsv color
254 """generator for getting 10k of evenly distibuted colors using hsv color
244 and golden ratio.
255 and golden ratio.
245 """
256 """
246 import colorsys
257 import colorsys
247 n = 10000
258 n = 10000
248 golden_ratio = 0.618033988749895
259 golden_ratio = 0.618033988749895
249 h = 0.22717784590367374
260 h = 0.22717784590367374
250 #generate 10k nice web friendly colors in the same order
261 #generate 10k nice web friendly colors in the same order
251 for c in xrange(n):
262 for c in xrange(n):
252 h += golden_ratio
263 h += golden_ratio
253 h %= 1
264 h %= 1
254 HSV_tuple = [h, 0.95, 0.95]
265 HSV_tuple = [h, 0.95, 0.95]
255 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
266 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
256 yield map(lambda x:str(int(x * 256)), RGB_tuple)
267 yield map(lambda x:str(int(x * 256)), RGB_tuple)
257
268
258 cgenerator = gen_color()
269 cgenerator = gen_color()
259
270
260 def get_color_string(cs):
271 def get_color_string(cs):
261 if color_dict.has_key(cs):
272 if color_dict.has_key(cs):
262 col = color_dict[cs]
273 col = color_dict[cs]
263 else:
274 else:
264 col = color_dict[cs] = cgenerator.next()
275 col = color_dict[cs] = cgenerator.next()
265 return "color: rgb(%s)! important;" % (', '.join(col))
276 return "color: rgb(%s)! important;" % (', '.join(col))
266
277
267 def url_func(changeset):
278 def url_func(changeset):
268 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
279 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
269 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
280 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
270
281
271 tooltip_html = tooltip_html % (changeset.author,
282 tooltip_html = tooltip_html % (changeset.author,
272 changeset.date,
283 changeset.date,
273 tooltip(changeset.message))
284 tooltip(changeset.message))
274 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
285 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
275 short_id(changeset.raw_id))
286 short_id(changeset.raw_id))
276 uri = link_to(
287 uri = link_to(
277 lnk_format,
288 lnk_format,
278 url('changeset_home', repo_name=changeset.repository.name,
289 url('changeset_home', repo_name=changeset.repository.name,
279 revision=changeset.raw_id),
290 revision=changeset.raw_id),
280 style=get_color_string(changeset.raw_id),
291 style=get_color_string(changeset.raw_id),
281 class_='tooltip',
292 class_='tooltip',
282 tooltip_title=tooltip_html
293 tooltip_title=tooltip_html
283 )
294 )
284
295
285 uri += '\n'
296 uri += '\n'
286 return uri
297 return uri
287 return literal(annotate_highlight(filenode, url_func, **kwargs))
298 return literal(annotate_highlight(filenode, url_func, **kwargs))
288
299
289 def repo_name_slug(value):
300 def repo_name_slug(value):
290 """Return slug of name of repository
301 """Return slug of name of repository
291 This function is called on each creation/modification
302 This function is called on each creation/modification
292 of repository to prevent bad names in repo
303 of repository to prevent bad names in repo
293 """
304 """
294 slug = remove_formatting(value)
305 slug = remove_formatting(value)
295 slug = strip_tags(slug)
306 slug = strip_tags(slug)
296
307
297 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
308 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
298 slug = slug.replace(c, '-')
309 slug = slug.replace(c, '-')
299 slug = recursive_replace(slug, '-')
310 slug = recursive_replace(slug, '-')
300 slug = collapse(slug, '-')
311 slug = collapse(slug, '-')
301 return slug
312 return slug
302
313
303 def get_changeset_safe(repo, rev):
314 def get_changeset_safe(repo, rev):
304 from vcs.backends.base import BaseRepository
315 from vcs.backends.base import BaseRepository
305 from vcs.exceptions import RepositoryError
316 from vcs.exceptions import RepositoryError
306 if not isinstance(repo, BaseRepository):
317 if not isinstance(repo, BaseRepository):
307 raise Exception('You must pass an Repository '
318 raise Exception('You must pass an Repository '
308 'object as first argument got %s', type(repo))
319 'object as first argument got %s', type(repo))
309
320
310 try:
321 try:
311 cs = repo.get_changeset(rev)
322 cs = repo.get_changeset(rev)
312 except RepositoryError:
323 except RepositoryError:
313 from rhodecode.lib.utils import EmptyChangeset
324 from rhodecode.lib.utils import EmptyChangeset
314 cs = EmptyChangeset()
325 cs = EmptyChangeset()
315 return cs
326 return cs
316
327
317
328
318 flash = _Flash()
329 flash = _Flash()
319
330
320
331
321 #==============================================================================
332 #==============================================================================
322 # MERCURIAL FILTERS available via h.
333 # MERCURIAL FILTERS available via h.
323 #==============================================================================
334 #==============================================================================
324 from mercurial import util
335 from mercurial import util
325 from mercurial.templatefilters import person as _person
336 from mercurial.templatefilters import person as _person
326
337
327
338
328
339
329 def _age(curdate):
340 def _age(curdate):
330 """turns a datetime into an age string."""
341 """turns a datetime into an age string."""
331
342
332 if not curdate:
343 if not curdate:
333 return ''
344 return ''
334
345
335 from datetime import timedelta, datetime
346 from datetime import timedelta, datetime
336
347
337 agescales = [("year", 3600 * 24 * 365),
348 agescales = [("year", 3600 * 24 * 365),
338 ("month", 3600 * 24 * 30),
349 ("month", 3600 * 24 * 30),
339 ("day", 3600 * 24),
350 ("day", 3600 * 24),
340 ("hour", 3600),
351 ("hour", 3600),
341 ("minute", 60),
352 ("minute", 60),
342 ("second", 1), ]
353 ("second", 1), ]
343
354
344 age = datetime.now() - curdate
355 age = datetime.now() - curdate
345 age_seconds = (age.days * agescales[2][1]) + age.seconds
356 age_seconds = (age.days * agescales[2][1]) + age.seconds
346 pos = 1
357 pos = 1
347 for scale in agescales:
358 for scale in agescales:
348 if scale[1] <= age_seconds:
359 if scale[1] <= age_seconds:
349 if pos == 6:pos = 5
360 if pos == 6:pos = 5
350 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
361 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
351 pos += 1
362 pos += 1
352
363
353 return _('just now')
364 return _('just now')
354
365
355 age = lambda x:_age(x)
366 age = lambda x:_age(x)
356 capitalize = lambda x: x.capitalize()
367 capitalize = lambda x: x.capitalize()
357 email = util.email
368 email = util.email
358 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
369 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
359 person = lambda x: _person(x)
370 person = lambda x: _person(x)
360 short_id = lambda x: x[:12]
371 short_id = lambda x: x[:12]
361
372
362
373
363 def action_parser(user_log):
374 def action_parser(user_log):
364 """
375 """
365 This helper will map the specified string action into translated
376 This helper will map the specified string action into translated
366 fancy names with icons and links
377 fancy names with icons and links
367
378
368 @param action:
379 @param action:
369 """
380 """
370 action = user_log.action
381 action = user_log.action
371 action_params = None
382 action_params = None
372 cs_links = ''
383 cs_links = ''
373
384
374 x = action.split(':')
385 x = action.split(':')
375
386
376 if len(x) > 1:
387 if len(x) > 1:
377 action, action_params = x
388 action, action_params = x
378
389
379 if action == 'push':
390 if action == 'push':
380 revs_limit = 5
391 revs_limit = 5
381 revs = action_params.split(',')
392 revs = action_params.split(',')
382 cs_links = " " + ', '.join ([link(rev,
393 cs_links = " " + ', '.join ([link(rev,
383 url('changeset_home',
394 url('changeset_home',
384 repo_name=user_log.repository.repo_name,
395 repo_name=user_log.repository.repo_name,
385 revision=rev)) for rev in revs[:revs_limit] ])
396 revision=rev)) for rev in revs[:revs_limit] ])
386 if len(revs) > revs_limit:
397 if len(revs) > revs_limit:
387 html_tmpl = '<span title="%s"> %s </span>'
398 html_tmpl = '<span title="%s"> %s </span>'
388 cs_links += html_tmpl % (', '.join(r for r in revs[revs_limit:]),
399 cs_links += html_tmpl % (', '.join(r for r in revs[revs_limit:]),
389 _('and %s more revisions') % (len(revs) - revs_limit))
400 _('and %s more revisions') % (len(revs) - revs_limit))
390
401
391 map = {'user_deleted_repo':_('User deleted repository'),
402 map = {'user_deleted_repo':_('User deleted repository'),
392 'user_created_repo':_('User created repository'),
403 'user_created_repo':_('User created repository'),
393 'user_forked_repo':_('User forked repository'),
404 'user_forked_repo':_('User forked repository'),
394 'user_updated_repo':_('User updated repository'),
405 'user_updated_repo':_('User updated repository'),
395 'admin_deleted_repo':_('Admin delete repository'),
406 'admin_deleted_repo':_('Admin delete repository'),
396 'admin_created_repo':_('Admin created repository'),
407 'admin_created_repo':_('Admin created repository'),
397 'admin_forked_repo':_('Admin forked repository'),
408 'admin_forked_repo':_('Admin forked repository'),
398 'admin_updated_repo':_('Admin updated repository'),
409 'admin_updated_repo':_('Admin updated repository'),
399 'push':_('Pushed') + literal(cs_links),
410 'push':_('Pushed') + literal(cs_links),
400 'pull':_('Pulled'), }
411 'pull':_('Pulled'), }
401
412
402 print action, action_params
413 print action, action_params
403 return map.get(action, action)
414 return map.get(action, action)
404
415
405
416
406 #==============================================================================
417 #==============================================================================
407 # PERMS
418 # PERMS
408 #==============================================================================
419 #==============================================================================
409 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
420 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
410 HasRepoPermissionAny, HasRepoPermissionAll
421 HasRepoPermissionAny, HasRepoPermissionAll
411
422
412 #==============================================================================
423 #==============================================================================
413 # GRAVATAR URL
424 # GRAVATAR URL
414 #==============================================================================
425 #==============================================================================
415 import hashlib
426 import hashlib
416 import urllib
427 import urllib
417 from pylons import request
428 from pylons import request
418
429
419 def gravatar_url(email_address, size=30):
430 def gravatar_url(email_address, size=30):
420 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
431 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
421 default = 'identicon'
432 default = 'identicon'
422 baseurl_nossl = "http://www.gravatar.com/avatar/"
433 baseurl_nossl = "http://www.gravatar.com/avatar/"
423 baseurl_ssl = "https://secure.gravatar.com/avatar/"
434 baseurl_ssl = "https://secure.gravatar.com/avatar/"
424 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
435 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
425
436
426
437
427 # construct the url
438 # construct the url
428 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
439 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
429 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
440 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
430
441
431 return gravatar_url
442 return gravatar_url
432
443
433 def safe_unicode(str):
444 def safe_unicode(str):
434 """safe unicode function. In case of UnicodeDecode error we try to return
445 """safe unicode function. In case of UnicodeDecode error we try to return
435 unicode with errors replace, if this failes we return unicode with
446 unicode with errors replace, if this failes we return unicode with
436 string_escape decoding """
447 string_escape decoding """
437
448
438 try:
449 try:
439 u_str = unicode(str)
450 u_str = unicode(str)
440 except UnicodeDecodeError:
451 except UnicodeDecodeError:
441 try:
452 try:
442 u_str = unicode(str, 'utf-8', 'replace')
453 u_str = unicode(str, 'utf-8', 'replace')
443 except UnicodeDecodeError:
454 except UnicodeDecodeError:
444 #incase we have a decode error just represent as byte string
455 #incase we have a decode error just represent as byte string
445 u_str = unicode(str(str).encode('string_escape'))
456 u_str = unicode(str(str).encode('string_escape'))
446
457
447 return u_str
458 return u_str
@@ -1,282 +1,283 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name}
5 ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('Repositories'),h.url('repos'))}
11 ${h.link_to(_('Repositories'),h.url('repos'))}
12 &raquo;
12 &raquo;
13 ${_('edit')} "${c.repo_name}"
13 ${_('edit')} "${c.repo_name}"
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box">
21 <div class="box">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
26 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
27 <div class="form">
27 <div class="form">
28 <!-- fields -->
28 <!-- fields -->
29 <div class="fields">
29 <div class="fields">
30 <div class="field">
30 <div class="field">
31 <div class="label">
31 <div class="label">
32 <label for="repo_name">${_('Name')}:</label>
32 <label for="repo_name">${_('Name')}:</label>
33 </div>
33 </div>
34 <div class="input input-medium">
34 <div class="input input-medium">
35 ${h.text('repo_name',class_="small")}
35 ${h.text('repo_name',class_="small")}
36 </div>
36 </div>
37 </div>
37 </div>
38 <div class="field">
38 <div class="field">
39 <div class="label">
39 <div class="label">
40 <label for="repo_type">${_('Type')}:</label>
40 <label for="repo_type">${_('Type')}:</label>
41 </div>
41 </div>
42 <div class="input">
42 <div class="input">
43 ${h.select('repo_type','hg',c.backends,class_="small")}
43 ${h.select('repo_type','hg',c.backends,class_="small")}
44 </div>
44 </div>
45 </div>
45 </div>
46 <div class="field">
46 <div class="field">
47 <div class="label label-textarea">
47 <div class="label label-textarea">
48 <label for="description">${_('Description')}:</label>
48 <label for="description">${_('Description')}:</label>
49 </div>
49 </div>
50 <div class="textarea text-area editor">
50 <div class="textarea text-area editor">
51 ${h.textarea('description',cols=23,rows=5)}
51 ${h.textarea('description',cols=23,rows=5)}
52 </div>
52 </div>
53 </div>
53 </div>
54
54
55 <div class="field">
55 <div class="field">
56 <div class="label label-checkbox">
56 <div class="label label-checkbox">
57 <label for="private">${_('Private')}:</label>
57 <label for="private">${_('Private')}:</label>
58 </div>
58 </div>
59 <div class="checkboxes">
59 <div class="checkboxes">
60 ${h.checkbox('private',value="True")}
60 ${h.checkbox('private',value="True")}
61 </div>
61 </div>
62 </div>
62 </div>
63
63
64 <div class="field">
64 <div class="field">
65 <div class="label">
65 <div class="label">
66 <label for="user">${_('Owner')}:</label>
66 <label for="user">${_('Owner')}:</label>
67 </div>
67 </div>
68 <div class="input input-small ac">
68 <div class="input input-small ac">
69 <div class="perm_ac">
69 <div class="perm_ac">
70 ${h.text('user',class_='yui-ac-input')}
70 ${h.text('user',class_='yui-ac-input')}
71 <div id="owner_container"></div>
71 <div id="owner_container"></div>
72 </div>
72 </div>
73 </div>
73 </div>
74 </div>
74 </div>
75
75
76 <div class="field">
76 <div class="field">
77 <div class="label">
77 <div class="label">
78 <label for="input">${_('Permissions')}:</label>
78 <label for="input">${_('Permissions')}:</label>
79 </div>
79 </div>
80 <div class="input">
80 <div class="input">
81 <table id="permissions_manage">
81 <table id="permissions_manage">
82 <tr>
82 <tr>
83 <td>${_('none')}</td>
83 <td>${_('none')}</td>
84 <td>${_('read')}</td>
84 <td>${_('read')}</td>
85 <td>${_('write')}</td>
85 <td>${_('write')}</td>
86 <td>${_('admin')}</td>
86 <td>${_('admin')}</td>
87 <td>${_('user')}</td>
87 <td>${_('user')}</td>
88 <td></td>
88 <td></td>
89 </tr>
89 </tr>
90
90
91 %for r2p in c.repo_info.repo_to_perm:
91 %for r2p in c.repo_info.repo_to_perm:
92 %if r2p.user.username =='default' and c.repo_info.private:
92 %if r2p.user.username =='default' and c.repo_info.private:
93 <tr>
93 <tr>
94 <td colspan="4">
94 <td colspan="4">
95 <span class="private_repo_msg">
95 <span class="private_repo_msg">
96 ${_('private repository')}
96 ${_('private repository')}
97 </span>
97 </span>
98 </td>
98 </td>
99 <td class="private_repo_msg">${r2p.user.username}</td>
99 <td class="private_repo_msg">${r2p.user.username}</td>
100 </tr>
100 </tr>
101 %else:
101 %else:
102 <tr id="id${id(r2p.user.username)}">
102 <tr id="id${id(r2p.user.username)}">
103 <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
103 <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
104 <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
104 <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
105 <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
105 <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
106 <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
106 <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
107 <td>${r2p.user.username}</td>
107 <td>${r2p.user.username}</td>
108 <td>
108 <td>
109 %if r2p.user.username !='default':
109 %if r2p.user.username !='default':
110 <span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
110 <span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
111 <script type="text/javascript">
111 <script type="text/javascript">
112 function ajaxAction(user_id,field_id){
112 function ajaxAction(user_id,field_id){
113 var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
113 var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
114 var callback = { success:function(o){
114 var callback = { success:function(o){
115 var tr = YAHOO.util.Dom.get(String(field_id));
115 var tr = YAHOO.util.Dom.get(String(field_id));
116 tr.parentNode.removeChild(tr);},failure:function(o){
116 tr.parentNode.removeChild(tr);},failure:function(o){
117 alert("${_('Failed to remove user')}");},};
117 alert("${_('Failed to remove user')}");},};
118 var postData = '_method=delete&user_id='+user_id;
118 var postData = '_method=delete&user_id='+user_id;
119 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
119 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
120 </script>
120 </script>
121 </span>
121 </span>
122 %endif
122 %endif
123 </td>
123 </td>
124 </tr>
124 </tr>
125 %endif
125 %endif
126 %endfor
126 %endfor
127
127
128 <tr id="add_perm_input">
128 <tr id="add_perm_input">
129 <td>${h.radio('perm_new_user','repository.none')}</td>
129 <td>${h.radio('perm_new_user','repository.none')}</td>
130 <td>${h.radio('perm_new_user','repository.read')}</td>
130 <td>${h.radio('perm_new_user','repository.read')}</td>
131 <td>${h.radio('perm_new_user','repository.write')}</td>
131 <td>${h.radio('perm_new_user','repository.write')}</td>
132 <td>${h.radio('perm_new_user','repository.admin')}</td>
132 <td>${h.radio('perm_new_user','repository.admin')}</td>
133 <td class='ac'>
133 <td class='ac'>
134 <div class="perm_ac" id="perm_ac">
134 <div class="perm_ac" id="perm_ac">
135 ${h.text('perm_new_user_name',class_='yui-ac-input')}
135 ${h.text('perm_new_user_name',class_='yui-ac-input')}
136 <div id="perm_container"></div>
136 <div id="perm_container"></div>
137 </div>
137 </div>
138 </td>
138 </td>
139 <td></td>
139 <td></td>
140 </tr>
140 </tr>
141 <tr>
141 <tr>
142 <td colspan="6">
142 <td colspan="6">
143 <span id="add_perm" class="add_icon" style="cursor: pointer;">
143 <span id="add_perm" class="add_icon" style="cursor: pointer;">
144 ${_('Add another user')}
144 ${_('Add another user')}
145 </span>
145 </span>
146 </td>
146 </td>
147 </tr>
147 </tr>
148 </table>
148 </table>
149 </div>
149 </div>
150
150
151 <div class="buttons">
151 <div class="buttons">
152 ${h.submit('save','save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
152 ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
153 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
153 </div>
154 </div>
154 </div>
155 </div>
155 </div>
156 </div>
156 </div>
157 </div>
157 ${h.end_form()}
158 ${h.end_form()}
158 <script type="text/javascript">
159 <script type="text/javascript">
159 YAHOO.util.Event.onDOMReady(function(){
160 YAHOO.util.Event.onDOMReady(function(){
160 var D = YAHOO.util.Dom;
161 var D = YAHOO.util.Dom;
161 if(!D.hasClass('perm_new_user_name','error')){
162 if(!D.hasClass('perm_new_user_name','error')){
162 D.setStyle('add_perm_input','display','none');
163 D.setStyle('add_perm_input','display','none');
163 }
164 }
164 YAHOO.util.Event.addListener('add_perm','click',function(){
165 YAHOO.util.Event.addListener('add_perm','click',function(){
165 D.setStyle('add_perm_input','display','');
166 D.setStyle('add_perm_input','display','');
166 D.setStyle('add_perm','opacity','0.6');
167 D.setStyle('add_perm','opacity','0.6');
167 D.setStyle('add_perm','cursor','default');
168 D.setStyle('add_perm','cursor','default');
168 });
169 });
169 });
170 });
170 </script>
171 </script>
171 <script type="text/javascript">
172 <script type="text/javascript">
172 YAHOO.example.FnMultipleFields = function(){
173 YAHOO.example.FnMultipleFields = function(){
173 var myContacts = ${c.users_array|n}
174 var myContacts = ${c.users_array|n}
174
175
175 // Define a custom search function for the DataSource
176 // Define a custom search function for the DataSource
176 var matchNames = function(sQuery) {
177 var matchNames = function(sQuery) {
177 // Case insensitive matching
178 // Case insensitive matching
178 var query = sQuery.toLowerCase(),
179 var query = sQuery.toLowerCase(),
179 contact,
180 contact,
180 i=0,
181 i=0,
181 l=myContacts.length,
182 l=myContacts.length,
182 matches = [];
183 matches = [];
183
184
184 // Match against each name of each contact
185 // Match against each name of each contact
185 for(; i<l; i++) {
186 for(; i<l; i++) {
186 contact = myContacts[i];
187 contact = myContacts[i];
187 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
188 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
188 (contact.lname.toLowerCase().indexOf(query) > -1) ||
189 (contact.lname.toLowerCase().indexOf(query) > -1) ||
189 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
190 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
190 matches[matches.length] = contact;
191 matches[matches.length] = contact;
191 }
192 }
192 }
193 }
193
194
194 return matches;
195 return matches;
195 };
196 };
196
197
197 // Use a FunctionDataSource
198 // Use a FunctionDataSource
198 var oDS = new YAHOO.util.FunctionDataSource(matchNames);
199 var oDS = new YAHOO.util.FunctionDataSource(matchNames);
199 oDS.responseSchema = {
200 oDS.responseSchema = {
200 fields: ["id", "fname", "lname", "nname"]
201 fields: ["id", "fname", "lname", "nname"]
201 }
202 }
202
203
203 // Instantiate AutoComplete for perms
204 // Instantiate AutoComplete for perms
204 var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
205 var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
205 oAC_perms.useShadow = false;
206 oAC_perms.useShadow = false;
206 oAC_perms.resultTypeList = false;
207 oAC_perms.resultTypeList = false;
207
208
208 // Instantiate AutoComplete for owner
209 // Instantiate AutoComplete for owner
209 var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
210 var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
210 oAC_owner.useShadow = false;
211 oAC_owner.useShadow = false;
211 oAC_owner.resultTypeList = false;
212 oAC_owner.resultTypeList = false;
212
213
213
214
214 // Custom formatter to highlight the matching letters
215 // Custom formatter to highlight the matching letters
215 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
216 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
216 var query = sQuery.toLowerCase(),
217 var query = sQuery.toLowerCase(),
217 fname = oResultData.fname,
218 fname = oResultData.fname,
218 lname = oResultData.lname,
219 lname = oResultData.lname,
219 nname = oResultData.nname || "", // Guard against null value
220 nname = oResultData.nname || "", // Guard against null value
220 query = sQuery.toLowerCase(),
221 query = sQuery.toLowerCase(),
221 fnameMatchIndex = fname.toLowerCase().indexOf(query),
222 fnameMatchIndex = fname.toLowerCase().indexOf(query),
222 lnameMatchIndex = lname.toLowerCase().indexOf(query),
223 lnameMatchIndex = lname.toLowerCase().indexOf(query),
223 nnameMatchIndex = nname.toLowerCase().indexOf(query),
224 nnameMatchIndex = nname.toLowerCase().indexOf(query),
224 displayfname, displaylname, displaynname;
225 displayfname, displaylname, displaynname;
225
226
226 if(fnameMatchIndex > -1) {
227 if(fnameMatchIndex > -1) {
227 displayfname = highlightMatch(fname, query, fnameMatchIndex);
228 displayfname = highlightMatch(fname, query, fnameMatchIndex);
228 }
229 }
229 else {
230 else {
230 displayfname = fname;
231 displayfname = fname;
231 }
232 }
232
233
233 if(lnameMatchIndex > -1) {
234 if(lnameMatchIndex > -1) {
234 displaylname = highlightMatch(lname, query, lnameMatchIndex);
235 displaylname = highlightMatch(lname, query, lnameMatchIndex);
235 }
236 }
236 else {
237 else {
237 displaylname = lname;
238 displaylname = lname;
238 }
239 }
239
240
240 if(nnameMatchIndex > -1) {
241 if(nnameMatchIndex > -1) {
241 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
242 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
242 }
243 }
243 else {
244 else {
244 displaynname = nname ? "(" + nname + ")" : "";
245 displaynname = nname ? "(" + nname + ")" : "";
245 }
246 }
246
247
247 return displayfname + " " + displaylname + " " + displaynname;
248 return displayfname + " " + displaylname + " " + displaynname;
248
249
249 };
250 };
250 oAC_perms.formatResult = custom_formatter;
251 oAC_perms.formatResult = custom_formatter;
251 oAC_owner.formatResult = custom_formatter;
252 oAC_owner.formatResult = custom_formatter;
252
253
253 // Helper function for the formatter
254 // Helper function for the formatter
254 var highlightMatch = function(full, snippet, matchindex) {
255 var highlightMatch = function(full, snippet, matchindex) {
255 return full.substring(0, matchindex) +
256 return full.substring(0, matchindex) +
256 "<span class='match'>" +
257 "<span class='match'>" +
257 full.substr(matchindex, snippet.length) +
258 full.substr(matchindex, snippet.length) +
258 "</span>" +
259 "</span>" +
259 full.substring(matchindex + snippet.length);
260 full.substring(matchindex + snippet.length);
260 };
261 };
261
262
262 var myHandler = function(sType, aArgs) {
263 var myHandler = function(sType, aArgs) {
263 var myAC = aArgs[0]; // reference back to the AC instance
264 var myAC = aArgs[0]; // reference back to the AC instance
264 var elLI = aArgs[1]; // reference to the selected LI element
265 var elLI = aArgs[1]; // reference to the selected LI element
265 var oData = aArgs[2]; // object literal of selected item's result data
266 var oData = aArgs[2]; // object literal of selected item's result data
266 myAC.getInputEl().value = oData.nname;
267 myAC.getInputEl().value = oData.nname;
267 };
268 };
268
269
269 oAC_perms.itemSelectEvent.subscribe(myHandler);
270 oAC_perms.itemSelectEvent.subscribe(myHandler);
270 oAC_owner.itemSelectEvent.subscribe(myHandler);
271 oAC_owner.itemSelectEvent.subscribe(myHandler);
271
272
272 return {
273 return {
273 oDS: oDS,
274 oDS: oDS,
274 oAC_perms: oAC_perms,
275 oAC_perms: oAC_perms,
275 oAC_owner: oAC_owner,
276 oAC_owner: oAC_owner,
276 };
277 };
277 }();
278 }();
278
279
279 </script>
280 </script>
280
281
281 </div>
282 </div>
282 </%def> No newline at end of file
283 </%def>
@@ -1,178 +1,180 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Settings administration')} - ${c.rhodecode_name}
5 ${_('Settings administration')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Settings')}
9 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Settings')}
10 </%def>
10 </%def>
11
11
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 </%def>
14 </%def>
15
15
16 <%def name="main()">
16 <%def name="main()">
17 <div class="box">
17 <div class="box">
18 <!-- box / title -->
18 <!-- box / title -->
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 <!-- end box / title -->
22 <!-- end box / title -->
23
23
24 <h3>${_('Remap and rescan repositories')}</h3>
24 <h3>${_('Remap and rescan repositories')}</h3>
25 ${h.form(url('admin_setting', setting_id='mapping'),method='put')}
25 ${h.form(url('admin_setting', setting_id='mapping'),method='put')}
26 <div class="form">
26 <div class="form">
27 <!-- fields -->
27 <!-- fields -->
28
28
29 <div class="fields">
29 <div class="fields">
30 <div class="field">
30 <div class="field">
31 <div class="label label-checkbox">
31 <div class="label label-checkbox">
32 <label for="destroy">${_('rescan option')}:</label>
32 <label for="destroy">${_('rescan option')}:</label>
33 </div>
33 </div>
34 <div class="checkboxes">
34 <div class="checkboxes">
35 <div class="checkbox">
35 <div class="checkbox">
36 ${h.checkbox('destroy',True)}
36 ${h.checkbox('destroy',True)}
37 <label for="checkbox-1">
37 <label for="checkbox-1">
38 <span class="tooltip" tooltip_title="${h.tooltip(_('In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it.'))}">
38 <span class="tooltip" tooltip_title="${h.tooltip(_('In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it.'))}">
39 ${_('destroy old data')}</span> </label>
39 ${_('destroy old data')}</span> </label>
40 </div>
40 </div>
41 </div>
41 </div>
42 </div>
42 </div>
43
43
44 <div class="buttons">
44 <div class="buttons">
45 ${h.submit('rescan','rescan repositories',class_="ui-button ui-widget ui-state-default ui-corner-all")}
45 ${h.submit('rescan','Rescan repositories',class_="ui-button ui-widget ui-state-default ui-corner-all")}
46 </div>
46 </div>
47 </div>
47 </div>
48 </div>
48 </div>
49 ${h.end_form()}
49 ${h.end_form()}
50
50
51 <h3>${_('Whoosh indexing')}</h3>
51 <h3>${_('Whoosh indexing')}</h3>
52 ${h.form(url('admin_setting', setting_id='whoosh'),method='put')}
52 ${h.form(url('admin_setting', setting_id='whoosh'),method='put')}
53 <div class="form">
53 <div class="form">
54 <!-- fields -->
54 <!-- fields -->
55
55
56 <div class="fields">
56 <div class="fields">
57 <div class="field">
57 <div class="field">
58 <div class="label label-checkbox">
58 <div class="label label-checkbox">
59 <label for="destroy">${_('index build option')}:</label>
59 <label for="destroy">${_('index build option')}:</label>
60 </div>
60 </div>
61 <div class="checkboxes">
61 <div class="checkboxes">
62 <div class="checkbox">
62 <div class="checkbox">
63 ${h.checkbox('full_index',True)}
63 ${h.checkbox('full_index',True)}
64 <label for="checkbox-1">${_('build from scratch')}</label>
64 <label for="checkbox-1">${_('build from scratch')}</label>
65 </div>
65 </div>
66 </div>
66 </div>
67 </div>
67 </div>
68
68
69 <div class="buttons">
69 <div class="buttons">
70 ${h.submit('reindex','reindex',class_="ui-button ui-widget ui-state-default ui-corner-all")}
70 ${h.submit('reindex','Reindex',class_="ui-button ui-widget ui-state-default ui-corner-all")}
71 </div>
71 </div>
72 </div>
72 </div>
73 </div>
73 </div>
74 ${h.end_form()}
74 ${h.end_form()}
75
75
76 <h3>${_('Global application settings')}</h3>
76 <h3>${_('Global application settings')}</h3>
77 ${h.form(url('admin_setting', setting_id='global'),method='put')}
77 ${h.form(url('admin_setting', setting_id='global'),method='put')}
78 <div class="form">
78 <div class="form">
79 <!-- fields -->
79 <!-- fields -->
80
80
81 <div class="fields">
81 <div class="fields">
82
82
83 <div class="field">
83 <div class="field">
84 <div class="label">
84 <div class="label">
85 <label for="rhodecode_title">${_('Application name')}:</label>
85 <label for="rhodecode_title">${_('Application name')}:</label>
86 </div>
86 </div>
87 <div class="input">
87 <div class="input">
88 ${h.text('rhodecode_title',size=30)}
88 ${h.text('rhodecode_title',size=30)}
89 </div>
89 </div>
90 </div>
90 </div>
91
91
92 <div class="field">
92 <div class="field">
93 <div class="label">
93 <div class="label">
94 <label for="rhodecode_realm">${_('Realm text')}:</label>
94 <label for="rhodecode_realm">${_('Realm text')}:</label>
95 </div>
95 </div>
96 <div class="input">
96 <div class="input">
97 ${h.text('rhodecode_realm',size=30)}
97 ${h.text('rhodecode_realm',size=30)}
98 </div>
98 </div>
99 </div>
99 </div>
100
100
101 <div class="buttons">
101 <div class="buttons">
102 ${h.submit('save','save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
102 ${h.submit('save','Save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
103 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
103 </div>
104 </div>
104 </div>
105 </div>
105 </div>
106 </div>
106 ${h.end_form()}
107 ${h.end_form()}
107
108
108 <h3>${_('Mercurial settings')}</h3>
109 <h3>${_('Mercurial settings')}</h3>
109 ${h.form(url('admin_setting', setting_id='mercurial'),method='put')}
110 ${h.form(url('admin_setting', setting_id='mercurial'),method='put')}
110 <div class="form">
111 <div class="form">
111 <!-- fields -->
112 <!-- fields -->
112
113
113 <div class="fields">
114 <div class="fields">
114
115
115 <div class="field">
116 <div class="field">
116 <div class="label label-checkbox">
117 <div class="label label-checkbox">
117 <label for="web_push_ssl">${_('Web')}:</label>
118 <label for="web_push_ssl">${_('Web')}:</label>
118 </div>
119 </div>
119 <div class="checkboxes">
120 <div class="checkboxes">
120 <div class="checkbox">
121 <div class="checkbox">
121 ${h.checkbox('web_push_ssl','true')}
122 ${h.checkbox('web_push_ssl','true')}
122 <label for="web_push_ssl">${_('require ssl for pushing')}</label>
123 <label for="web_push_ssl">${_('require ssl for pushing')}</label>
123 </div>
124 </div>
124 </div>
125 </div>
125 </div>
126 </div>
126
127
127 <div class="field">
128 <div class="field">
128 <div class="label label-checkbox">
129 <div class="label label-checkbox">
129 <label for="web_push_ssl">${_('Hooks')}:</label>
130 <label for="web_push_ssl">${_('Hooks')}:</label>
130 </div>
131 </div>
131 <div class="checkboxes">
132 <div class="checkboxes">
132 <div class="checkbox">
133 <div class="checkbox">
133 ${h.checkbox('hooks_changegroup_update','True')}
134 ${h.checkbox('hooks_changegroup_update','True')}
134 <label for="hooks_changegroup_update">${_('Update repository after push (hg update)')}</label>
135 <label for="hooks_changegroup_update">${_('Update repository after push (hg update)')}</label>
135 </div>
136 </div>
136 <div class="checkbox">
137 <div class="checkbox">
137 ${h.checkbox('hooks_changegroup_repo_size','True')}
138 ${h.checkbox('hooks_changegroup_repo_size','True')}
138 <label for="hooks_changegroup_repo_size">${_('Show repository size after push')}</label>
139 <label for="hooks_changegroup_repo_size">${_('Show repository size after push')}</label>
139 </div>
140 </div>
140 <div class="checkbox">
141 <div class="checkbox">
141 ${h.checkbox('hooks_pretxnchangegroup_push_logger','True')}
142 ${h.checkbox('hooks_pretxnchangegroup_push_logger','True')}
142 <label for="hooks_pretxnchangegroup_push_logger">${_('Log user push commands')}</label>
143 <label for="hooks_pretxnchangegroup_push_logger">${_('Log user push commands')}</label>
143 </div>
144 </div>
144 <div class="checkbox">
145 <div class="checkbox">
145 ${h.checkbox('hooks_preoutgoing_pull_logger','True')}
146 ${h.checkbox('hooks_preoutgoing_pull_logger','True')}
146 <label for="hooks_preoutgoing_pull_logger">${_('Log user pull commands')}</label>
147 <label for="hooks_preoutgoing_pull_logger">${_('Log user pull commands')}</label>
147 </div>
148 </div>
148 </div>
149 </div>
149 </div>
150 </div>
150
151
151 <div class="field">
152 <div class="field">
152 <div class="label">
153 <div class="label">
153 <label for="paths_root_path">${_('Repositories location')}:</label>
154 <label for="paths_root_path">${_('Repositories location')}:</label>
154 </div>
155 </div>
155 <div class="input">
156 <div class="input">
156 ${h.text('paths_root_path',size=30,readonly="readonly")}
157 ${h.text('paths_root_path',size=30,readonly="readonly")}
157 <span id="path_unlock" class="tooltip"
158 <span id="path_unlock" class="tooltip"
158 tooltip_title="${h.tooltip(_('This a crucial application setting. If You really sure you need to change this, you must restart application in order to make this settings take effect. Click this label to unlock.'))}">
159 tooltip_title="${h.tooltip(_('This a crucial application setting. If You really sure you need to change this, you must restart application in order to make this settings take effect. Click this label to unlock.'))}">
159 ${_('unlock')}</span>
160 ${_('unlock')}</span>
160 </div>
161 </div>
161 </div>
162 </div>
162
163
163 <div class="buttons">
164 <div class="buttons">
164 ${h.submit('save','save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
165 ${h.submit('save','Save settings',class_="ui-button ui-widget ui-state-default ui-corner-all")}
166 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
165 </div>
167 </div>
166 </div>
168 </div>
167 </div>
169 </div>
168 ${h.end_form()}
170 ${h.end_form()}
169
171
170 <script type="text/javascript">
172 <script type="text/javascript">
171 YAHOO.util.Event.onDOMReady(function(){
173 YAHOO.util.Event.onDOMReady(function(){
172 YAHOO.util.Event.addListener('path_unlock','click',function(){
174 YAHOO.util.Event.addListener('path_unlock','click',function(){
173 YAHOO.util.Dom.get('paths_root_path').removeAttribute('readonly');
175 YAHOO.util.Dom.get('paths_root_path').removeAttribute('readonly');
174 });
176 });
175 });
177 });
176 </script>
178 </script>
177 </div>
179 </div>
178 </%def>
180 </%def>
@@ -1,110 +1,111 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit user')} ${c.user.username} - ${c.rhodecode_name}
5 ${_('Edit user')} ${c.user.username} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('Users'),h.url('users'))}
11 ${h.link_to(_('Users'),h.url('users'))}
12 &raquo;
12 &raquo;
13 ${_('edit')} "${c.user.username}"
13 ${_('edit')} "${c.user.username}"
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box">
21 <div class="box">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 <!-- end box / title -->
26 <!-- end box / title -->
27 ${h.form(url('user', id=c.user.user_id),method='put')}
27 ${h.form(url('user', id=c.user.user_id),method='put')}
28 <div class="form">
28 <div class="form">
29 <!-- fields -->
29 <!-- fields -->
30 <div class="fields">
30 <div class="fields">
31 <div class="field">
31 <div class="field">
32 <div class="gravatar_box">
32 <div class="gravatar_box">
33 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
33 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
34 <p>
34 <p>
35 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
35 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
36 ${_('Using')} ${c.user.email}
36 ${_('Using')} ${c.user.email}
37 </p>
37 </p>
38 </div>
38 </div>
39 </div>
39 </div>
40
40
41 <div class="field">
41 <div class="field">
42 <div class="label">
42 <div class="label">
43 <label for="username">${_('Username')}:</label>
43 <label for="username">${_('Username')}:</label>
44 </div>
44 </div>
45 <div class="input">
45 <div class="input">
46 ${h.text('username',class_='small')}
46 ${h.text('username',class_='small')}
47 </div>
47 </div>
48 </div>
48 </div>
49
49
50 <div class="field">
50 <div class="field">
51 <div class="label">
51 <div class="label">
52 <label for="new_password">${_('New password')}:</label>
52 <label for="new_password">${_('New password')}:</label>
53 </div>
53 </div>
54 <div class="input">
54 <div class="input">
55 ${h.password('new_password',class_='small')}
55 ${h.password('new_password',class_='small')}
56 </div>
56 </div>
57 </div>
57 </div>
58
58
59 <div class="field">
59 <div class="field">
60 <div class="label">
60 <div class="label">
61 <label for="name">${_('First Name')}:</label>
61 <label for="name">${_('First Name')}:</label>
62 </div>
62 </div>
63 <div class="input">
63 <div class="input">
64 ${h.text('name',class_='small')}
64 ${h.text('name',class_='small')}
65 </div>
65 </div>
66 </div>
66 </div>
67
67
68 <div class="field">
68 <div class="field">
69 <div class="label">
69 <div class="label">
70 <label for="lastname">${_('Last Name')}:</label>
70 <label for="lastname">${_('Last Name')}:</label>
71 </div>
71 </div>
72 <div class="input">
72 <div class="input">
73 ${h.text('lastname',class_='small')}
73 ${h.text('lastname',class_='small')}
74 </div>
74 </div>
75 </div>
75 </div>
76
76
77 <div class="field">
77 <div class="field">
78 <div class="label">
78 <div class="label">
79 <label for="email">${_('Email')}:</label>
79 <label for="email">${_('Email')}:</label>
80 </div>
80 </div>
81 <div class="input">
81 <div class="input">
82 ${h.text('email',class_='small')}
82 ${h.text('email',class_='small')}
83 </div>
83 </div>
84 </div>
84 </div>
85
85
86 <div class="field">
86 <div class="field">
87 <div class="label label-checkbox">
87 <div class="label label-checkbox">
88 <label for="active">${_('Active')}:</label>
88 <label for="active">${_('Active')}:</label>
89 </div>
89 </div>
90 <div class="checkboxes">
90 <div class="checkboxes">
91 ${h.checkbox('active',value=True)}
91 ${h.checkbox('active',value=True)}
92 </div>
92 </div>
93 </div>
93 </div>
94
94
95 <div class="field">
95 <div class="field">
96 <div class="label label-checkbox">
96 <div class="label label-checkbox">
97 <label for="admin">${_('Admin')}:</label>
97 <label for="admin">${_('Admin')}:</label>
98 </div>
98 </div>
99 <div class="checkboxes">
99 <div class="checkboxes">
100 ${h.checkbox('admin',value=True)}
100 ${h.checkbox('admin',value=True)}
101 </div>
101 </div>
102 </div>
102 </div>
103 <div class="buttons">
103 <div class="buttons">
104 ${h.submit('save','save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
104 ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
105 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
105 </div>
106 </div>
106 </div>
107 </div>
107 </div>
108 </div>
108 ${h.end_form()}
109 ${h.end_form()}
109 </div>
110 </div>
110 </%def> No newline at end of file
111 </%def>
@@ -1,188 +1,192 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('My account')} ${c.rhodecode_user.username} - ${c.rhodecode_name}
5 ${_('My account')} ${c.rhodecode_user.username} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${_('My Account')}
9 ${_('My Account')}
10 </%def>
10 </%def>
11
11
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 </%def>
14 </%def>
15
15
16 <%def name="main()">
16 <%def name="main()">
17
17
18 <div class="box box-left">
18 <div class="box box-left">
19 <!-- box / title -->
19 <!-- box / title -->
20 <div class="title">
20 <div class="title">
21 ${self.breadcrumbs()}
21 ${self.breadcrumbs()}
22 </div>
22 </div>
23 <!-- end box / title -->
23 <!-- end box / title -->
24 <div class="ui-tabs-panel ui-widget-content ui-corner-bottom">
24 <div class="ui-tabs-panel ui-widget-content ui-corner-bottom">
25 ${h.form(url('admin_settings_my_account_update'),method='put')}
25 ${h.form(url('admin_settings_my_account_update'),method='put')}
26 <div class="form">
26 <div class="form">
27 <div class="fields">
27 <div class="fields">
28 <div class="field">
28 <div class="field">
29 <div class="label">
29 <div class="label">
30 <label for="username">${_('Username')}:</label>
30 <label for="username">${_('Username')}:</label>
31 </div>
31 </div>
32 <div class="input">
32 <div class="input">
33 ${h.text('username')}
33 ${h.text('username')}
34 </div>
34 </div>
35 </div>
35 </div>
36
36
37 <div class="field">
37 <div class="field">
38 <div class="label">
38 <div class="label">
39 <label for="new_password">${_('New password')}:</label>
39 <label for="new_password">${_('New password')}:</label>
40 </div>
40 </div>
41 <div class="input">
41 <div class="input">
42 ${h.password('new_password')}
42 ${h.password('new_password')}
43 </div>
43 </div>
44 </div>
44 </div>
45
45
46 <div class="field">
46 <div class="field">
47 <div class="label">
47 <div class="label">
48 <label for="name">${_('First Name')}:</label>
48 <label for="name">${_('First Name')}:</label>
49 </div>
49 </div>
50 <div class="input">
50 <div class="input">
51 ${h.text('name')}
51 ${h.text('name')}
52 </div>
52 </div>
53 </div>
53 </div>
54
54
55 <div class="field">
55 <div class="field">
56 <div class="label">
56 <div class="label">
57 <label for="lastname">${_('Last Name')}:</label>
57 <label for="lastname">${_('Last Name')}:</label>
58 </div>
58 </div>
59 <div class="input">
59 <div class="input">
60 ${h.text('lastname')}
60 ${h.text('lastname')}
61 </div>
61 </div>
62 </div>
62 </div>
63
63
64 <div class="field">
64 <div class="field">
65 <div class="label">
65 <div class="label">
66 <label for="email">${_('Email')}:</label>
66 <label for="email">${_('Email')}:</label>
67 </div>
67 </div>
68 <div class="input">
68 <div class="input">
69 ${h.text('email')}
69 ${h.text('email')}
70 </div>
70 </div>
71 </div>
71 </div>
72
72
73 <div class="buttons">
73 <div class="buttons">
74 ${h.submit('save','save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
74 ${h.submit('save','Save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
75 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
76
77
78
75 </div>
79 </div>
76 </div>
80 </div>
77 </div>
81 </div>
78 ${h.end_form()}
82 ${h.end_form()}
79 </div>
83 </div>
80 </div>
84 </div>
81
85
82 <div class="box box-right">
86 <div class="box box-right">
83 <!-- box / title -->
87 <!-- box / title -->
84 <div class="title">
88 <div class="title">
85 <h5>${_('My repositories')}
89 <h5>${_('My repositories')}
86 <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...')}"/>
90 <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...')}"/>
87 </h5>
91 </h5>
88 </div>
92 </div>
89 <!-- end box / title -->
93 <!-- end box / title -->
90 <div class="table">
94 <div class="table">
91 <table>
95 <table>
92 <thead>
96 <thead>
93 <tr>
97 <tr>
94 <th class="left">${_('Name')}</th>
98 <th class="left">${_('Name')}</th>
95 <th class="left">${_('revision')}</th>
99 <th class="left">${_('revision')}</th>
96 <th colspan="2" class="left">${_('action')}</th>
100 <th colspan="2" class="left">${_('action')}</th>
97 </thead>
101 </thead>
98 <tbody>
102 <tbody>
99 %if c.user_repos:
103 %if c.user_repos:
100 %for repo in c.user_repos:
104 %for repo in c.user_repos:
101 <tr>
105 <tr>
102 <td>
106 <td>
103 %if repo['repo'].dbrepo.repo_type =='hg':
107 %if repo['repo'].dbrepo.repo_type =='hg':
104 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
108 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
105 %elif repo['repo'].dbrepo.repo_type =='git':
109 %elif repo['repo'].dbrepo.repo_type =='git':
106 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
110 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
107 %else:
111 %else:
108
112
109 %endif
113 %endif
110 %if repo['repo'].dbrepo.private:
114 %if repo['repo'].dbrepo.private:
111 <img class="icon" alt="${_('private')}" src="/images/icons/lock.png"/>
115 <img class="icon" alt="${_('private')}" src="/images/icons/lock.png"/>
112 %else:
116 %else:
113 <img class="icon" alt="${_('public')}" src="/images/icons/lock_open.png"/>
117 <img class="icon" alt="${_('public')}" src="/images/icons/lock_open.png"/>
114 %endif
118 %endif
115
119
116 ${h.link_to(repo['repo'].name, h.url('summary_home',repo_name=repo['repo'].name),class_="repo_name")}
120 ${h.link_to(repo['repo'].name, h.url('summary_home',repo_name=repo['repo'].name),class_="repo_name")}
117 %if repo['repo'].dbrepo.fork:
121 %if repo['repo'].dbrepo.fork:
118 <a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
122 <a href="${h.url('summary_home',repo_name=repo['repo'].dbrepo.fork.repo_name)}">
119 <img class="icon" alt="${_('public')}"
123 <img class="icon" alt="${_('public')}"
120 title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}"
124 title="${_('Fork of')} ${repo['repo'].dbrepo.fork.repo_name}"
121 src="/images/icons/arrow_divide.png"/></a>
125 src="/images/icons/arrow_divide.png"/></a>
122 %endif
126 %endif
123 </td>
127 </td>
124 <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>
128 <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>
125 <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>
129 <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>
126 <td>
130 <td>
127 ${h.form(url('repo_settings_delete', repo_name=repo['repo'].name),method='delete')}
131 ${h.form(url('repo_settings_delete', repo_name=repo['repo'].name),method='delete')}
128 ${h.submit('remove_%s' % repo['repo'].name,'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
132 ${h.submit('remove_%s' % repo['repo'].name,'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
129 ${h.end_form()}
133 ${h.end_form()}
130 </td>
134 </td>
131 </tr>
135 </tr>
132 %endfor
136 %endfor
133 %else:
137 %else:
134 ${_('No repositories yet')}
138 ${_('No repositories yet')}
135 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
139 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
136 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
140 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
137 %endif
141 %endif
138 %endif
142 %endif
139 </tbody>
143 </tbody>
140 </table>
144 </table>
141 </div>
145 </div>
142
146
143 </div>
147 </div>
144 <script type="text/javascript">
148 <script type="text/javascript">
145 var D = YAHOO.util.Dom;
149 var D = YAHOO.util.Dom;
146 var E = YAHOO.util.Event;
150 var E = YAHOO.util.Event;
147 var S = YAHOO.util.Selector;
151 var S = YAHOO.util.Selector;
148
152
149 var q_filter = D.get('q_filter');
153 var q_filter = D.get('q_filter');
150 var F = YAHOO.namespace('q_filter');
154 var F = YAHOO.namespace('q_filter');
151
155
152 E.on(q_filter,'click',function(){
156 E.on(q_filter,'click',function(){
153 q_filter.value = '';
157 q_filter.value = '';
154 });
158 });
155
159
156 F.filterTimeout = null;
160 F.filterTimeout = null;
157
161
158 F.updateFilter = function() {
162 F.updateFilter = function() {
159 // Reset timeout
163 // Reset timeout
160 F.filterTimeout = null;
164 F.filterTimeout = null;
161
165
162 var obsolete = [];
166 var obsolete = [];
163 var nodes = S.query('div.table tr td a.repo_name');
167 var nodes = S.query('div.table tr td a.repo_name');
164 var req = D.get('q_filter').value;
168 var req = D.get('q_filter').value;
165 for (n in nodes){
169 for (n in nodes){
166 D.setStyle(nodes[n].parentNode.parentNode,'display','')
170 D.setStyle(nodes[n].parentNode.parentNode,'display','')
167 }
171 }
168 if (req){
172 if (req){
169 for (n in nodes){
173 for (n in nodes){
170 if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
174 if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
171 obsolete.push(nodes[n]);
175 obsolete.push(nodes[n]);
172 }
176 }
173 }
177 }
174 if(obsolete){
178 if(obsolete){
175 for (n in obsolete){
179 for (n in obsolete){
176 D.setStyle(obsolete[n].parentNode.parentNode,'display','none');
180 D.setStyle(obsolete[n].parentNode.parentNode,'display','none');
177 }
181 }
178 }
182 }
179 }
183 }
180 }
184 }
181
185
182 E.on(q_filter,'keyup',function(e){
186 E.on(q_filter,'keyup',function(e){
183 clearTimeout(F.filterTimeout);
187 clearTimeout(F.filterTimeout);
184 setTimeout(F.updateFilter,600);
188 setTimeout(F.updateFilter,600);
185 });
189 });
186
190
187 </script>
191 </script>
188 </%def> No newline at end of file
192 </%def>
@@ -1,262 +1,263 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${c.repo_name} ${_('Settings')} - ${c.rhodecode_name}
5 ${c.repo_name} ${_('Settings')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(c.repo_info.repo_name,h.url('summary_home',repo_name=c.repo_info.repo_name))}
9 ${h.link_to(c.repo_info.repo_name,h.url('summary_home',repo_name=c.repo_info.repo_name))}
10 &raquo;
10 &raquo;
11 ${_('Settings')}
11 ${_('Settings')}
12 </%def>
12 </%def>
13
13
14 <%def name="page_nav()">
14 <%def name="page_nav()">
15 ${self.menu('settings')}
15 ${self.menu('settings')}
16 </%def>
16 </%def>
17 <%def name="main()">
17 <%def name="main()">
18 <div class="box">
18 <div class="box">
19 <!-- box / title -->
19 <!-- box / title -->
20 <div class="title">
20 <div class="title">
21 ${self.breadcrumbs()}
21 ${self.breadcrumbs()}
22 </div>
22 </div>
23 ${h.form(url('repo_settings_update', repo_name=c.repo_info.repo_name),method='put')}
23 ${h.form(url('repo_settings_update', repo_name=c.repo_info.repo_name),method='put')}
24 <div class="form">
24 <div class="form">
25 <!-- fields -->
25 <!-- fields -->
26 <div class="fields">
26 <div class="fields">
27 <div class="field">
27 <div class="field">
28 <div class="label">
28 <div class="label">
29 <label for="repo_name">${_('Name')}:</label>
29 <label for="repo_name">${_('Name')}:</label>
30 </div>
30 </div>
31 <div class="input input-medium">
31 <div class="input input-medium">
32 ${h.text('repo_name',class_="small")}
32 ${h.text('repo_name',class_="small")}
33 </div>
33 </div>
34 </div>
34 </div>
35
35
36 <div class="field">
36 <div class="field">
37 <div class="label label-textarea">
37 <div class="label label-textarea">
38 <label for="description">${_('Description')}:</label>
38 <label for="description">${_('Description')}:</label>
39 </div>
39 </div>
40 <div class="textarea text-area editor">
40 <div class="textarea text-area editor">
41 ${h.textarea('description',cols=23,rows=5)}
41 ${h.textarea('description',cols=23,rows=5)}
42 </div>
42 </div>
43 </div>
43 </div>
44
44
45 <div class="field">
45 <div class="field">
46 <div class="label label-checkbox">
46 <div class="label label-checkbox">
47 <label for="private">${_('Private')}:</label>
47 <label for="private">${_('Private')}:</label>
48 </div>
48 </div>
49 <div class="checkboxes">
49 <div class="checkboxes">
50 ${h.checkbox('private',value="True")}
50 ${h.checkbox('private',value="True")}
51 </div>
51 </div>
52 </div>
52 </div>
53
53
54 <div class="field">
54 <div class="field">
55 <div class="label">
55 <div class="label">
56 <label for="">${_('Permissions')}:</label>
56 <label for="">${_('Permissions')}:</label>
57 </div>
57 </div>
58 <div class="input">
58 <div class="input">
59 <table id="permissions_manage">
59 <table id="permissions_manage">
60 <tr>
60 <tr>
61 <td>${_('none')}</td>
61 <td>${_('none')}</td>
62 <td>${_('read')}</td>
62 <td>${_('read')}</td>
63 <td>${_('write')}</td>
63 <td>${_('write')}</td>
64 <td>${_('admin')}</td>
64 <td>${_('admin')}</td>
65 <td>${_('user')}</td>
65 <td>${_('user')}</td>
66 <td></td>
66 <td></td>
67 </tr>
67 </tr>
68
68
69 %for r2p in c.repo_info.repo_to_perm:
69 %for r2p in c.repo_info.repo_to_perm:
70 %if r2p.user.username =='default' and c.repo_info.private:
70 %if r2p.user.username =='default' and c.repo_info.private:
71 <tr>
71 <tr>
72 <td colspan="4">
72 <td colspan="4">
73 <span class="private_repo_msg">
73 <span class="private_repo_msg">
74 ${_('private repository')}
74 ${_('private repository')}
75 </span>
75 </span>
76 </td>
76 </td>
77 <td class="private_repo_msg">${r2p.user.username}</td>
77 <td class="private_repo_msg">${r2p.user.username}</td>
78 </tr>
78 </tr>
79 %else:
79 %else:
80 <tr id="id${id(r2p.user.username)}">
80 <tr id="id${id(r2p.user.username)}">
81 <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
81 <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
82 <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
82 <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
83 <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
83 <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
84 <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
84 <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
85 <td>${r2p.user.username}</td>
85 <td>${r2p.user.username}</td>
86 <td>
86 <td>
87 %if r2p.user.username !='default':
87 %if r2p.user.username !='default':
88 <span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
88 <span class="delete_icon action_button" onclick="ajaxAction(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
89 <script type="text/javascript">
89 <script type="text/javascript">
90 function ajaxAction(user_id,field_id){
90 function ajaxAction(user_id,field_id){
91 var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
91 var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
92 var callback = { success:function(o){
92 var callback = { success:function(o){
93 var tr = YAHOO.util.Dom.get(String(field_id));
93 var tr = YAHOO.util.Dom.get(String(field_id));
94 tr.parentNode.removeChild(tr);},failure:function(o){
94 tr.parentNode.removeChild(tr);},failure:function(o){
95 alert("${_('Failed to remove user')}");},};
95 alert("${_('Failed to remove user')}");},};
96 var postData = '_method=delete&user_id='+user_id;
96 var postData = '_method=delete&user_id='+user_id;
97 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
97 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);};
98 </script>
98 </script>
99 </span>
99 </span>
100 %endif
100 %endif
101 </td>
101 </td>
102 </tr>
102 </tr>
103 %endif
103 %endif
104 %endfor
104 %endfor
105
105
106
106
107 <tr id="add_perm_input">
107 <tr id="add_perm_input">
108 <td>${h.radio('perm_new_user','repository.none')}</td>
108 <td>${h.radio('perm_new_user','repository.none')}</td>
109 <td>${h.radio('perm_new_user','repository.read')}</td>
109 <td>${h.radio('perm_new_user','repository.read')}</td>
110 <td>${h.radio('perm_new_user','repository.write')}</td>
110 <td>${h.radio('perm_new_user','repository.write')}</td>
111 <td>${h.radio('perm_new_user','repository.admin')}</td>
111 <td>${h.radio('perm_new_user','repository.admin')}</td>
112 <td class='ac'>
112 <td class='ac'>
113 <div class="perm_ac" id="perm_ac">
113 <div class="perm_ac" id="perm_ac">
114 ${h.text('perm_new_user_name',class_='yui-ac-input')}
114 ${h.text('perm_new_user_name',class_='yui-ac-input')}
115 <div id="perm_container"></div>
115 <div id="perm_container"></div>
116 </div>
116 </div>
117 </td>
117 </td>
118 <td></td>
118 <td></td>
119 </tr>
119 </tr>
120 <tr>
120 <tr>
121 <td colspan="6">
121 <td colspan="6">
122 <span id="add_perm" class="add_icon" style="cursor: pointer;">
122 <span id="add_perm" class="add_icon" style="cursor: pointer;">
123 ${_('Add another user')}
123 ${_('Add another user')}
124 </span>
124 </span>
125 </td>
125 </td>
126 </tr>
126 </tr>
127 </table>
127 </table>
128 </div>
128 </div>
129
129
130 <div class="buttons">
130 <div class="buttons">
131 ${h.submit('update','update',class_="ui-button ui-widget ui-state-default ui-corner-all")}
131 ${h.submit('update','Update',class_="ui-button ui-widget ui-state-default ui-corner-all")}
132 ${h.reset('reset','Reset',class_="ui-button ui-widget ui-state-default ui-corner-all")}
132 </div>
133 </div>
133 </div>
134 </div>
134 </div>
135 </div>
135 ${h.end_form()}
136 ${h.end_form()}
136 <script type="text/javascript">
137 <script type="text/javascript">
137 YAHOO.util.Event.onDOMReady(function(){
138 YAHOO.util.Event.onDOMReady(function(){
138 var D = YAHOO.util.Dom;
139 var D = YAHOO.util.Dom;
139 if(!D.hasClass('perm_new_user_name','error')){
140 if(!D.hasClass('perm_new_user_name','error')){
140 D.setStyle('add_perm_input','display','none');
141 D.setStyle('add_perm_input','display','none');
141 }
142 }
142 YAHOO.util.Event.addListener('add_perm','click',function(){
143 YAHOO.util.Event.addListener('add_perm','click',function(){
143 D.setStyle('add_perm_input','display','');
144 D.setStyle('add_perm_input','display','');
144 D.setStyle('add_perm','opacity','0.6');
145 D.setStyle('add_perm','opacity','0.6');
145 D.setStyle('add_perm','cursor','default');
146 D.setStyle('add_perm','cursor','default');
146 });
147 });
147 });
148 });
148 </script>
149 </script>
149 <script type="text/javascript">
150 <script type="text/javascript">
150 YAHOO.example.FnMultipleFields = function(){
151 YAHOO.example.FnMultipleFields = function(){
151 var myContacts = ${c.users_array|n}
152 var myContacts = ${c.users_array|n}
152
153
153 // Define a custom search function for the DataSource
154 // Define a custom search function for the DataSource
154 var matchNames = function(sQuery) {
155 var matchNames = function(sQuery) {
155 // Case insensitive matching
156 // Case insensitive matching
156 var query = sQuery.toLowerCase(),
157 var query = sQuery.toLowerCase(),
157 contact,
158 contact,
158 i=0,
159 i=0,
159 l=myContacts.length,
160 l=myContacts.length,
160 matches = [];
161 matches = [];
161
162
162 // Match against each name of each contact
163 // Match against each name of each contact
163 for(; i<l; i++) {
164 for(; i<l; i++) {
164 contact = myContacts[i];
165 contact = myContacts[i];
165 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
166 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
166 (contact.lname.toLowerCase().indexOf(query) > -1) ||
167 (contact.lname.toLowerCase().indexOf(query) > -1) ||
167 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
168 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
168 matches[matches.length] = contact;
169 matches[matches.length] = contact;
169 }
170 }
170 }
171 }
171
172
172 return matches;
173 return matches;
173 };
174 };
174
175
175 // Use a FunctionDataSource
176 // Use a FunctionDataSource
176 var oDS = new YAHOO.util.FunctionDataSource(matchNames);
177 var oDS = new YAHOO.util.FunctionDataSource(matchNames);
177 oDS.responseSchema = {
178 oDS.responseSchema = {
178 fields: ["id", "fname", "lname", "nname"]
179 fields: ["id", "fname", "lname", "nname"]
179 }
180 }
180
181
181 // Instantiate AutoComplete for perms
182 // Instantiate AutoComplete for perms
182 var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
183 var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
183 oAC_perms.useShadow = false;
184 oAC_perms.useShadow = false;
184 oAC_perms.resultTypeList = false;
185 oAC_perms.resultTypeList = false;
185
186
186 // Instantiate AutoComplete for owner
187 // Instantiate AutoComplete for owner
187 var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
188 var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
188 oAC_owner.useShadow = false;
189 oAC_owner.useShadow = false;
189 oAC_owner.resultTypeList = false;
190 oAC_owner.resultTypeList = false;
190
191
191
192
192 // Custom formatter to highlight the matching letters
193 // Custom formatter to highlight the matching letters
193 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
194 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
194 var query = sQuery.toLowerCase(),
195 var query = sQuery.toLowerCase(),
195 fname = oResultData.fname,
196 fname = oResultData.fname,
196 lname = oResultData.lname,
197 lname = oResultData.lname,
197 nname = oResultData.nname || "", // Guard against null value
198 nname = oResultData.nname || "", // Guard against null value
198 query = sQuery.toLowerCase(),
199 query = sQuery.toLowerCase(),
199 fnameMatchIndex = fname.toLowerCase().indexOf(query),
200 fnameMatchIndex = fname.toLowerCase().indexOf(query),
200 lnameMatchIndex = lname.toLowerCase().indexOf(query),
201 lnameMatchIndex = lname.toLowerCase().indexOf(query),
201 nnameMatchIndex = nname.toLowerCase().indexOf(query),
202 nnameMatchIndex = nname.toLowerCase().indexOf(query),
202 displayfname, displaylname, displaynname;
203 displayfname, displaylname, displaynname;
203
204
204 if(fnameMatchIndex > -1) {
205 if(fnameMatchIndex > -1) {
205 displayfname = highlightMatch(fname, query, fnameMatchIndex);
206 displayfname = highlightMatch(fname, query, fnameMatchIndex);
206 }
207 }
207 else {
208 else {
208 displayfname = fname;
209 displayfname = fname;
209 }
210 }
210
211
211 if(lnameMatchIndex > -1) {
212 if(lnameMatchIndex > -1) {
212 displaylname = highlightMatch(lname, query, lnameMatchIndex);
213 displaylname = highlightMatch(lname, query, lnameMatchIndex);
213 }
214 }
214 else {
215 else {
215 displaylname = lname;
216 displaylname = lname;
216 }
217 }
217
218
218 if(nnameMatchIndex > -1) {
219 if(nnameMatchIndex > -1) {
219 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
220 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
220 }
221 }
221 else {
222 else {
222 displaynname = nname ? "(" + nname + ")" : "";
223 displaynname = nname ? "(" + nname + ")" : "";
223 }
224 }
224
225
225 return displayfname + " " + displaylname + " " + displaynname;
226 return displayfname + " " + displaylname + " " + displaynname;
226
227
227 };
228 };
228 oAC_perms.formatResult = custom_formatter;
229 oAC_perms.formatResult = custom_formatter;
229 oAC_owner.formatResult = custom_formatter;
230 oAC_owner.formatResult = custom_formatter;
230
231
231 // Helper function for the formatter
232 // Helper function for the formatter
232 var highlightMatch = function(full, snippet, matchindex) {
233 var highlightMatch = function(full, snippet, matchindex) {
233 return full.substring(0, matchindex) +
234 return full.substring(0, matchindex) +
234 "<span class='match'>" +
235 "<span class='match'>" +
235 full.substr(matchindex, snippet.length) +
236 full.substr(matchindex, snippet.length) +
236 "</span>" +
237 "</span>" +
237 full.substring(matchindex + snippet.length);
238 full.substring(matchindex + snippet.length);
238 };
239 };
239
240
240 var myHandler = function(sType, aArgs) {
241 var myHandler = function(sType, aArgs) {
241 var myAC = aArgs[0]; // reference back to the AC instance
242 var myAC = aArgs[0]; // reference back to the AC instance
242 var elLI = aArgs[1]; // reference to the selected LI element
243 var elLI = aArgs[1]; // reference to the selected LI element
243 var oData = aArgs[2]; // object literal of selected item's result data
244 var oData = aArgs[2]; // object literal of selected item's result data
244 myAC.getInputEl().value = oData.nname;
245 myAC.getInputEl().value = oData.nname;
245 };
246 };
246
247
247 oAC_perms.itemSelectEvent.subscribe(myHandler);
248 oAC_perms.itemSelectEvent.subscribe(myHandler);
248 //oAC_owner.itemSelectEvent.subscribe(myHandler);
249 //oAC_owner.itemSelectEvent.subscribe(myHandler);
249
250
250 return {
251 return {
251 oDS: oDS,
252 oDS: oDS,
252 oAC_perms: oAC_perms,
253 oAC_perms: oAC_perms,
253 oAC_owner: oAC_owner,
254 oAC_owner: oAC_owner,
254 };
255 };
255 }();
256 }();
256
257
257 </script>
258 </script>
258 </div>
259 </div>
259 </div>
260 </div>
260 </%def>
261 </%def>
261
262
262
263
General Comments 0
You need to be logged in to leave comments. Login now