##// END OF EJS Templates
user-groups: on admin view redirect links to public profile. We have an explicit...
marcink -
r2639:336bd192 default
parent child Browse files
Show More
@@ -1,247 +1,246 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 import formencode
24 24 import formencode.htmlfill
25 25
26 26 from pyramid.httpexceptions import HTTPFound
27 27 from pyramid.view import view_config
28 28 from pyramid.response import Response
29 29 from pyramid.renderers import render
30 30
31 31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 32 from rhodecode.lib.auth import (
33 33 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
34 34 from rhodecode.lib import helpers as h, audit_logger
35 35 from rhodecode.lib.utils2 import safe_unicode
36 36
37 37 from rhodecode.model.forms import UserGroupForm
38 38 from rhodecode.model.permission import PermissionModel
39 39 from rhodecode.model.scm import UserGroupList
40 40 from rhodecode.model.db import (
41 41 or_, count, User, UserGroup, UserGroupMember)
42 42 from rhodecode.model.meta import Session
43 43 from rhodecode.model.user_group import UserGroupModel
44 44
45 45 log = logging.getLogger(__name__)
46 46
47 47
48 48 class AdminUserGroupsView(BaseAppView, DataGridAppView):
49 49
50 50 def load_default_context(self):
51 51 c = self._get_local_tmpl_context()
52 52
53 53 PermissionModel().set_global_permission_choices(
54 54 c, gettext_translator=self.request.translate)
55 55
56 56 return c
57 57
58 58 # permission check in data loading of
59 59 # `user_groups_list_data` via UserGroupList
60 60 @LoginRequired()
61 61 @NotAnonymous()
62 62 @view_config(
63 63 route_name='user_groups', request_method='GET',
64 64 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
65 65 def user_groups_list(self):
66 66 c = self.load_default_context()
67 67 return self._get_template_context(c)
68 68
69 69 # permission check inside
70 70 @LoginRequired()
71 71 @NotAnonymous()
72 72 @view_config(
73 73 route_name='user_groups_data', request_method='GET',
74 74 renderer='json_ext', xhr=True)
75 75 def user_groups_list_data(self):
76 76 self.load_default_context()
77 77 column_map = {
78 78 'active': 'users_group_active',
79 79 'description': 'user_group_description',
80 80 'members': 'members_total',
81 81 'owner': 'user_username',
82 82 'sync': 'group_data'
83 83 }
84 84 draw, start, limit = self._extract_chunk(self.request)
85 85 search_q, order_by, order_dir = self._extract_ordering(
86 86 self.request, column_map=column_map)
87 87
88 88 _render = self.request.get_partial_renderer(
89 89 'rhodecode:templates/data_table/_dt_elements.mako')
90 90
91 def user_group_name(user_group_id, user_group_name):
92 return _render("user_group_name", user_group_id, user_group_name)
91 def user_group_name(user_group_name):
92 return _render("user_group_name", user_group_name)
93 93
94 94 def user_group_actions(user_group_id, user_group_name):
95 95 return _render("user_group_actions", user_group_id, user_group_name)
96 96
97 97 def user_profile(username):
98 98 return _render('user_profile', username)
99 99
100 100 auth_user_group_list = UserGroupList(
101 101 UserGroup.query().all(), perm_set=['usergroup.admin'])
102 102
103 103 allowed_ids = [-1]
104 104 for user_group in auth_user_group_list:
105 105 allowed_ids.append(user_group.users_group_id)
106 106
107 107 user_groups_data_total_count = UserGroup.query()\
108 108 .filter(UserGroup.users_group_id.in_(allowed_ids))\
109 109 .count()
110 110
111 111 member_count = count(UserGroupMember.user_id)
112 112 base_q = Session.query(
113 113 UserGroup.users_group_name,
114 114 UserGroup.user_group_description,
115 115 UserGroup.users_group_active,
116 116 UserGroup.users_group_id,
117 117 UserGroup.group_data,
118 118 User,
119 119 member_count.label('member_count')
120 120 ) \
121 121 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
122 122 .outerjoin(UserGroupMember) \
123 123 .join(User, User.user_id == UserGroup.user_id) \
124 124 .group_by(UserGroup, User)
125 125
126 126 if search_q:
127 127 like_expression = u'%{}%'.format(safe_unicode(search_q))
128 128 base_q = base_q.filter(or_(
129 129 UserGroup.users_group_name.ilike(like_expression),
130 130 ))
131 131
132 132 user_groups_data_total_filtered_count = base_q.count()
133 133
134 134 if order_by == 'members_total':
135 135 sort_col = member_count
136 136 elif order_by == 'user_username':
137 137 sort_col = User.username
138 138 else:
139 139 sort_col = getattr(UserGroup, order_by, None)
140 140
141 141 if isinstance(sort_col, count) or sort_col:
142 142 if order_dir == 'asc':
143 143 sort_col = sort_col.asc()
144 144 else:
145 145 sort_col = sort_col.desc()
146 146
147 147 base_q = base_q.order_by(sort_col)
148 148 base_q = base_q.offset(start).limit(limit)
149 149
150 150 # authenticated access to user groups
151 151 auth_user_group_list = base_q.all()
152 152
153 153 user_groups_data = []
154 154 for user_gr in auth_user_group_list:
155 155 user_groups_data.append({
156 "users_group_name": user_group_name(
157 user_gr.users_group_id, h.escape(user_gr.users_group_name)),
156 "users_group_name": user_group_name(user_gr.users_group_name),
158 157 "name_raw": h.escape(user_gr.users_group_name),
159 158 "description": h.escape(user_gr.user_group_description),
160 159 "members": user_gr.member_count,
161 160 # NOTE(marcink): because of advanced query we
162 161 # need to load it like that
163 162 "sync": UserGroup._load_group_data(
164 163 user_gr.group_data).get('extern_type'),
165 164 "active": h.bool2icon(user_gr.users_group_active),
166 165 "owner": user_profile(user_gr.User.username),
167 166 "action": user_group_actions(
168 167 user_gr.users_group_id, user_gr.users_group_name)
169 168 })
170 169
171 170 data = ({
172 171 'draw': draw,
173 172 'data': user_groups_data,
174 173 'recordsTotal': user_groups_data_total_count,
175 174 'recordsFiltered': user_groups_data_total_filtered_count,
176 175 })
177 176
178 177 return data
179 178
180 179 @LoginRequired()
181 180 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
182 181 @view_config(
183 182 route_name='user_groups_new', request_method='GET',
184 183 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
185 184 def user_groups_new(self):
186 185 c = self.load_default_context()
187 186 return self._get_template_context(c)
188 187
189 188 @LoginRequired()
190 189 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
191 190 @CSRFRequired()
192 191 @view_config(
193 192 route_name='user_groups_create', request_method='POST',
194 193 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
195 194 def user_groups_create(self):
196 195 _ = self.request.translate
197 196 c = self.load_default_context()
198 197 users_group_form = UserGroupForm(self.request.translate)()
199 198
200 199 user_group_name = self.request.POST.get('users_group_name')
201 200 try:
202 201 form_result = users_group_form.to_python(dict(self.request.POST))
203 202 user_group = UserGroupModel().create(
204 203 name=form_result['users_group_name'],
205 204 description=form_result['user_group_description'],
206 205 owner=self._rhodecode_user.user_id,
207 206 active=form_result['users_group_active'])
208 207 Session().flush()
209 208 creation_data = user_group.get_api_data()
210 209 user_group_name = form_result['users_group_name']
211 210
212 211 audit_logger.store_web(
213 212 'user_group.create', action_data={'data': creation_data},
214 213 user=self._rhodecode_user)
215 214
216 215 user_group_link = h.link_to(
217 216 h.escape(user_group_name),
218 217 h.route_path(
219 218 'edit_user_group', user_group_id=user_group.users_group_id))
220 219 h.flash(h.literal(_('Created user group %(user_group_link)s')
221 220 % {'user_group_link': user_group_link}),
222 221 category='success')
223 222 Session().commit()
224 223 user_group_id = user_group.users_group_id
225 224 except formencode.Invalid as errors:
226 225
227 226 data = render(
228 227 'rhodecode:templates/admin/user_groups/user_group_add.mako',
229 228 self._get_template_context(c), self.request)
230 229 html = formencode.htmlfill.render(
231 230 data,
232 231 defaults=errors.value,
233 232 errors=errors.error_dict or {},
234 233 prefix_error=False,
235 234 encoding="UTF-8",
236 235 force_defaults=False
237 236 )
238 237 return Response(html)
239 238
240 239 except Exception:
241 240 log.exception("Exception creating user group")
242 241 h.flash(_('Error occurred during creation of user group %s') \
243 242 % user_group_name, category='error')
244 243 raise HTTPFound(h.route_path('user_groups_new'))
245 244
246 245 raise HTTPFound(
247 246 h.route_path('edit_user_group', user_group_id=user_group_id))
@@ -1,377 +1,377 b''
1 1 ## DATA TABLE RE USABLE ELEMENTS
2 2 ## usage:
3 3 ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4 4 <%namespace name="base" file="/base/base.mako"/>
5 5
6 6 <%def name="metatags_help()">
7 7 <table>
8 8 <%
9 9 example_tags = [
10 10 ('state','[stable]'),
11 11 ('state','[stale]'),
12 12 ('state','[featured]'),
13 13 ('state','[dev]'),
14 14 ('state','[dead]'),
15 15 ('state','[deprecated]'),
16 16
17 17 ('label','[personal]'),
18 18 ('generic','[v2.0.0]'),
19 19
20 20 ('lang','[lang =&gt; JavaScript]'),
21 21 ('license','[license =&gt; LicenseName]'),
22 22
23 23 ('ref','[requires =&gt; RepoName]'),
24 24 ('ref','[recommends =&gt; GroupName]'),
25 25 ('ref','[conflicts =&gt; SomeName]'),
26 26 ('ref','[base =&gt; SomeName]'),
27 27 ('url','[url =&gt; [linkName](https://rhodecode.com)]'),
28 28 ('see','[see =&gt; http://rhodecode.com]'),
29 29 ]
30 30 %>
31 31 % for tag_type, tag in example_tags:
32 32 <tr>
33 33 <td>${tag|n}</td>
34 34 <td>${h.style_metatag(tag_type, tag)|n}</td>
35 35 </tr>
36 36 % endfor
37 37 </table>
38 38 </%def>
39 39
40 40 ## REPOSITORY RENDERERS
41 41 <%def name="quick_menu(repo_name)">
42 42 <i class="icon-more"></i>
43 43 <div class="menu_items_container hidden">
44 44 <ul class="menu_items">
45 45 <li>
46 46 <a title="${_('Summary')}" href="${h.route_path('repo_summary',repo_name=repo_name)}">
47 47 <span>${_('Summary')}</span>
48 48 </a>
49 49 </li>
50 50 <li>
51 51 <a title="${_('Changelog')}" href="${h.route_path('repo_changelog',repo_name=repo_name)}">
52 52 <span>${_('Changelog')}</span>
53 53 </a>
54 54 </li>
55 55 <li>
56 56 <a title="${_('Files')}" href="${h.route_path('repo_files:default_commit',repo_name=repo_name)}">
57 57 <span>${_('Files')}</span>
58 58 </a>
59 59 </li>
60 60 <li>
61 61 <a title="${_('Fork')}" href="${h.route_path('repo_fork_new',repo_name=repo_name)}">
62 62 <span>${_('Fork')}</span>
63 63 </a>
64 64 </li>
65 65 </ul>
66 66 </div>
67 67 </%def>
68 68
69 69 <%def name="repo_name(name,rtype,rstate,private,fork_of,short_name=False,admin=False)">
70 70 <%
71 71 def get_name(name,short_name=short_name):
72 72 if short_name:
73 73 return name.split('/')[-1]
74 74 else:
75 75 return name
76 76 %>
77 77 <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate">
78 78 ##NAME
79 79 <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.route_path('repo_summary',repo_name=name)}">
80 80
81 81 ##TYPE OF REPO
82 82 %if h.is_hg(rtype):
83 83 <span title="${_('Mercurial repository')}"><i class="icon-hg" style="font-size: 14px;"></i></span>
84 84 %elif h.is_git(rtype):
85 85 <span title="${_('Git repository')}"><i class="icon-git" style="font-size: 14px"></i></span>
86 86 %elif h.is_svn(rtype):
87 87 <span title="${_('Subversion repository')}"><i class="icon-svn" style="font-size: 14px"></i></span>
88 88 %endif
89 89
90 90 ##PRIVATE/PUBLIC
91 91 %if private and c.visual.show_private_icon:
92 92 <i class="icon-lock" title="${_('Private repository')}"></i>
93 93 %elif not private and c.visual.show_public_icon:
94 94 <i class="icon-unlock-alt" title="${_('Public repository')}"></i>
95 95 %else:
96 96 <span></span>
97 97 %endif
98 98 ${get_name(name)}
99 99 </a>
100 100 %if fork_of:
101 101 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
102 102 %endif
103 103 %if rstate == 'repo_state_pending':
104 104 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
105 105 (${_('creating...')})
106 106 </span>
107 107 %endif
108 108 </div>
109 109 </%def>
110 110
111 111 <%def name="repo_desc(description, stylify_metatags)">
112 112 <%
113 113 tags, description = h.extract_metatags(description)
114 114 %>
115 115
116 116 <div class="truncate-wrap">
117 117 % if stylify_metatags:
118 118 % for tag_type, tag in tags:
119 119 ${h.style_metatag(tag_type, tag)|n}
120 120 % endfor
121 121 % endif
122 122 ${description}
123 123 </div>
124 124
125 125 </%def>
126 126
127 127 <%def name="last_change(last_change)">
128 128 ${h.age_component(last_change, time_is_local=True)}
129 129 </%def>
130 130
131 131 <%def name="revision(name,rev,tip,author,last_msg, commit_date)">
132 132 <div>
133 133 %if rev >= 0:
134 134 <code><a title="${h.tooltip('%s\n%s\n\n%s' % (author, commit_date, last_msg))}" class="tooltip" href="${h.route_path('repo_commit',repo_name=name,commit_id=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code>
135 135 %else:
136 136 ${_('No commits yet')}
137 137 %endif
138 138 </div>
139 139 </%def>
140 140
141 141 <%def name="rss(name)">
142 142 %if c.rhodecode_user.username != h.DEFAULT_USER:
143 143 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
144 144 %else:
145 145 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
146 146 %endif
147 147 </%def>
148 148
149 149 <%def name="atom(name)">
150 150 %if c.rhodecode_user.username != h.DEFAULT_USER:
151 151 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
152 152 %else:
153 153 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
154 154 %endif
155 155 </%def>
156 156
157 157 <%def name="user_gravatar(email, size=16)">
158 158 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
159 159 ${base.gravatar(email, 16)}
160 160 </div>
161 161 </%def>
162 162
163 163 <%def name="repo_actions(repo_name, super_user=True)">
164 164 <div>
165 165 <div class="grid_edit">
166 166 <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
167 167 <i class="icon-pencil"></i>Edit</a>
168 168 </div>
169 169 <div class="grid_delete">
170 170 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), request=request)}
171 171 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger",
172 172 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
173 173 ${h.end_form()}
174 174 </div>
175 175 </div>
176 176 </%def>
177 177
178 178 <%def name="repo_state(repo_state)">
179 179 <div>
180 180 %if repo_state == 'repo_state_pending':
181 181 <div class="tag tag4">${_('Creating')}</div>
182 182 %elif repo_state == 'repo_state_created':
183 183 <div class="tag tag1">${_('Created')}</div>
184 184 %else:
185 185 <div class="tag alert2" title="${h.tooltip(repo_state)}">invalid</div>
186 186 %endif
187 187 </div>
188 188 </%def>
189 189
190 190
191 191 ## REPO GROUP RENDERERS
192 192 <%def name="quick_repo_group_menu(repo_group_name)">
193 193 <i class="icon-more"></i>
194 194 <div class="menu_items_container hidden">
195 195 <ul class="menu_items">
196 196 <li>
197 197 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">${_('Summary')}</a>
198 198 </li>
199 199
200 200 </ul>
201 201 </div>
202 202 </%def>
203 203
204 204 <%def name="repo_group_name(repo_group_name, children_groups=None)">
205 205 <div>
206 206 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">
207 207 <i class="icon-folder-close" title="${_('Repository group')}" style="font-size: 16px"></i>
208 208 %if children_groups:
209 209 ${h.literal(' &raquo; '.join(children_groups))}
210 210 %else:
211 211 ${repo_group_name}
212 212 %endif
213 213 </a>
214 214 </div>
215 215 </%def>
216 216
217 217 <%def name="repo_group_desc(description, personal, stylify_metatags)">
218 218
219 219 <%
220 220 tags, description = h.extract_metatags(description)
221 221 %>
222 222
223 223 <div class="truncate-wrap">
224 224 % if personal:
225 225 <div class="metatag" tag="personal">${_('personal')}</div>
226 226 % endif
227 227
228 228 % if stylify_metatags:
229 229 % for tag_type, tag in tags:
230 230 ${h.style_metatag(tag_type, tag)|n}
231 231 % endfor
232 232 % endif
233 233 ${description}
234 234 </div>
235 235
236 236 </%def>
237 237
238 238 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
239 239 <div class="grid_edit">
240 240 <a href="${h.route_path('edit_repo_group',repo_group_name=repo_group_name)}" title="${_('Edit')}">Edit</a>
241 241 </div>
242 242 <div class="grid_delete">
243 243 ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=repo_group_name), request=request)}
244 244 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger",
245 245 onclick="return confirm('"+_ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")}
246 246 ${h.end_form()}
247 247 </div>
248 248 </%def>
249 249
250 250
251 251 <%def name="user_actions(user_id, username)">
252 252 <div class="grid_edit">
253 253 <a href="${h.route_path('user_edit',user_id=user_id)}" title="${_('Edit')}">
254 254 <i class="icon-pencil"></i>${_('Edit')}</a>
255 255 </div>
256 256 <div class="grid_delete">
257 257 ${h.secure_form(h.route_path('user_delete', user_id=user_id), request=request)}
258 258 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger",
259 259 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
260 260 ${h.end_form()}
261 261 </div>
262 262 </%def>
263 263
264 264 <%def name="user_group_actions(user_group_id, user_group_name)">
265 265 <div class="grid_edit">
266 266 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
267 267 </div>
268 268 <div class="grid_delete">
269 269 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), request=request)}
270 270 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger",
271 271 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
272 272 ${h.end_form()}
273 273 </div>
274 274 </%def>
275 275
276 276
277 277 <%def name="user_name(user_id, username)">
278 278 ${h.link_to(h.person(username, 'username_or_name_or_email'), h.route_path('user_edit', user_id=user_id))}
279 279 </%def>
280 280
281 281 <%def name="user_profile(username)">
282 282 ${base.gravatar_with_user(username, 16)}
283 283 </%def>
284 284
285 <%def name="user_group_name(user_group_id, user_group_name)">
285 <%def name="user_group_name(user_group_name)">
286 286 <div>
287 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}">
288 <i class="icon-group" title="${_('User group')}"></i> ${user_group_name}</a>
287 <i class="icon-group" title="${_('User group')}"></i>
288 ${h.link_to_group(user_group_name)}
289 289 </div>
290 290 </%def>
291 291
292 292
293 293 ## GISTS
294 294
295 295 <%def name="gist_gravatar(full_contact)">
296 296 <div class="gist_gravatar">
297 297 ${base.gravatar(full_contact, 30)}
298 298 </div>
299 299 </%def>
300 300
301 301 <%def name="gist_access_id(gist_access_id, full_contact)">
302 302 <div>
303 303 <b>
304 304 <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">gist: ${gist_access_id}</a>
305 305 </b>
306 306 </div>
307 307 </%def>
308 308
309 309 <%def name="gist_author(full_contact, created_on, expires)">
310 310 ${base.gravatar_with_user(full_contact, 16)}
311 311 </%def>
312 312
313 313
314 314 <%def name="gist_created(created_on)">
315 315 <div class="created">
316 316 ${h.age_component(created_on, time_is_local=True)}
317 317 </div>
318 318 </%def>
319 319
320 320 <%def name="gist_expires(expires)">
321 321 <div class="created">
322 322 %if expires == -1:
323 323 ${_('never')}
324 324 %else:
325 325 ${h.age_component(h.time_to_utcdatetime(expires))}
326 326 %endif
327 327 </div>
328 328 </%def>
329 329
330 330 <%def name="gist_type(gist_type)">
331 331 %if gist_type != 'public':
332 332 <div class="tag">${_('Private')}</div>
333 333 %endif
334 334 </%def>
335 335
336 336 <%def name="gist_description(gist_description)">
337 337 ${gist_description}
338 338 </%def>
339 339
340 340
341 341 ## PULL REQUESTS GRID RENDERERS
342 342
343 343 <%def name="pullrequest_target_repo(repo_name)">
344 344 <div class="truncate">
345 345 ${h.link_to(repo_name,h.route_path('repo_summary',repo_name=repo_name))}
346 346 </div>
347 347 </%def>
348 348 <%def name="pullrequest_status(status)">
349 349 <div class="${'flag_status %s' % status} pull-left"></div>
350 350 </%def>
351 351
352 352 <%def name="pullrequest_title(title, description)">
353 353 ${title} <br/>
354 354 ${h.shorter(description, 40)}
355 355 </%def>
356 356
357 357 <%def name="pullrequest_comments(comments_nr)">
358 358 <i class="icon-comment"></i> ${comments_nr}
359 359 </%def>
360 360
361 361 <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)">
362 362 <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}">
363 363 % if short:
364 364 #${pull_request_id}
365 365 % else:
366 366 ${_('Pull request #%(pr_number)s') % {'pr_number': pull_request_id,}}
367 367 % endif
368 368 </a>
369 369 </%def>
370 370
371 371 <%def name="pullrequest_updated_on(updated_on)">
372 372 ${h.age_component(h.time_to_utcdatetime(updated_on))}
373 373 </%def>
374 374
375 375 <%def name="pullrequest_author(full_contact)">
376 376 ${base.gravatar_with_user(full_contact, 16)}
377 377 </%def>
General Comments 0
You need to be logged in to leave comments. Login now