##// END OF EJS Templates
autocomplete for repository managment of users
marcink -
r298:15e96b5a default
parent child Browse files
Show More
@@ -1,181 +1,184 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # repos controller for pylons
3 # repos 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 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
7 # as published by the Free Software Foundation; version 2
8 # of the License or (at your opinion) any later version of the license.
8 # of the License or (at your opinion) any later version of the license.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
18 # MA 02110-1301, USA.
19 """
19 """
20 Created on April 7, 2010
20 Created on April 7, 2010
21 admin controller for pylons
21 admin controller for pylons
22 @author: marcink
22 @author: marcink
23 """
23 """
24 from operator import itemgetter
24 from operator import itemgetter
25 from pylons import request, response, session, tmpl_context as c, url, \
25 from pylons import request, response, session, tmpl_context as c, url, \
26 app_globals as g
26 app_globals as g
27 from pylons.controllers.util import abort, redirect
27 from pylons.controllers.util import abort, redirect
28 from pylons.i18n.translation import _
28 from pylons.i18n.translation import _
29 from pylons_app.lib import helpers as h
29 from pylons_app.lib import helpers as h
30 from pylons_app.lib.auth import LoginRequired
30 from pylons_app.lib.auth import LoginRequired
31 from pylons_app.lib.base import BaseController, render
31 from pylons_app.lib.base import BaseController, render
32 from pylons_app.lib.utils import invalidate_cache
32 from pylons_app.lib.utils import invalidate_cache
33 from pylons_app.model.repo_model import RepoModel
33 from pylons_app.model.repo_model import RepoModel
34 from pylons_app.model.hg_model import HgModel
34 from pylons_app.model.hg_model import HgModel
35 from pylons_app.model.forms import RepoForm
35 from pylons_app.model.forms import RepoForm
36 from pylons_app.model.meta import Session
36 from pylons_app.model.meta import Session
37 from datetime import datetime
37 from datetime import datetime
38 import formencode
38 import formencode
39 from formencode import htmlfill
39 from formencode import htmlfill
40 import logging
40 import logging
41 import os
41 import os
42 import shutil
42 import shutil
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45 class ReposController(BaseController):
45 class ReposController(BaseController):
46 """REST Controller styled on the Atom Publishing Protocol"""
46 """REST Controller styled on the Atom Publishing Protocol"""
47 # To properly map this controller, ensure your config/routing.py
47 # To properly map this controller, ensure your config/routing.py
48 # file has a resource setup:
48 # file has a resource setup:
49 # map.resource('repo', 'repos')
49 # map.resource('repo', 'repos')
50 @LoginRequired()
50 @LoginRequired()
51 def __before__(self):
51 def __before__(self):
52 c.admin_user = session.get('admin_user')
52 c.admin_user = session.get('admin_user')
53 c.admin_username = session.get('admin_username')
53 c.admin_username = session.get('admin_username')
54 super(ReposController, self).__before__()
54 super(ReposController, self).__before__()
55
55
56 def index(self, format='html'):
56 def index(self, format='html'):
57 """GET /repos: All items in the collection"""
57 """GET /repos: All items in the collection"""
58 # url('repos')
58 # url('repos')
59 cached_repo_list = HgModel().get_repos()
59 cached_repo_list = HgModel().get_repos()
60 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
60 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
61 return render('admin/repos/repos.html')
61 return render('admin/repos/repos.html')
62
62
63 def create(self):
63 def create(self):
64 """POST /repos: Create a new item"""
64 """POST /repos: Create a new item"""
65 # url('repos')
65 # url('repos')
66 repo_model = RepoModel()
66 repo_model = RepoModel()
67 _form = RepoForm()()
67 _form = RepoForm()()
68 try:
68 try:
69 form_result = _form.to_python(dict(request.POST))
69 form_result = _form.to_python(dict(request.POST))
70 repo_model.create(form_result, c.hg_app_user)
70 repo_model.create(form_result, c.hg_app_user)
71 invalidate_cache('cached_repo_list')
71 invalidate_cache('cached_repo_list')
72 h.flash(_('created repository %s') % form_result['repo_name'],
72 h.flash(_('created repository %s') % form_result['repo_name'],
73 category='success')
73 category='success')
74
74
75 except formencode.Invalid as errors:
75 except formencode.Invalid as errors:
76 c.form_errors = errors.error_dict
76 c.form_errors = errors.error_dict
77 c.new_repo = errors.value['repo_name']
77 c.new_repo = errors.value['repo_name']
78 return htmlfill.render(
78 return htmlfill.render(
79 render('admin/repos/repo_add.html'),
79 render('admin/repos/repo_add.html'),
80 defaults=errors.value,
80 defaults=errors.value,
81 encoding="UTF-8")
81 encoding="UTF-8")
82
82
83 except Exception:
83 except Exception:
84 h.flash(_('error occured during creation of repository %s') \
84 h.flash(_('error occured during creation of repository %s') \
85 % form_result['repo_name'], category='error')
85 % form_result['repo_name'], category='error')
86
86
87 return redirect('repos')
87 return redirect('repos')
88
88
89 def new(self, format='html'):
89 def new(self, format='html'):
90 """GET /repos/new: Form to create a new item"""
90 """GET /repos/new: Form to create a new item"""
91 new_repo = request.GET.get('repo', '')
91 new_repo = request.GET.get('repo', '')
92 c.new_repo = h.repo_name_slug(new_repo)
92 c.new_repo = h.repo_name_slug(new_repo)
93
93
94 return render('admin/repos/repo_add.html')
94 return render('admin/repos/repo_add.html')
95
95
96 def update(self, id):
96 def update(self, id):
97 """PUT /repos/id: Update an existing item"""
97 """PUT /repos/id: Update an existing item"""
98 # Forms posted to this method should contain a hidden field:
98 # Forms posted to this method should contain a hidden field:
99 # <input type="hidden" name="_method" value="PUT" />
99 # <input type="hidden" name="_method" value="PUT" />
100 # Or using helpers:
100 # Or using helpers:
101 # h.form(url('repo', id=ID),
101 # h.form(url('repo', id=ID),
102 # method='put')
102 # method='put')
103 # url('repo', id=ID)
103 # url('repo', id=ID)
104 repo_model = RepoModel()
104 repo_model = RepoModel()
105 _form = RepoForm(edit=True)()
105 _form = RepoForm(edit=True)()
106 try:
106 try:
107 form_result = _form.to_python(dict(request.POST))
107 form_result = _form.to_python(dict(request.POST))
108 repo_model.update(id, form_result)
108 repo_model.update(id, form_result)
109 invalidate_cache('cached_repo_list')
109 invalidate_cache('cached_repo_list')
110 h.flash(_('Repository %s updated succesfully' % id), category='success')
110 h.flash(_('Repository %s updated succesfully' % id), category='success')
111
111
112 except formencode.Invalid as errors:
112 except formencode.Invalid as errors:
113 c.repo_info = repo_model.get(id)
113 c.repo_info = repo_model.get(id)
114 c.users_array = repo_model.get_users_js()
114 errors.value.update({'user':c.repo_info.user.username})
115 errors.value.update({'user':c.repo_info.user.username})
115 c.form_errors = errors.error_dict
116 c.form_errors = errors.error_dict
116 return htmlfill.render(
117 return htmlfill.render(
117 render('admin/repos/repo_edit.html'),
118 render('admin/repos/repo_edit.html'),
118 defaults=errors.value,
119 defaults=errors.value,
119 encoding="UTF-8")
120 encoding="UTF-8")
120 except Exception:
121 except Exception:
121 h.flash(_('error occured during update of repository %s') \
122 h.flash(_('error occured during update of repository %s') \
122 % form_result['repo_name'], category='error')
123 % form_result['repo_name'], category='error')
123 return redirect(url('repos'))
124 return redirect(url('repos'))
124
125
125 def delete(self, id):
126 def delete(self, id):
126 """DELETE /repos/id: Delete an existing item"""
127 """DELETE /repos/id: Delete an existing item"""
127 # Forms posted to this method should contain a hidden field:
128 # Forms posted to this method should contain a hidden field:
128 # <input type="hidden" name="_method" value="DELETE" />
129 # <input type="hidden" name="_method" value="DELETE" />
129 # Or using helpers:
130 # Or using helpers:
130 # h.form(url('repo', id=ID),
131 # h.form(url('repo', id=ID),
131 # method='delete')
132 # method='delete')
132 # url('repo', id=ID)
133 # url('repo', id=ID)
133
134
134 repo_model = RepoModel()
135 repo_model = RepoModel()
135 repo = repo_model.get(id)
136 repo = repo_model.get(id)
136 if not repo:
137 if not repo:
137 h.flash(_('%s repository is not mapped to db perhaps'
138 h.flash(_('%s repository is not mapped to db perhaps'
138 ' it was moved or renamed from the filesystem'
139 ' it was moved or renamed from the filesystem'
139 ' please run the application again'
140 ' please run the application again'
140 ' in order to rescan repositories') % id, category='error')
141 ' in order to rescan repositories') % id, category='error')
141
142
142 return redirect(url('repos'))
143 return redirect(url('repos'))
143 try:
144 try:
144 repo_model.delete(repo)
145 repo_model.delete(repo)
145 invalidate_cache('cached_repo_list')
146 invalidate_cache('cached_repo_list')
146 h.flash(_('deleted repository %s') % id, category='success')
147 h.flash(_('deleted repository %s') % id, category='success')
147 except Exception:
148 except Exception:
148 h.flash(_('An error occured during deletion of %s') % id,
149 h.flash(_('An error occured during deletion of %s') % id,
149 category='error')
150 category='error')
150
151
151 return redirect(url('repos'))
152 return redirect(url('repos'))
152
153
153 def show(self, id, format='html'):
154 def show(self, id, format='html'):
154 """GET /repos/id: Show a specific item"""
155 """GET /repos/id: Show a specific item"""
155 # url('repo', id=ID)
156 # url('repo', id=ID)
156
157
157 def edit(self, id, format='html'):
158 def edit(self, id, format='html'):
158 """GET /repos/id/edit: Form to edit an existing item"""
159 """GET /repos/id/edit: Form to edit an existing item"""
159 # url('edit_repo', id=ID)
160 # url('edit_repo', id=ID)
160 repo_model = RepoModel()
161 repo_model = RepoModel()
161 c.repo_info = repo = repo_model.get(id)
162 c.repo_info = repo = repo_model.get(id)
162 if not repo:
163 if not repo:
163 h.flash(_('%s repository is not mapped to db perhaps'
164 h.flash(_('%s repository is not mapped to db perhaps'
164 ' it was created or renamed from the filesystem'
165 ' it was created or renamed from the filesystem'
165 ' please run the application again'
166 ' please run the application again'
166 ' in order to rescan repositories') % id, category='error')
167 ' in order to rescan repositories') % id, category='error')
167
168
168 return redirect(url('repos'))
169 return redirect(url('repos'))
169 defaults = c.repo_info.__dict__
170 defaults = c.repo_info.__dict__
170 defaults.update({'user':c.repo_info.user.username})
171 defaults.update({'user':c.repo_info.user.username})
171
172
173 c.users_array = repo_model.get_users_js()
174
172 for p in c.repo_info.repo2perm:
175 for p in c.repo_info.repo2perm:
173 defaults.update({'perm_%s' % p.user.username:
176 defaults.update({'perm_%s' % p.user.username:
174 p.permission.permission_name})
177 p.permission.permission_name})
175
178
176 return htmlfill.render(
179 return htmlfill.render(
177 render('admin/repos/repo_edit.html'),
180 render('admin/repos/repo_edit.html'),
178 defaults=defaults,
181 defaults=defaults,
179 encoding="UTF-8",
182 encoding="UTF-8",
180 force_defaults=False
183 force_defaults=False
181 )
184 )
@@ -1,145 +1,154 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # model for handling repositories actions
3 # model for handling repositories actions
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
7 # as published by the Free Software Foundation; version 2
8 # of the License or (at your opinion) any later version of the license.
8 # of the License or (at your opinion) any later version of the license.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
18 # MA 02110-1301, USA.
19
19
20 """
20 """
21 Created on Jun 5, 2010
21 Created on Jun 5, 2010
22 model for handling repositories actions
22 model for handling repositories actions
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from pylons_app.model.meta import Session
25 from pylons_app.model.meta import Session
26 from pylons_app.model.db import Repository, Repo2Perm, User, Permission
26 from pylons_app.model.db import Repository, Repo2Perm, User, Permission
27 import shutil
27 import shutil
28 import os
28 import os
29 from datetime import datetime
29 from datetime import datetime
30 from pylons_app.lib.utils import check_repo
30 from pylons_app.lib.utils import check_repo
31 from pylons import app_globals as g
31 from pylons import app_globals as g
32 import traceback
32 import traceback
33 import logging
33 import logging
34 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
35
35
36 class RepoModel(object):
36 class RepoModel(object):
37
37
38 def __init__(self):
38 def __init__(self):
39 self.sa = Session()
39 self.sa = Session()
40
40
41 def get(self, id):
41 def get(self, id):
42 return self.sa.query(Repository).get(id)
42 return self.sa.query(Repository).get(id)
43
43
44 def get_users_js(self):
45
46 users = self.sa.query(User).all()
47 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
48 users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
49 u.lastname, u.username)
50 for u in users])
51 return users_array
52
44
53
45 def update(self, repo_id, form_data):
54 def update(self, repo_id, form_data):
46 try:
55 try:
47 if repo_id != form_data['repo_name']:
56 if repo_id != form_data['repo_name']:
48 self.__rename_repo(repo_id, form_data['repo_name'])
57 self.__rename_repo(repo_id, form_data['repo_name'])
49 cur_repo = self.sa.query(Repository).get(repo_id)
58 cur_repo = self.sa.query(Repository).get(repo_id)
50 for k, v in form_data.items():
59 for k, v in form_data.items():
51 if k == 'user':
60 if k == 'user':
52 cur_repo.user_id = v
61 cur_repo.user_id = v
53 else:
62 else:
54 setattr(cur_repo, k, v)
63 setattr(cur_repo, k, v)
55
64
56 #update permissions
65 #update permissions
57 for username, perm in form_data['perms_updates']:
66 for username, perm in form_data['perms_updates']:
58 r2p = self.sa.query(Repo2Perm)\
67 r2p = self.sa.query(Repo2Perm)\
59 .filter(Repo2Perm.user == self.sa.query(User)\
68 .filter(Repo2Perm.user == self.sa.query(User)\
60 .filter(User.username == username).one())\
69 .filter(User.username == username).one())\
61 .filter(Repo2Perm.repository == repo_id).one()
70 .filter(Repo2Perm.repository == repo_id).one()
62
71
63 r2p.permission_id = self.sa.query(Permission).filter(
72 r2p.permission_id = self.sa.query(Permission).filter(
64 Permission.permission_name ==
73 Permission.permission_name ==
65 perm).one().permission_id
74 perm).one().permission_id
66 self.sa.add(r2p)
75 self.sa.add(r2p)
67
76
68 for username, perm in form_data['perms_new']:
77 for username, perm in form_data['perms_new']:
69 r2p = Repo2Perm()
78 r2p = Repo2Perm()
70 r2p.repository = repo_id
79 r2p.repository = repo_id
71 r2p.user = self.sa.query(User)\
80 r2p.user = self.sa.query(User)\
72 .filter(User.username == username).one()
81 .filter(User.username == username).one()
73
82
74 r2p.permission_id = self.sa.query(Permission).filter(
83 r2p.permission_id = self.sa.query(Permission).filter(
75 Permission.permission_name ==
84 Permission.permission_name ==
76 perm).one().permission_id
85 perm).one().permission_id
77 self.sa.add(r2p)
86 self.sa.add(r2p)
78
87
79 self.sa.add(cur_repo)
88 self.sa.add(cur_repo)
80 self.sa.commit()
89 self.sa.commit()
81 except:
90 except:
82 log.error(traceback.format_exc())
91 log.error(traceback.format_exc())
83 self.sa.rollback()
92 self.sa.rollback()
84 raise
93 raise
85
94
86 def create(self, form_data, cur_user, just_db=False):
95 def create(self, form_data, cur_user, just_db=False):
87 try:
96 try:
88 repo_name = form_data['repo_name']
97 repo_name = form_data['repo_name']
89 new_repo = Repository()
98 new_repo = Repository()
90 for k, v in form_data.items():
99 for k, v in form_data.items():
91 setattr(new_repo, k, v)
100 setattr(new_repo, k, v)
92
101
93 new_repo.user_id = cur_user.user_id
102 new_repo.user_id = cur_user.user_id
94 self.sa.add(new_repo)
103 self.sa.add(new_repo)
95
104
96 #create default permission
105 #create default permission
97 repo2perm = Repo2Perm()
106 repo2perm = Repo2Perm()
98 repo2perm.permission_id = self.sa.query(Permission)\
107 repo2perm.permission_id = self.sa.query(Permission)\
99 .filter(Permission.permission_name == 'repository.read')\
108 .filter(Permission.permission_name == 'repository.read')\
100 .one().permission_id
109 .one().permission_id
101
110
102 repo2perm.repository = repo_name
111 repo2perm.repository = repo_name
103 repo2perm.user_id = self.sa.query(User)\
112 repo2perm.user_id = self.sa.query(User)\
104 .filter(User.username == 'default').one().user_id
113 .filter(User.username == 'default').one().user_id
105
114
106 self.sa.add(repo2perm)
115 self.sa.add(repo2perm)
107 self.sa.commit()
116 self.sa.commit()
108 if not just_db:
117 if not just_db:
109 self.__create_repo(repo_name)
118 self.__create_repo(repo_name)
110 except:
119 except:
111 log.error(traceback.format_exc())
120 log.error(traceback.format_exc())
112 self.sa.rollback()
121 self.sa.rollback()
113 raise
122 raise
114
123
115 def delete(self, repo):
124 def delete(self, repo):
116 try:
125 try:
117 self.sa.delete(repo)
126 self.sa.delete(repo)
118 self.sa.commit()
127 self.sa.commit()
119 self.__delete_repo(repo.repo_name)
128 self.__delete_repo(repo.repo_name)
120 except:
129 except:
121 log.error(traceback.format_exc())
130 log.error(traceback.format_exc())
122 self.sa.rollback()
131 self.sa.rollback()
123 raise
132 raise
124
133
125 def __create_repo(self, repo_name):
134 def __create_repo(self, repo_name):
126 repo_path = os.path.join(g.base_path, repo_name)
135 repo_path = os.path.join(g.base_path, repo_name)
127 if check_repo(repo_name, g.base_path):
136 if check_repo(repo_name, g.base_path):
128 log.info('creating repo %s in %s', repo_name, repo_path)
137 log.info('creating repo %s in %s', repo_name, repo_path)
129 from vcs.backends.hg import MercurialRepository
138 from vcs.backends.hg import MercurialRepository
130 MercurialRepository(repo_path, create=True)
139 MercurialRepository(repo_path, create=True)
131
140
132 def __rename_repo(self, old, new):
141 def __rename_repo(self, old, new):
133 log.info('renaming repoo from %s to %s', old, new)
142 log.info('renaming repoo from %s to %s', old, new)
134 old_path = os.path.join(g.base_path, old)
143 old_path = os.path.join(g.base_path, old)
135 new_path = os.path.join(g.base_path, new)
144 new_path = os.path.join(g.base_path, new)
136 shutil.move(old_path, new_path)
145 shutil.move(old_path, new_path)
137
146
138 def __delete_repo(self, name):
147 def __delete_repo(self, name):
139 rm_path = os.path.join(g.base_path, name)
148 rm_path = os.path.join(g.base_path, name)
140 log.info("Removing %s", rm_path)
149 log.info("Removing %s", rm_path)
141 #disable hg
150 #disable hg
142 shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
151 shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
143 #disable repo
152 #disable repo
144 shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
153 shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
145 % (datetime.today(), name)))
154 % (datetime.today(), name)))
@@ -1,838 +1,946 b''
1 /*** Initial Settings ***/
1 /*** Initial Settings ***/
2 #mainhtml{
2 #mainhtml {
3 margin: 15px 50px;
3 margin: 15px 50px;
4 background: #DBD4C6;
4 background: #DBD4C6;
5 font-family: sans-serif;
5 font-family: sans-serif;
6 }
6 }
7
7 #mainhtml .breadcrumbs a:HOVER{
8 #mainhtml .breadcrumbs a:HOVER {
8 text-decoration: underline;
9 text-decoration: underline;
9 }
10 }
11
10 a {
12 a {
11 color: #556CB5;
13 color: #556CB5;
12 text-decoration: none;
14 text-decoration: none;
13 }
15 }
16
14 a:HOVER{
17 a:HOVER {
15 text-decoration: underline;
18 text-decoration: underline;
16 }
19 }
17
20
18 /*** end of Initial Settings ***/
21 /*** end of Initial Settings ***/
19
22
20 /*** ***/
23 /*** ***/
21 .table_disp {
24 .table_disp {
22 border-left: 0px solid #666666;
25 border-left: 0px solid #666666;
23 border-bottom: 1px solid #666666;
26 border-bottom: 1px solid #666666;
24 border-right: 1px solid #666666;
27 border-right: 1px solid #666666;
25 padding: 0px;
28 padding: 0px;
26 margin: 0px;
29 margin: 0px;
27 border-spacing: 0px;
30 border-spacing: 0px;
28 }
31 }
29
32
30 .table_disp .header {
33 .table_disp .header {
31 border-top: 1px solid #666666;
34 border-top: 1px solid #666666;
32 background-color: #556CB5;
35 background-color: #556CB5;
33 font-weight: bold;
36 font-weight: bold;
34 color: white;
37 color: white;
35 vertical-align: middle;
38 vertical-align: middle;
36 padding: 3px 5px;
39 padding: 3px 5px;
37 text-align: left;
40 text-align: left;
38 font-size: 0.9em;
41 font-size: 0.9em;
39 }
42 }
40
43
41 .table_disp .header td {
44 .table_disp .header td {
42 padding: 4px;
45 padding: 4px;
43 vertical-align: middle;
46 vertical-align: middle;
44 border-top: 1px solid #AAAAAA;
47 border-top: 1px solid #AAAAAA;
45 border-bottom: 2px solid #666666;
48 border-bottom: 2px solid #666666;
46 }
49 }
50
47 .table_disp td {
51 .table_disp td {
48 border-left: 1px solid #AAAAAA;
52 border-left: 1px solid #AAAAAA;
49 padding-left: 4px;
53 padding-left: 4px;
50 padding-right: 4px;
54 padding-right: 4px;
51 }
55 }
52
56
53 table tr.parity0:hover,table tr.parity1:hover {
57 table tr.parity0:hover,table tr.parity1:hover {
54 background: #D5E1E6;
58 background: #D5E1E6;
55 }
59 }
56
60
57 table tr.parity0 {
61 table tr.parity0 {
58 background: #EAEAE9;
62 background: #EAEAE9;
59 }
63 }
60
64
61 table tr.parity1 {
65 table tr.parity1 {
62 background: #FFFFFF;
66 background: #FFFFFF;
63 }
67 }
64
68
65
66 /*** ***/
69 /*** ***/
67
70
68 /** common settings **/
71 /** COMMON SETTINGS **/
69 .add_icon{
72 .add_icon {
70 background: url("/images/icons/add.png") no-repeat scroll 3px;
73 background: url("/images/icons/add.png") no-repeat scroll 3px;
71 height: 16px;
74 height: 16px;
72 padding-left: 20px;
75 padding-left: 20px;
73 padding-top: 0px;
76 padding-top: 0px;
74 text-align: left;
77 text-align: left;
78 }
75
79
76 }
77 .edit_icon{
80 .edit_icon {
78 background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
81 background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
79 height: 16px;
82 height: 16px;
80 padding-left: 20px;
83 padding-left: 20px;
81 padding-top: 0px;
84 padding-top: 0px;
82 text-align: left;
85 text-align: left;
83 }
86 }
84
87
85 .delete_icon{
88 .delete_icon {
86 background: url("/images/icons/delete.png") no-repeat scroll 3px;
89 background: url("/images/icons/delete.png") no-repeat scroll 3px;
87 height: 16px;
90 height: 16px;
88 padding-left: 20px;
91 padding-left: 20px;
89 padding-top: 0px;
92 padding-top: 0px;
90 text-align: left;
93 text-align: left;
91
92 }
94 }
93
95
94 .action_button{
96 .action_button {
95 border:0px;
97 border: 0px;
96 display: block;
98 display: block;
97 }
99 }
100
98 .action_button:hover{
101 .action_button:hover {
99 border:0px;
102 border: 0px;
100 font-style:italic;
103 font-style: italic;
101 cursor: pointer;
104 cursor: pointer;
102 }
105 }
103
106
104 .flash_msg ul{
107 .flash_msg ul {
105 margin:0;
108 margin: 0;
106 padding:25px 0px 0px 0px;
109 padding: 25px 0px 0px 0px;
110 }
107
111
108 }
109 .error_msg {
112 .error_msg {
110 background-color:#FFCFCF;
113 background-color: #FFCFCF;
111 background-image: url("/images/icons/error_msg.png");
114 background-image: url("/images/icons/error_msg.png");
112 border:1px solid #FF9595;
115 border: 1px solid #FF9595;
113 color:#CC3300;
116 color: #CC3300;
114 }
117 }
118
115 .warning_msg {
119 .warning_msg {
116 background-color:#FFFBCC;
120 background-color: #FFFBCC;
117 background-image: url("/images/icons/warning_msg.png");
121 background-image: url("/images/icons/warning_msg.png");
118 border:1px solid #FFF35E;
122 border: 1px solid #FFF35E;
119 color:#C69E00;
123 color: #C69E00;
120 }
124 }
125
121 .success_msg {
126 .success_msg {
122 background-color:#D5FFCF;
127 background-color: #D5FFCF;
123 background-image: url("/images/icons/success_msg.png");
128 background-image: url("/images/icons/success_msg.png");
124 border:1px solid #97FF88;
129 border: 1px solid #97FF88;
125 color:#009900;
130 color: #009900;
126 }
131 }
132
127 .notice_msg {
133 .notice_msg {
128 background-color:#DCE3FF;
134 background-color: #DCE3FF;
129 background-image: url("/images/icons/notice_msg.png");
135 background-image: url("/images/icons/notice_msg.png");
130 border:1px solid #93A8FF;
136 border: 1px solid #93A8FF;
131 color:#556CB5;
137 color: #556CB5;
132 }
138 }
133
139
134 .success_msg, .error_msg, .notice_msg, .warning_msg{
140 .success_msg,.error_msg,.notice_msg,.warning_msg {
135 background-position:10px center;
141 background-position: 10px center;
136 background-repeat:no-repeat;
142 background-repeat: no-repeat;
137 font-size:12px;
143 font-size: 12px;
138 font-weight:bold;
144 font-weight: bold;
139 min-height:14px;
145 min-height: 14px;
140 line-height:14px;
146 line-height: 14px;
141 margin-bottom:0px;
147 margin-bottom: 0px;
142 margin-top:0px;
148 margin-top: 0px;
143 padding:3px 10px 3px 40px;
149 padding: 3px 10px 3px 40px;
144 display:block;
150 display: block;
145 overflow: auto;
151 overflow: auto;
146 }
152 }
147
153
148 #msg_close {
154 #msg_close {
149 background:transparent url("icons/cross_grey_small.png") no-repeat scroll 0 0;
155 background: transparent url("icons/cross_grey_small.png") no-repeat
156 scroll 0 0;
150 cursor:pointer;
157 cursor: pointer;
151 height:16px;
158 height: 16px;
152 position:absolute;
159 position: absolute;
153 right:5px;
160 right: 5px;
154 top:5px;
161 top: 5px;
155 width:16px;
162 width: 16px;
156 }
163 }
157
164
158 .error-message{
165 .error-message {
159 color:#CC3300;
166 color: #CC3300;
160 }
167 }
161 /**** Tooltip ****/
168
162 .yui-overlay,
169 /**** TOOLTIP ****/
163 .yui-panel-container {
170 .yui-overlay,.yui-panel-container {
164 visibility:hidden;
171 visibility: hidden;
165 position:absolute;
172 position: absolute;
166 z-index: 2;
173 z-index: 2;
167 }
174 }
168
175
169 .yui-tt {
176 .yui-tt {
170 visibility:hidden;
177 visibility: hidden;
171 position:absolute;
178 position: absolute;
172 color:#666666;
179 color: #666666;
173 background-color:#FFFFFF;
180 background-color: #FFFFFF;
174 font-family:arial,helvetica,verdana,sans-serif;
181 font-family: arial, helvetica, verdana, sans-serif;
175 padding:8px;
182 padding: 8px;
176 border:2px solid #556CB5;
183 border: 2px solid #556CB5;
177 font:100% sans-serif;
184 font: 100% sans-serif;
178 width:auto;
185 width: auto;
179 opacity:1.0;
186 opacity: 1.0;
180 }
187 }
181
188
182 .yui-tt-shadow {
189 .yui-tt-shadow {
183 display: none;
190 display: none;
184 }
191 }
185 /** end of Tooltip **/
192
193 /** END TOOLTIP **/
194
195 /** AUTOCOMPLETE **/
196
197 .ac{
198 vertical-align: top;
199
200 }
201 .ac .match {
202 font-weight:bold;
203 }
204
205 .ac .yui-ac {
206 position: relative;
207 font-family: arial;
208 font-size: 100%;
209 }
210
211 .ac #perm_ac{
212 width:15em;
213 }
214 /* styles for input field */
215 .ac .yui-ac-input {
216 position: absolute;
217 width: 100%;
218 }
219
220 /* styles for results container */
221 .ac .yui-ac-container {
222 position: absolute;
223 top: 1.6em;
224 width: 100%;
225 }
186
226
227 /* styles for header/body/footer wrapper within container */
228 .ac .yui-ac-content {
229 position: absolute;
230 width: 100%;
231 border: 1px solid #808080;
232 background: #fff;
233 overflow: hidden;
234 z-index: 9050;
235 }
187
236
237 /* styles for container shadow */
238 .ac .yui-ac-shadow {
239 position: absolute;
240 margin: .3em;
241 width: 100%;
242 background: #000;
243 -moz-opacity: 0.10;
244 opacity: .10;
245 filter: alpha(opacity = 10);
246 z-index: 9049;
247 }
248
249 /* styles for results list */
250 .ac .yui-ac-content ul {
251 margin: 0;
252 padding: 0;
253 width: 100%;
254 }
255
256 /* styles for result item */
257 .ac .yui-ac-content li {
258 margin: 0;
259 padding: 2px 5px;
260 cursor: default;
261 white-space: nowrap;
262 }
263
264 /* styles for prehighlighted result item */
265 .ac .yui-ac-content li.yui-ac-prehighlight {
266 background: #B3D4FF;
267 }
268
269 /* styles for highlighted result item */
270 .ac .yui-ac-content li.yui-ac-highlight {
271 background: #556CB5;
272 color: #FFF;
273 }
274
275 /** END AUTOCOMPLETE **/
188 div#main {
276 div#main {
189 padding: 5px;
277 padding: 5px;
190 }
278 }
191
279
192 div#container {
280 div#container {
193 background: #FFFFFF;
281 background: #FFFFFF;
194 position: relative;
282 position: relative;
195 color: #666;
283 color: #666;
196 }
284 }
197
285
198 div.page-header {
286 div.page-header {
199 padding: 50px 20px 0;
287 padding: 50px 20px 0;
200 background: #556cb5 top left repeat-x;
288 background: #556cb5 top left repeat-x;
201 position: relative;
289 position: relative;
202 }
290 }
203
291
204 div.page-header h1 {
292 div.page-header h1 {
205 margin: 10px 0 30px;
293 margin: 10px 0 30px;
206 font-size: 1.8em;
294 font-size: 1.8em;
207 font-weight: bold;
295 font-weight: bold;
208 font-family: sans-serif;
296 font-family: sans-serif;
209 letter-spacing: 1px;
297 letter-spacing: 1px;
210 color: #FFFFFF;
298 color: #FFFFFF;
211 }
299 }
212
300
213 div.page-header h1 a {
301 div.page-header h1 a {
214 font-weight: bold;
302 font-weight: bold;
215 color: #FFFFFF;
303 color: #FFFFFF;
216 }
304 }
217
305
218 div.page-header a {
306 div.page-header a {
219 text-decoration: none;
307 text-decoration: none;
220 }
308 }
221
309
222 div.page-header form {
310 div.page-header form {
223 position: absolute;
311 position: absolute;
224 margin-bottom: 2px;
312 margin-bottom: 2px;
225 bottom: 0;
313 bottom: 0;
226 right: 20px;
314 right: 20px;
227 }
315 }
228
316
229 div.page-header form label {
317 div.page-header form label {
230 color: #DDD;
318 color: #DDD;
231 }
319 }
232
320
233 div.page-header form input {
321 div.page-header form input {
234 padding: 2px;
322 padding: 2px;
235 border: solid 1px #DDD;
323 border: solid 1px #DDD;
236 }
324 }
237
325
238 div.page-header form dl {
326 div.page-header form dl {
239 overflow: hidden;
327 overflow: hidden;
240 }
328 }
241
329
242 div.page-header form dl dt {
330 div.page-header form dl dt {
243 font-size: 1.2em;
331 font-size: 1.2em;
244 }
332 }
245
333
246 div.page-header form dl dt,div.page-header form dl dd {
334 div.page-header form dl dt,div.page-header form dl dd {
247 margin: 0 0 0 5px;
335 margin: 0 0 0 5px;
248 float: left;
336 float: left;
249 height: 24px;
337 height: 24px;
250 line-height: 20px;
338 line-height: 20px;
251 }
339 }
252
340
253 ul.page-nav {
341 ul.page-nav {
254 margin: 10px 0 0 0;
342 margin: 10px 0 0 0;
255 list-style-type: none;
343 list-style-type: none;
256 overflow: hidden;
344 overflow: hidden;
257 width: 800px;
345 width: 800px;
258 padding: 0;
346 padding: 0;
259 }
347 }
260
348
261 ul.page-nav li {
349 ul.page-nav li {
262 margin: 0 4px 0 0;
350 margin: 0 4px 0 0;
263 float: left;
351 float: left;
264 height: 24px;
352 height: 24px;
265 font-size: 1.1em;
353 font-size: 1.1em;
266 line-height: 24px;
354 line-height: 24px;
267 text-align: center;
355 text-align: center;
268 background: #556CB5;
356 background: #556CB5;
269 }
357 }
270
358
271 ul.page-nav li.current {
359 ul.page-nav li.current {
272 background: #FFF;
360 background: #FFF;
273 padding-right: 5px;
361 padding-right: 5px;
274 padding-left: 5px;
362 padding-left: 5px;
275 }
363 }
364
276 ul.page-nav li.current a {
365 ul.page-nav li.current a {
277 color: #556CB5;
366 color: #556CB5;
278 }
367 }
368
279 ul.page-nav li a {
369 ul.page-nav li a {
280 height: 24px;
370 height: 24px;
281 color: #FFF;
371 color: #FFF;
282 padding-right: 5px;
372 padding-right: 5px;
283 padding-left: 5px;
373 padding-left: 5px;
284 display: block;
374 display: block;
285 text-decoration: none;
375 text-decoration: none;
286 font-weight: bold;
376 font-weight: bold;
287 }
377 }
378
288 ul.page-nav li.logout a {
379 ul.page-nav li.logout a {
289 color: #FDAC9D;
380 color: #FDAC9D;
290 }
381 }
382
291 ul.page-nav li a:hover {
383 ul.page-nav li a:hover {
292 background: #FFF;
384 background: #FFF;
293 color: #556CB5;
385 color: #556CB5;
294 }
386 }
295
387
296 ul.submenu {
388 ul.submenu {
297 margin: 5px 0px -20px 0px;
389 margin: 5px 0px -20px 0px;
298 list-style-type: none;
390 list-style-type: none;
299 }
391 }
300
392
301 ul.submenu li {
393 ul.submenu li {
302 margin: 0 10px 0 0;
394 margin: 0 10px 0 0;
303 font-size: 0.9em;
395 font-size: 0.9em;
304 font-weight:bold;
396 font-weight: bold;
305 display: inline;
397 display: inline;
306 }
398 }
399
307 ul.submenu .repos {
400 ul.submenu .repos {
308 background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
401 background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
309 height: 16px;
402 height: 16px;
310 padding-left: 20px;
403 padding-left: 20px;
311 padding-top: 0px;
404 padding-top: 0px;
312 text-align: left;
405 text-align: left;
406 }
313
407
314 }
315 ul.submenu .users {
408 ul.submenu .users {
316 background: url("/images/icons/user_edit.png") no-repeat scroll 3px;
409 background: url("/images/icons/user_edit.png") no-repeat scroll 3px;
317 height: 16px;
410 height: 16px;
318 padding-left: 20px;
411 padding-left: 20px;
319 padding-top: 0px;
412 padding-top: 0px;
320 text-align: left;
413 text-align: left;
321 }
414 }
415
322 ul.submenu .permissions {
416 ul.submenu .permissions {
323 background: url("/images/icons/folder_key.png") no-repeat scroll 3px;
417 background: url("/images/icons/folder_key.png") no-repeat scroll 3px;
324 height: 16px;
418 height: 16px;
325 padding-left: 20px;
419 padding-left: 20px;
326 padding-top: 0px;
420 padding-top: 0px;
327 text-align: left;
421 text-align: left;
328 }
422 }
329
423
330 ul.submenu .current_submenu {
424 ul.submenu .current_submenu {
331 border-bottom: 2px solid #556CB5;
425 border-bottom: 2px solid #556CB5;
332 }
426 }
333
427
334 h2 {
428 h2 {
335 margin: 20px 0 10px;
429 margin: 20px 0 10px;
336 height: 30px;
430 height: 30px;
337 line-height: 30px;
431 line-height: 30px;
338 text-indent: 20px;
432 text-indent: 20px;
339 background: #FFF;
433 background: #FFF;
340 font-size: 1.2em;
434 font-size: 1.2em;
341 border-top: dotted 1px #D5E1E6;
435 border-top: dotted 1px #D5E1E6;
342 font-weight: bold;
436 font-weight: bold;
343 color:#556CB5;
437 color: #556CB5;
344 }
438 }
345
439
346 h2.no-link {
440 h2.no-link {
347 color: #006699;
441 color: #006699;
348 }
442 }
349
443
350 h2.no-border {
444 h2.no-border {
351 color: #FFF;
445 color: #FFF;
352 background: #556CB5;
446 background: #556CB5;
353 border: 0;
447 border: 0;
354 }
448 }
355
449
356 h2 a {
450 h2 a {
357 font-weight: bold;
451 font-weight: bold;
358 color: #006699;
452 color: #006699;
359 }
453 }
360
454
361 div.page-path {
455 div.page-path {
362 text-align: right;
456 text-align: right;
363 padding: 20px 30px 10px 0;
457 padding: 20px 30px 10px 0;
364 border: solid #d9d8d1;
458 border: solid #d9d8d1;
365 border-width: 0px 0px 1px;
459 border-width: 0px 0px 1px;
366 font-size: 1.2em;
460 font-size: 1.2em;
367 }
461 }
368
462
369 div.page-footer {
463 div.page-footer {
370 margin: 50px 0 0;
464 margin: 50px 0 0;
371 position: relative;
465 position: relative;
372 text-align: center;
466 text-align: center;
373 font-weight: bold;
467 font-weight: bold;
374 font-size: 90%;
468 font-size: 90%;
375 }
469 }
376
470
377 div.page-footer p {
471 div.page-footer p {
378 position: relative;
472 position: relative;
379 left: 20px;
473 left: 20px;
380 bottom: 5px;
474 bottom: 5px;
381 font-size: 1.2em;
475 font-size: 1.2em;
382 }
476 }
383
477
384 ul.rss-logo {
478 ul.rss-logo {
385 position: absolute;
479 position: absolute;
386 top: -10px;
480 top: -10px;
387 right: 20px;
481 right: 20px;
388 height: 20px;
482 height: 20px;
389 list-style-type: none;
483 list-style-type: none;
390 }
484 }
391
485
392 ul.rss-logo li {
486 ul.rss-logo li {
393 display: inline;
487 display: inline;
394 }
488 }
395
489
396 ul.rss-logo li a {
490 ul.rss-logo li a {
397 padding: 3px 6px;
491 padding: 3px 6px;
398 line-height: 10px;
492 line-height: 10px;
399 border: 1px solid;
493 border: 1px solid;
400 border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
494 border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
401 color: #ffffff;
495 color: #ffffff;
402 background-color: #ff6600;
496 background-color: #ff6600;
403 font-weight: bold;
497 font-weight: bold;
404 font-family: sans-serif;
498 font-family: sans-serif;
405 font-size: 10px;
499 font-size: 10px;
406 text-align: center;
500 text-align: center;
407 text-decoration: none;
501 text-decoration: none;
408 }
502 }
409
503
410 div.rss-logo li a:hover {
504 div.rss-logo li a:hover {
411 background-color: #ee5500;
505 background-color: #ee5500;
412 }
506 }
413
507
414 p.normal {
508 p.normal {
415 margin: 20px 0 20px 30px;
509 margin: 20px 0 20px 30px;
416 font-size: 1.2em;
510 font-size: 1.2em;
417 }
511 }
418
512
419 span.logtags span {
513 span.logtags span {
420 background-repeat: no-repeat;
514 background-repeat: no-repeat;
421 height: 16px;
515 height: 16px;
422 padding-left: 20px;
516 padding-left: 20px;
423 padding-top: 0px;
517 padding-top: 0px;
424 text-align: left;
518 text-align: left;
425 font-weight: bold;
519 font-weight: bold;
426 }
520 }
427
521
428 span.logtags span.tagtag {
522 span.logtags span.tagtag {
429 background-image: url("/images/icons/tag_green.png");
523 background-image: url("/images/icons/tag_green.png");
430 }
524 }
431
525
432 span.logtags span.branchtag {
526 span.logtags span.branchtag {
433 background-image: url("/images/icons/arrow_branch.png");
527 background-image: url("/images/icons/arrow_branch.png");
434 color: #628F53;
528 color: #628F53;
435 }
529 }
436
530
437 span.logtags span.inbranchtag {
531 span.logtags span.inbranchtag {
438 background-image: url("/images/icons/arrow_branch.png");
532 background-image: url("/images/icons/arrow_branch.png");
439 }
533 }
440
534
441 div.diff pre {
535 div.diff pre {
442 margin: 10px 0 0 0;
536 margin: 10px 0 0 0;
443 }
537 }
444
538
445 div.diff pre span {
539 div.diff pre span {
446 font-family: monospace;
540 font-family: monospace;
447 white-space: pre;
541 white-space: pre;
448 font-size: 1.2em;
542 font-size: 1.2em;
449 padding: 3px 0;
543 padding: 3px 0;
450 }
544 }
451
545
452 td.source {
546 td.source {
453 white-space: pre;
547 white-space: pre;
454 font-family: monospace;
548 font-family: monospace;
455 margin: 10px 30px 0;
549 margin: 10px 30px 0;
456 font-size: 1.2em;
550 font-size: 1.2em;
457 font-family: monospace;
551 font-family: monospace;
458 }
552 }
459
553
460 div.source div.parity0,div.source div.parity1 {
554 div.source div.parity0,div.source div.parity1 {
461 padding: 1px;
555 padding: 1px;
462 font-size: 1.2em;
556 font-size: 1.2em;
463 }
557 }
464
558
465 div.source div.parity0 {
559 div.source div.parity0 {
466 background: #F1F6F7;
560 background: #F1F6F7;
467 }
561 }
468
562
469 div.source div.parity1 {
563 div.source div.parity1 {
470 background: #FFFFFF;
564 background: #FFFFFF;
471 }
565 }
472
566
473 div.parity0:hover,div.parity1:hover {
567 div.parity0:hover,div.parity1:hover {
474 background: #D5E1E6;
568 background: #D5E1E6;
475 }
569 }
476
570
477 .linenr {
571 .linenr {
478 color: #999;
572 color: #999;
479 text-align: right;
573 text-align: right;
480 }
574 }
481
575
482 .lineno {
576 .lineno {
483 text-align: right;
577 text-align: right;
484 }
578 }
485
579
486 .lineno a {
580 .lineno a {
487 color: #999;
581 color: #999;
488 }
582 }
489
583
490 td.linenr {
584 td.linenr {
491 width: 60px;
585 width: 60px;
492 }
586 }
493
587
494 div#powered-by {
588 div#powered-by {
495 position: absolute;
589 position: absolute;
496 width: 75px;
590 width: 75px;
497 top: 15px;
591 top: 15px;
498 right: 20px;
592 right: 20px;
499 font-size: 1.2em;
593 font-size: 1.2em;
500 }
594 }
501
595
502 div#powered-by a {
596 div#powered-by a {
503 color: #EEE;
597 color: #EEE;
504 text-decoration: none;
598 text-decoration: none;
505 }
599 }
506
600
507 div#powered-by a:hover {
601 div#powered-by a:hover {
508 text-decoration: underline;
602 text-decoration: underline;
509 }
603 }
510
604
511 dl.overview {
605 dl.overview {
512 margin: 0 0 0 30px;
606 margin: 0 0 0 30px;
513 font-size: 1.1em;
607 font-size: 1.1em;
514 overflow: hidden;
608 overflow: hidden;
515 }
609 }
516
610
517 dl.overview dt,dl.overview dd {
611 dl.overview dt,dl.overview dd {
518 margin: 5px 0;
612 margin: 5px 0;
519 float: left;
613 float: left;
520 }
614 }
521
615
522 dl.overview dt {
616 dl.overview dt {
523 clear: left;
617 clear: left;
524 font-weight: bold;
618 font-weight: bold;
525 width: 150px;
619 width: 150px;
526 }
620 }
527
621
528 #clone_url{
622 #clone_url {
529 border: 0px;
623 border: 0px;
530 }
624 }
531 /** end of summary **/
532
625
533 /** chagelog **/
626 /** end of summary **/ /** chagelog **/
534 h3.changelog {
627 h3.changelog {
535 margin: 20px 0 5px 30px;
628 margin: 20px 0 5px 30px;
536 padding: 0 0 2px;
629 padding: 0 0 2px;
537 font-size: 1.4em;
630 font-size: 1.4em;
538 border-bottom: dotted 1px #D5E1E6;
631 border-bottom: dotted 1px #D5E1E6;
539 }
632 }
540
633
541 ul.changelog-entry {
634 ul.changelog-entry {
542 margin: 0 0 10px 30px;
635 margin: 0 0 10px 30px;
543 list-style-type: none;
636 list-style-type: none;
544 position: relative;
637 position: relative;
545 }
638 }
546
639
547 ul.changelog-entry li span.revdate {
640 ul.changelog-entry li span.revdate {
548 font-size: 1.1em;
641 font-size: 1.1em;
549 }
642 }
550
643
551 ul.changelog-entry li.age {
644 ul.changelog-entry li.age {
552 position: absolute;
645 position: absolute;
553 top: -25px;
646 top: -25px;
554 right: 10px;
647 right: 10px;
555 font-size: 1.4em;
648 font-size: 1.4em;
556 color: #CCC;
649 color: #CCC;
557 font-weight: bold;
650 font-weight: bold;
558 font-style: italic;
651 font-style: italic;
559 }
652 }
560
653
561 ul.changelog-entry li span.name {
654 ul.changelog-entry li span.name {
562 font-size: 1.2em;
655 font-size: 1.2em;
563 font-weight: bold;
656 font-weight: bold;
564 }
657 }
565
658
566 ul.changelog-entry li.description {
659 ul.changelog-entry li.description {
567 margin: 10px 0 0;
660 margin: 10px 0 0;
568 font-size: 1.1em;
661 font-size: 1.1em;
569 }
662 }
570
663
571 /** end of changelog **/
664 /** end of changelog **/ /** file **/
572
573 /** file **/
574 p.files {
665 p.files {
575 margin: 0 0 0 20px;
666 margin: 0 0 0 20px;
576 font-size: 2.0em;
667 font-size: 2.0em;
577 font-weight: bold;
668 font-weight: bold;
578 }
669 }
579
670
580 /** end of file **/
671 /** end of file **/ /** changeset **/
581
582 /** changeset **/
583 #changeset_content{
672 #changeset_content {
584 width:60%;
673 width: 60%;
585 float:left;
674 float: left;
586 }
675 }
587
676
588 #changeset_content .container .wrapper{
677 #changeset_content .container .wrapper {
589 width: 600px;
678 width: 600px;
590 }
679 }
680
591 #changeset_content .container{
681 #changeset_content .container {
592 border:1px solid #CCCCCC;
682 border: 1px solid #CCCCCC;
593 height:120px;
683 height: 120px;
594 }
684 }
595
685
596 #changeset_content .container .left{
686 #changeset_content .container .left {
597 float:left;
687 float: left;
598 width: 70%;
688 width: 70%;
599 padding-left: 5px;
689 padding-left: 5px;
600 }
690 }
601
691
602 #changeset_content .container .right{
692 #changeset_content .container .right {
603 float:right;
693 float: right;
604 width: 25%;
694 width: 25%;
605 text-align: right;
695 text-align: right;
606 }
696 }
607
697
608 #changeset_content .container .left .date{
698 #changeset_content .container .left .date {
609 font-weight:bold;
699 font-weight: bold;
610 }
700 }
701
611 #changeset_content .container .left .author{
702 #changeset_content .container .left .author {
612
703
613 }
704 }
705
614 #changeset_content .container .left .message{
706 #changeset_content .container .left .message {
615 font-style: italic;
707 font-style: italic;
616 color: #556CB5;
708 color: #556CB5;
617 }
709 }
618
710
619 .cs_files{
711 .cs_files {
620 width: 60%;
712 width: 60%;
621 }
713 }
622
714
623 .cs_files .cs_added{
715 .cs_files .cs_added {
624 background: url("/images/icons/page_white_add.png") no-repeat scroll 3px;
716 background: url("/images/icons/page_white_add.png") no-repeat scroll 3px;
625 /*background-color:#BBFFBB;*/
717 /*background-color:#BBFFBB;*/
626 height: 16px;
718 height: 16px;
627 padding-left: 20px;
719 padding-left: 20px;
628 margin-top: 7px;
720 margin-top: 7px;
629 text-align: left;
721 text-align: left;
630 }
722 }
723
631 .cs_files .cs_changed{
724 .cs_files .cs_changed {
632 background: url("/images/icons/page_white_edit.png") no-repeat scroll 3px;
725 background: url("/images/icons/page_white_edit.png") no-repeat scroll
726 3px;
633 /*background-color: #FFDD88;*/
727 /*background-color: #FFDD88;*/
634 height: 16px;
728 height: 16px;
635 padding-left: 20px;
729 padding-left: 20px;
636 margin-top: 7px;
730 margin-top: 7px;
637 text-align: left;
731 text-align: left;
638 }
732 }
733
639 .cs_files .cs_removed{
734 .cs_files .cs_removed {
640 background: url("/images/icons/page_white_delete.png") no-repeat scroll 3px;
735 background: url("/images/icons/page_white_delete.png") no-repeat scroll
736 3px;
641 /*background-color: #FF8888;*/
737 /*background-color: #FF8888;*/
642 height: 16px;
738 height: 16px;
643 padding-left: 20px;
739 padding-left: 20px;
644 margin-top: 7px;
740 margin-top: 7px;
645 text-align: left;
741 text-align: left;
646 }
742 }
647
743
648 /** end of changeset **/
744 /** end of changeset **/ /** canvas **/
649
650 /** canvas **/
651 #graph_nodes{
745 #graph_nodes {
652 margin-top:8px;
746 margin-top: 8px;
653 }
747 }
748
654 #graph{
749 #graph {
655 overflow: hidden;
750 overflow: hidden;
751 }
656
752
657 }
658 #graph_nodes{
753 #graph_nodes {
659 width:160px;
754 width: 160px;
660 float:left;
755 float: left;
661 }
756 }
662
757
663 #graph_content{
758 #graph_content {
664 width:800px;
759 width: 800px;
665 float:left;
760 float: left;
666 }
761 }
762
667 #graph_content .container_header{
763 #graph_content .container_header {
668 border:1px solid #CCCCCC;
764 border: 1px solid #CCCCCC;
669 height:30px;
765 height: 30px;
670 background: #EEEEEE;
766 background: #EEEEEE;
671 }
767 }
672
768
673
674 #graph_content .container .wrapper{
769 #graph_content .container .wrapper {
675 width: 600px;
770 width: 600px;
676 }
771 }
772
677 #graph_content .container{
773 #graph_content .container {
678 border-bottom: 1px solid #CCCCCC;
774 border-bottom: 1px solid #CCCCCC;
679 border-left: 1px solid #CCCCCC;
775 border-left: 1px solid #CCCCCC;
680 border-right: 1px solid #CCCCCC;
776 border-right: 1px solid #CCCCCC;
681 height:120px;
777 height: 120px;
682 }
778 }
683
779
684 #graph_content .container .left{
780 #graph_content .container .left {
685 float:left;
781 float: left;
686 width: 70%;
782 width: 70%;
687 padding-left: 5px;
783 padding-left: 5px;
688 }
784 }
689
785
690 #graph_content .container .right{
786 #graph_content .container .right {
691 float:right;
787 float: right;
692 width: 25%;
788 width: 25%;
693 text-align: right;
789 text-align: right;
694 }
790 }
791
695 #graph_content .container .left .date{
792 #graph_content .container .left .date {
696 font-weight:bold;
793 font-weight: bold;
697 }
794 }
795
698 #graph_content .container .left .author{
796 #graph_content .container .left .author {
699
797
700 }
798 }
799
701 #graph_content .container .left .message{
800 #graph_content .container .left .message {
702 font-size: 80%;
801 font-size: 80%;
703 }
802 }
704
803
705 .right div{
804 .right div {
706 clear: both;
805 clear: both;
707 }
806 }
807
708 .right .changes .added,.changed,.removed{
808 .right .changes .added,.changed,.removed {
709 border:1px solid #DDDDDD;
809 border: 1px solid #DDDDDD;
710 display:block;
810 display: block;
711 float:right;
811 float: right;
712 font-size:0.75em;
812 font-size: 0.75em;
713 text-align:center;
813 text-align: center;
714 min-width:15px;
814 min-width: 15px;
715 }
815 }
816
716 .right .changes .added{
817 .right .changes .added {
717 background:#BBFFBB;
818 background: #BBFFBB;
718 }
819 }
820
719 .right .changes .changed{
821 .right .changes .changed {
720 background: #FFDD88;
822 background: #FFDD88;
721 }
823 }
824
722 .right .changes .removed{
825 .right .changes .removed {
723 background: #FF8888;
826 background: #FF8888;
724 }
827 }
725
828
726 .right .merge{
829 .right .merge {
727 vertical-align: top;
830 vertical-align: top;
728 font-size: 60%;
831 font-size: 60%;
729 font-weight: bold;
832 font-weight: bold;
730 }
833 }
834
731 .right .merge img{
835 .right .merge img {
732 vertical-align: bottom;
836 vertical-align: bottom;
733 }
837 }
734
838
735 .right .parent{
839 .right .parent {
736 font-size: 90%;
840 font-size: 90%;
737 font-family: monospace;
841 font-family: monospace;
738 }
842 }
739 /** end of canvas **/
740
843
741 /* FILE BROWSER */
844 /** end of canvas **/ /* FILE BROWSER */
742 div.browserblock {
845 div.browserblock {
743 overflow: hidden;
846 overflow: hidden;
744 padding: 0px;
847 padding: 0px;
745 border: 1px solid #ccc;
848 border: 1px solid #ccc;
746 background: #f8f8f8;
849 background: #f8f8f8;
747 font-size: 100%;
850 font-size: 100%;
748 line-height: 100%;
851 line-height: 100%;
749 /* new */
852 /* new */
750 line-height: 125%;
853 line-height: 125%;
751 }
854 }
855
752 div.browserblock .browser-header{
856 div.browserblock .browser-header {
753 border-bottom: 1px solid #CCCCCC;
857 border-bottom: 1px solid #CCCCCC;
754 background: #EEEEEE;
858 background: #EEEEEE;
755 color:blue;
859 color: blue;
756 padding:10px 0 10px 0;
860 padding: 10px 0 10px 0;
757 }
861 }
862
758 div.browserblock .browser-header span{
863 div.browserblock .browser-header span {
759 margin-left:25px;
864 margin-left: 25px;
760 font-weight: bold;
865 font-weight: bold;
761 }
866 }
867
762 div.browserblock .browser-body{
868 div.browserblock .browser-body {
763 background: #EEEEEE;
869 background: #EEEEEE;
764 }
870 }
765
871
766 table.code-browser {
872 table.code-browser {
767 border-collapse:collapse;
873 border-collapse: collapse;
768 width: 100%;
874 width: 100%;
769 }
875 }
876
770 table.code-browser tr{
877 table.code-browser tr {
771 margin:3px;
878 margin: 3px;
772 }
879 }
773
880
774 table.code-browser thead th {
881 table.code-browser thead th {
775 background-color: #EEEEEE;
882 background-color: #EEEEEE;
776 height: 20px;
883 height: 20px;
777 font-size: 1.1em;
884 font-size: 1.1em;
778 font-weight: bold;
885 font-weight: bold;
779 text-align: center;
886 text-align: center;
780 text-align: left;
887 text-align: left;
781 padding-left: 10px;
888 padding-left: 10px;
782 }
889 }
890
783 table.code-browser tbody tr {
891 table.code-browser tbody tr {
784
892
785 }
893 }
786
894
787 table.code-browser tbody td {
895 table.code-browser tbody td {
788
789 padding-left:10px;
896 padding-left: 10px;
790 height: 20px;
897 height: 20px;
791 }
898 }
792
899
793 .info-table {
900 .info-table {
794 background: none repeat scroll 0 0 #FAFAFA;
901 background: none repeat scroll 0 0 #FAFAFA;
795 border-bottom: 1px solid #DDDDDD;
902 border-bottom: 1px solid #DDDDDD;
796 width: 100%;
903 width: 100%;
797 }
904 }
798
905
799 .rss_logo {
906 .rss_logo {
800 background: url("/images/icons/rss_16.png") no-repeat scroll 3px;
907 background: url("/images/icons/rss_16.png") no-repeat scroll 3px;
801 height: 16px;
908 height: 16px;
802 padding-left: 20px;
909 padding-left: 20px;
803 padding-top: 0px;
910 padding-top: 0px;
804 text-align: left;
911 text-align: left;
805 }
912 }
806
913
807 .atom_logo {
914 .atom_logo {
808 background: url("/images/icons/atom.png") no-repeat scroll 3px;
915 background: url("/images/icons/atom.png") no-repeat scroll 3px;
809 height: 16px;
916 height: 16px;
810 padding-left: 20px;
917 padding-left: 20px;
811 padding-top: 0px;
918 padding-top: 0px;
812 text-align: left;
919 text-align: left;
813 }
920 }
921
814 .archive_logo{
922 .archive_logo {
815 background: url("/images/icons/compress.png") no-repeat scroll 3px;
923 background: url("/images/icons/compress.png") no-repeat scroll 3px;
816 height: 16px;
924 height: 16px;
817 padding-left: 20px;
925 padding-left: 20px;
818 text-align: left;
926 text-align: left;
819 }
927 }
820
928
821 .browser-file {
929 .browser-file {
822 background: url("/images/icons/document_16.png") no-repeat scroll 3px;
930 background: url("/images/icons/document_16.png") no-repeat scroll 3px;
823 height: 16px;
931 height: 16px;
824 padding-left: 20px;
932 padding-left: 20px;
825 text-align: left;
933 text-align: left;
826 }
934 }
827
935
828 .browser-dir {
936 .browser-dir {
829 background: url("/images/icons/folder_16.png") no-repeat scroll 3px;
937 background: url("/images/icons/folder_16.png") no-repeat scroll 3px;
830 height: 16px;
938 height: 16px;
831 padding-left: 20px;
939 padding-left: 20px;
832 text-align: left;
940 text-align: left;
833 }
941 }
834
942
835 #repos_list {
943 #repos_list {
836 border: 1px solid #556CB5;
944 border: 1px solid #556CB5;
837 background: #FFFFFF;
945 background: #FFFFFF;
838 } No newline at end of file
946 }
@@ -1,109 +1,225 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 ${_('Repositories administration')}
5 ${_('Repositories administration')}
6 </%def>
6 </%def>
7 <%def name="breadcrumbs()">
7 <%def name="breadcrumbs()">
8 ${h.link_to(u'Admin',h.url('admin_home'))}
8 ${h.link_to(u'Admin',h.url('admin_home'))}
9 /
9 /
10 ${_('Repos')}
10 ${_('Repos')}
11 </%def>
11 </%def>
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 ${self.submenu('repos')}
14 ${self.submenu('repos')}
15 </%def>
15 </%def>
16 <%def name="main()">
16 <%def name="main()">
17 <div>
17 <div>
18 <h2>${_('Repositories')} - ${_('edit')}</h2>
18 <h2>${_('Repositories')} - ${_('edit')}</h2>
19 ${h.form(url('repo', id=c.repo_info.repo_name),method='put')}
19 ${h.form(url('repo', id=c.repo_info.repo_name),method='put')}
20 <table>
20 <table>
21 <tr>
21 <tr>
22 <td>${_('Name')}</td>
22 <td>${_('Name')}</td>
23 <td>${h.text('repo_name')}</td>
23 <td>${h.text('repo_name')}</td>
24 <td>${self.get_form_error('repo_name')}</td>
24 <td>${self.get_form_error('repo_name')}</td>
25 </tr>
25 </tr>
26 <tr>
26 <tr>
27 <td>${_('Description')}</td>
27 <td>${_('Description')}</td>
28 <td>${h.textarea('description',cols=23,rows=5)}</td>
28 <td>${h.textarea('description',cols=23,rows=5)}</td>
29 <td>${self.get_form_error('description')}</td>
29 <td>${self.get_form_error('description')}</td>
30 </tr>
30 </tr>
31 <tr>
31 <tr>
32 <td>${_('Private')}</td>
32 <td>${_('Private')}</td>
33 <td>${h.checkbox('private')}</td>
33 <td>${h.checkbox('private')}</td>
34 <td>${self.get_form_error('private')}</td>
34 <td>${self.get_form_error('private')}</td>
35 </tr>
35 </tr>
36 <tr>
36 <tr>
37 <td>${_('Owner')}</td>
37 <td>${_('Owner')}</td>
38 <td>${h.text('user')}</td>
38 <td class='ac'>
39 <div id="perm_ac">
40 ${h.text('user',class_='yui-ac-input')}
41 <div id="owner_container"></div>
42 </div>
43 </td>
39 <td>${self.get_form_error('user')}</td>
44 <td>${self.get_form_error('user')}</td>
40 </tr>
45 </tr>
41 <tr>
46 <tr>
42 <td>${_('Permissions')}</td>
47 <td>${_('Permissions')}</td>
43 <td>
48 <td>
44 <table>
49 <table>
45 <tr>
50 <tr>
46 <td>${_('none')}</td>
51 <td>${_('none')}</td>
47 <td>${_('read')}</td>
52 <td>${_('read')}</td>
48 <td>${_('write')}</td>
53 <td>${_('write')}</td>
49 <td>${_('admin')}</td>
54 <td>${_('admin')}</td>
50 <td>${_('user')}</td>
55 <td>${_('user')}</td>
51 </tr>
56 </tr>
52
57
53 %for r2p in c.repo_info.repo2perm:
58 %for r2p in c.repo_info.repo2perm:
54 <tr>
59 <tr>
55 <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
60 <td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
56 <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
61 <td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
57 <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
62 <td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
58 <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
63 <td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
59 <td>${r2p.user.username}</td>
64 <td>${r2p.user.username}</td>
60 </tr>
65 </tr>
61 %endfor
66 %endfor
62
63
64 <%
67 <%
65
66 if not hasattr(c,'form_errors'):
68 if not hasattr(c,'form_errors'):
67 d = 'display:none;'
69 d = 'display:none;'
68 else:
70 else:
69 d=''
71 d=''
70 %>
72 %>
71
73
72 <tr id="add_perm_input" style="${d}">
74 <tr id="add_perm_input" style="${d}">
73 <td>${h.radio('perm_new_user','repository.none')}</td>
75 <td>${h.radio('perm_new_user','repository.none')}</td>
74 <td>${h.radio('perm_new_user','repository.read')}</td>
76 <td>${h.radio('perm_new_user','repository.read')}</td>
75 <td>${h.radio('perm_new_user','repository.write')}</td>
77 <td>${h.radio('perm_new_user','repository.write')}</td>
76 <td>${h.radio('perm_new_user','repository.admin')}</td>
78 <td>${h.radio('perm_new_user','repository.admin')}</td>
77 <td>${h.text('perm_new_user_name',size=10)}</td>
79 <td class='ac'>
80 <div id="perm_ac">
81 ${h.text('perm_new_user_name',class_='yui-ac-input')}
82 <div id="perm_container"></div>
83 </div>
84 </td>
78 <td>${self.get_form_error('perm_new_user_name')}</td>
85 <td>${self.get_form_error('perm_new_user_name')}</td>
79 </tr>
86 </tr>
80 <tr>
87 <tr>
81 <td colspan="4">
88 <td colspan="4">
82 <span id="add_perm" class="add_icon" style="cursor: pointer;">
89 <span id="add_perm" class="add_icon" style="cursor: pointer;">
83 ${_('Add another user')}
90 ${_('Add another user')}
84 </span>
91 </span>
85 </td>
92 </td>
86 </tr>
93 </tr>
87 </table>
94 </table>
88 </td>
95 </td>
89
96
90 </tr>
97 </tr>
91 <tr>
98 <tr>
92 <td></td>
99 <td></td>
93 <td>${h.submit('update','update')}</td>
100 <td>${h.submit('update','update')}</td>
94 </tr>
101 </tr>
95
102
96 </table>
103 </table>
97 ${h.end_form()}
104 ${h.end_form()}
98 <script type="text/javascript">
105 <script type="text/javascript">
99 YAHOO.util.Event.onDOMReady(function(){
106 YAHOO.util.Event.onDOMReady(function(){
100 var D = YAHOO.util.Dom;
107 var D = YAHOO.util.Dom;
101 YAHOO.util.Event.addListener('add_perm','click',function(){
108 YAHOO.util.Event.addListener('add_perm','click',function(){
102 D.setStyle('add_perm_input','display','');
109 D.setStyle('add_perm_input','display','');
103 D.setStyle('add_perm','opacity','0.6');
110 D.setStyle('add_perm','opacity','0.6');
104 D.setStyle('add_perm','cursor','default');
111 D.setStyle('add_perm','cursor','default');
105 });
112 });
106 });
113 });
107 </script>
114 </script>
115 <script type="text/javascript">
116 YAHOO.example.FnMultipleFields = function(){
117 var myContacts = ${c.users_array|n}
118
119 // Define a custom search function for the DataSource
120 var matchNames = function(sQuery) {
121 // Case insensitive matching
122 var query = sQuery.toLowerCase(),
123 contact,
124 i=0,
125 l=myContacts.length,
126 matches = [];
127
128 // Match against each name of each contact
129 for(; i<l; i++) {
130 contact = myContacts[i];
131 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
132 (contact.lname.toLowerCase().indexOf(query) > -1) ||
133 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
134 matches[matches.length] = contact;
135 }
136 }
137
138 return matches;
139 };
140
141 // Use a FunctionDataSource
142 var oDS = new YAHOO.util.FunctionDataSource(matchNames);
143 oDS.responseSchema = {
144 fields: ["id", "fname", "lname", "nname"]
145 }
146
147 // Instantiate AutoComplete for perms
148 var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
149 oAC_perms.useShadow = false;
150 oAC_perms.resultTypeList = false;
151
152 // Instantiate AutoComplete for owner
153 var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
154 oAC_owner.useShadow = false;
155 oAC_owner.resultTypeList = false;
156
157
158 // Custom formatter to highlight the matching letters
159 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
160 var query = sQuery.toLowerCase(),
161 fname = oResultData.fname,
162 lname = oResultData.lname,
163 nname = oResultData.nname || "", // Guard against null value
164 query = sQuery.toLowerCase(),
165 fnameMatchIndex = fname.toLowerCase().indexOf(query),
166 lnameMatchIndex = lname.toLowerCase().indexOf(query),
167 nnameMatchIndex = nname.toLowerCase().indexOf(query),
168 displayfname, displaylname, displaynname;
169
170 if(fnameMatchIndex > -1) {
171 displayfname = highlightMatch(fname, query, fnameMatchIndex);
172 }
173 else {
174 displayfname = fname;
175 }
176
177 if(lnameMatchIndex > -1) {
178 displaylname = highlightMatch(lname, query, lnameMatchIndex);
179 }
180 else {
181 displaylname = lname;
182 }
183
184 if(nnameMatchIndex > -1) {
185 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
186 }
187 else {
188 displaynname = nname ? "(" + nname + ")" : "";
189 }
190
191 return displayfname + " " + displaylname + " " + displaynname;
192
193 };
194 oAC_perms.formatResult = custom_formatter;
195 oAC_owner.formatResult = custom_formatter;
196
197 // Helper function for the formatter
198 var highlightMatch = function(full, snippet, matchindex) {
199 return full.substring(0, matchindex) +
200 "<span class='match'>" +
201 full.substr(matchindex, snippet.length) +
202 "</span>" +
203 full.substring(matchindex + snippet.length);
204 };
205
206 var myHandler = function(sType, aArgs) {
207 var myAC = aArgs[0]; // reference back to the AC instance
208 var elLI = aArgs[1]; // reference to the selected LI element
209 var oData = aArgs[2]; // object literal of selected item's result data
210 myAC.getInputEl().value = oData.nname;
211 };
212
213 oAC_perms.itemSelectEvent.subscribe(myHandler);
214 oAC_owner.itemSelectEvent.subscribe(myHandler);
215
216 return {
217 oDS: oDS,
218 oAC_perms: oAC_perms,
219 oAC_owner: oAC_owner,
220 };
221 }();
222
223 </script>
108 </div>
224 </div>
109 </%def>
225 </%def>
@@ -1,156 +1,159 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
4 <head>
4 <head>
5 <link rel="icon" href="/images/hgicon.png" type="image/png" />
5 <link rel="icon" href="/images/hgicon.png" type="image/png" />
6 <meta name="robots" content="index, nofollow"/>
6 <meta name="robots" content="index, nofollow"/>
7 <title>${next.title()}</title>
7 <title>${next.title()}</title>
8 ##For future use yui reset for cross browser compatability.
8 ##For future use yui reset for cross browser compatability.
9 ##<link rel="stylesheet" href="/js/yui/reset-fonts-grids/reset-fonts-grids.css" type="text/css" />
9 ##<link rel="stylesheet" href="/js/yui/reset-fonts-grids/reset-fonts-grids.css" type="text/css" />
10 ${self.css()}
10 ${self.css()}
11 ${self.js()}
11 ${self.js()}
12 </head>
12 </head>
13
13
14 <body class="mainbody">
14 <body class="mainbody">
15 <div id="container">
15 <div id="container">
16 <div class="page-header">
16 <div class="page-header">
17 <h1 class="breadcrumbs">${next.breadcrumbs()}</h1>
17 <h1 class="breadcrumbs">${next.breadcrumbs()}</h1>
18 ${self.page_nav()}
18 ${self.page_nav()}
19 <div class="flash_msg">
19 <div class="flash_msg">
20 <% messages = h.flash.pop_messages() %>
20 <% messages = h.flash.pop_messages() %>
21 % if messages:
21 % if messages:
22 <ul id="flash-messages">
22 <ul id="flash-messages">
23 % for message in messages:
23 % for message in messages:
24 <li class="${message.category}_msg">${message}</li>
24 <li class="${message.category}_msg">${message}</li>
25 % endfor
25 % endfor
26 </ul>
26 </ul>
27 % endif
27 % endif
28 </div>
28 </div>
29 <div id="main">
29 <div id="main">
30 ${next.main()}
30 ${next.main()}
31 <script type="text/javascript">${h.tooltip.activate()}</script>
31 <script type="text/javascript">${h.tooltip.activate()}</script>
32 </div>
32 </div>
33 <div class="page-footer">
33 <div class="page-footer">
34 Hg App ${c.hg_app_version} &copy; 2010 by Marcin Kuzminski
34 Hg App ${c.hg_app_version} &copy; 2010 by Marcin Kuzminski
35 </div>
35 </div>
36
36
37 <div id="powered-by">
37 <div id="powered-by">
38 <p>
38 <p>
39 <a href="http://mercurial.selenic.com/" title="Mercurial">
39 <a href="http://mercurial.selenic.com/" title="Mercurial">
40 <img src="/images/hglogo.png" width="75" height="90" alt="mercurial"/></a>
40 <img src="/images/hglogo.png" width="75" height="90" alt="mercurial"/></a>
41 </p>
41 </p>
42 </div>
42 </div>
43
43
44 <div id="corner-top-left"></div>
44 <div id="corner-top-left"></div>
45 <div id="corner-top-right"></div>
45 <div id="corner-top-right"></div>
46 <div id="corner-bottom-left"></div>
46 <div id="corner-bottom-left"></div>
47 <div id="corner-bottom-right"></div>
47 <div id="corner-bottom-right"></div>
48
48
49 </div>
49 </div>
50 </body>
50 </body>
51 </html>
51 </html>
52
52
53 ### MAKO DEFS ###
53 ### MAKO DEFS ###
54
54
55 <%def name="page_nav()">
55 <%def name="page_nav()">
56 ${self.menu()}
56 ${self.menu()}
57 ${self.submenu()}
57 ${self.submenu()}
58 </%def>
58 </%def>
59
59
60 <%def name="menu(current)">
60 <%def name="menu(current)">
61 <%
61 <%
62 def is_current(selected):
62 def is_current(selected):
63 if selected == current:
63 if selected == current:
64 return "class='current'"
64 return "class='current'"
65 %>
65 %>
66 %if current not in ['home','admin']:
66 %if current not in ['home','admin']:
67 ##regular menu
67 ##regular menu
68 <script type="text/javascript">
68 <script type="text/javascript">
69 YAHOO.util.Event.onDOMReady(function(){
69 YAHOO.util.Event.onDOMReady(function(){
70 YAHOO.util.Event.addListener('repo_switcher','click',function(){
70 YAHOO.util.Event.addListener('repo_switcher','click',function(){
71 if(YAHOO.util.Dom.hasClass('repo_switcher','selected')){
71 if(YAHOO.util.Dom.hasClass('repo_switcher','selected')){
72 YAHOO.util.Dom.setStyle('switch_repos','display','none');
72 YAHOO.util.Dom.setStyle('switch_repos','display','none');
73 YAHOO.util.Dom.setStyle('repo_switcher','background','');
73 YAHOO.util.Dom.setStyle('repo_switcher','background','');
74 YAHOO.util.Dom.removeClass('repo_switcher','selected');
74 YAHOO.util.Dom.removeClass('repo_switcher','selected');
75 YAHOO.util.Dom.get('repo_switcher').removeAttribute('style');
75 YAHOO.util.Dom.get('repo_switcher').removeAttribute('style');
76 }
76 }
77 else{
77 else{
78 YAHOO.util.Dom.setStyle('switch_repos','display','');
78 YAHOO.util.Dom.setStyle('switch_repos','display','');
79 YAHOO.util.Dom.setStyle('repo_switcher','background','#FFFFFF');
79 YAHOO.util.Dom.setStyle('repo_switcher','background','#FFFFFF');
80 YAHOO.util.Dom.setStyle('repo_switcher','color','#556CB5');
80 YAHOO.util.Dom.setStyle('repo_switcher','color','#556CB5');
81 YAHOO.util.Dom.addClass('repo_switcher','selected');
81 YAHOO.util.Dom.addClass('repo_switcher','selected');
82 }
82 }
83 });
83 });
84 YAHOO.util.Event.addListener('repos_list','change',function(e){
84 YAHOO.util.Event.addListener('repos_list','change',function(e){
85 var wa = YAHOO.util.Dom.get('repos_list').value;
85 var wa = YAHOO.util.Dom.get('repos_list').value;
86
86
87 var url = "${h.url('summary_home',repo_name='__REPLACE__')}".replace('__REPLACE__',wa);
87 var url = "${h.url('summary_home',repo_name='__REPLACE__')}".replace('__REPLACE__',wa);
88 window.location = url;
88 window.location = url;
89 })
89 })
90 });
90 });
91 </script>
91 </script>
92 <ul class="page-nav">
92 <ul class="page-nav">
93 <li>
93 <li>
94 <a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
94 <a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
95 <div id="switch_repos" style="display:none;position: absolute;height: 25px">
95 <div id="switch_repos" style="display:none;position: absolute;height: 25px">
96 <select id="repos_list" size="=10" style="min-width: 150px">
96 <select id="repos_list" size="=10" style="min-width: 150px">
97 %for repo in sorted(x.name.lower() for x in c.cached_repo_list.values()):
97 %for repo in sorted(x.name.lower() for x in c.cached_repo_list.values()):
98 <option value="${repo}">${repo}</option>
98 <option value="${repo}">${repo}</option>
99 %endfor
99 %endfor
100 </select>
100 </select>
101 </div>
101 </div>
102 </li>
102 </li>
103 <li ${is_current('summary')}>${h.link_to(_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
103 <li ${is_current('summary')}>${h.link_to(_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
104 <li ${is_current('shortlog')}>${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</li>
104 <li ${is_current('shortlog')}>${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</li>
105 <li ${is_current('changelog')}>${h.link_to(_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>
105 <li ${is_current('changelog')}>${h.link_to(_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>
106 <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
106 <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
107 <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
107 <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
108 <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
108 <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
109 <li>${h.link_to(_('settings'),h.url('edit_repo',id=c.repo_name))}</li>
109 </ul>
110 </ul>
110 %else:
111 %else:
111 ##Root menu
112 ##Root menu
112 <ul class="page-nav">
113 <ul class="page-nav">
113 <li ${is_current('home')}>${h.link_to(_('Home'),h.url('/'))}</li>
114 <li ${is_current('home')}>${h.link_to(_('Home'),h.url('/'))}</li>
114 <li ${is_current('admin')}>${h.link_to(_('Admin'),h.url('admin_home'))}</li>
115 <li ${is_current('admin')}>${h.link_to(_('Admin'),h.url('admin_home'))}</li>
115 <li class="logout">${h.link_to(u'Logout',h.url('logout_home'))}</li>
116 <li class="logout">${h.link_to(u'Logout',h.url('logout_home'))}</li>
116 </ul>
117 </ul>
117 %endif
118 %endif
118 </div>
119 </div>
119 </%def>
120 </%def>
120 <%def name="submenu(current=None)">
121 <%def name="submenu(current=None)">
121 <%
122 <%
122 def is_current(selected):
123 def is_current(selected):
123 if selected == current:
124 if selected == current:
124 return "class='current_submenu'"
125 return "class='current_submenu'"
125 %>
126 %>
126 %if current != None:
127 %if current != None:
127 <div>
128 <div>
128 <ul class="submenu">
129 <ul class="submenu">
129 <li ${is_current('repos')}>${h.link_to(u'repos',h.url('repos'),class_='repos')}</li>
130 <li ${is_current('repos')}>${h.link_to(u'repos',h.url('repos'),class_='repos')}</li>
130 <li ${is_current('users')}>${h.link_to(u'users',h.url('users'),class_='users')}</li>
131 <li ${is_current('users')}>${h.link_to(u'users',h.url('users'),class_='users')}</li>
131 <li ${is_current('permissions')}>${h.link_to(u'permissions',h.url('permissions'),class_='permissions')}</li>
132 <li ${is_current('permissions')}>${h.link_to(u'permissions',h.url('permissions'),class_='permissions')}</li>
132 </ul>
133 </ul>
133 </div>
134 </div>
134 %endif
135 %endif
135 </%def>
136 </%def>
136
137
137
138
138 <%def name="css()">
139 <%def name="css()">
139 <link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
140 <link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
140 </%def>
141 </%def>
141
142
142 <%def name="js()">
143 <%def name="js()">
143 <script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
144 <script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
144 <script type="text/javascript" src="/js/yui/container/container-min.js"></script>
145 <script type="text/javascript" src="/js/yui/container/container-min.js"></script>
146 <script type="text/javascript" src="/js/yui/datasource/datasource-min.js"></script>
147 <script type="text/javascript" src="/js/yui/autocomplete/autocomplete-min.js"></script>
145 </%def>
148 </%def>
146
149
147 <!-- DEFINITION OF FORM ERROR FETCHER -->
150 <!-- DEFINITION OF FORM ERROR FETCHER -->
148 <%def name="get_form_error(element)">
151 <%def name="get_form_error(element)">
149 %if hasattr(c,'form_errors') and type(c.form_errors) == dict:
152 %if hasattr(c,'form_errors') and type(c.form_errors) == dict:
150 %if c.form_errors.get(element,False):
153 %if c.form_errors.get(element,False):
151 <span class="error-message">
154 <span class="error-message">
152 ${c.form_errors.get(element,'')}
155 ${c.form_errors.get(element,'')}
153 </span>
156 </span>
154 %endif
157 %endif
155 %endif
158 %endif
156 </%def> No newline at end of file
159 </%def>
@@ -1,37 +1,38 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/base.html"/>
2 <%inherit file="base/base.html"/>
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repos_prefix} Mercurial Repositories
4 ${c.repos_prefix} Mercurial Repositories
5 </%def>
5 </%def>
6 <%def name="breadcrumbs()">
6 <%def name="breadcrumbs()">
7 ${c.repos_prefix} Mercurial Repositories
7 ${c.repos_prefix} Mercurial Repositories
8 </%def>
8 </%def>
9 <%def name="page_nav()">
9 <%def name="page_nav()">
10 ${self.menu('home')}
10 &nbsp;
11 </div>
11 </%def>
12 </%def>
12 <%def name="main()">
13 <%def name="main()">
13 <div>
14 <div>
14 <br />
15 <br />
15 <h2>${_('Login')}</h2>
16 <h2>${_('Login to hg app')}</h2>
16 ${h.form(h.url.current())}
17 ${h.form(h.url.current())}
17 <table>
18 <table>
18 <tr>
19 <tr>
19 <td>${_('Username')}</td>
20 <td>${_('Username')}</td>
20 <td>${h.text('username')}</td>
21 <td>${h.text('username')}</td>
21 <td>${self.get_form_error('username')}</td>
22 <td>${self.get_form_error('username')}</td>
22 </tr>
23 </tr>
23 <tr>
24 <tr>
24 <td>${_('Password')}</td>
25 <td>${_('Password')}</td>
25 <td>${h.password('password')}</td>
26 <td>${h.password('password')}</td>
26 <td>${self.get_form_error('password')}</td>
27 <td>${self.get_form_error('password')}</td>
27 </tr>
28 </tr>
28 <tr>
29 <tr>
29 <td></td>
30 <td></td>
30 <td>${h.submit('login','login')}</td>
31 <td>${h.submit('login','login')}</td>
31 </tr>
32 </tr>
32 </table>
33 </table>
33 ${h.end_form()}
34 ${h.end_form()}
34 </div>
35 </div>
35 </%def>
36 </%def>
36
37
37
38
General Comments 0
You need to be logged in to leave comments. Login now