##// END OF EJS Templates
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
marcink -
r1345:3bce31f0 beta
parent child Browse files
Show More
@@ -0,0 +1,133 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.model.user_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 users groups model for RhodeCode
7
8 :created_on: Jan 25, 2011
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
26 import os
27 import logging
28 import traceback
29
30 from pylons.i18n.translation import _
31
32 from vcs.utils.lazy import LazyProperty
33
34 from rhodecode.model import BaseModel
35 from rhodecode.model.caching_query import FromCache
36 from rhodecode.model.db import Group, RhodeCodeUi
37
38 log = logging.getLogger(__name__)
39
40
41 class ReposGroupModel(BaseModel):
42
43 @LazyProperty
44 def repos_path(self):
45 """
46 Get's the repositories root path from database
47 """
48
49 q = RhodeCodeUi.get_by_key('/').one()
50 return q.ui_value
51
52 def __create_group(self, group_name, parent_id):
53 """
54 makes repositories group on filesystem
55
56 :param repo_name:
57 :param parent_id:
58 """
59
60 if parent_id:
61 parent_group_name = Group.get(parent_id).group_name
62 else:
63 parent_group_name = ''
64
65 create_path = os.path.join(self.repos_path, parent_group_name,
66 group_name)
67 log.debug('creating new group in %s', create_path)
68
69 if os.path.isdir(create_path):
70 raise Exception('That directory already exists !')
71
72
73 os.makedirs(create_path)
74
75
76 def __rename_group(self, group_name):
77 """
78 Renames a group on filesystem
79
80 :param group_name:
81 """
82 pass
83
84 def __delete_group(self, group_name):
85 """
86 Deletes a group from a filesystem
87
88 :param group_name:
89 """
90 pass
91
92 def create(self, form_data):
93 try:
94 new_repos_group = Group()
95 new_repos_group.group_name = form_data['repos_group_name']
96 new_repos_group.group_description = \
97 form_data['repos_group_description']
98 new_repos_group.group_parent_id = form_data['repos_group_parent']
99
100 self.sa.add(new_repos_group)
101
102 self.__create_group(form_data['repos_group_name'],
103 form_data['repos_group_parent'])
104
105 self.sa.commit()
106 except:
107 log.error(traceback.format_exc())
108 self.sa.rollback()
109 raise
110
111 def update(self, repos_group_id, form_data):
112
113 try:
114 repos_group = Group.get(repos_group_id)
115
116
117
118 self.sa.add(repos_group)
119 self.sa.commit()
120 except:
121 log.error(traceback.format_exc())
122 self.sa.rollback()
123 raise
124
125 def delete(self, users_group_id):
126 try:
127 users_group = self.get(users_group_id, cache=False)
128 self.sa.delete(users_group)
129 self.sa.commit()
130 except:
131 log.error(traceback.format_exc())
132 self.sa.rollback()
133 raise
@@ -0,0 +1,64 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${_('Add repos group')} - ${c.rhodecode_name}
6 </%def>
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 &raquo;
10 ${h.link_to(_('Repos groups'),h.url('repos_groups'))}
11 &raquo;
12 ${_('add new repos group')}
13 </%def>
14
15 <%def name="page_nav()">
16 ${self.menu('admin')}
17 </%def>
18
19 <%def name="main()">
20 <div class="box">
21 <!-- box / title -->
22 <div class="title">
23 ${self.breadcrumbs()}
24 </div>
25 <!-- end box / title -->
26 ${h.form(url('repos_groups'))}
27 <div class="form">
28 <!-- fields -->
29 <div class="fields">
30 <div class="field">
31 <div class="label">
32 <label for="users_group_name">${_('Group name')}:</label>
33 </div>
34 <div class="input">
35 ${h.text('repos_group_name',class_='medium')}
36 </div>
37 </div>
38
39 <div class="field">
40 <div class="label label-textarea">
41 <label for="description">${_('Description')}:</label>
42 </div>
43 <div class="textarea text-area editor">
44 ${h.textarea('repos_group_description',cols=23,rows=5,class_="medium")}
45 </div>
46 </div>
47
48 <div class="field">
49 <div class="label">
50 <label for="repo_group">${_('Group parent')}:</label>
51 </div>
52 <div class="input">
53 ${h.select('repos_group_parent','',c.repo_groups,class_="medium")}
54 </div>
55 </div>
56
57 <div class="buttons">
58 ${h.submit('save','save',class_="ui-button")}
59 </div>
60 </div>
61 </div>
62 ${h.end_form()}
63 </div>
64 </%def> No newline at end of file
@@ -0,0 +1,68 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${_('Repositories groups administration')} - ${c.rhodecode_name}
6 </%def>
7
8
9 <%def name="breadcrumbs_links()">
10 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Repositories')}
11 </%def>
12 <%def name="page_nav()">
13 ${self.menu('admin')}
14 </%def>
15 <%def name="main()">
16 <div class="box">
17 <!-- box / title -->
18 <div class="title">
19 ${self.breadcrumbs()}
20 <ul class="links">
21 <li>
22 <span>${h.link_to(u'ADD NEW GROUP',h.url('new_repos_group'))}</span>
23 </li>
24 </ul>
25 </div>
26 <!-- end box / title -->
27 <div class="table">
28 % if c.groups:
29 <table class="table_disp">
30
31 <thead>
32 <tr>
33 <th class="left"><a href="#">${_('Group name')}</a></th>
34 <th class="left"><a href="#">${_('Description')}</a></th>
35 <th class="left"><a href="#">${_('Number of repositories')}</a></th>
36 <th class="left">${_('action')}</th>
37 </tr>
38 </thead>
39
40 ## REPO GROUPS
41
42 % for gr in c.groups:
43 <tr>
44 <td>
45 <div style="white-space: nowrap">
46 <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
47 ${h.link_to(h.literal(' &raquo; '.join([g.group_name for g in gr.parents+[gr]])),url('edit_repos_group',id=gr.group_id))}
48 </div>
49 </td>
50 <td>${gr.group_description}</td>
51 <td><b>${gr.repositories.count()}</b></td>
52 <td>
53 ${h.form(url('repos_group', id=gr.group_id),method='delete')}
54 ${h.submit('remove_%s' % gr.group_name,'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this group');")}
55 ${h.end_form()}
56 </td>
57 </tr>
58 % endfor
59
60 </table>
61 % else:
62 {_('There are no repositories groups yet')}
63 % endif
64
65 </div>
66 </div>
67
68 </%def>
@@ -74,6 +74,8 b' class ReposController(BaseController):'
74
74
75 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
75 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
76 x in self.sa.query(Group).all()])
76 x in self.sa.query(Group).all()])
77 c.repo_groups = sorted(c.repo_groups,
78 key=lambda t: t[1].split('&raquo;')[0])
77 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
79 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
78 c.users_array = repo_model.get_users_js()
80 c.users_array = repo_model.get_users_js()
79 c.users_groups_array = repo_model.get_users_groups_js()
81 c.users_groups_array = repo_model.get_users_groups_js()
@@ -1,11 +1,21 b''
1 import logging
1 import logging
2 import traceback
3 import formencode
4
5 from formencode import htmlfill
2 from operator import itemgetter
6 from operator import itemgetter
3
7
4 from pylons import request, response, session, tmpl_context as c, url
8 from pylons import request, response, session, tmpl_context as c, url
5 from pylons.controllers.util import abort, redirect
9 from pylons.controllers.util import abort, redirect
10 from pylons.i18n.translation import _
6
11
12 from rhodecode.lib import helpers as h
13 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
14 HasPermissionAnyDecorator
7 from rhodecode.lib.base import BaseController, render
15 from rhodecode.lib.base import BaseController, render
8 from rhodecode.model.db import Group
16 from rhodecode.model.db import Group
17 from rhodecode.model.repos_group import ReposGroupModel
18 from rhodecode.model.forms import ReposGroupForm
9
19
10 log = logging.getLogger(__name__)
20 log = logging.getLogger(__name__)
11
21
@@ -16,18 +26,73 b' class ReposGroupsController(BaseControll'
16 # file has a resource setup:
26 # file has a resource setup:
17 # map.resource('repos_group', 'repos_groups')
27 # map.resource('repos_group', 'repos_groups')
18
28
29 def __load_defaults(self):
30
31 c.repo_groups = [('', '')]
32 parents_link = lambda k: h.literal('&raquo;'.join(
33 map(lambda k: k.group_name,
34 k.parents + [k])
35 )
36 )
37
38 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
39 x in self.sa.query(Group).all()])
40
41 c.repo_groups = sorted(c.repo_groups,
42 key=lambda t: t[1].split('&raquo;')[0])
43 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
44
45 @LoginRequired()
46 def __before__(self):
47 super(ReposGroupsController, self).__before__()
48
49 @HasPermissionAnyDecorator('hg.admin')
19 def index(self, format='html'):
50 def index(self, format='html'):
20 """GET /repos_groups: All items in the collection"""
51 """GET /repos_groups: All items in the collection"""
21 # url('repos_groups')
52 # url('repos_groups')
22
53
54 sk = lambda g:g.parents[0].group_name if g.parents else g.group_name
55 c.groups = sorted(Group.query().all(), key=sk)
56 return render('admin/repos_groups/repos_groups_show.html')
57
58 @HasPermissionAnyDecorator('hg.admin')
23 def create(self):
59 def create(self):
24 """POST /repos_groups: Create a new item"""
60 """POST /repos_groups: Create a new item"""
25 # url('repos_groups')
61 # url('repos_groups')
62 self.__load_defaults()
63 repos_group_model = ReposGroupModel()
64 repos_group_form = ReposGroupForm(available_groups=
65 c.repo_groups_choices)()
66 try:
67 form_result = repos_group_form.to_python(dict(request.POST))
68 repos_group_model.create(form_result)
69 h.flash(_('created repos group %s') \
70 % form_result['repos_group_name'], category='success')
71 #TODO: in futureaction_logger(, '', '', '', self.sa)
72 except formencode.Invalid, errors:
26
73
74 return htmlfill.render(
75 render('admin/repos_groups/repos_groups_add.html'),
76 defaults=errors.value,
77 errors=errors.error_dict or {},
78 prefix_error=False,
79 encoding="UTF-8")
80 except Exception:
81 log.error(traceback.format_exc())
82 h.flash(_('error occurred during creation of repos group %s') \
83 % request.POST.get('repos_group_name'), category='error')
84
85 return redirect(url('repos_groups'))
86
87
88 @HasPermissionAnyDecorator('hg.admin')
27 def new(self, format='html'):
89 def new(self, format='html'):
28 """GET /repos_groups/new: Form to create a new item"""
90 """GET /repos_groups/new: Form to create a new item"""
29 # url('new_repos_group')
91 # url('new_repos_group')
92 self.__load_defaults()
93 return render('admin/repos_groups/repos_groups_add.html')
30
94
95 @HasPermissionAnyDecorator('hg.admin')
31 def update(self, id):
96 def update(self, id):
32 """PUT /repos_groups/id: Update an existing item"""
97 """PUT /repos_groups/id: Update an existing item"""
33 # Forms posted to this method should contain a hidden field:
98 # Forms posted to this method should contain a hidden field:
@@ -37,6 +102,7 b' class ReposGroupsController(BaseControll'
37 # method='put')
102 # method='put')
38 # url('repos_group', id=ID)
103 # url('repos_group', id=ID)
39
104
105 @HasPermissionAnyDecorator('hg.admin')
40 def delete(self, id):
106 def delete(self, id):
41 """DELETE /repos_groups/id: Delete an existing item"""
107 """DELETE /repos_groups/id: Delete an existing item"""
42 # Forms posted to this method should contain a hidden field:
108 # Forms posted to this method should contain a hidden field:
@@ -88,6 +154,7 b' class ReposGroupsController(BaseControll'
88
154
89 return render('admin/repos_groups/repos_groups.html')
155 return render('admin/repos_groups/repos_groups.html')
90
156
157 @HasPermissionAnyDecorator('hg.admin')
91 def edit(self, id, format='html'):
158 def edit(self, id, format='html'):
92 """GET /repos_groups/id/edit: Form to edit an existing item"""
159 """GET /repos_groups/id/edit: Form to edit an existing item"""
93 # url('edit_repos_group', id=ID)
160 # url('edit_repos_group', id=ID)
@@ -332,6 +332,8 b' class SettingsController(BaseController)'
332
332
333 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
333 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
334 x in self.sa.query(Group).all()])
334 x in self.sa.query(Group).all()])
335 c.repo_groups = sorted(c.repo_groups,
336 key=lambda t: t[1].split('&raquo;')[0])
335 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
337 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
336
338
337 new_repo = request.GET.get('repo', '')
339 new_repo = request.GET.get('repo', '')
@@ -66,8 +66,7 b' class HomeController(BaseController):'
66 c.repo_cnt = len(c.repos_list)
66 c.repo_cnt = len(c.repos_list)
67
67
68
68
69 c.groups = self.sa.query(Group)\
69 c.groups = Group.query().filter(Group.group_parent_id == None).all()
70 .filter(Group.group_parent_id == None).all()
71
70
72
71
73 return render('/index.html')
72 return render('/index.html')
@@ -107,6 +107,11 b' class RhodeCodeUi(Base):'
107 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
107 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
108
108
109
109
110 @classmethod
111 def get_by_key(cls, key):
112 return Session.query(cls).filter(cls.ui_key == key)
113
114
110 class User(Base):
115 class User(Base):
111 __tablename__ = 'users'
116 __tablename__ = 'users'
112 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
117 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
@@ -296,7 +301,7 b' class Repository(Base):'
296
301
297 class Group(Base):
302 class Group(Base):
298 __tablename__ = 'groups'
303 __tablename__ = 'groups'
299 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
304 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'), {'useexisting':True},)
300 __mapper_args__ = {'order_by':'group_name'}
305 __mapper_args__ = {'order_by':'group_name'}
301
306
302 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
307 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -35,7 +35,6 b' from webhelpers.pylonslib.secure_form im'
35 from rhodecode.lib.utils import repo_name_slug
35 from rhodecode.lib.utils import repo_name_slug
36 from rhodecode.lib.auth import authenticate, get_crypt_password
36 from rhodecode.lib.auth import authenticate, get_crypt_password
37 from rhodecode.lib.exceptions import LdapImportError
37 from rhodecode.lib.exceptions import LdapImportError
38 from rhodecode.model import meta
39 from rhodecode.model.user import UserModel
38 from rhodecode.model.user import UserModel
40 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.repo import RepoModel
41 from rhodecode.model.db import User, UsersGroup, Group
40 from rhodecode.model.db import User, UsersGroup, Group
@@ -117,6 +116,27 b' def ValidUsersGroup(edit, old_data):'
117 return _ValidUsersGroup
116 return _ValidUsersGroup
118
117
119
118
119 def ValidReposGroup(edit, old_data):
120
121 class _ValidReposGroup(formencode.validators.FancyValidator):
122
123 def validate_python(self, value, state):
124 #TODO WRITE VALIDATIONS
125 group_name = value.get('repos_group_name')
126 parent_id = value.get('repos_group_parent')
127
128 # slugify repo group just in case :)
129 slug = repo_name_slug(group_name)
130
131 # check filesystem
132 gr = Group.query().filter(Group.group_name == slug)\
133 .filter(Group.group_parent_id == parent_id).scalar()
134
135 if gr:
136 e_dict = {'repos_group_name':_('This group already exists')}
137 raise formencode.Invalid('', value, state,
138 error_dict=e_dict)
139 return _ValidReposGroup
120
140
121 class ValidPassword(formencode.validators.FancyValidator):
141 class ValidPassword(formencode.validators.FancyValidator):
122
142
@@ -193,17 +213,13 b' class ValidAuth(formencode.validators.Fa'
193 class ValidRepoUser(formencode.validators.FancyValidator):
213 class ValidRepoUser(formencode.validators.FancyValidator):
194
214
195 def to_python(self, value, state):
215 def to_python(self, value, state):
196 sa = meta.Session()
197 try:
216 try:
198 self.user_db = sa.query(User)\
217 self.user_db = User.query()\
199 .filter(User.active == True)\
218 .filter(User.active == True)\
200 .filter(User.username == value).one()
219 .filter(User.username == value).one()
201 except Exception:
220 except Exception:
202 raise formencode.Invalid(_('This username is not valid'),
221 raise formencode.Invalid(_('This username is not valid'),
203 value, state)
222 value, state)
204 finally:
205 meta.Session.remove()
206
207 return value
223 return value
208
224
209 def ValidRepoName(edit, old_data):
225 def ValidRepoName(edit, old_data):
@@ -222,6 +238,7 b' def ValidRepoName(edit, old_data):'
222 gr = Group.get(value.get('repo_group'))
238 gr = Group.get(value.get('repo_group'))
223 group_path = gr.full_path
239 group_path = gr.full_path
224 # value needs to be aware of group name
240 # value needs to be aware of group name
241 # it has to use '/'
225 repo_name_full = group_path + '/' + repo_name
242 repo_name_full = group_path + '/' + repo_name
226 else:
243 else:
227 group_path = ''
244 group_path = ''
@@ -250,13 +267,13 b' def ValidRepoName(edit, old_data):'
250
267
251 return _ValidRepoName
268 return _ValidRepoName
252
269
253 def SlugifyRepo():
270 def SlugifyName():
254 class _SlugifyRepo(formencode.validators.FancyValidator):
271 class _SlugifyName(formencode.validators.FancyValidator):
255
272
256 def to_python(self, value, state):
273 def to_python(self, value, state):
257 return repo_name_slug(value)
274 return repo_name_slug(value)
258
275
259 return _SlugifyRepo
276 return _SlugifyName
260
277
261 def ValidCloneUri():
278 def ValidCloneUri():
262 from mercurial.httprepo import httprepository, httpsrepository
279 from mercurial.httprepo import httprepository, httpsrepository
@@ -331,15 +348,14 b' class ValidPerms(formencode.validators.F'
331 value['perms_new'] = perms_new
348 value['perms_new'] = perms_new
332
349
333 #update permissions
350 #update permissions
334 sa = meta.Session
335 for k, v, t in perms_new:
351 for k, v, t in perms_new:
336 try:
352 try:
337 if t is 'user':
353 if t is 'user':
338 self.user_db = sa.query(User)\
354 self.user_db = User.query()\
339 .filter(User.active == True)\
355 .filter(User.active == True)\
340 .filter(User.username == k).one()
356 .filter(User.username == k).one()
341 if t is 'users_group':
357 if t is 'users_group':
342 self.user_db = sa.query(UsersGroup)\
358 self.user_db = UsersGroup.query()\
343 .filter(UsersGroup.users_group_active == True)\
359 .filter(UsersGroup.users_group_active == True)\
344 .filter(UsersGroup.users_group_name == k).one()
360 .filter(UsersGroup.users_group_name == k).one()
345
361
@@ -373,15 +389,11 b' def UniqSystemEmail(old_data):'
373 def to_python(self, value, state):
389 def to_python(self, value, state):
374 value = value.lower()
390 value = value.lower()
375 if old_data.get('email') != value:
391 if old_data.get('email') != value:
376 sa = meta.Session()
392 user = User.query().filter(User.email == value).scalar()
377 try:
393 if user:
378 user = sa.query(User).filter(User.email == value).scalar()
394 raise formencode.Invalid(
379 if user:
395 _("This e-mail address is already taken"),
380 raise formencode.Invalid(_("This e-mail address is already taken") ,
396 value, state)
381 value, state)
382 finally:
383 meta.Session.remove()
384
385 return value
397 return value
386
398
387 return _UniqSystemEmail
399 return _UniqSystemEmail
@@ -389,14 +401,10 b' def UniqSystemEmail(old_data):'
389 class ValidSystemEmail(formencode.validators.FancyValidator):
401 class ValidSystemEmail(formencode.validators.FancyValidator):
390 def to_python(self, value, state):
402 def to_python(self, value, state):
391 value = value.lower()
403 value = value.lower()
392 sa = meta.Session
404 user = User.query().filter(User.email == value).scalar()
393 try:
405 if user is None:
394 user = sa.query(User).filter(User.email == value).scalar()
406 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
395 if user is None:
407 value, state)
396 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
397 value, state)
398 finally:
399 meta.Session.remove()
400
408
401 return value
409 return value
402
410
@@ -489,6 +497,23 b' def UsersGroupForm(edit=False, old_data='
489
497
490 return _UsersGroupForm
498 return _UsersGroupForm
491
499
500 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
501 class _ReposGroupForm(formencode.Schema):
502 allow_extra_fields = True
503 filter_extra_fields = True
504
505 repos_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
506 SlugifyName())
507 repos_group_description = UnicodeString(strip=True, min=1,
508 not_empty=True)
509 repos_group_parent = OneOf(available_groups, hideList=False,
510 testValueList=True,
511 if_missing=None, not_empty=False)
512
513 chained_validators = [ValidReposGroup(edit, old_data)]
514
515 return _ReposGroupForm
516
492 def RegisterForm(edit=False, old_data={}):
517 def RegisterForm(edit=False, old_data={}):
493 class _RegisterForm(formencode.Schema):
518 class _RegisterForm(formencode.Schema):
494 allow_extra_fields = True
519 allow_extra_fields = True
@@ -519,7 +544,7 b' def RepoForm(edit=False, old_data={}, su'
519 allow_extra_fields = True
544 allow_extra_fields = True
520 filter_extra_fields = False
545 filter_extra_fields = False
521 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
546 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
522 SlugifyRepo())
547 SlugifyName())
523 clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False),
548 clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False),
524 ValidCloneUri()())
549 ValidCloneUri()())
525 repo_group = OneOf(repo_groups, hideList=True)
550 repo_group = OneOf(repo_groups, hideList=True)
@@ -541,7 +566,7 b' def RepoForkForm(edit=False, old_data={}'
541 allow_extra_fields = True
566 allow_extra_fields = True
542 filter_extra_fields = False
567 filter_extra_fields = False
543 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
568 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
544 SlugifyRepo())
569 SlugifyName())
545 description = UnicodeString(strip=True, min=1, not_empty=True)
570 description = UnicodeString(strip=True, min=1, not_empty=True)
546 private = StringBoolean(if_missing=False)
571 private = StringBoolean(if_missing=False)
547 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
572 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
@@ -552,7 +577,7 b' def RepoSettingsForm(edit=False, old_dat'
552 allow_extra_fields = True
577 allow_extra_fields = True
553 filter_extra_fields = False
578 filter_extra_fields = False
554 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
579 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
555 SlugifyRepo())
580 SlugifyName())
556 description = UnicodeString(strip=True, min=1, not_empty=True)
581 description = UnicodeString(strip=True, min=1, not_empty=True)
557 private = StringBoolean(if_missing=False)
582 private = StringBoolean(if_missing=False)
558
583
@@ -477,6 +477,13 b' margin:0;'
477 padding:12px 9px 7px 24px;
477 padding:12px 9px 7px 24px;
478 }
478 }
479
479
480 #header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover {
481 background:url("../images/icons/database_link.png") no-repeat scroll 4px 9px #FFF;
482 width:167px;
483 margin:0;
484 padding:12px 9px 7px 24px;
485 }
486
480 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
487 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
481 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
488 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
482 width:167px;
489 width:167px;
@@ -26,7 +26,6 b''
26 </div>
26 </div>
27 <div class="input">
27 <div class="input">
28 ${h.select('repo_group','',c.repo_groups,class_="medium")}
28 ${h.select('repo_group','',c.repo_groups,class_="medium")}
29 <span>${h.link_to(_('add new group'),h.url(''))}</span>
30 </div>
29 </div>
31 </div>
30 </div>
32 <div class="field">
31 <div class="field">
@@ -49,7 +49,6 b''
49 </div>
49 </div>
50 <div class="input">
50 <div class="input">
51 ${h.select('repo_group','',c.repo_groups,class_="medium")}
51 ${h.select('repo_group','',c.repo_groups,class_="medium")}
52 <span>${h.link_to(_('add new group'),h.url(''))}</span>
53 </div>
52 </div>
54 </div>
53 </div>
55 <div class="field">
54 <div class="field">
@@ -322,6 +322,7 b''
322 <ul>
322 <ul>
323 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
323 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
324 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
324 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
325 <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
325 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
326 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
326 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
327 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
327 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
328 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
General Comments 0
You need to be logged in to leave comments. Login now