##// END OF EJS Templates
started my page rewrite
marcink -
r446:a0a93357 default
parent child Browse files
Show More
@@ -1,281 +1,286 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # settings controller for pylons
3 # settings controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on July 14, 2010
21 Created on July 14, 2010
22 settings controller for pylons
22 settings controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from formencode import htmlfill
25 from formencode import htmlfill
26 from pylons import request, session, tmpl_context as c, url, app_globals as g, \
26 from pylons import request, session, tmpl_context as c, url, app_globals as g, \
27 config
27 config
28 from pylons.controllers.util import abort, redirect
28 from pylons.controllers.util import abort, redirect
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from pylons_app.lib import helpers as h
30 from pylons_app.lib import helpers as h
31 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator, \
31 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator, \
32 HasPermissionAnyDecorator
32 HasPermissionAnyDecorator
33 from pylons_app.lib.base import BaseController, render
33 from pylons_app.lib.base import BaseController, render
34 from pylons_app.lib.utils import repo2db_mapper, invalidate_cache, \
34 from pylons_app.lib.utils import repo2db_mapper, invalidate_cache, \
35 set_hg_app_config, get_hg_settings, get_hg_ui_settings, make_ui
35 set_hg_app_config, get_hg_settings, get_hg_ui_settings, make_ui
36 from pylons_app.model.db import User, UserLog, HgAppSettings, HgAppUi
36 from pylons_app.model.db import User, UserLog, HgAppSettings, HgAppUi
37 from pylons_app.model.forms import UserForm, ApplicationSettingsForm, \
37 from pylons_app.model.forms import UserForm, ApplicationSettingsForm, \
38 ApplicationUiSettingsForm
38 ApplicationUiSettingsForm
39 from pylons_app.model.hg_model import HgModel
39 from pylons_app.model.hg_model import HgModel
40 from pylons_app.model.user_model import UserModel
40 from pylons_app.model.user_model import UserModel
41 import formencode
41 import formencode
42 import logging
42 import logging
43 import traceback
43 import traceback
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47
47
48 class SettingsController(BaseController):
48 class SettingsController(BaseController):
49 """REST Controller styled on the Atom Publishing Protocol"""
49 """REST Controller styled on the Atom Publishing Protocol"""
50 # To properly map this controller, ensure your config/routing.py
50 # To properly map this controller, ensure your config/routing.py
51 # file has a resource setup:
51 # file has a resource setup:
52 # map.resource('setting', 'settings', controller='admin/settings',
52 # map.resource('setting', 'settings', controller='admin/settings',
53 # path_prefix='/admin', name_prefix='admin_')
53 # path_prefix='/admin', name_prefix='admin_')
54
54
55
55
56 @LoginRequired()
56 @LoginRequired()
57 def __before__(self):
57 def __before__(self):
58 c.admin_user = session.get('admin_user')
58 c.admin_user = session.get('admin_user')
59 c.admin_username = session.get('admin_username')
59 c.admin_username = session.get('admin_username')
60 super(SettingsController, self).__before__()
60 super(SettingsController, self).__before__()
61
61
62
62
63 @HasPermissionAllDecorator('hg.admin')
63 @HasPermissionAllDecorator('hg.admin')
64 def index(self, format='html'):
64 def index(self, format='html'):
65 """GET /admin/settings: All items in the collection"""
65 """GET /admin/settings: All items in the collection"""
66 # url('admin_settings')
66 # url('admin_settings')
67
67
68 defaults = get_hg_settings()
68 defaults = get_hg_settings()
69 defaults.update(get_hg_ui_settings())
69 defaults.update(get_hg_ui_settings())
70 return htmlfill.render(
70 return htmlfill.render(
71 render('admin/settings/settings.html'),
71 render('admin/settings/settings.html'),
72 defaults=defaults,
72 defaults=defaults,
73 encoding="UTF-8",
73 encoding="UTF-8",
74 force_defaults=False
74 force_defaults=False
75 )
75 )
76
76
77 @HasPermissionAllDecorator('hg.admin')
77 @HasPermissionAllDecorator('hg.admin')
78 def create(self):
78 def create(self):
79 """POST /admin/settings: Create a new item"""
79 """POST /admin/settings: Create a new item"""
80 # url('admin_settings')
80 # url('admin_settings')
81
81
82 @HasPermissionAllDecorator('hg.admin')
82 @HasPermissionAllDecorator('hg.admin')
83 def new(self, format='html'):
83 def new(self, format='html'):
84 """GET /admin/settings/new: Form to create a new item"""
84 """GET /admin/settings/new: Form to create a new item"""
85 # url('admin_new_setting')
85 # url('admin_new_setting')
86
86
87 @HasPermissionAllDecorator('hg.admin')
87 @HasPermissionAllDecorator('hg.admin')
88 def update(self, setting_id):
88 def update(self, setting_id):
89 """PUT /admin/settings/setting_id: Update an existing item"""
89 """PUT /admin/settings/setting_id: Update an existing item"""
90 # Forms posted to this method should contain a hidden field:
90 # Forms posted to this method should contain a hidden field:
91 # <input type="hidden" name="_method" value="PUT" />
91 # <input type="hidden" name="_method" value="PUT" />
92 # Or using helpers:
92 # Or using helpers:
93 # h.form(url('admin_setting', setting_id=ID),
93 # h.form(url('admin_setting', setting_id=ID),
94 # method='put')
94 # method='put')
95 # url('admin_setting', setting_id=ID)
95 # url('admin_setting', setting_id=ID)
96 if setting_id == 'mapping':
96 if setting_id == 'mapping':
97 rm_obsolete = request.POST.get('destroy', False)
97 rm_obsolete = request.POST.get('destroy', False)
98 log.debug('Rescanning directories with destroy=%s', rm_obsolete)
98 log.debug('Rescanning directories with destroy=%s', rm_obsolete)
99
99
100 initial = HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
100 initial = HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
101 repo2db_mapper(initial, rm_obsolete)
101 repo2db_mapper(initial, rm_obsolete)
102 invalidate_cache('cached_repo_list')
102 invalidate_cache('cached_repo_list')
103 h.flash(_('Repositories sucessfully rescanned'), category='success')
103 h.flash(_('Repositories sucessfully rescanned'), category='success')
104
104
105 if setting_id == 'global':
105 if setting_id == 'global':
106
106
107 application_form = ApplicationSettingsForm()()
107 application_form = ApplicationSettingsForm()()
108 try:
108 try:
109 form_result = application_form.to_python(dict(request.POST))
109 form_result = application_form.to_python(dict(request.POST))
110
110
111 try:
111 try:
112 hgsettings1 = self.sa.query(HgAppSettings)\
112 hgsettings1 = self.sa.query(HgAppSettings)\
113 .filter(HgAppSettings.app_settings_name == 'title').one()
113 .filter(HgAppSettings.app_settings_name == 'title').one()
114 hgsettings1.app_settings_value = form_result['hg_app_title']
114 hgsettings1.app_settings_value = form_result['hg_app_title']
115
115
116 hgsettings2 = self.sa.query(HgAppSettings)\
116 hgsettings2 = self.sa.query(HgAppSettings)\
117 .filter(HgAppSettings.app_settings_name == 'realm').one()
117 .filter(HgAppSettings.app_settings_name == 'realm').one()
118 hgsettings2.app_settings_value = form_result['hg_app_realm']
118 hgsettings2.app_settings_value = form_result['hg_app_realm']
119
119
120
120
121 self.sa.add(hgsettings1)
121 self.sa.add(hgsettings1)
122 self.sa.add(hgsettings2)
122 self.sa.add(hgsettings2)
123 self.sa.commit()
123 self.sa.commit()
124 set_hg_app_config(config)
124 set_hg_app_config(config)
125 h.flash(_('Updated application settings'),
125 h.flash(_('Updated application settings'),
126 category='success')
126 category='success')
127
127
128 except:
128 except:
129 log.error(traceback.format_exc())
129 log.error(traceback.format_exc())
130 h.flash(_('error occured during updating application settings'),
130 h.flash(_('error occured during updating application settings'),
131 category='error')
131 category='error')
132
132
133 self.sa.rollback()
133 self.sa.rollback()
134
134
135
135
136 except formencode.Invalid as errors:
136 except formencode.Invalid as errors:
137 return htmlfill.render(
137 return htmlfill.render(
138 render('admin/settings/settings.html'),
138 render('admin/settings/settings.html'),
139 defaults=errors.value,
139 defaults=errors.value,
140 errors=errors.error_dict or {},
140 errors=errors.error_dict or {},
141 prefix_error=False,
141 prefix_error=False,
142 encoding="UTF-8")
142 encoding="UTF-8")
143
143
144 if setting_id == 'mercurial':
144 if setting_id == 'mercurial':
145 application_form = ApplicationUiSettingsForm()()
145 application_form = ApplicationUiSettingsForm()()
146 try:
146 try:
147 form_result = application_form.to_python(dict(request.POST))
147 form_result = application_form.to_python(dict(request.POST))
148
148
149 try:
149 try:
150
150
151 hgsettings1 = self.sa.query(HgAppUi)\
151 hgsettings1 = self.sa.query(HgAppUi)\
152 .filter(HgAppUi.ui_key == 'push_ssl').one()
152 .filter(HgAppUi.ui_key == 'push_ssl').one()
153 hgsettings1.ui_value = form_result['web_push_ssl']
153 hgsettings1.ui_value = form_result['web_push_ssl']
154
154
155 hgsettings2 = self.sa.query(HgAppUi)\
155 hgsettings2 = self.sa.query(HgAppUi)\
156 .filter(HgAppUi.ui_key == '/').one()
156 .filter(HgAppUi.ui_key == '/').one()
157 hgsettings2.ui_value = form_result['paths_root_path']
157 hgsettings2.ui_value = form_result['paths_root_path']
158
158
159
159
160 #HOOKS
160 #HOOKS
161 hgsettings3 = self.sa.query(HgAppUi)\
161 hgsettings3 = self.sa.query(HgAppUi)\
162 .filter(HgAppUi.ui_key == 'changegroup.update').one()
162 .filter(HgAppUi.ui_key == 'changegroup.update').one()
163 hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
163 hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
164
164
165 hgsettings4 = self.sa.query(HgAppUi)\
165 hgsettings4 = self.sa.query(HgAppUi)\
166 .filter(HgAppUi.ui_key == 'changegroup.repo_size').one()
166 .filter(HgAppUi.ui_key == 'changegroup.repo_size').one()
167 hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
167 hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
168
168
169
169
170
170
171
171
172 self.sa.add(hgsettings1)
172 self.sa.add(hgsettings1)
173 self.sa.add(hgsettings2)
173 self.sa.add(hgsettings2)
174 self.sa.add(hgsettings3)
174 self.sa.add(hgsettings3)
175 self.sa.add(hgsettings4)
175 self.sa.add(hgsettings4)
176 self.sa.commit()
176 self.sa.commit()
177
177
178 h.flash(_('Updated mercurial settings'),
178 h.flash(_('Updated mercurial settings'),
179 category='success')
179 category='success')
180
180
181 except:
181 except:
182 log.error(traceback.format_exc())
182 log.error(traceback.format_exc())
183 h.flash(_('error occured during updating application settings'),
183 h.flash(_('error occured during updating application settings'),
184 category='error')
184 category='error')
185
185
186 self.sa.rollback()
186 self.sa.rollback()
187
187
188
188
189 except formencode.Invalid as errors:
189 except formencode.Invalid as errors:
190 return htmlfill.render(
190 return htmlfill.render(
191 render('admin/settings/settings.html'),
191 render('admin/settings/settings.html'),
192 defaults=errors.value,
192 defaults=errors.value,
193 errors=errors.error_dict or {},
193 errors=errors.error_dict or {},
194 prefix_error=False,
194 prefix_error=False,
195 encoding="UTF-8")
195 encoding="UTF-8")
196
196
197
197
198
198
199 return redirect(url('admin_settings'))
199 return redirect(url('admin_settings'))
200
200
201 @HasPermissionAllDecorator('hg.admin')
201 @HasPermissionAllDecorator('hg.admin')
202 def delete(self, setting_id):
202 def delete(self, setting_id):
203 """DELETE /admin/settings/setting_id: Delete an existing item"""
203 """DELETE /admin/settings/setting_id: Delete an existing item"""
204 # Forms posted to this method should contain a hidden field:
204 # Forms posted to this method should contain a hidden field:
205 # <input type="hidden" name="_method" value="DELETE" />
205 # <input type="hidden" name="_method" value="DELETE" />
206 # Or using helpers:
206 # Or using helpers:
207 # h.form(url('admin_setting', setting_id=ID),
207 # h.form(url('admin_setting', setting_id=ID),
208 # method='delete')
208 # method='delete')
209 # url('admin_setting', setting_id=ID)
209 # url('admin_setting', setting_id=ID)
210
210
211 @HasPermissionAllDecorator('hg.admin')
211 @HasPermissionAllDecorator('hg.admin')
212 def show(self, setting_id, format='html'):
212 def show(self, setting_id, format='html'):
213 """GET /admin/settings/setting_id: Show a specific item"""
213 """GET /admin/settings/setting_id: Show a specific item"""
214 # url('admin_setting', setting_id=ID)
214 # url('admin_setting', setting_id=ID)
215
215
216 @HasPermissionAllDecorator('hg.admin')
216 @HasPermissionAllDecorator('hg.admin')
217 def edit(self, setting_id, format='html'):
217 def edit(self, setting_id, format='html'):
218 """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
218 """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
219 # url('admin_edit_setting', setting_id=ID)
219 # url('admin_edit_setting', setting_id=ID)
220
220
221
221
222 def my_account(self):
222 def my_account(self):
223 """
223 """
224 GET /_admin/my_account Displays info about my account
224 GET /_admin/my_account Displays info about my account
225 """
225 """
226 # url('admin_settings_my_account')
226 # url('admin_settings_my_account')
227 c.user = self.sa.query(User).get(c.hg_app_user.user_id)
227 c.user = self.sa.query(User).get(c.hg_app_user.user_id)
228 c.user_repos = []
229 for repo in c.cached_repo_list.values():
230 if repo.dbrepo.user.username == c.user.username:
231 c.user_repos.append(repo)
232
228 if c.user.username == 'default':
233 if c.user.username == 'default':
229 h.flash(_("You can't edit this user since it's"
234 h.flash(_("You can't edit this user since it's"
230 " crucial for entire application"), category='warning')
235 " crucial for entire application"), category='warning')
231 return redirect(url('users'))
236 return redirect(url('users'))
232
237
233 defaults = c.user.__dict__
238 defaults = c.user.__dict__
234 return htmlfill.render(
239 return htmlfill.render(
235 render('admin/users/user_edit_my_account.html'),
240 render('admin/users/user_edit_my_account.html'),
236 defaults=defaults,
241 defaults=defaults,
237 encoding="UTF-8",
242 encoding="UTF-8",
238 force_defaults=False
243 force_defaults=False
239 )
244 )
240
245
241 def my_account_update(self):
246 def my_account_update(self):
242 """PUT /_admin/my_account_update: Update an existing item"""
247 """PUT /_admin/my_account_update: Update an existing item"""
243 # Forms posted to this method should contain a hidden field:
248 # Forms posted to this method should contain a hidden field:
244 # <input type="hidden" name="_method" value="PUT" />
249 # <input type="hidden" name="_method" value="PUT" />
245 # Or using helpers:
250 # Or using helpers:
246 # h.form(url('admin_settings_my_account_update'),
251 # h.form(url('admin_settings_my_account_update'),
247 # method='put')
252 # method='put')
248 # url('admin_settings_my_account_update', id=ID)
253 # url('admin_settings_my_account_update', id=ID)
249 user_model = UserModel()
254 user_model = UserModel()
250 uid = c.hg_app_user.user_id
255 uid = c.hg_app_user.user_id
251 _form = UserForm(edit=True, old_data={'user_id':uid})()
256 _form = UserForm(edit=True, old_data={'user_id':uid})()
252 form_result = {}
257 form_result = {}
253 try:
258 try:
254 form_result = _form.to_python(dict(request.POST))
259 form_result = _form.to_python(dict(request.POST))
255 user_model.update_my_account(uid, form_result)
260 user_model.update_my_account(uid, form_result)
256 h.flash(_('Your account was updated succesfully'),
261 h.flash(_('Your account was updated succesfully'),
257 category='success')
262 category='success')
258
263
259 except formencode.Invalid as errors:
264 except formencode.Invalid as errors:
260 #c.user = self.sa.query(User).get(c.hg_app_user.user_id)
265 #c.user = self.sa.query(User).get(c.hg_app_user.user_id)
261 return htmlfill.render(
266 return htmlfill.render(
262 render('admin/users/user_edit_my_account.html'),
267 render('admin/users/user_edit_my_account.html'),
263 defaults=errors.value,
268 defaults=errors.value,
264 errors=errors.error_dict or {},
269 errors=errors.error_dict or {},
265 prefix_error=False,
270 prefix_error=False,
266 encoding="UTF-8")
271 encoding="UTF-8")
267 except Exception:
272 except Exception:
268 log.error(traceback.format_exc())
273 log.error(traceback.format_exc())
269 h.flash(_('error occured during update of user %s') \
274 h.flash(_('error occured during update of user %s') \
270 % form_result.get('username'), category='error')
275 % form_result.get('username'), category='error')
271
276
272 return redirect(url('my_account'))
277 return redirect(url('my_account'))
273
278
274 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
279 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
275 def create_repository(self):
280 def create_repository(self):
276 """GET /_admin/create_repository: Form to create a new item"""
281 """GET /_admin/create_repository: Form to create a new item"""
277 new_repo = request.GET.get('repo', '')
282 new_repo = request.GET.get('repo', '')
278 c.new_repo = h.repo_name_slug(new_repo)
283 c.new_repo = h.repo_name_slug(new_repo)
279
284
280 return render('admin/repos/repo_add_create_repository.html')
285 return render('admin/repos/repo_add_create_repository.html')
281
286
@@ -1,79 +1,109 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.hg_app_user.username} ${_('account')}
5 ${c.hg_app_user.username} ${_('account')}
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 <div class="box">
17 <div class="box box-left">
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 ${h.form(url('admin_settings_my_account_update'),method='put')}
23 ${h.form(url('admin_settings_my_account_update'),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="username">${_('Username')}:</label>
29 <label for="username">${_('Username')}:</label>
30 </div>
30 </div>
31 <div class="input">
31 <div class="input">
32 ${h.text('username')}
32 ${h.text('username')}
33 </div>
33 </div>
34 </div>
34 </div>
35
35
36 <div class="field">
36 <div class="field">
37 <div class="label">
37 <div class="label">
38 <label for="new_password">${_('New password')}:</label>
38 <label for="new_password">${_('New password')}:</label>
39 </div>
39 </div>
40 <div class="input">
40 <div class="input">
41 ${h.password('new_password')}
41 ${h.password('new_password')}
42 </div>
42 </div>
43 </div>
43 </div>
44
44
45 <div class="field">
45 <div class="field">
46 <div class="label">
46 <div class="label">
47 <label for="name">${_('Name')}:</label>
47 <label for="name">${_('Name')}:</label>
48 </div>
48 </div>
49 <div class="input">
49 <div class="input">
50 ${h.text('name')}
50 ${h.text('name')}
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="lastname">${_('Lastname')}:</label>
56 <label for="lastname">${_('Lastname')}:</label>
57 </div>
57 </div>
58 <div class="input">
58 <div class="input">
59 ${h.text('lastname')}
59 ${h.text('lastname')}
60 </div>
60 </div>
61 </div>
61 </div>
62
62
63 <div class="field">
63 <div class="field">
64 <div class="label">
64 <div class="label">
65 <label for="email">${_('Email')}:</label>
65 <label for="email">${_('Email')}:</label>
66 </div>
66 </div>
67 <div class="input">
67 <div class="input">
68 ${h.text('email')}
68 ${h.text('email')}
69 </div>
69 </div>
70 </div>
70 </div>
71
71
72 <div class="buttons">
72 <div class="buttons">
73 ${h.submit('save','save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
73 ${h.submit('save','save',class_="ui-button ui-widget ui-state-default ui-corner-all")}
74 </div>
74 </div>
75 </div>
75 </div>
76 </div>
76 </div>
77 ${h.end_form()}
77 ${h.end_form()}
78 </div>
78 </div>
79
80 <div class="box box-right">
81 <!-- box / title -->
82 <div class="title">
83 <h5>${_('My repositories')}</h5>
84 </div>
85 <!-- end box / title -->
86 <div class="table">
87 <table>
88 <tbody>
89 %for repo in c.user_repos:
90 <tr>
91 <td>
92 %if repo.dbrepo.private:
93 <img alt="${_('private')}" src="/images/icons/lock.png"/>
94 %else:
95 <img alt="${_('public')}" src="/images/icons/lock_open.png"/>
96 %endif
97
98 ${h.link_to(repo.name, h.url('summary_home',repo_name=repo.name))}</td>
99 ##<td>${_('created')} ${repo.dbrepo.}</td>
100 <td>${_('last changed')} ${h.age(repo.last_change)}</td>
101 <td>${h.link_to(_('[edit]'),h.url('edit_repo',repo_name=repo.name))}</td>
102 </tr>
103 %endfor
104 </tbody>
105 </table>
106 </div>
107
108 </div>
79 </%def> No newline at end of file
109 </%def>
General Comments 0
You need to be logged in to leave comments. Login now