##// END OF EJS Templates
#109, added manual pull of changes for repositories that have remote location filled in....
marcink -
r1114:4de3fa62 beta
parent child Browse files
Show More
@@ -1,232 +1,236 b''
1 """
1 """
2 Routes configuration
2 Routes configuration
3
3
4 The more specific and detailed routes should be defined first so they
4 The more specific and detailed routes should be defined first so they
5 may take precedent over the more generic routes. For more information
5 may take precedent over the more generic routes. For more information
6 refer to the routes manual at http://routes.groovie.org/docs/
6 refer to the routes manual at http://routes.groovie.org/docs/
7 """
7 """
8 from __future__ import with_statement
8 from __future__ import with_statement
9 from routes import Mapper
9 from routes import Mapper
10 from rhodecode.lib.utils import check_repo_fast as cr
10 from rhodecode.lib.utils import check_repo_fast as cr
11
11
12 def make_map(config):
12 def make_map(config):
13 """Create, configure and return the routes Mapper"""
13 """Create, configure and return the routes Mapper"""
14 routes_map = Mapper(directory=config['pylons.paths']['controllers'],
14 routes_map = Mapper(directory=config['pylons.paths']['controllers'],
15 always_scan=config['debug'])
15 always_scan=config['debug'])
16 routes_map.minimization = False
16 routes_map.minimization = False
17 routes_map.explicit = False
17 routes_map.explicit = False
18
18
19 def check_repo(environ, match_dict):
19 def check_repo(environ, match_dict):
20 """
20 """
21 check for valid repository for proper 404 handling
21 check for valid repository for proper 404 handling
22
22
23 :param environ:
23 :param environ:
24 :param match_dict:
24 :param match_dict:
25 """
25 """
26 repo_name = match_dict.get('repo_name')
26 repo_name = match_dict.get('repo_name')
27 return not cr(repo_name, config['base_path'])
27 return not cr(repo_name, config['base_path'])
28
28
29 # The ErrorController route (handles 404/500 error pages); it should
29 # The ErrorController route (handles 404/500 error pages); it should
30 # likely stay at the top, ensuring it can always be resolved
30 # likely stay at the top, ensuring it can always be resolved
31 routes_map.connect('/error/{action}', controller='error')
31 routes_map.connect('/error/{action}', controller='error')
32 routes_map.connect('/error/{action}/{id}', controller='error')
32 routes_map.connect('/error/{action}/{id}', controller='error')
33
33
34 #==========================================================================
34 #==========================================================================
35 # CUSTOM ROUTES HERE
35 # CUSTOM ROUTES HERE
36 #==========================================================================
36 #==========================================================================
37
37
38 #MAIN PAGE
38 #MAIN PAGE
39 routes_map.connect('home', '/', controller='home', action='index')
39 routes_map.connect('home', '/', controller='home', action='index')
40 routes_map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
40 routes_map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
41 routes_map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
41 routes_map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
42 #ADMIN REPOSITORY REST ROUTES
42 #ADMIN REPOSITORY REST ROUTES
43 with routes_map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
43 with routes_map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
44 m.connect("repos", "/repos",
44 m.connect("repos", "/repos",
45 action="create", conditions=dict(method=["POST"]))
45 action="create", conditions=dict(method=["POST"]))
46 m.connect("repos", "/repos",
46 m.connect("repos", "/repos",
47 action="index", conditions=dict(method=["GET"]))
47 action="index", conditions=dict(method=["GET"]))
48 m.connect("formatted_repos", "/repos.{format}",
48 m.connect("formatted_repos", "/repos.{format}",
49 action="index",
49 action="index",
50 conditions=dict(method=["GET"]))
50 conditions=dict(method=["GET"]))
51 m.connect("new_repo", "/repos/new",
51 m.connect("new_repo", "/repos/new",
52 action="new", conditions=dict(method=["GET"]))
52 action="new", conditions=dict(method=["GET"]))
53 m.connect("formatted_new_repo", "/repos/new.{format}",
53 m.connect("formatted_new_repo", "/repos/new.{format}",
54 action="new", conditions=dict(method=["GET"]))
54 action="new", conditions=dict(method=["GET"]))
55 m.connect("/repos/{repo_name:.*}",
55 m.connect("/repos/{repo_name:.*}",
56 action="update", conditions=dict(method=["PUT"],
56 action="update", conditions=dict(method=["PUT"],
57 function=check_repo))
57 function=check_repo))
58 m.connect("/repos/{repo_name:.*}",
58 m.connect("/repos/{repo_name:.*}",
59 action="delete", conditions=dict(method=["DELETE"],
59 action="delete", conditions=dict(method=["DELETE"],
60 function=check_repo))
60 function=check_repo))
61 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
61 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
62 action="edit", conditions=dict(method=["GET"],
62 action="edit", conditions=dict(method=["GET"],
63 function=check_repo))
63 function=check_repo))
64 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
64 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
65 action="edit", conditions=dict(method=["GET"],
65 action="edit", conditions=dict(method=["GET"],
66 function=check_repo))
66 function=check_repo))
67 m.connect("repo", "/repos/{repo_name:.*}",
67 m.connect("repo", "/repos/{repo_name:.*}",
68 action="show", conditions=dict(method=["GET"],
68 action="show", conditions=dict(method=["GET"],
69 function=check_repo))
69 function=check_repo))
70 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
70 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
71 action="show", conditions=dict(method=["GET"],
71 action="show", conditions=dict(method=["GET"],
72 function=check_repo))
72 function=check_repo))
73 #ajax delete repo perm user
73 #ajax delete repo perm user
74 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
74 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
75 action="delete_perm_user", conditions=dict(method=["DELETE"],
75 action="delete_perm_user", conditions=dict(method=["DELETE"],
76 function=check_repo))
76 function=check_repo))
77 #ajax delete repo perm users_group
77 #ajax delete repo perm users_group
78 m.connect('delete_repo_users_group', "/repos_delete_users_group/{repo_name:.*}",
78 m.connect('delete_repo_users_group', "/repos_delete_users_group/{repo_name:.*}",
79 action="delete_perm_users_group", conditions=dict(method=["DELETE"],
79 action="delete_perm_users_group", conditions=dict(method=["DELETE"],
80 function=check_repo))
80 function=check_repo))
81
81
82 #settings actions
82 #settings actions
83 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
83 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
84 action="repo_stats", conditions=dict(method=["DELETE"],
84 action="repo_stats", conditions=dict(method=["DELETE"],
85 function=check_repo))
85 function=check_repo))
86 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
86 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
87 action="repo_cache", conditions=dict(method=["DELETE"],
87 action="repo_cache", conditions=dict(method=["DELETE"],
88 function=check_repo))
88 function=check_repo))
89 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
89 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
90 action="repo_public_journal", conditions=dict(method=["PUT"],
90 action="repo_public_journal", conditions=dict(method=["PUT"],
91 function=check_repo))
91 function=check_repo))
92 m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
93 action="repo_pull", conditions=dict(method=["PUT"],
94 function=check_repo))
95
92
96
93 #ADMIN USER REST ROUTES
97 #ADMIN USER REST ROUTES
94 routes_map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
98 routes_map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
95
99
96 #ADMIN USER REST ROUTES
100 #ADMIN USER REST ROUTES
97 routes_map.resource('users_group', 'users_groups', controller='admin/users_groups', path_prefix='/_admin')
101 routes_map.resource('users_group', 'users_groups', controller='admin/users_groups', path_prefix='/_admin')
98
102
99 #ADMIN GROUP REST ROUTES
103 #ADMIN GROUP REST ROUTES
100 routes_map.resource('group', 'groups', controller='admin/groups', path_prefix='/_admin')
104 routes_map.resource('group', 'groups', controller='admin/groups', path_prefix='/_admin')
101
105
102 #ADMIN PERMISSIONS REST ROUTES
106 #ADMIN PERMISSIONS REST ROUTES
103 routes_map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
107 routes_map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
104
108
105 ##ADMIN LDAP SETTINGS
109 ##ADMIN LDAP SETTINGS
106 routes_map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
110 routes_map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
107 action='ldap_settings', conditions=dict(method=["POST"]))
111 action='ldap_settings', conditions=dict(method=["POST"]))
108 routes_map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
112 routes_map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
109
113
110
114
111 #ADMIN SETTINGS REST ROUTES
115 #ADMIN SETTINGS REST ROUTES
112 with routes_map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
116 with routes_map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
113 m.connect("admin_settings", "/settings",
117 m.connect("admin_settings", "/settings",
114 action="create", conditions=dict(method=["POST"]))
118 action="create", conditions=dict(method=["POST"]))
115 m.connect("admin_settings", "/settings",
119 m.connect("admin_settings", "/settings",
116 action="index", conditions=dict(method=["GET"]))
120 action="index", conditions=dict(method=["GET"]))
117 m.connect("formatted_admin_settings", "/settings.{format}",
121 m.connect("formatted_admin_settings", "/settings.{format}",
118 action="index", conditions=dict(method=["GET"]))
122 action="index", conditions=dict(method=["GET"]))
119 m.connect("admin_new_setting", "/settings/new",
123 m.connect("admin_new_setting", "/settings/new",
120 action="new", conditions=dict(method=["GET"]))
124 action="new", conditions=dict(method=["GET"]))
121 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
125 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
122 action="new", conditions=dict(method=["GET"]))
126 action="new", conditions=dict(method=["GET"]))
123 m.connect("/settings/{setting_id}",
127 m.connect("/settings/{setting_id}",
124 action="update", conditions=dict(method=["PUT"]))
128 action="update", conditions=dict(method=["PUT"]))
125 m.connect("/settings/{setting_id}",
129 m.connect("/settings/{setting_id}",
126 action="delete", conditions=dict(method=["DELETE"]))
130 action="delete", conditions=dict(method=["DELETE"]))
127 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
131 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
128 action="edit", conditions=dict(method=["GET"]))
132 action="edit", conditions=dict(method=["GET"]))
129 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
133 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
130 action="edit", conditions=dict(method=["GET"]))
134 action="edit", conditions=dict(method=["GET"]))
131 m.connect("admin_setting", "/settings/{setting_id}",
135 m.connect("admin_setting", "/settings/{setting_id}",
132 action="show", conditions=dict(method=["GET"]))
136 action="show", conditions=dict(method=["GET"]))
133 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
137 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
134 action="show", conditions=dict(method=["GET"]))
138 action="show", conditions=dict(method=["GET"]))
135 m.connect("admin_settings_my_account", "/my_account",
139 m.connect("admin_settings_my_account", "/my_account",
136 action="my_account", conditions=dict(method=["GET"]))
140 action="my_account", conditions=dict(method=["GET"]))
137 m.connect("admin_settings_my_account_update", "/my_account_update",
141 m.connect("admin_settings_my_account_update", "/my_account_update",
138 action="my_account_update", conditions=dict(method=["PUT"]))
142 action="my_account_update", conditions=dict(method=["PUT"]))
139 m.connect("admin_settings_create_repository", "/create_repository",
143 m.connect("admin_settings_create_repository", "/create_repository",
140 action="create_repository", conditions=dict(method=["GET"]))
144 action="create_repository", conditions=dict(method=["GET"]))
141
145
142 #ADMIN MAIN PAGES
146 #ADMIN MAIN PAGES
143 with routes_map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
147 with routes_map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
144 m.connect('admin_home', '', action='index')#main page
148 m.connect('admin_home', '', action='index')#main page
145 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
149 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
146 action='add_repo')
150 action='add_repo')
147
151
148
152
149 #USER JOURNAL
153 #USER JOURNAL
150 routes_map.connect('journal', '/_admin/journal', controller='journal',)
154 routes_map.connect('journal', '/_admin/journal', controller='journal',)
151 routes_map.connect('public_journal', '/_admin/public_journal', controller='journal', action="public_journal")
155 routes_map.connect('public_journal', '/_admin/public_journal', controller='journal', action="public_journal")
152 routes_map.connect('public_journal_rss', '/_admin/public_journal_rss', controller='journal', action="public_journal_rss")
156 routes_map.connect('public_journal_rss', '/_admin/public_journal_rss', controller='journal', action="public_journal_rss")
153 routes_map.connect('public_journal_atom', '/_admin/public_journal_atom', controller='journal', action="public_journal_atom")
157 routes_map.connect('public_journal_atom', '/_admin/public_journal_atom', controller='journal', action="public_journal_atom")
154
158
155 routes_map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
159 routes_map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
156 action='toggle_following', conditions=dict(method=["POST"]))
160 action='toggle_following', conditions=dict(method=["POST"]))
157
161
158
162
159 #SEARCH
163 #SEARCH
160 routes_map.connect('search', '/_admin/search', controller='search',)
164 routes_map.connect('search', '/_admin/search', controller='search',)
161 routes_map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
165 routes_map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
162
166
163 #LOGIN/LOGOUT/REGISTER/SIGN IN
167 #LOGIN/LOGOUT/REGISTER/SIGN IN
164 routes_map.connect('login_home', '/_admin/login', controller='login')
168 routes_map.connect('login_home', '/_admin/login', controller='login')
165 routes_map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
169 routes_map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
166 routes_map.connect('register', '/_admin/register', controller='login', action='register')
170 routes_map.connect('register', '/_admin/register', controller='login', action='register')
167 routes_map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
171 routes_map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
168
172
169 #FEEDS
173 #FEEDS
170 routes_map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
174 routes_map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
171 controller='feed', action='rss',
175 controller='feed', action='rss',
172 conditions=dict(function=check_repo))
176 conditions=dict(function=check_repo))
173 routes_map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
177 routes_map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
174 controller='feed', action='atom',
178 controller='feed', action='atom',
175 conditions=dict(function=check_repo))
179 conditions=dict(function=check_repo))
176
180
177
181
178 #REPOSITORY ROUTES
182 #REPOSITORY ROUTES
179 routes_map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
183 routes_map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
180 controller='changeset', revision='tip',
184 controller='changeset', revision='tip',
181 conditions=dict(function=check_repo))
185 conditions=dict(function=check_repo))
182 routes_map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
186 routes_map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
183 controller='changeset', action='raw_changeset', revision='tip',
187 controller='changeset', action='raw_changeset', revision='tip',
184 conditions=dict(function=check_repo))
188 conditions=dict(function=check_repo))
185 routes_map.connect('summary_home', '/{repo_name:.*}',
189 routes_map.connect('summary_home', '/{repo_name:.*}',
186 controller='summary', conditions=dict(function=check_repo))
190 controller='summary', conditions=dict(function=check_repo))
187 routes_map.connect('summary_home', '/{repo_name:.*}/summary',
191 routes_map.connect('summary_home', '/{repo_name:.*}/summary',
188 controller='summary', conditions=dict(function=check_repo))
192 controller='summary', conditions=dict(function=check_repo))
189 routes_map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
193 routes_map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
190 controller='shortlog', conditions=dict(function=check_repo))
194 controller='shortlog', conditions=dict(function=check_repo))
191 routes_map.connect('branches_home', '/{repo_name:.*}/branches',
195 routes_map.connect('branches_home', '/{repo_name:.*}/branches',
192 controller='branches', conditions=dict(function=check_repo))
196 controller='branches', conditions=dict(function=check_repo))
193 routes_map.connect('tags_home', '/{repo_name:.*}/tags',
197 routes_map.connect('tags_home', '/{repo_name:.*}/tags',
194 controller='tags', conditions=dict(function=check_repo))
198 controller='tags', conditions=dict(function=check_repo))
195 routes_map.connect('changelog_home', '/{repo_name:.*}/changelog',
199 routes_map.connect('changelog_home', '/{repo_name:.*}/changelog',
196 controller='changelog', conditions=dict(function=check_repo))
200 controller='changelog', conditions=dict(function=check_repo))
197 routes_map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
201 routes_map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
198 controller='files', revision='tip', f_path='',
202 controller='files', revision='tip', f_path='',
199 conditions=dict(function=check_repo))
203 conditions=dict(function=check_repo))
200 routes_map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
204 routes_map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
201 controller='files', action='diff', revision='tip', f_path='',
205 controller='files', action='diff', revision='tip', f_path='',
202 conditions=dict(function=check_repo))
206 conditions=dict(function=check_repo))
203 routes_map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
207 routes_map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
204 controller='files', action='rawfile', revision='tip', f_path='',
208 controller='files', action='rawfile', revision='tip', f_path='',
205 conditions=dict(function=check_repo))
209 conditions=dict(function=check_repo))
206 routes_map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
210 routes_map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
207 controller='files', action='raw', revision='tip', f_path='',
211 controller='files', action='raw', revision='tip', f_path='',
208 conditions=dict(function=check_repo))
212 conditions=dict(function=check_repo))
209 routes_map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
213 routes_map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
210 controller='files', action='annotate', revision='tip', f_path='',
214 controller='files', action='annotate', revision='tip', f_path='',
211 conditions=dict(function=check_repo))
215 conditions=dict(function=check_repo))
212 routes_map.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
216 routes_map.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
213 controller='files', action='archivefile',
217 controller='files', action='archivefile',
214 conditions=dict(function=check_repo))
218 conditions=dict(function=check_repo))
215 routes_map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
219 routes_map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
216 controller='settings', action="delete",
220 controller='settings', action="delete",
217 conditions=dict(method=["DELETE"], function=check_repo))
221 conditions=dict(method=["DELETE"], function=check_repo))
218 routes_map.connect('repo_settings_update', '/{repo_name:.*}/settings',
222 routes_map.connect('repo_settings_update', '/{repo_name:.*}/settings',
219 controller='settings', action="update",
223 controller='settings', action="update",
220 conditions=dict(method=["PUT"], function=check_repo))
224 conditions=dict(method=["PUT"], function=check_repo))
221 routes_map.connect('repo_settings_home', '/{repo_name:.*}/settings',
225 routes_map.connect('repo_settings_home', '/{repo_name:.*}/settings',
222 controller='settings', action='index',
226 controller='settings', action='index',
223 conditions=dict(function=check_repo))
227 conditions=dict(function=check_repo))
224
228
225 routes_map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
229 routes_map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
226 controller='settings', action='fork_create',
230 controller='settings', action='fork_create',
227 conditions=dict(function=check_repo, method=["POST"]))
231 conditions=dict(function=check_repo, method=["POST"]))
228 routes_map.connect('repo_fork_home', '/{repo_name:.*}/fork',
232 routes_map.connect('repo_fork_home', '/{repo_name:.*}/fork',
229 controller='settings', action='fork',
233 controller='settings', action='fork',
230 conditions=dict(function=check_repo))
234 conditions=dict(function=check_repo))
231
235
232 return routes_map
236 return routes_map
@@ -1,395 +1,410 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.repos
3 rhodecode.controllers.admin.repos
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Admin controller for RhodeCode
6 Admin controller for RhodeCode
7
7
8 :created_on: Apr 7, 2010
8 :created_on: Apr 7, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 import logging
28 import logging
29 import traceback
29 import traceback
30 import formencode
30 import formencode
31 from operator import itemgetter
31 from operator import itemgetter
32 from formencode import htmlfill
32 from formencode import htmlfill
33
33
34 from paste.httpexceptions import HTTPInternalServerError
34 from paste.httpexceptions import HTTPInternalServerError
35 from pylons import request, response, session, tmpl_context as c, url
35 from pylons import request, response, session, tmpl_context as c, url
36 from pylons.controllers.util import abort, redirect
36 from pylons.controllers.util import abort, redirect
37 from pylons.i18n.translation import _
37 from pylons.i18n.translation import _
38
38
39 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
41 HasPermissionAnyDecorator
41 HasPermissionAnyDecorator
42 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.base import BaseController, render
43 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
43 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
44 from rhodecode.lib.helpers import get_token
44 from rhodecode.lib.helpers import get_token
45 from rhodecode.model.db import User, Repository, UserFollowing, Group
45 from rhodecode.model.db import User, Repository, UserFollowing, Group
46 from rhodecode.model.forms import RepoForm
46 from rhodecode.model.forms import RepoForm
47 from rhodecode.model.scm import ScmModel
47 from rhodecode.model.scm import ScmModel
48 from rhodecode.model.repo import RepoModel
48 from rhodecode.model.repo import RepoModel
49
49
50 log = logging.getLogger(__name__)
50 log = logging.getLogger(__name__)
51
51
52 class ReposController(BaseController):
52 class ReposController(BaseController):
53 """
53 """
54 REST Controller styled on the Atom Publishing Protocol"""
54 REST Controller styled on the Atom Publishing Protocol"""
55 # To properly map this controller, ensure your config/routing.py
55 # To properly map this controller, ensure your config/routing.py
56 # file has a resource setup:
56 # file has a resource setup:
57 # map.resource('repo', 'repos')
57 # map.resource('repo', 'repos')
58
58
59 @LoginRequired()
59 @LoginRequired()
60 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
60 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
61 def __before__(self):
61 def __before__(self):
62 c.admin_user = session.get('admin_user')
62 c.admin_user = session.get('admin_user')
63 c.admin_username = session.get('admin_username')
63 c.admin_username = session.get('admin_username')
64 super(ReposController, self).__before__()
64 super(ReposController, self).__before__()
65
65
66
66
67
67
68 def __load_data(self, repo_name):
68 def __load_data(self, repo_name):
69 """
69 """
70 Load defaults settings for edit, and update
70 Load defaults settings for edit, and update
71
71
72 :param repo_name:
72 :param repo_name:
73 """
73 """
74 repo, dbrepo = ScmModel().get(repo_name, retval='repo')
74 repo, dbrepo = ScmModel().get(repo_name, retval='repo')
75
75
76 repo_model = RepoModel()
76 repo_model = RepoModel()
77 c.repo_info = repo_model.get_by_repo_name(repo_name)
77 c.repo_info = repo_model.get_by_repo_name(repo_name)
78
78
79 if c.repo_info is None:
79 if c.repo_info is None:
80 h.flash(_('%s repository is not mapped to db perhaps'
80 h.flash(_('%s repository is not mapped to db perhaps'
81 ' it was created or renamed from the filesystem'
81 ' it was created or renamed from the filesystem'
82 ' please run the application again'
82 ' please run the application again'
83 ' in order to rescan repositories') % repo_name,
83 ' in order to rescan repositories') % repo_name,
84 category='error')
84 category='error')
85
85
86 return redirect(url('repos'))
86 return redirect(url('repos'))
87
87
88
88
89
89
90 c.repo_groups = [('', '')]
90 c.repo_groups = [('', '')]
91 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
91 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
92
92
93 c.default_user_id = User.by_username('default').user_id
93 c.default_user_id = User.by_username('default').user_id
94 c.in_public_journal = self.sa.query(UserFollowing)\
94 c.in_public_journal = self.sa.query(UserFollowing)\
95 .filter(UserFollowing.user_id == c.default_user_id)\
95 .filter(UserFollowing.user_id == c.default_user_id)\
96 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
96 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
97
97
98 if c.repo_info.stats:
98 if c.repo_info.stats:
99 last_rev = c.repo_info.stats.stat_on_revision
99 last_rev = c.repo_info.stats.stat_on_revision
100 else:
100 else:
101 last_rev = 0
101 last_rev = 0
102 c.stats_revision = last_rev
102 c.stats_revision = last_rev
103
103
104 c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
104 c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
105
105
106 if last_rev == 0 or c.repo_last_rev == 0:
106 if last_rev == 0 or c.repo_last_rev == 0:
107 c.stats_percentage = 0
107 c.stats_percentage = 0
108 else:
108 else:
109 c.stats_percentage = '%.2f' % ((float((last_rev)) /
109 c.stats_percentage = '%.2f' % ((float((last_rev)) /
110 c.repo_last_rev) * 100)
110 c.repo_last_rev) * 100)
111
111
112 c.users_array = repo_model.get_users_js()
112 c.users_array = repo_model.get_users_js()
113 c.users_groups_array = repo_model.get_users_groups_js()
113 c.users_groups_array = repo_model.get_users_groups_js()
114
114
115 defaults = c.repo_info.get_dict()
115 defaults = c.repo_info.get_dict()
116 group, repo_name = c.repo_info.groups_and_repo
116 group, repo_name = c.repo_info.groups_and_repo
117 defaults['repo_name'] = repo_name
117 defaults['repo_name'] = repo_name
118 defaults['repo_group'] = getattr(group, 'group_id', None)
118 defaults['repo_group'] = getattr(group, 'group_id', None)
119 #fill owner
119 #fill owner
120 if c.repo_info.user:
120 if c.repo_info.user:
121 defaults.update({'user':c.repo_info.user.username})
121 defaults.update({'user':c.repo_info.user.username})
122 else:
122 else:
123 replacement_user = self.sa.query(User)\
123 replacement_user = self.sa.query(User)\
124 .filter(User.admin == True).first().username
124 .filter(User.admin == True).first().username
125 defaults.update({'user':replacement_user})
125 defaults.update({'user':replacement_user})
126
126
127
127
128 #fill repository users
128 #fill repository users
129 for p in c.repo_info.repo_to_perm:
129 for p in c.repo_info.repo_to_perm:
130 defaults.update({'u_perm_%s' % p.user.username:
130 defaults.update({'u_perm_%s' % p.user.username:
131 p.permission.permission_name})
131 p.permission.permission_name})
132
132
133 #fill repository groups
133 #fill repository groups
134 for p in c.repo_info.users_group_to_perm:
134 for p in c.repo_info.users_group_to_perm:
135 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
135 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
136 p.permission.permission_name})
136 p.permission.permission_name})
137
137
138
138
139 return defaults
139 return defaults
140
140
141
141
142 @HasPermissionAllDecorator('hg.admin')
142 @HasPermissionAllDecorator('hg.admin')
143 def index(self, format='html'):
143 def index(self, format='html'):
144 """GET /repos: All items in the collection"""
144 """GET /repos: All items in the collection"""
145 # url('repos')
145 # url('repos')
146 cached_repo_list = ScmModel().get_repos()
146 cached_repo_list = ScmModel().get_repos()
147 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
147 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
148 return render('admin/repos/repos.html')
148 return render('admin/repos/repos.html')
149
149
150 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
150 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
151 def create(self):
151 def create(self):
152 """
152 """
153 POST /repos: Create a new item"""
153 POST /repos: Create a new item"""
154 # url('repos')
154 # url('repos')
155 repo_model = RepoModel()
155 repo_model = RepoModel()
156 c.repo_groups = [('', '')]
156 c.repo_groups = [('', '')]
157 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
157 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
158 form_result = {}
158 form_result = {}
159 try:
159 try:
160 form_result = RepoForm()(repo_groups=c.repo_groups).to_python(dict(request.POST))
160 form_result = RepoForm()(repo_groups=c.repo_groups).to_python(dict(request.POST))
161 repo_model.create(form_result, c.rhodecode_user)
161 repo_model.create(form_result, c.rhodecode_user)
162 if form_result['clone_uri']:
162 if form_result['clone_uri']:
163 h.flash(_('created repository %s from %s') \
163 h.flash(_('created repository %s from %s') \
164 % (form_result['repo_name'], form_result['clone_uri']),
164 % (form_result['repo_name'], form_result['clone_uri']),
165 category='success')
165 category='success')
166 else:
166 else:
167 h.flash(_('created repository %s') % form_result['repo_name'],
167 h.flash(_('created repository %s') % form_result['repo_name'],
168 category='success')
168 category='success')
169
169
170 if request.POST.get('user_created'):
170 if request.POST.get('user_created'):
171 action_logger(self.rhodecode_user, 'user_created_repo',
171 action_logger(self.rhodecode_user, 'user_created_repo',
172 form_result['repo_name'], '', self.sa)
172 form_result['repo_name'], '', self.sa)
173 else:
173 else:
174 action_logger(self.rhodecode_user, 'admin_created_repo',
174 action_logger(self.rhodecode_user, 'admin_created_repo',
175 form_result['repo_name'], '', self.sa)
175 form_result['repo_name'], '', self.sa)
176
176
177 except formencode.Invalid, errors:
177 except formencode.Invalid, errors:
178
178
179 c.new_repo = errors.value['repo_name']
179 c.new_repo = errors.value['repo_name']
180 c.repo_groups = [('', '')]
180 c.repo_groups = [('', '')]
181 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
181 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
182
182
183 if request.POST.get('user_created'):
183 if request.POST.get('user_created'):
184 r = render('admin/repos/repo_add_create_repository.html')
184 r = render('admin/repos/repo_add_create_repository.html')
185 else:
185 else:
186 r = render('admin/repos/repo_add.html')
186 r = render('admin/repos/repo_add.html')
187
187
188 return htmlfill.render(
188 return htmlfill.render(
189 r,
189 r,
190 defaults=errors.value,
190 defaults=errors.value,
191 errors=errors.error_dict or {},
191 errors=errors.error_dict or {},
192 prefix_error=False,
192 prefix_error=False,
193 encoding="UTF-8")
193 encoding="UTF-8")
194
194
195 except Exception:
195 except Exception:
196 log.error(traceback.format_exc())
196 log.error(traceback.format_exc())
197 msg = _('error occurred during creation of repository %s') \
197 msg = _('error occurred during creation of repository %s') \
198 % form_result.get('repo_name')
198 % form_result.get('repo_name')
199 h.flash(msg, category='error')
199 h.flash(msg, category='error')
200 if request.POST.get('user_created'):
200 if request.POST.get('user_created'):
201 return redirect(url('home'))
201 return redirect(url('home'))
202 return redirect(url('repos'))
202 return redirect(url('repos'))
203
203
204 @HasPermissionAllDecorator('hg.admin')
204 @HasPermissionAllDecorator('hg.admin')
205 def new(self, format='html'):
205 def new(self, format='html'):
206 """GET /repos/new: Form to create a new item"""
206 """GET /repos/new: Form to create a new item"""
207 new_repo = request.GET.get('repo', '')
207 new_repo = request.GET.get('repo', '')
208 c.new_repo = repo_name_slug(new_repo)
208 c.new_repo = repo_name_slug(new_repo)
209 c.repo_groups = [('', '')]
209 c.repo_groups = [('', '')]
210 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
210 c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
211 return render('admin/repos/repo_add.html')
211 return render('admin/repos/repo_add.html')
212
212
213 @HasPermissionAllDecorator('hg.admin')
213 @HasPermissionAllDecorator('hg.admin')
214 def update(self, repo_name):
214 def update(self, repo_name):
215 """
215 """
216 PUT /repos/repo_name: Update an existing item"""
216 PUT /repos/repo_name: Update an existing item"""
217 # Forms posted to this method should contain a hidden field:
217 # Forms posted to this method should contain a hidden field:
218 # <input type="hidden" name="_method" value="PUT" />
218 # <input type="hidden" name="_method" value="PUT" />
219 # Or using helpers:
219 # Or using helpers:
220 # h.form(url('repo', repo_name=ID),
220 # h.form(url('repo', repo_name=ID),
221 # method='put')
221 # method='put')
222 # url('repo', repo_name=ID)
222 # url('repo', repo_name=ID)
223 repo_model = RepoModel()
223 repo_model = RepoModel()
224 changed_name = repo_name
224 changed_name = repo_name
225 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
225 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
226 try:
226 try:
227 form_result = _form.to_python(dict(request.POST))
227 form_result = _form.to_python(dict(request.POST))
228 repo_model.update(repo_name, form_result)
228 repo_model.update(repo_name, form_result)
229 invalidate_cache('get_repo_cached_%s' % repo_name)
229 invalidate_cache('get_repo_cached_%s' % repo_name)
230 h.flash(_('Repository %s updated successfully' % repo_name),
230 h.flash(_('Repository %s updated successfully' % repo_name),
231 category='success')
231 category='success')
232 changed_name = form_result['repo_name']
232 changed_name = form_result['repo_name']
233 action_logger(self.rhodecode_user, 'admin_updated_repo',
233 action_logger(self.rhodecode_user, 'admin_updated_repo',
234 changed_name, '', self.sa)
234 changed_name, '', self.sa)
235
235
236 except formencode.Invalid, errors:
236 except formencode.Invalid, errors:
237 defaults = self.__load_data(repo_name)
237 defaults = self.__load_data(repo_name)
238 defaults.update(errors.value)
238 defaults.update(errors.value)
239 return htmlfill.render(
239 return htmlfill.render(
240 render('admin/repos/repo_edit.html'),
240 render('admin/repos/repo_edit.html'),
241 defaults=defaults,
241 defaults=defaults,
242 errors=errors.error_dict or {},
242 errors=errors.error_dict or {},
243 prefix_error=False,
243 prefix_error=False,
244 encoding="UTF-8")
244 encoding="UTF-8")
245
245
246 except Exception:
246 except Exception:
247 log.error(traceback.format_exc())
247 log.error(traceback.format_exc())
248 h.flash(_('error occurred during update of repository %s') \
248 h.flash(_('error occurred during update of repository %s') \
249 % repo_name, category='error')
249 % repo_name, category='error')
250 return redirect(url('edit_repo', repo_name=changed_name))
250 return redirect(url('edit_repo', repo_name=changed_name))
251
251
252 @HasPermissionAllDecorator('hg.admin')
252 @HasPermissionAllDecorator('hg.admin')
253 def delete(self, repo_name):
253 def delete(self, repo_name):
254 """
254 """
255 DELETE /repos/repo_name: Delete an existing item"""
255 DELETE /repos/repo_name: Delete an existing item"""
256 # Forms posted to this method should contain a hidden field:
256 # Forms posted to this method should contain a hidden field:
257 # <input type="hidden" name="_method" value="DELETE" />
257 # <input type="hidden" name="_method" value="DELETE" />
258 # Or using helpers:
258 # Or using helpers:
259 # h.form(url('repo', repo_name=ID),
259 # h.form(url('repo', repo_name=ID),
260 # method='delete')
260 # method='delete')
261 # url('repo', repo_name=ID)
261 # url('repo', repo_name=ID)
262
262
263 repo_model = RepoModel()
263 repo_model = RepoModel()
264 repo = repo_model.get_by_repo_name(repo_name)
264 repo = repo_model.get_by_repo_name(repo_name)
265 if not repo:
265 if not repo:
266 h.flash(_('%s repository is not mapped to db perhaps'
266 h.flash(_('%s repository is not mapped to db perhaps'
267 ' it was moved or renamed from the filesystem'
267 ' it was moved or renamed from the filesystem'
268 ' please run the application again'
268 ' please run the application again'
269 ' in order to rescan repositories') % repo_name,
269 ' in order to rescan repositories') % repo_name,
270 category='error')
270 category='error')
271
271
272 return redirect(url('repos'))
272 return redirect(url('repos'))
273 try:
273 try:
274 action_logger(self.rhodecode_user, 'admin_deleted_repo',
274 action_logger(self.rhodecode_user, 'admin_deleted_repo',
275 repo_name, '', self.sa)
275 repo_name, '', self.sa)
276 repo_model.delete(repo)
276 repo_model.delete(repo)
277 invalidate_cache('get_repo_cached_%s' % repo_name)
277 invalidate_cache('get_repo_cached_%s' % repo_name)
278 h.flash(_('deleted repository %s') % repo_name, category='success')
278 h.flash(_('deleted repository %s') % repo_name, category='success')
279
279
280 except Exception, e:
280 except Exception, e:
281 log.error(traceback.format_exc())
281 log.error(traceback.format_exc())
282 h.flash(_('An error occurred during deletion of %s') % repo_name,
282 h.flash(_('An error occurred during deletion of %s') % repo_name,
283 category='error')
283 category='error')
284
284
285 return redirect(url('repos'))
285 return redirect(url('repos'))
286
286
287 @HasPermissionAllDecorator('hg.admin')
287 @HasPermissionAllDecorator('hg.admin')
288 def delete_perm_user(self, repo_name):
288 def delete_perm_user(self, repo_name):
289 """
289 """
290 DELETE an existing repository permission user
290 DELETE an existing repository permission user
291
291
292 :param repo_name:
292 :param repo_name:
293 """
293 """
294
294
295 try:
295 try:
296 repo_model = RepoModel()
296 repo_model = RepoModel()
297 repo_model.delete_perm_user(request.POST, repo_name)
297 repo_model.delete_perm_user(request.POST, repo_name)
298 except Exception, e:
298 except Exception, e:
299 h.flash(_('An error occurred during deletion of repository user'),
299 h.flash(_('An error occurred during deletion of repository user'),
300 category='error')
300 category='error')
301 raise HTTPInternalServerError()
301 raise HTTPInternalServerError()
302
302
303 @HasPermissionAllDecorator('hg.admin')
303 @HasPermissionAllDecorator('hg.admin')
304 def delete_perm_users_group(self, repo_name):
304 def delete_perm_users_group(self, repo_name):
305 """
305 """
306 DELETE an existing repository permission users group
306 DELETE an existing repository permission users group
307
307
308 :param repo_name:
308 :param repo_name:
309 """
309 """
310 try:
310 try:
311 repo_model = RepoModel()
311 repo_model = RepoModel()
312 repo_model.delete_perm_users_group(request.POST, repo_name)
312 repo_model.delete_perm_users_group(request.POST, repo_name)
313 except Exception, e:
313 except Exception, e:
314 h.flash(_('An error occurred during deletion of repository'
314 h.flash(_('An error occurred during deletion of repository'
315 ' users groups'),
315 ' users groups'),
316 category='error')
316 category='error')
317 raise HTTPInternalServerError()
317 raise HTTPInternalServerError()
318
318
319 @HasPermissionAllDecorator('hg.admin')
319 @HasPermissionAllDecorator('hg.admin')
320 def repo_stats(self, repo_name):
320 def repo_stats(self, repo_name):
321 """
321 """
322 DELETE an existing repository statistics
322 DELETE an existing repository statistics
323
323
324 :param repo_name:
324 :param repo_name:
325 """
325 """
326
326
327 try:
327 try:
328 repo_model = RepoModel()
328 repo_model = RepoModel()
329 repo_model.delete_stats(repo_name)
329 repo_model.delete_stats(repo_name)
330 except Exception, e:
330 except Exception, e:
331 h.flash(_('An error occurred during deletion of repository stats'),
331 h.flash(_('An error occurred during deletion of repository stats'),
332 category='error')
332 category='error')
333 return redirect(url('edit_repo', repo_name=repo_name))
333 return redirect(url('edit_repo', repo_name=repo_name))
334
334
335 @HasPermissionAllDecorator('hg.admin')
335 @HasPermissionAllDecorator('hg.admin')
336 def repo_cache(self, repo_name):
336 def repo_cache(self, repo_name):
337 """
337 """
338 INVALIDATE existing repository cache
338 INVALIDATE existing repository cache
339
339
340 :param repo_name:
340 :param repo_name:
341 """
341 """
342
342
343 try:
343 try:
344 ScmModel().mark_for_invalidation(repo_name)
344 ScmModel().mark_for_invalidation(repo_name)
345 except Exception, e:
345 except Exception, e:
346 h.flash(_('An error occurred during cache invalidation'),
346 h.flash(_('An error occurred during cache invalidation'),
347 category='error')
347 category='error')
348 return redirect(url('edit_repo', repo_name=repo_name))
348 return redirect(url('edit_repo', repo_name=repo_name))
349
349
350 @HasPermissionAllDecorator('hg.admin')
350 @HasPermissionAllDecorator('hg.admin')
351 def repo_public_journal(self, repo_name):
351 def repo_public_journal(self, repo_name):
352 """
352 """
353 Set's this repository to be visible in public journal,
353 Set's this repository to be visible in public journal,
354 in other words assing default user to follow this repo
354 in other words assing default user to follow this repo
355
355
356 :param repo_name:
356 :param repo_name:
357 """
357 """
358
358
359 cur_token = request.POST.get('auth_token')
359 cur_token = request.POST.get('auth_token')
360 token = get_token()
360 token = get_token()
361 if cur_token == token:
361 if cur_token == token:
362 try:
362 try:
363 repo_id = Repository.by_repo_name(repo_name).repo_id
363 repo_id = Repository.by_repo_name(repo_name).repo_id
364 user_id = User.by_username('default').user_id
364 user_id = User.by_username('default').user_id
365 self.scm_model.toggle_following_repo(repo_id, user_id)
365 self.scm_model.toggle_following_repo(repo_id, user_id)
366 h.flash(_('Updated repository visibility in public journal'),
366 h.flash(_('Updated repository visibility in public journal'),
367 category='success')
367 category='success')
368 except:
368 except:
369 h.flash(_('An error occurred during setting this'
369 h.flash(_('An error occurred during setting this'
370 ' repository in public journal'),
370 ' repository in public journal'),
371 category='error')
371 category='error')
372
372
373 else:
373 else:
374 h.flash(_('Token mismatch'), category='error')
374 h.flash(_('Token mismatch'), category='error')
375 return redirect(url('edit_repo', repo_name=repo_name))
375 return redirect(url('edit_repo', repo_name=repo_name))
376
376
377 @HasPermissionAllDecorator('hg.admin')
378 def repo_pull(self, repo_name):
379 """
380 Runs task to update given repository with remote changes,
381 ie. make pull on remote location
377
382
383 :param repo_name:
384 """
385 try:
386 ScmModel().pull_changes(repo_name, c.rhodecode_user.username)
387 h.flash(_('Pulled from remote location'), category='success')
388 except Exception, e:
389 h.flash(_('An error occurred during pull from remote location'),
390 category='error')
391
392 return redirect(url('edit_repo', repo_name=repo_name))
378
393
379 @HasPermissionAllDecorator('hg.admin')
394 @HasPermissionAllDecorator('hg.admin')
380 def show(self, repo_name, format='html'):
395 def show(self, repo_name, format='html'):
381 """GET /repos/repo_name: Show a specific item"""
396 """GET /repos/repo_name: Show a specific item"""
382 # url('repo', repo_name=ID)
397 # url('repo', repo_name=ID)
383
398
384 @HasPermissionAllDecorator('hg.admin')
399 @HasPermissionAllDecorator('hg.admin')
385 def edit(self, repo_name, format='html'):
400 def edit(self, repo_name, format='html'):
386 """GET /repos/repo_name/edit: Form to edit an existing item"""
401 """GET /repos/repo_name/edit: Form to edit an existing item"""
387 # url('edit_repo', repo_name=ID)
402 # url('edit_repo', repo_name=ID)
388 defaults = self.__load_data(repo_name)
403 defaults = self.__load_data(repo_name)
389
404
390 return htmlfill.render(
405 return htmlfill.render(
391 render('admin/repos/repo_edit.html'),
406 render('admin/repos/repo_edit.html'),
392 defaults=defaults,
407 defaults=defaults,
393 encoding="UTF-8",
408 encoding="UTF-8",
394 force_defaults=False
409 force_defaults=False
395 )
410 )
@@ -1,691 +1,694 b''
1 """Helper functions
1 """Helper functions
2
2
3 Consists of functions to typically be used within templates, but also
3 Consists of functions to typically be used within templates, but also
4 available to Controllers. This module is available to both as 'h'.
4 available to Controllers. This module is available to both as 'h'.
5 """
5 """
6 import random
6 import random
7 import hashlib
7 import hashlib
8 import StringIO
8 import StringIO
9 import urllib
9 import urllib
10
10
11 from pygments.formatters import HtmlFormatter
11 from pygments.formatters import HtmlFormatter
12 from pygments import highlight as code_highlight
12 from pygments import highlight as code_highlight
13 from pylons import url, request
13 from pylons import url, request
14 from pylons.i18n.translation import _, ungettext
14 from pylons.i18n.translation import _, ungettext
15
15
16 from webhelpers.html import literal, HTML, escape
16 from webhelpers.html import literal, HTML, escape
17 from webhelpers.html.tools import *
17 from webhelpers.html.tools import *
18 from webhelpers.html.builder import make_tag
18 from webhelpers.html.builder import make_tag
19 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
19 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
20 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
20 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
21 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
21 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
22 password, textarea, title, ul, xml_declaration, radio
22 password, textarea, title, ul, xml_declaration, radio
23 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
23 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
24 mail_to, strip_links, strip_tags, tag_re
24 mail_to, strip_links, strip_tags, tag_re
25 from webhelpers.number import format_byte_size, format_bit_size
25 from webhelpers.number import format_byte_size, format_bit_size
26 from webhelpers.pylonslib import Flash as _Flash
26 from webhelpers.pylonslib import Flash as _Flash
27 from webhelpers.pylonslib.secure_form import secure_form
27 from webhelpers.pylonslib.secure_form import secure_form
28 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
28 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
29 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
29 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
30 replace_whitespace, urlify, truncate, wrap_paragraphs
30 replace_whitespace, urlify, truncate, wrap_paragraphs
31 from webhelpers.date import time_ago_in_words
31 from webhelpers.date import time_ago_in_words
32 from webhelpers.paginate import Page
32 from webhelpers.paginate import Page
33 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
33 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
34 convert_boolean_attrs, NotGiven
34 convert_boolean_attrs, NotGiven
35
35
36 from vcs.utils.annotate import annotate_highlight
36 from vcs.utils.annotate import annotate_highlight
37 from rhodecode.lib.utils import repo_name_slug
37 from rhodecode.lib.utils import repo_name_slug
38
38
39 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
39 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
40 """Reset button
40 """Reset button
41 """
41 """
42 _set_input_attrs(attrs, type, name, value)
42 _set_input_attrs(attrs, type, name, value)
43 _set_id_attr(attrs, id, name)
43 _set_id_attr(attrs, id, name)
44 convert_boolean_attrs(attrs, ["disabled"])
44 convert_boolean_attrs(attrs, ["disabled"])
45 return HTML.input(**attrs)
45 return HTML.input(**attrs)
46
46
47 reset = _reset
47 reset = _reset
48
48
49
49
50 def get_token():
50 def get_token():
51 """Return the current authentication token, creating one if one doesn't
51 """Return the current authentication token, creating one if one doesn't
52 already exist.
52 already exist.
53 """
53 """
54 token_key = "_authentication_token"
54 token_key = "_authentication_token"
55 from pylons import session
55 from pylons import session
56 if not token_key in session:
56 if not token_key in session:
57 try:
57 try:
58 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
58 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
59 except AttributeError: # Python < 2.4
59 except AttributeError: # Python < 2.4
60 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
60 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
61 session[token_key] = token
61 session[token_key] = token
62 if hasattr(session, 'save'):
62 if hasattr(session, 'save'):
63 session.save()
63 session.save()
64 return session[token_key]
64 return session[token_key]
65
65
66 class _GetError(object):
66 class _GetError(object):
67 """Get error from form_errors, and represent it as span wrapped error
67 """Get error from form_errors, and represent it as span wrapped error
68 message
68 message
69
69
70 :param field_name: field to fetch errors for
70 :param field_name: field to fetch errors for
71 :param form_errors: form errors dict
71 :param form_errors: form errors dict
72 """
72 """
73
73
74 def __call__(self, field_name, form_errors):
74 def __call__(self, field_name, form_errors):
75 tmpl = """<span class="error_msg">%s</span>"""
75 tmpl = """<span class="error_msg">%s</span>"""
76 if form_errors and form_errors.has_key(field_name):
76 if form_errors and form_errors.has_key(field_name):
77 return literal(tmpl % form_errors.get(field_name))
77 return literal(tmpl % form_errors.get(field_name))
78
78
79 get_error = _GetError()
79 get_error = _GetError()
80
80
81 class _ToolTip(object):
81 class _ToolTip(object):
82
82
83 def __call__(self, tooltip_title, trim_at=50):
83 def __call__(self, tooltip_title, trim_at=50):
84 """Special function just to wrap our text into nice formatted
84 """Special function just to wrap our text into nice formatted
85 autowrapped text
85 autowrapped text
86
86
87 :param tooltip_title:
87 :param tooltip_title:
88 """
88 """
89
89
90 return wrap_paragraphs(escape(tooltip_title), trim_at)\
90 return wrap_paragraphs(escape(tooltip_title), trim_at)\
91 .replace('\n', '<br/>')
91 .replace('\n', '<br/>')
92
92
93 def activate(self):
93 def activate(self):
94 """Adds tooltip mechanism to the given Html all tooltips have to have
94 """Adds tooltip mechanism to the given Html all tooltips have to have
95 set class `tooltip` and set attribute `tooltip_title`.
95 set class `tooltip` and set attribute `tooltip_title`.
96 Then a tooltip will be generated based on that. All with yui js tooltip
96 Then a tooltip will be generated based on that. All with yui js tooltip
97 """
97 """
98
98
99 js = '''
99 js = '''
100 YAHOO.util.Event.onDOMReady(function(){
100 YAHOO.util.Event.onDOMReady(function(){
101 function toolTipsId(){
101 function toolTipsId(){
102 var ids = [];
102 var ids = [];
103 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
103 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
104
104
105 for (var i = 0; i < tts.length; i++) {
105 for (var i = 0; i < tts.length; i++) {
106 //if element doesn't not have and id autogenerate one for tooltip
106 //if element doesn't not have and id autogenerate one for tooltip
107
107
108 if (!tts[i].id){
108 if (!tts[i].id){
109 tts[i].id='tt'+i*100;
109 tts[i].id='tt'+i*100;
110 }
110 }
111 ids.push(tts[i].id);
111 ids.push(tts[i].id);
112 }
112 }
113 return ids
113 return ids
114 };
114 };
115 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
115 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
116 context: toolTipsId(),
116 context: toolTipsId(),
117 monitorresize:false,
117 monitorresize:false,
118 xyoffset :[0,0],
118 xyoffset :[0,0],
119 autodismissdelay:300000,
119 autodismissdelay:300000,
120 hidedelay:5,
120 hidedelay:5,
121 showdelay:20,
121 showdelay:20,
122 });
122 });
123
123
124 // Set the text for the tooltip just before we display it. Lazy method
124 // Set the text for the tooltip just before we display it. Lazy method
125 myToolTips.contextTriggerEvent.subscribe(
125 myToolTips.contextTriggerEvent.subscribe(
126 function(type, args) {
126 function(type, args) {
127
127
128 var context = args[0];
128 var context = args[0];
129
129
130 //positioning of tooltip
130 //positioning of tooltip
131 var tt_w = this.element.clientWidth;//tooltip width
131 var tt_w = this.element.clientWidth;//tooltip width
132 var tt_h = this.element.clientHeight;//tooltip height
132 var tt_h = this.element.clientHeight;//tooltip height
133
133
134 var context_w = context.offsetWidth;
134 var context_w = context.offsetWidth;
135 var context_h = context.offsetHeight;
135 var context_h = context.offsetHeight;
136
136
137 var pos_x = YAHOO.util.Dom.getX(context);
137 var pos_x = YAHOO.util.Dom.getX(context);
138 var pos_y = YAHOO.util.Dom.getY(context);
138 var pos_y = YAHOO.util.Dom.getY(context);
139
139
140 var display_strategy = 'right';
140 var display_strategy = 'right';
141 var xy_pos = [0,0];
141 var xy_pos = [0,0];
142 switch (display_strategy){
142 switch (display_strategy){
143
143
144 case 'top':
144 case 'top':
145 var cur_x = (pos_x+context_w/2)-(tt_w/2);
145 var cur_x = (pos_x+context_w/2)-(tt_w/2);
146 var cur_y = (pos_y-tt_h-4);
146 var cur_y = (pos_y-tt_h-4);
147 xy_pos = [cur_x,cur_y];
147 xy_pos = [cur_x,cur_y];
148 break;
148 break;
149 case 'bottom':
149 case 'bottom':
150 var cur_x = (pos_x+context_w/2)-(tt_w/2);
150 var cur_x = (pos_x+context_w/2)-(tt_w/2);
151 var cur_y = pos_y+context_h+4;
151 var cur_y = pos_y+context_h+4;
152 xy_pos = [cur_x,cur_y];
152 xy_pos = [cur_x,cur_y];
153 break;
153 break;
154 case 'left':
154 case 'left':
155 var cur_x = (pos_x-tt_w-4);
155 var cur_x = (pos_x-tt_w-4);
156 var cur_y = pos_y-((tt_h/2)-context_h/2);
156 var cur_y = pos_y-((tt_h/2)-context_h/2);
157 xy_pos = [cur_x,cur_y];
157 xy_pos = [cur_x,cur_y];
158 break;
158 break;
159 case 'right':
159 case 'right':
160 var cur_x = (pos_x+context_w+4);
160 var cur_x = (pos_x+context_w+4);
161 var cur_y = pos_y-((tt_h/2)-context_h/2);
161 var cur_y = pos_y-((tt_h/2)-context_h/2);
162 xy_pos = [cur_x,cur_y];
162 xy_pos = [cur_x,cur_y];
163 break;
163 break;
164 default:
164 default:
165 var cur_x = (pos_x+context_w/2)-(tt_w/2);
165 var cur_x = (pos_x+context_w/2)-(tt_w/2);
166 var cur_y = pos_y-tt_h-4;
166 var cur_y = pos_y-tt_h-4;
167 xy_pos = [cur_x,cur_y];
167 xy_pos = [cur_x,cur_y];
168 break;
168 break;
169
169
170 }
170 }
171
171
172 this.cfg.setProperty("xy",xy_pos);
172 this.cfg.setProperty("xy",xy_pos);
173
173
174 });
174 });
175
175
176 //Mouse out
176 //Mouse out
177 myToolTips.contextMouseOutEvent.subscribe(
177 myToolTips.contextMouseOutEvent.subscribe(
178 function(type, args) {
178 function(type, args) {
179 var context = args[0];
179 var context = args[0];
180
180
181 });
181 });
182 });
182 });
183 '''
183 '''
184 return literal(js)
184 return literal(js)
185
185
186 tooltip = _ToolTip()
186 tooltip = _ToolTip()
187
187
188 class _FilesBreadCrumbs(object):
188 class _FilesBreadCrumbs(object):
189
189
190 def __call__(self, repo_name, rev, paths):
190 def __call__(self, repo_name, rev, paths):
191 if isinstance(paths, str):
191 if isinstance(paths, str):
192 paths = paths.decode('utf-8', 'replace')
192 paths = paths.decode('utf-8', 'replace')
193 url_l = [link_to(repo_name, url('files_home',
193 url_l = [link_to(repo_name, url('files_home',
194 repo_name=repo_name,
194 repo_name=repo_name,
195 revision=rev, f_path=''))]
195 revision=rev, f_path=''))]
196 paths_l = paths.split('/')
196 paths_l = paths.split('/')
197 for cnt, p in enumerate(paths_l):
197 for cnt, p in enumerate(paths_l):
198 if p != '':
198 if p != '':
199 url_l.append(link_to(p, url('files_home',
199 url_l.append(link_to(p, url('files_home',
200 repo_name=repo_name,
200 repo_name=repo_name,
201 revision=rev,
201 revision=rev,
202 f_path='/'.join(paths_l[:cnt + 1]))))
202 f_path='/'.join(paths_l[:cnt + 1]))))
203
203
204 return literal('/'.join(url_l))
204 return literal('/'.join(url_l))
205
205
206 files_breadcrumbs = _FilesBreadCrumbs()
206 files_breadcrumbs = _FilesBreadCrumbs()
207
207
208 class CodeHtmlFormatter(HtmlFormatter):
208 class CodeHtmlFormatter(HtmlFormatter):
209 """My code Html Formatter for source codes
209 """My code Html Formatter for source codes
210 """
210 """
211
211
212 def wrap(self, source, outfile):
212 def wrap(self, source, outfile):
213 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
213 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
214
214
215 def _wrap_code(self, source):
215 def _wrap_code(self, source):
216 for cnt, it in enumerate(source):
216 for cnt, it in enumerate(source):
217 i, t = it
217 i, t = it
218 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
218 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
219 yield i, t
219 yield i, t
220
220
221 def _wrap_tablelinenos(self, inner):
221 def _wrap_tablelinenos(self, inner):
222 dummyoutfile = StringIO.StringIO()
222 dummyoutfile = StringIO.StringIO()
223 lncount = 0
223 lncount = 0
224 for t, line in inner:
224 for t, line in inner:
225 if t:
225 if t:
226 lncount += 1
226 lncount += 1
227 dummyoutfile.write(line)
227 dummyoutfile.write(line)
228
228
229 fl = self.linenostart
229 fl = self.linenostart
230 mw = len(str(lncount + fl - 1))
230 mw = len(str(lncount + fl - 1))
231 sp = self.linenospecial
231 sp = self.linenospecial
232 st = self.linenostep
232 st = self.linenostep
233 la = self.lineanchors
233 la = self.lineanchors
234 aln = self.anchorlinenos
234 aln = self.anchorlinenos
235 nocls = self.noclasses
235 nocls = self.noclasses
236 if sp:
236 if sp:
237 lines = []
237 lines = []
238
238
239 for i in range(fl, fl + lncount):
239 for i in range(fl, fl + lncount):
240 if i % st == 0:
240 if i % st == 0:
241 if i % sp == 0:
241 if i % sp == 0:
242 if aln:
242 if aln:
243 lines.append('<a href="#%s%d" class="special">%*d</a>' %
243 lines.append('<a href="#%s%d" class="special">%*d</a>' %
244 (la, i, mw, i))
244 (la, i, mw, i))
245 else:
245 else:
246 lines.append('<span class="special">%*d</span>' % (mw, i))
246 lines.append('<span class="special">%*d</span>' % (mw, i))
247 else:
247 else:
248 if aln:
248 if aln:
249 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
249 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
250 else:
250 else:
251 lines.append('%*d' % (mw, i))
251 lines.append('%*d' % (mw, i))
252 else:
252 else:
253 lines.append('')
253 lines.append('')
254 ls = '\n'.join(lines)
254 ls = '\n'.join(lines)
255 else:
255 else:
256 lines = []
256 lines = []
257 for i in range(fl, fl + lncount):
257 for i in range(fl, fl + lncount):
258 if i % st == 0:
258 if i % st == 0:
259 if aln:
259 if aln:
260 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
260 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
261 else:
261 else:
262 lines.append('%*d' % (mw, i))
262 lines.append('%*d' % (mw, i))
263 else:
263 else:
264 lines.append('')
264 lines.append('')
265 ls = '\n'.join(lines)
265 ls = '\n'.join(lines)
266
266
267 # in case you wonder about the seemingly redundant <div> here: since the
267 # in case you wonder about the seemingly redundant <div> here: since the
268 # content in the other cell also is wrapped in a div, some browsers in
268 # content in the other cell also is wrapped in a div, some browsers in
269 # some configurations seem to mess up the formatting...
269 # some configurations seem to mess up the formatting...
270 if nocls:
270 if nocls:
271 yield 0, ('<table class="%stable">' % self.cssclass +
271 yield 0, ('<table class="%stable">' % self.cssclass +
272 '<tr><td><div class="linenodiv" '
272 '<tr><td><div class="linenodiv" '
273 'style="background-color: #f0f0f0; padding-right: 10px">'
273 'style="background-color: #f0f0f0; padding-right: 10px">'
274 '<pre style="line-height: 125%">' +
274 '<pre style="line-height: 125%">' +
275 ls + '</pre></div></td><td class="code">')
275 ls + '</pre></div></td><td class="code">')
276 else:
276 else:
277 yield 0, ('<table class="%stable">' % self.cssclass +
277 yield 0, ('<table class="%stable">' % self.cssclass +
278 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
278 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
279 ls + '</pre></div></td><td class="code">')
279 ls + '</pre></div></td><td class="code">')
280 yield 0, dummyoutfile.getvalue()
280 yield 0, dummyoutfile.getvalue()
281 yield 0, '</td></tr></table>'
281 yield 0, '</td></tr></table>'
282
282
283
283
284 def pygmentize(filenode, **kwargs):
284 def pygmentize(filenode, **kwargs):
285 """pygmentize function using pygments
285 """pygmentize function using pygments
286
286
287 :param filenode:
287 :param filenode:
288 """
288 """
289
289
290 return literal(code_highlight(filenode.content,
290 return literal(code_highlight(filenode.content,
291 filenode.lexer, CodeHtmlFormatter(**kwargs)))
291 filenode.lexer, CodeHtmlFormatter(**kwargs)))
292
292
293 def pygmentize_annotation(filenode, **kwargs):
293 def pygmentize_annotation(filenode, **kwargs):
294 """pygmentize function for annotation
294 """pygmentize function for annotation
295
295
296 :param filenode:
296 :param filenode:
297 """
297 """
298
298
299 color_dict = {}
299 color_dict = {}
300 def gen_color(n=10000):
300 def gen_color(n=10000):
301 """generator for getting n of evenly distributed colors using
301 """generator for getting n of evenly distributed colors using
302 hsv color and golden ratio. It always return same order of colors
302 hsv color and golden ratio. It always return same order of colors
303
303
304 :returns: RGB tuple
304 :returns: RGB tuple
305 """
305 """
306 import colorsys
306 import colorsys
307 golden_ratio = 0.618033988749895
307 golden_ratio = 0.618033988749895
308 h = 0.22717784590367374
308 h = 0.22717784590367374
309
309
310 for c in xrange(n):
310 for c in xrange(n):
311 h += golden_ratio
311 h += golden_ratio
312 h %= 1
312 h %= 1
313 HSV_tuple = [h, 0.95, 0.95]
313 HSV_tuple = [h, 0.95, 0.95]
314 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
314 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
315 yield map(lambda x:str(int(x * 256)), RGB_tuple)
315 yield map(lambda x:str(int(x * 256)), RGB_tuple)
316
316
317 cgenerator = gen_color()
317 cgenerator = gen_color()
318
318
319 def get_color_string(cs):
319 def get_color_string(cs):
320 if color_dict.has_key(cs):
320 if color_dict.has_key(cs):
321 col = color_dict[cs]
321 col = color_dict[cs]
322 else:
322 else:
323 col = color_dict[cs] = cgenerator.next()
323 col = color_dict[cs] = cgenerator.next()
324 return "color: rgb(%s)! important;" % (', '.join(col))
324 return "color: rgb(%s)! important;" % (', '.join(col))
325
325
326 def url_func(changeset):
326 def url_func(changeset):
327 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
327 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
328 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
328 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
329
329
330 tooltip_html = tooltip_html % (changeset.author,
330 tooltip_html = tooltip_html % (changeset.author,
331 changeset.date,
331 changeset.date,
332 tooltip(changeset.message))
332 tooltip(changeset.message))
333 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
333 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
334 short_id(changeset.raw_id))
334 short_id(changeset.raw_id))
335 uri = link_to(
335 uri = link_to(
336 lnk_format,
336 lnk_format,
337 url('changeset_home', repo_name=changeset.repository.name,
337 url('changeset_home', repo_name=changeset.repository.name,
338 revision=changeset.raw_id),
338 revision=changeset.raw_id),
339 style=get_color_string(changeset.raw_id),
339 style=get_color_string(changeset.raw_id),
340 class_='tooltip',
340 class_='tooltip',
341 title=tooltip_html
341 title=tooltip_html
342 )
342 )
343
343
344 uri += '\n'
344 uri += '\n'
345 return uri
345 return uri
346 return literal(annotate_highlight(filenode, url_func, **kwargs))
346 return literal(annotate_highlight(filenode, url_func, **kwargs))
347
347
348 def get_changeset_safe(repo, rev):
348 def get_changeset_safe(repo, rev):
349 from vcs.backends.base import BaseRepository
349 from vcs.backends.base import BaseRepository
350 from vcs.exceptions import RepositoryError
350 from vcs.exceptions import RepositoryError
351 if not isinstance(repo, BaseRepository):
351 if not isinstance(repo, BaseRepository):
352 raise Exception('You must pass an Repository '
352 raise Exception('You must pass an Repository '
353 'object as first argument got %s', type(repo))
353 'object as first argument got %s', type(repo))
354
354
355 try:
355 try:
356 cs = repo.get_changeset(rev)
356 cs = repo.get_changeset(rev)
357 except RepositoryError:
357 except RepositoryError:
358 from rhodecode.lib.utils import EmptyChangeset
358 from rhodecode.lib.utils import EmptyChangeset
359 cs = EmptyChangeset()
359 cs = EmptyChangeset()
360 return cs
360 return cs
361
361
362
362
363 def is_following_repo(repo_name, user_id):
363 def is_following_repo(repo_name, user_id):
364 from rhodecode.model.scm import ScmModel
364 from rhodecode.model.scm import ScmModel
365 return ScmModel().is_following_repo(repo_name, user_id)
365 return ScmModel().is_following_repo(repo_name, user_id)
366
366
367 flash = _Flash()
367 flash = _Flash()
368
368
369
369
370 #==============================================================================
370 #==============================================================================
371 # MERCURIAL FILTERS available via h.
371 # MERCURIAL FILTERS available via h.
372 #==============================================================================
372 #==============================================================================
373 from mercurial import util
373 from mercurial import util
374 from mercurial.templatefilters import person as _person
374 from mercurial.templatefilters import person as _person
375
375
376 def _age(curdate):
376 def _age(curdate):
377 """turns a datetime into an age string."""
377 """turns a datetime into an age string."""
378
378
379 if not curdate:
379 if not curdate:
380 return ''
380 return ''
381
381
382 from datetime import timedelta, datetime
382 from datetime import timedelta, datetime
383
383
384 agescales = [("year", 3600 * 24 * 365),
384 agescales = [("year", 3600 * 24 * 365),
385 ("month", 3600 * 24 * 30),
385 ("month", 3600 * 24 * 30),
386 ("day", 3600 * 24),
386 ("day", 3600 * 24),
387 ("hour", 3600),
387 ("hour", 3600),
388 ("minute", 60),
388 ("minute", 60),
389 ("second", 1), ]
389 ("second", 1), ]
390
390
391 age = datetime.now() - curdate
391 age = datetime.now() - curdate
392 age_seconds = (age.days * agescales[2][1]) + age.seconds
392 age_seconds = (age.days * agescales[2][1]) + age.seconds
393 pos = 1
393 pos = 1
394 for scale in agescales:
394 for scale in agescales:
395 if scale[1] <= age_seconds:
395 if scale[1] <= age_seconds:
396 if pos == 6:pos = 5
396 if pos == 6:pos = 5
397 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
397 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
398 pos += 1
398 pos += 1
399
399
400 return _('just now')
400 return _('just now')
401
401
402 age = lambda x:_age(x)
402 age = lambda x:_age(x)
403 capitalize = lambda x: x.capitalize()
403 capitalize = lambda x: x.capitalize()
404 email = util.email
404 email = util.email
405 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
405 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
406 person = lambda x: _person(x)
406 person = lambda x: _person(x)
407 short_id = lambda x: x[:12]
407 short_id = lambda x: x[:12]
408
408
409
409
410 def bool2icon(value):
410 def bool2icon(value):
411 """Returns True/False values represented as small html image of true/false
411 """Returns True/False values represented as small html image of true/false
412 icons
412 icons
413
413
414 :param value: bool value
414 :param value: bool value
415 """
415 """
416
416
417 if value is True:
417 if value is True:
418 return HTML.tag('img', src=url("/images/icons/accept.png"),
418 return HTML.tag('img', src=url("/images/icons/accept.png"),
419 alt=_('True'))
419 alt=_('True'))
420
420
421 if value is False:
421 if value is False:
422 return HTML.tag('img', src=url("/images/icons/cancel.png"),
422 return HTML.tag('img', src=url("/images/icons/cancel.png"),
423 alt=_('False'))
423 alt=_('False'))
424
424
425 return value
425 return value
426
426
427
427
428 def action_parser(user_log, feed=False):
428 def action_parser(user_log, feed=False):
429 """This helper will action_map the specified string action into translated
429 """This helper will action_map the specified string action into translated
430 fancy names with icons and links
430 fancy names with icons and links
431
431
432 :param user_log: user log instance
432 :param user_log: user log instance
433 :param feed: use output for feeds (no html and fancy icons)
433 :param feed: use output for feeds (no html and fancy icons)
434 """
434 """
435
435
436 action = user_log.action
436 action = user_log.action
437 action_params = ' '
437 action_params = ' '
438
438
439 x = action.split(':')
439 x = action.split(':')
440
440
441 if len(x) > 1:
441 if len(x) > 1:
442 action, action_params = x
442 action, action_params = x
443
443
444 def get_cs_links():
444 def get_cs_links():
445 revs_limit = 5 #display this amount always
445 revs_limit = 5 #display this amount always
446 revs_top_limit = 50 #show upto this amount of changesets hidden
446 revs_top_limit = 50 #show upto this amount of changesets hidden
447 revs = action_params.split(',')
447 revs = action_params.split(',')
448 repo_name = user_log.repository.repo_name
448 repo_name = user_log.repository.repo_name
449
449
450 from rhodecode.model.scm import ScmModel
450 from rhodecode.model.scm import ScmModel
451 repo, dbrepo = ScmModel().get(repo_name, retval='repo',
451 repo, dbrepo = ScmModel().get(repo_name, retval='repo',
452 invalidation_list=[])
452 invalidation_list=[])
453
453
454 message = lambda rev: get_changeset_safe(repo, rev).message
454 message = lambda rev: get_changeset_safe(repo, rev).message
455
455
456 cs_links = " " + ', '.join ([link_to(rev,
456 cs_links = " " + ', '.join ([link_to(rev,
457 url('changeset_home',
457 url('changeset_home',
458 repo_name=repo_name,
458 repo_name=repo_name,
459 revision=rev), title=tooltip(message(rev)),
459 revision=rev), title=tooltip(message(rev)),
460 class_='tooltip') for rev in revs[:revs_limit] ])
460 class_='tooltip') for rev in revs[:revs_limit] ])
461
461
462 compare_view = (' <div class="compare_view tooltip" title="%s">'
462 compare_view = (' <div class="compare_view tooltip" title="%s">'
463 '<a href="%s">%s</a> '
463 '<a href="%s">%s</a> '
464 '</div>' % (_('Show all combined changesets %s->%s' \
464 '</div>' % (_('Show all combined changesets %s->%s' \
465 % (revs[0], revs[-1])),
465 % (revs[0], revs[-1])),
466 url('changeset_home', repo_name=repo_name,
466 url('changeset_home', repo_name=repo_name,
467 revision='%s...%s' % (revs[0], revs[-1])
467 revision='%s...%s' % (revs[0], revs[-1])
468 ),
468 ),
469 _('compare view'))
469 _('compare view'))
470 )
470 )
471
471
472 if len(revs) > revs_limit:
472 if len(revs) > revs_limit:
473 uniq_id = revs[0]
473 uniq_id = revs[0]
474 html_tmpl = ('<span> %s '
474 html_tmpl = ('<span> %s '
475 '<a class="show_more" id="_%s" href="#more">%s</a> '
475 '<a class="show_more" id="_%s" href="#more">%s</a> '
476 '%s</span>')
476 '%s</span>')
477 if not feed:
477 if not feed:
478 cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
478 cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
479 % (len(revs) - revs_limit),
479 % (len(revs) - revs_limit),
480 _('revisions'))
480 _('revisions'))
481
481
482 if not feed:
482 if not feed:
483 html_tmpl = '<span id="%s" style="display:none"> %s </span>'
483 html_tmpl = '<span id="%s" style="display:none"> %s </span>'
484 else:
484 else:
485 html_tmpl = '<span id="%s"> %s </span>'
485 html_tmpl = '<span id="%s"> %s </span>'
486
486
487 cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
487 cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
488 url('changeset_home',
488 url('changeset_home',
489 repo_name=repo_name, revision=rev),
489 repo_name=repo_name, revision=rev),
490 title=message(rev), class_='tooltip')
490 title=message(rev), class_='tooltip')
491 for rev in revs[revs_limit:revs_top_limit]]))
491 for rev in revs[revs_limit:revs_top_limit]]))
492 if len(revs) > 1:
492 if len(revs) > 1:
493 cs_links += compare_view
493 cs_links += compare_view
494 return cs_links
494 return cs_links
495
495
496 def get_fork_name():
496 def get_fork_name():
497 repo_name = action_params
497 repo_name = action_params
498 return _('fork name ') + str(link_to(action_params, url('summary_home',
498 return _('fork name ') + str(link_to(action_params, url('summary_home',
499 repo_name=repo_name,)))
499 repo_name=repo_name,)))
500
500
501 action_map = {'user_deleted_repo':(_('[deleted] repository'), None),
501 action_map = {'user_deleted_repo':(_('[deleted] repository'), None),
502 'user_created_repo':(_('[created] repository'), None),
502 'user_created_repo':(_('[created] repository'), None),
503 'user_forked_repo':(_('[forked] repository'), get_fork_name),
503 'user_forked_repo':(_('[forked] repository'), get_fork_name),
504 'user_updated_repo':(_('[updated] repository'), None),
504 'user_updated_repo':(_('[updated] repository'), None),
505 'admin_deleted_repo':(_('[delete] repository'), None),
505 'admin_deleted_repo':(_('[delete] repository'), None),
506 'admin_created_repo':(_('[created] repository'), None),
506 'admin_created_repo':(_('[created] repository'), None),
507 'admin_forked_repo':(_('[forked] repository'), None),
507 'admin_forked_repo':(_('[forked] repository'), None),
508 'admin_updated_repo':(_('[updated] repository'), None),
508 'admin_updated_repo':(_('[updated] repository'), None),
509 'push':(_('[pushed] into'), get_cs_links),
509 'push':(_('[pushed] into'), get_cs_links),
510 'push_remote':(_('[pulled from remote] into'), get_cs_links),
510 'pull':(_('[pulled] from'), None),
511 'pull':(_('[pulled] from'), None),
511 'started_following_repo':(_('[started following] repository'), None),
512 'started_following_repo':(_('[started following] repository'), None),
512 'stopped_following_repo':(_('[stopped following] repository'), None),
513 'stopped_following_repo':(_('[stopped following] repository'), None),
513 }
514 }
514
515
515 action_str = action_map.get(action, action)
516 action_str = action_map.get(action, action)
516 if feed:
517 if feed:
517 action = action_str[0].replace('[', '').replace(']', '')
518 action = action_str[0].replace('[', '').replace(']', '')
518 else:
519 else:
519 action = action_str[0].replace('[', '<span class="journal_highlight">')\
520 action = action_str[0].replace('[', '<span class="journal_highlight">')\
520 .replace(']', '</span>')
521 .replace(']', '</span>')
522
521 action_params_func = lambda :""
523 action_params_func = lambda :""
522
524
523 if action_str[1] is not None:
525 if callable(action_str[1]):
524 action_params_func = action_str[1]
526 action_params_func = action_str[1]
525
527
526 return [literal(action), action_params_func]
528 return [literal(action), action_params_func]
527
529
528 def action_parser_icon(user_log):
530 def action_parser_icon(user_log):
529 action = user_log.action
531 action = user_log.action
530 action_params = None
532 action_params = None
531 x = action.split(':')
533 x = action.split(':')
532
534
533 if len(x) > 1:
535 if len(x) > 1:
534 action, action_params = x
536 action, action_params = x
535
537
536 tmpl = """<img src="%s/%s" alt="%s"/>"""
538 tmpl = """<img src="%s%s" alt="%s"/>"""
537 map = {'user_deleted_repo':'database_delete.png',
539 map = {'user_deleted_repo':'database_delete.png',
538 'user_created_repo':'database_add.png',
540 'user_created_repo':'database_add.png',
539 'user_forked_repo':'arrow_divide.png',
541 'user_forked_repo':'arrow_divide.png',
540 'user_updated_repo':'database_edit.png',
542 'user_updated_repo':'database_edit.png',
541 'admin_deleted_repo':'database_delete.png',
543 'admin_deleted_repo':'database_delete.png',
542 'admin_created_repo':'database_add.png',
544 'admin_created_repo':'database_add.png',
543 'admin_forked_repo':'arrow_divide.png',
545 'admin_forked_repo':'arrow_divide.png',
544 'admin_updated_repo':'database_edit.png',
546 'admin_updated_repo':'database_edit.png',
545 'push':'script_add.png',
547 'push':'script_add.png',
548 'push_remote':'connect.png',
546 'pull':'down_16.png',
549 'pull':'down_16.png',
547 'started_following_repo':'heart_add.png',
550 'started_following_repo':'heart_add.png',
548 'stopped_following_repo':'heart_delete.png',
551 'stopped_following_repo':'heart_delete.png',
549 }
552 }
550 return literal(tmpl % ((url('/images/icons/')),
553 return literal(tmpl % ((url('/images/icons/')),
551 map.get(action, action), action))
554 map.get(action, action), action))
552
555
553
556
554 #==============================================================================
557 #==============================================================================
555 # PERMS
558 # PERMS
556 #==============================================================================
559 #==============================================================================
557 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
560 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
558 HasRepoPermissionAny, HasRepoPermissionAll
561 HasRepoPermissionAny, HasRepoPermissionAll
559
562
560 #==============================================================================
563 #==============================================================================
561 # GRAVATAR URL
564 # GRAVATAR URL
562 #==============================================================================
565 #==============================================================================
563
566
564 def gravatar_url(email_address, size=30):
567 def gravatar_url(email_address, size=30):
565 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
568 ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
566 default = 'identicon'
569 default = 'identicon'
567 baseurl_nossl = "http://www.gravatar.com/avatar/"
570 baseurl_nossl = "http://www.gravatar.com/avatar/"
568 baseurl_ssl = "https://secure.gravatar.com/avatar/"
571 baseurl_ssl = "https://secure.gravatar.com/avatar/"
569 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
572 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
570
573
571 if isinstance(email_address, unicode):
574 if isinstance(email_address, unicode):
572 #hashlib crashes on unicode items
575 #hashlib crashes on unicode items
573 email_address = email_address.encode('utf8', 'replace')
576 email_address = email_address.encode('utf8', 'replace')
574 # construct the url
577 # construct the url
575 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
578 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
576 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
579 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
577
580
578 return gravatar_url
581 return gravatar_url
579
582
580
583
581 #==============================================================================
584 #==============================================================================
582 # REPO PAGER
585 # REPO PAGER
583 #==============================================================================
586 #==============================================================================
584 class RepoPage(Page):
587 class RepoPage(Page):
585
588
586 def __init__(self, collection, page=1, items_per_page=20,
589 def __init__(self, collection, page=1, items_per_page=20,
587 item_count=None, url=None, branch_name=None, **kwargs):
590 item_count=None, url=None, branch_name=None, **kwargs):
588
591
589 """Create a "RepoPage" instance. special pager for paging
592 """Create a "RepoPage" instance. special pager for paging
590 repository
593 repository
591 """
594 """
592 self._url_generator = url
595 self._url_generator = url
593
596
594 # Safe the kwargs class-wide so they can be used in the pager() method
597 # Safe the kwargs class-wide so they can be used in the pager() method
595 self.kwargs = kwargs
598 self.kwargs = kwargs
596
599
597 # Save a reference to the collection
600 # Save a reference to the collection
598 self.original_collection = collection
601 self.original_collection = collection
599
602
600 self.collection = collection
603 self.collection = collection
601
604
602 # The self.page is the number of the current page.
605 # The self.page is the number of the current page.
603 # The first page has the number 1!
606 # The first page has the number 1!
604 try:
607 try:
605 self.page = int(page) # make it int() if we get it as a string
608 self.page = int(page) # make it int() if we get it as a string
606 except (ValueError, TypeError):
609 except (ValueError, TypeError):
607 self.page = 1
610 self.page = 1
608
611
609 self.items_per_page = items_per_page
612 self.items_per_page = items_per_page
610
613
611 # Unless the user tells us how many items the collections has
614 # Unless the user tells us how many items the collections has
612 # we calculate that ourselves.
615 # we calculate that ourselves.
613 if item_count is not None:
616 if item_count is not None:
614 self.item_count = item_count
617 self.item_count = item_count
615 else:
618 else:
616 self.item_count = len(self.collection)
619 self.item_count = len(self.collection)
617
620
618 # Compute the number of the first and last available page
621 # Compute the number of the first and last available page
619 if self.item_count > 0:
622 if self.item_count > 0:
620 self.first_page = 1
623 self.first_page = 1
621 self.page_count = ((self.item_count - 1) / self.items_per_page) + 1
624 self.page_count = ((self.item_count - 1) / self.items_per_page) + 1
622 self.last_page = self.first_page + self.page_count - 1
625 self.last_page = self.first_page + self.page_count - 1
623
626
624 # Make sure that the requested page number is the range of valid pages
627 # Make sure that the requested page number is the range of valid pages
625 if self.page > self.last_page:
628 if self.page > self.last_page:
626 self.page = self.last_page
629 self.page = self.last_page
627 elif self.page < self.first_page:
630 elif self.page < self.first_page:
628 self.page = self.first_page
631 self.page = self.first_page
629
632
630 # Note: the number of items on this page can be less than
633 # Note: the number of items on this page can be less than
631 # items_per_page if the last page is not full
634 # items_per_page if the last page is not full
632 self.first_item = max(0, (self.item_count) - (self.page * items_per_page))
635 self.first_item = max(0, (self.item_count) - (self.page * items_per_page))
633 self.last_item = ((self.item_count - 1) - items_per_page * (self.page - 1))
636 self.last_item = ((self.item_count - 1) - items_per_page * (self.page - 1))
634
637
635 iterator = self.collection.get_changesets(start=self.first_item,
638 iterator = self.collection.get_changesets(start=self.first_item,
636 end=self.last_item,
639 end=self.last_item,
637 reverse=True,
640 reverse=True,
638 branch_name=branch_name)
641 branch_name=branch_name)
639 self.items = list(iterator)
642 self.items = list(iterator)
640
643
641 # Links to previous and next page
644 # Links to previous and next page
642 if self.page > self.first_page:
645 if self.page > self.first_page:
643 self.previous_page = self.page - 1
646 self.previous_page = self.page - 1
644 else:
647 else:
645 self.previous_page = None
648 self.previous_page = None
646
649
647 if self.page < self.last_page:
650 if self.page < self.last_page:
648 self.next_page = self.page + 1
651 self.next_page = self.page + 1
649 else:
652 else:
650 self.next_page = None
653 self.next_page = None
651
654
652 # No items available
655 # No items available
653 else:
656 else:
654 self.first_page = None
657 self.first_page = None
655 self.page_count = 0
658 self.page_count = 0
656 self.last_page = None
659 self.last_page = None
657 self.first_item = None
660 self.first_item = None
658 self.last_item = None
661 self.last_item = None
659 self.previous_page = None
662 self.previous_page = None
660 self.next_page = None
663 self.next_page = None
661 self.items = []
664 self.items = []
662
665
663 # This is a subclass of the 'list' type. Initialise the list now.
666 # This is a subclass of the 'list' type. Initialise the list now.
664 list.__init__(self, self.items)
667 list.__init__(self, self.items)
665
668
666
669
667 def safe_unicode(str):
670 def safe_unicode(str):
668 """safe unicode function. In case of UnicodeDecode error we try to return
671 """safe unicode function. In case of UnicodeDecode error we try to return
669 unicode with errors replace, if this failes we return unicode with
672 unicode with errors replace, if this failes we return unicode with
670 string_escape decoding """
673 string_escape decoding """
671
674
672 try:
675 try:
673 u_str = unicode(str)
676 u_str = unicode(str)
674 except UnicodeDecodeError:
677 except UnicodeDecodeError:
675 try:
678 try:
676 u_str = unicode(str, 'utf-8', 'replace')
679 u_str = unicode(str, 'utf-8', 'replace')
677 except UnicodeDecodeError:
680 except UnicodeDecodeError:
678 #incase we have a decode error just represent as byte string
681 #incase we have a decode error just represent as byte string
679 u_str = unicode(str(str).encode('string_escape'))
682 u_str = unicode(str(str).encode('string_escape'))
680
683
681 return u_str
684 return u_str
682
685
683 def changed_tooltip(nodes):
686 def changed_tooltip(nodes):
684 if nodes:
687 if nodes:
685 pref = ': <br/> '
688 pref = ': <br/> '
686 suf = ''
689 suf = ''
687 if len(nodes) > 30:
690 if len(nodes) > 30:
688 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
691 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
689 return literal(pref + '<br/> '.join([x.path.decode('utf-8', 'replace') for x in nodes[:30]]) + suf)
692 return literal(pref + '<br/> '.join([x.path.decode('utf-8', 'replace') for x in nodes[:30]]) + suf)
690 else:
693 else:
691 return ': ' + _('No Files')
694 return ': ' + _('No Files')
@@ -1,116 +1,116 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.hooks
3 rhodecode.lib.hooks
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Hooks runned by rhodecode
6 Hooks runned by rhodecode
7
7
8 :created_on: Aug 6, 2010
8 :created_on: Aug 6, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27 import os
27 import os
28 import sys
28 import sys
29 import getpass
29 import getpass
30
30
31 from mercurial.cmdutil import revrange
31 from mercurial.cmdutil import revrange
32 from mercurial.node import nullrev
32 from mercurial.node import nullrev
33
33
34 from rhodecode.lib import helpers as h
34 from rhodecode.lib import helpers as h
35 from rhodecode.lib.utils import action_logger
35 from rhodecode.lib.utils import action_logger
36
36
37 def repo_size(ui, repo, hooktype=None, **kwargs):
37 def repo_size(ui, repo, hooktype=None, **kwargs):
38 """Presents size of repository after push
38 """Presents size of repository after push
39
39
40 :param ui:
40 :param ui:
41 :param repo:
41 :param repo:
42 :param hooktype:
42 :param hooktype:
43 """
43 """
44
44
45 if hooktype != 'changegroup':
45 if hooktype != 'changegroup':
46 return False
46 return False
47 size_hg, size_root = 0, 0
47 size_hg, size_root = 0, 0
48 for path, dirs, files in os.walk(repo.root):
48 for path, dirs, files in os.walk(repo.root):
49 if path.find('.hg') != -1:
49 if path.find('.hg') != -1:
50 for f in files:
50 for f in files:
51 try:
51 try:
52 size_hg += os.path.getsize(os.path.join(path, f))
52 size_hg += os.path.getsize(os.path.join(path, f))
53 except OSError:
53 except OSError:
54 pass
54 pass
55 else:
55 else:
56 for f in files:
56 for f in files:
57 try:
57 try:
58 size_root += os.path.getsize(os.path.join(path, f))
58 size_root += os.path.getsize(os.path.join(path, f))
59 except OSError:
59 except OSError:
60 pass
60 pass
61
61
62 size_hg_f = h.format_byte_size(size_hg)
62 size_hg_f = h.format_byte_size(size_hg)
63 size_root_f = h.format_byte_size(size_root)
63 size_root_f = h.format_byte_size(size_root)
64 size_total_f = h.format_byte_size(size_root + size_hg)
64 size_total_f = h.format_byte_size(size_root + size_hg)
65 sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
65 sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
66 % (size_hg_f, size_root_f, size_total_f))
66 % (size_hg_f, size_root_f, size_total_f))
67
67
68 def log_pull_action(ui, repo, **kwargs):
68 def log_pull_action(ui, repo, **kwargs):
69 """Logs user last pull action
69 """Logs user last pull action
70
70
71 :param ui:
71 :param ui:
72 :param repo:
72 :param repo:
73 """
73 """
74
74
75 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
75 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
76 username = extra_params['username']
76 username = extra_params['username']
77 repository = extra_params['repository']
77 repository = extra_params['repository']
78 action = 'pull'
78 action = 'pull'
79
79
80 action_logger(username, action, repository, extra_params['ip'])
80 action_logger(username, action, repository, extra_params['ip'])
81
81
82 return 0
82 return 0
83
83
84 def log_push_action(ui, repo, **kwargs):
84 def log_push_action(ui, repo, **kwargs):
85 """Maps user last push action to new changeset id, from mercurial
85 """Maps user last push action to new changeset id, from mercurial
86
86
87 :param ui:
87 :param ui:
88 :param repo:
88 :param repo:
89 """
89 """
90
90
91 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
91 extra_params = dict(repo.ui.configitems('rhodecode_extras'))
92 username = extra_params['username']
92 username = extra_params['username']
93 repository = extra_params['repository']
93 repository = extra_params['repository']
94 action = 'push:%s'
94 action = extra_params['action'] + ':%s'
95 node = kwargs['node']
95 node = kwargs['node']
96
96
97 def get_revs(repo, rev_opt):
97 def get_revs(repo, rev_opt):
98 if rev_opt:
98 if rev_opt:
99 revs = revrange(repo, rev_opt)
99 revs = revrange(repo, rev_opt)
100
100
101 if len(revs) == 0:
101 if len(revs) == 0:
102 return (nullrev, nullrev)
102 return (nullrev, nullrev)
103 return (max(revs), min(revs))
103 return (max(revs), min(revs))
104 else:
104 else:
105 return (len(repo) - 1, 0)
105 return (len(repo) - 1, 0)
106
106
107 stop, start = get_revs(repo, [node + ':'])
107 stop, start = get_revs(repo, [node + ':'])
108
108
109 revs = (str(repo[r]) for r in xrange(start, stop + 1))
109 revs = (str(repo[r]) for r in xrange(start, stop + 1))
110
110
111 action = action % ','.join(revs)
111 action = action % ','.join(revs)
112
112
113 action_logger(username, action, repository, extra_params['ip'])
113 action_logger(username, action, repository, extra_params['ip'])
114
114
115 return 0
115 return 0
116
116
@@ -1,395 +1,412 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.scm
3 rhodecode.model.scm
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Scm model for RhodeCode
6 Scm model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27 import os
27 import os
28 import time
28 import time
29 import traceback
29 import traceback
30 import logging
30 import logging
31
31
32 from mercurial import ui
32 from mercurial import ui
33
33
34 from sqlalchemy.exc import DatabaseError
34 from sqlalchemy.exc import DatabaseError
35 from sqlalchemy.orm import make_transient
35 from sqlalchemy.orm import make_transient
36
36
37 from beaker.cache import cache_region, region_invalidate
37 from beaker.cache import cache_region, region_invalidate
38
38
39 from vcs import get_backend
39 from vcs import get_backend
40 from vcs.utils.helpers import get_scm
40 from vcs.utils.helpers import get_scm
41 from vcs.exceptions import RepositoryError, VCSError
41 from vcs.exceptions import RepositoryError, VCSError
42 from vcs.utils.lazy import LazyProperty
42 from vcs.utils.lazy import LazyProperty
43
43
44 from rhodecode import BACKENDS
44 from rhodecode import BACKENDS
45 from rhodecode.lib import helpers as h
45 from rhodecode.lib import helpers as h
46 from rhodecode.lib.auth import HasRepoPermissionAny
46 from rhodecode.lib.auth import HasRepoPermissionAny
47 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
47 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
48 action_logger
48 action_logger
49 from rhodecode.model import BaseModel
49 from rhodecode.model import BaseModel
50 from rhodecode.model.user import UserModel
50 from rhodecode.model.user import UserModel
51 from rhodecode.model.repo import RepoModel
51 from rhodecode.model.repo import RepoModel
52 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
52 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
53 UserFollowing, UserLog
53 UserFollowing, UserLog
54 from rhodecode.model.caching_query import FromCache
54 from rhodecode.model.caching_query import FromCache
55
55
56 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
57
57
58
58
59 class UserTemp(object):
59 class UserTemp(object):
60 def __init__(self, user_id):
60 def __init__(self, user_id):
61 self.user_id = user_id
61 self.user_id = user_id
62
62
63 def __repr__(self):
63 def __repr__(self):
64 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
64 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
65
65
66 class RepoTemp(object):
66 class RepoTemp(object):
67 def __init__(self, repo_id):
67 def __init__(self, repo_id):
68 self.repo_id = repo_id
68 self.repo_id = repo_id
69
69
70 def __repr__(self):
70 def __repr__(self):
71 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
72
72
73 class ScmModel(BaseModel):
73 class ScmModel(BaseModel):
74 """Generic Scm Model
74 """Generic Scm Model
75 """
75 """
76
76
77 @LazyProperty
77 @LazyProperty
78 def repos_path(self):
78 def repos_path(self):
79 """Get's the repositories root path from database
79 """Get's the repositories root path from database
80 """
80 """
81
81
82 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
82 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
83
83
84 return q.ui_value
84 return q.ui_value
85
85
86 def repo_scan(self, repos_path=None):
86 def repo_scan(self, repos_path=None):
87 """Listing of repositories in given path. This path should not be a
87 """Listing of repositories in given path. This path should not be a
88 repository itself. Return a dictionary of repository objects
88 repository itself. Return a dictionary of repository objects
89
89
90 :param repos_path: path to directory containing repositories
90 :param repos_path: path to directory containing repositories
91 """
91 """
92
92
93 log.info('scanning for repositories in %s', repos_path)
93 log.info('scanning for repositories in %s', repos_path)
94
94
95 if repos_path is None:
95 if repos_path is None:
96 repos_path = self.repos_path
96 repos_path = self.repos_path
97
97
98 baseui = make_ui('db')
98 baseui = make_ui('db')
99 repos_list = {}
99 repos_list = {}
100
100
101 for name, path in get_filesystem_repos(repos_path, recursive=True):
101 for name, path in get_filesystem_repos(repos_path, recursive=True):
102 try:
102 try:
103 if repos_list.has_key(name):
103 if repos_list.has_key(name):
104 raise RepositoryError('Duplicate repository name %s '
104 raise RepositoryError('Duplicate repository name %s '
105 'found in %s' % (name, path))
105 'found in %s' % (name, path))
106 else:
106 else:
107
107
108 klass = get_backend(path[0])
108 klass = get_backend(path[0])
109
109
110 if path[0] == 'hg' and path[0] in BACKENDS.keys():
110 if path[0] == 'hg' and path[0] in BACKENDS.keys():
111 repos_list[name] = klass(path[1], baseui=baseui)
111 repos_list[name] = klass(path[1], baseui=baseui)
112
112
113 if path[0] == 'git' and path[0] in BACKENDS.keys():
113 if path[0] == 'git' and path[0] in BACKENDS.keys():
114 repos_list[name] = klass(path[1])
114 repos_list[name] = klass(path[1])
115 except OSError:
115 except OSError:
116 continue
116 continue
117
117
118 return repos_list
118 return repos_list
119
119
120 def get_repos(self, all_repos=None):
120 def get_repos(self, all_repos=None):
121 """Get all repos from db and for each repo create it's backend instance.
121 """Get all repos from db and for each repo create it's backend instance.
122 and fill that backed with information from database
122 and fill that backed with information from database
123
123
124 :param all_repos: give specific repositories list, good for filtering
124 :param all_repos: give specific repositories list, good for filtering
125 this have to be a list of just the repository names
125 this have to be a list of just the repository names
126 """
126 """
127 if all_repos is None:
127 if all_repos is None:
128 all_repos = [r.repo_name for r in self.sa.query(Repository)\
128 all_repos = [r.repo_name for r in self.sa.query(Repository)\
129 .order_by(Repository.repo_name).all()]
129 .order_by(Repository.repo_name).all()]
130
130
131 #get the repositories that should be invalidated
131 #get the repositories that should be invalidated
132 invalidation_list = [str(x.cache_key) for x in \
132 invalidation_list = [str(x.cache_key) for x in \
133 self.sa.query(CacheInvalidation.cache_key)\
133 self.sa.query(CacheInvalidation.cache_key)\
134 .filter(CacheInvalidation.cache_active == False)\
134 .filter(CacheInvalidation.cache_active == False)\
135 .all()]
135 .all()]
136 for r_name in all_repos:
136 for r_name in all_repos:
137 r_dbr = self.get(r_name, invalidation_list)
137 r_dbr = self.get(r_name, invalidation_list)
138 if r_dbr is not None:
138 if r_dbr is not None:
139 repo, dbrepo = r_dbr
139 repo, dbrepo = r_dbr
140
140
141 last_change = repo.last_change
141 last_change = repo.last_change
142 tip = h.get_changeset_safe(repo, 'tip')
142 tip = h.get_changeset_safe(repo, 'tip')
143
143
144 tmp_d = {}
144 tmp_d = {}
145 tmp_d['name'] = dbrepo.repo_name
145 tmp_d['name'] = dbrepo.repo_name
146 tmp_d['name_sort'] = tmp_d['name'].lower()
146 tmp_d['name_sort'] = tmp_d['name'].lower()
147 tmp_d['description'] = dbrepo.description
147 tmp_d['description'] = dbrepo.description
148 tmp_d['description_sort'] = tmp_d['description']
148 tmp_d['description_sort'] = tmp_d['description']
149 tmp_d['last_change'] = last_change
149 tmp_d['last_change'] = last_change
150 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
150 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
151 tmp_d['tip'] = tip.raw_id
151 tmp_d['tip'] = tip.raw_id
152 tmp_d['tip_sort'] = tip.revision
152 tmp_d['tip_sort'] = tip.revision
153 tmp_d['rev'] = tip.revision
153 tmp_d['rev'] = tip.revision
154 tmp_d['contact'] = dbrepo.user.full_contact
154 tmp_d['contact'] = dbrepo.user.full_contact
155 tmp_d['contact_sort'] = tmp_d['contact']
155 tmp_d['contact_sort'] = tmp_d['contact']
156 tmp_d['owner_sort'] = tmp_d['contact']
156 tmp_d['owner_sort'] = tmp_d['contact']
157 tmp_d['repo_archives'] = list(repo._get_archives())
157 tmp_d['repo_archives'] = list(repo._get_archives())
158 tmp_d['last_msg'] = tip.message
158 tmp_d['last_msg'] = tip.message
159 tmp_d['repo'] = repo
159 tmp_d['repo'] = repo
160 tmp_d['dbrepo'] = dbrepo.get_dict()
160 tmp_d['dbrepo'] = dbrepo.get_dict()
161 tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork else {}
161 tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork else {}
162 yield tmp_d
162 yield tmp_d
163
163
164 def get(self, repo_name, invalidation_list=None, retval='all'):
164 def get(self, repo_name, invalidation_list=None, retval='all'):
165 """Returns a tuple of Repository,DbRepository,
165 """Returns a tuple of Repository,DbRepository,
166 Get's repository from given name, creates BackendInstance and
166 Get's repository from given name, creates BackendInstance and
167 propagates it's data from database with all additional information
167 propagates it's data from database with all additional information
168
168
169 :param repo_name:
169 :param repo_name:
170 :param invalidation_list: if a invalidation list is given the get
170 :param invalidation_list: if a invalidation list is given the get
171 method should not manually check if this repository needs
171 method should not manually check if this repository needs
172 invalidation and just invalidate the repositories in list
172 invalidation and just invalidate the repositories in list
173 :param retval: string specifing what to return one of 'repo','dbrepo',
173 :param retval: string specifing what to return one of 'repo','dbrepo',
174 'all'if repo or dbrepo is given it'll just lazy load chosen type
174 'all'if repo or dbrepo is given it'll just lazy load chosen type
175 and return None as the second
175 and return None as the second
176 """
176 """
177 if not HasRepoPermissionAny('repository.read', 'repository.write',
177 if not HasRepoPermissionAny('repository.read', 'repository.write',
178 'repository.admin')(repo_name, 'get repo check'):
178 'repository.admin')(repo_name, 'get repo check'):
179 return
179 return
180
180
181 #======================================================================
181 #======================================================================
182 # CACHE FUNCTION
182 # CACHE FUNCTION
183 #======================================================================
183 #======================================================================
184 @cache_region('long_term')
184 @cache_region('long_term')
185 def _get_repo(repo_name):
185 def _get_repo(repo_name):
186
186
187 repo_path = os.path.join(self.repos_path, repo_name)
187 repo_path = os.path.join(self.repos_path, repo_name)
188
188
189 try:
189 try:
190 alias = get_scm(repo_path)[0]
190 alias = get_scm(repo_path)[0]
191 log.debug('Creating instance of %s repository', alias)
191 log.debug('Creating instance of %s repository', alias)
192 backend = get_backend(alias)
192 backend = get_backend(alias)
193 except VCSError:
193 except VCSError:
194 log.error(traceback.format_exc())
194 log.error(traceback.format_exc())
195 log.error('Perhaps this repository is in db and not in '
195 log.error('Perhaps this repository is in db and not in '
196 'filesystem run rescan repositories with '
196 'filesystem run rescan repositories with '
197 '"destroy old data " option from admin panel')
197 '"destroy old data " option from admin panel')
198 return
198 return
199
199
200 if alias == 'hg':
200 if alias == 'hg':
201 repo = backend(repo_path, create=False, baseui=make_ui('db'))
201 repo = backend(repo_path, create=False, baseui=make_ui('db'))
202 #skip hidden web repository
202 #skip hidden web repository
203 if repo._get_hidden():
203 if repo._get_hidden():
204 return
204 return
205 else:
205 else:
206 repo = backend(repo_path, create=False)
206 repo = backend(repo_path, create=False)
207
207
208 return repo
208 return repo
209
209
210 pre_invalidate = True
210 pre_invalidate = True
211 dbinvalidate = False
211 dbinvalidate = False
212
212
213 if invalidation_list is not None:
213 if invalidation_list is not None:
214 pre_invalidate = repo_name in invalidation_list
214 pre_invalidate = repo_name in invalidation_list
215
215
216 if pre_invalidate:
216 if pre_invalidate:
217 #this returns object to invalidate
217 #this returns object to invalidate
218 invalidate = self._should_invalidate(repo_name)
218 invalidate = self._should_invalidate(repo_name)
219 if invalidate:
219 if invalidate:
220 log.info('invalidating cache for repository %s', repo_name)
220 log.info('invalidating cache for repository %s', repo_name)
221 region_invalidate(_get_repo, None, repo_name)
221 region_invalidate(_get_repo, None, repo_name)
222 self._mark_invalidated(invalidate)
222 self._mark_invalidated(invalidate)
223 dbinvalidate = True
223 dbinvalidate = True
224
224
225 r, dbr = None, None
225 r, dbr = None, None
226 if retval == 'repo' or 'all':
226 if retval == 'repo' or 'all':
227 r = _get_repo(repo_name)
227 r = _get_repo(repo_name)
228 if retval == 'dbrepo' or 'all':
228 if retval == 'dbrepo' or 'all':
229 dbr = RepoModel().get_full(repo_name, cache=True,
229 dbr = RepoModel().get_full(repo_name, cache=True,
230 invalidate=dbinvalidate)
230 invalidate=dbinvalidate)
231
231
232
232
233 return r, dbr
233 return r, dbr
234
234
235
236
237 def mark_for_invalidation(self, repo_name):
235 def mark_for_invalidation(self, repo_name):
238 """Puts cache invalidation task into db for
236 """Puts cache invalidation task into db for
239 further global cache invalidation
237 further global cache invalidation
240
238
241 :param repo_name: this repo that should invalidation take place
239 :param repo_name: this repo that should invalidation take place
242 """
240 """
243
241
244 log.debug('marking %s for invalidation', repo_name)
242 log.debug('marking %s for invalidation', repo_name)
245 cache = self.sa.query(CacheInvalidation)\
243 cache = self.sa.query(CacheInvalidation)\
246 .filter(CacheInvalidation.cache_key == repo_name).scalar()
244 .filter(CacheInvalidation.cache_key == repo_name).scalar()
247
245
248 if cache:
246 if cache:
249 #mark this cache as inactive
247 #mark this cache as inactive
250 cache.cache_active = False
248 cache.cache_active = False
251 else:
249 else:
252 log.debug('cache key not found in invalidation db -> creating one')
250 log.debug('cache key not found in invalidation db -> creating one')
253 cache = CacheInvalidation(repo_name)
251 cache = CacheInvalidation(repo_name)
254
252
255 try:
253 try:
256 self.sa.add(cache)
254 self.sa.add(cache)
257 self.sa.commit()
255 self.sa.commit()
258 except (DatabaseError,):
256 except (DatabaseError,):
259 log.error(traceback.format_exc())
257 log.error(traceback.format_exc())
260 self.sa.rollback()
258 self.sa.rollback()
261
259
262
260
263 def toggle_following_repo(self, follow_repo_id, user_id):
261 def toggle_following_repo(self, follow_repo_id, user_id):
264
262
265 f = self.sa.query(UserFollowing)\
263 f = self.sa.query(UserFollowing)\
266 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
264 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
267 .filter(UserFollowing.user_id == user_id).scalar()
265 .filter(UserFollowing.user_id == user_id).scalar()
268
266
269 if f is not None:
267 if f is not None:
270
268
271 try:
269 try:
272 self.sa.delete(f)
270 self.sa.delete(f)
273 self.sa.commit()
271 self.sa.commit()
274 action_logger(UserTemp(user_id),
272 action_logger(UserTemp(user_id),
275 'stopped_following_repo',
273 'stopped_following_repo',
276 RepoTemp(follow_repo_id))
274 RepoTemp(follow_repo_id))
277 return
275 return
278 except:
276 except:
279 log.error(traceback.format_exc())
277 log.error(traceback.format_exc())
280 self.sa.rollback()
278 self.sa.rollback()
281 raise
279 raise
282
280
283
281
284 try:
282 try:
285 f = UserFollowing()
283 f = UserFollowing()
286 f.user_id = user_id
284 f.user_id = user_id
287 f.follows_repo_id = follow_repo_id
285 f.follows_repo_id = follow_repo_id
288 self.sa.add(f)
286 self.sa.add(f)
289 self.sa.commit()
287 self.sa.commit()
290 action_logger(UserTemp(user_id),
288 action_logger(UserTemp(user_id),
291 'started_following_repo',
289 'started_following_repo',
292 RepoTemp(follow_repo_id))
290 RepoTemp(follow_repo_id))
293 except:
291 except:
294 log.error(traceback.format_exc())
292 log.error(traceback.format_exc())
295 self.sa.rollback()
293 self.sa.rollback()
296 raise
294 raise
297
295
298 def toggle_following_user(self, follow_user_id , user_id):
296 def toggle_following_user(self, follow_user_id , user_id):
299 f = self.sa.query(UserFollowing)\
297 f = self.sa.query(UserFollowing)\
300 .filter(UserFollowing.follows_user_id == follow_user_id)\
298 .filter(UserFollowing.follows_user_id == follow_user_id)\
301 .filter(UserFollowing.user_id == user_id).scalar()
299 .filter(UserFollowing.user_id == user_id).scalar()
302
300
303 if f is not None:
301 if f is not None:
304 try:
302 try:
305 self.sa.delete(f)
303 self.sa.delete(f)
306 self.sa.commit()
304 self.sa.commit()
307 return
305 return
308 except:
306 except:
309 log.error(traceback.format_exc())
307 log.error(traceback.format_exc())
310 self.sa.rollback()
308 self.sa.rollback()
311 raise
309 raise
312
310
313 try:
311 try:
314 f = UserFollowing()
312 f = UserFollowing()
315 f.user_id = user_id
313 f.user_id = user_id
316 f.follows_user_id = follow_user_id
314 f.follows_user_id = follow_user_id
317 self.sa.add(f)
315 self.sa.add(f)
318 self.sa.commit()
316 self.sa.commit()
319 except:
317 except:
320 log.error(traceback.format_exc())
318 log.error(traceback.format_exc())
321 self.sa.rollback()
319 self.sa.rollback()
322 raise
320 raise
323
321
324 def is_following_repo(self, repo_name, user_id, cache=False):
322 def is_following_repo(self, repo_name, user_id, cache=False):
325 r = self.sa.query(Repository)\
323 r = self.sa.query(Repository)\
326 .filter(Repository.repo_name == repo_name).scalar()
324 .filter(Repository.repo_name == repo_name).scalar()
327
325
328 f = self.sa.query(UserFollowing)\
326 f = self.sa.query(UserFollowing)\
329 .filter(UserFollowing.follows_repository == r)\
327 .filter(UserFollowing.follows_repository == r)\
330 .filter(UserFollowing.user_id == user_id).scalar()
328 .filter(UserFollowing.user_id == user_id).scalar()
331
329
332 return f is not None
330 return f is not None
333
331
334 def is_following_user(self, username, user_id, cache=False):
332 def is_following_user(self, username, user_id, cache=False):
335 u = UserModel(self.sa).get_by_username(username)
333 u = UserModel(self.sa).get_by_username(username)
336
334
337 f = self.sa.query(UserFollowing)\
335 f = self.sa.query(UserFollowing)\
338 .filter(UserFollowing.follows_user == u)\
336 .filter(UserFollowing.follows_user == u)\
339 .filter(UserFollowing.user_id == user_id).scalar()
337 .filter(UserFollowing.user_id == user_id).scalar()
340
338
341 return f is not None
339 return f is not None
342
340
343 def get_followers(self, repo_id):
341 def get_followers(self, repo_id):
344 if isinstance(repo_id, int):
342 if isinstance(repo_id, int):
345 return self.sa.query(UserFollowing)\
343 return self.sa.query(UserFollowing)\
346 .filter(UserFollowing.follows_repo_id == repo_id).count()
344 .filter(UserFollowing.follows_repo_id == repo_id).count()
347 else:
345 else:
348 return self.sa.query(UserFollowing)\
346 return self.sa.query(UserFollowing)\
349 .filter(UserFollowing.follows_repository \
347 .filter(UserFollowing.follows_repository \
350 == RepoModel().get_by_repo_name(repo_id)).count()
348 == RepoModel().get_by_repo_name(repo_id)).count()
351
349
352 def get_forks(self, repo_id):
350 def get_forks(self, repo_id):
353 if isinstance(repo_id, int):
351 if isinstance(repo_id, int):
354 return self.sa.query(Repository)\
352 return self.sa.query(Repository)\
355 .filter(Repository.fork_id == repo_id).count()
353 .filter(Repository.fork_id == repo_id).count()
356 else:
354 else:
357 return self.sa.query(Repository)\
355 return self.sa.query(Repository)\
358 .filter(Repository.fork \
356 .filter(Repository.fork \
359 == RepoModel().get_by_repo_name(repo_id)).count()
357 == RepoModel().get_by_repo_name(repo_id)).count()
360
358
361
359
360 def pull_changes(self, repo_name, username):
361 repo, dbrepo = self.get(repo_name, retval='all')
362
363 try:
364 extras = {'ip':'',
365 'username':username,
366 'action':'push_remote',
367 'repository':repo_name}
368
369 #inject ui extra param to log this action via push logger
370 for k, v in extras.items():
371 repo._repo.ui.setconfig('rhodecode_extras', k, v)
372
373 repo.pull(dbrepo.clone_uri)
374 self.mark_for_invalidation(repo_name)
375 except:
376 log.error(traceback.format_exc())
377 raise
378
362 def get_unread_journal(self):
379 def get_unread_journal(self):
363 return self.sa.query(UserLog).count()
380 return self.sa.query(UserLog).count()
364
381
365
382
366 def _should_invalidate(self, repo_name):
383 def _should_invalidate(self, repo_name):
367 """Looks up database for invalidation signals for this repo_name
384 """Looks up database for invalidation signals for this repo_name
368
385
369 :param repo_name:
386 :param repo_name:
370 """
387 """
371
388
372 ret = self.sa.query(CacheInvalidation)\
389 ret = self.sa.query(CacheInvalidation)\
373 .filter(CacheInvalidation.cache_key == repo_name)\
390 .filter(CacheInvalidation.cache_key == repo_name)\
374 .filter(CacheInvalidation.cache_active == False)\
391 .filter(CacheInvalidation.cache_active == False)\
375 .scalar()
392 .scalar()
376
393
377 return ret
394 return ret
378
395
379 def _mark_invalidated(self, cache_key):
396 def _mark_invalidated(self, cache_key):
380 """ Marks all occurrences of cache to invalidation as already
397 """ Marks all occurrences of cache to invalidation as already
381 invalidated
398 invalidated
382
399
383 :param cache_key:
400 :param cache_key:
384 """
401 """
385
402
386 if cache_key:
403 if cache_key:
387 log.debug('marking %s as already invalidated', cache_key)
404 log.debug('marking %s as already invalidated', cache_key)
388 try:
405 try:
389 cache_key.cache_active = True
406 cache_key.cache_active = True
390 self.sa.add(cache_key)
407 self.sa.add(cache_key)
391 self.sa.commit()
408 self.sa.commit()
392 except (DatabaseError,):
409 except (DatabaseError,):
393 log.error(traceback.format_exc())
410 log.error(traceback.format_exc())
394 self.sa.rollback()
411 self.sa.rollback()
395
412
@@ -1,2508 +1,2516 b''
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
2 border:0;
2 border:0;
3 outline:0;
3 outline:0;
4 font-size:100%;
4 font-size:100%;
5 vertical-align:baseline;
5 vertical-align:baseline;
6 background:transparent;
6 background:transparent;
7 margin:0;
7 margin:0;
8 padding:0;
8 padding:0;
9 }
9 }
10
10
11 body {
11 body {
12 line-height:1;
12 line-height:1;
13 height:100%;
13 height:100%;
14 background:url("../images/background.png") repeat scroll 0 0 #B0B0B0;
14 background:url("../images/background.png") repeat scroll 0 0 #B0B0B0;
15 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
15 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
16 font-size:12px;
16 font-size:12px;
17 color:#000;
17 color:#000;
18 margin:0;
18 margin:0;
19 padding:0;
19 padding:0;
20 }
20 }
21
21
22 ol,ul {
22 ol,ul {
23 list-style:none;
23 list-style:none;
24 }
24 }
25
25
26 blockquote,q {
26 blockquote,q {
27 quotes:none;
27 quotes:none;
28 }
28 }
29
29
30 blockquote:before,blockquote:after,q:before,q:after {
30 blockquote:before,blockquote:after,q:before,q:after {
31 content:none;
31 content:none;
32 }
32 }
33
33
34 :focus {
34 :focus {
35 outline:0;
35 outline:0;
36 }
36 }
37
37
38 del {
38 del {
39 text-decoration:line-through;
39 text-decoration:line-through;
40 }
40 }
41
41
42 table {
42 table {
43 border-collapse:collapse;
43 border-collapse:collapse;
44 border-spacing:0;
44 border-spacing:0;
45 }
45 }
46
46
47 html {
47 html {
48 height:100%;
48 height:100%;
49 }
49 }
50
50
51 a {
51 a {
52 color:#003367;
52 color:#003367;
53 text-decoration:none;
53 text-decoration:none;
54 cursor:pointer;
54 cursor:pointer;
55 font-weight:700;
55 font-weight:700;
56 }
56 }
57
57
58 a:hover {
58 a:hover {
59 color:#316293;
59 color:#316293;
60 text-decoration:underline;
60 text-decoration:underline;
61 }
61 }
62
62
63 h1,h2,h3,h4,h5,h6 {
63 h1,h2,h3,h4,h5,h6 {
64 color:#292929;
64 color:#292929;
65 font-weight:700;
65 font-weight:700;
66 }
66 }
67
67
68 h1 {
68 h1 {
69 font-size:22px;
69 font-size:22px;
70 }
70 }
71
71
72 h2 {
72 h2 {
73 font-size:20px;
73 font-size:20px;
74 }
74 }
75
75
76 h3 {
76 h3 {
77 font-size:18px;
77 font-size:18px;
78 }
78 }
79
79
80 h4 {
80 h4 {
81 font-size:16px;
81 font-size:16px;
82 }
82 }
83
83
84 h5 {
84 h5 {
85 font-size:14px;
85 font-size:14px;
86 }
86 }
87
87
88 h6 {
88 h6 {
89 font-size:11px;
89 font-size:11px;
90 }
90 }
91
91
92 ul.circle {
92 ul.circle {
93 list-style-type:circle;
93 list-style-type:circle;
94 }
94 }
95
95
96 ul.disc {
96 ul.disc {
97 list-style-type:disc;
97 list-style-type:disc;
98 }
98 }
99
99
100 ul.square {
100 ul.square {
101 list-style-type:square;
101 list-style-type:square;
102 }
102 }
103
103
104 ol.lower-roman {
104 ol.lower-roman {
105 list-style-type:lower-roman;
105 list-style-type:lower-roman;
106 }
106 }
107
107
108 ol.upper-roman {
108 ol.upper-roman {
109 list-style-type:upper-roman;
109 list-style-type:upper-roman;
110 }
110 }
111
111
112 ol.lower-alpha {
112 ol.lower-alpha {
113 list-style-type:lower-alpha;
113 list-style-type:lower-alpha;
114 }
114 }
115
115
116 ol.upper-alpha {
116 ol.upper-alpha {
117 list-style-type:upper-alpha;
117 list-style-type:upper-alpha;
118 }
118 }
119
119
120 ol.decimal {
120 ol.decimal {
121 list-style-type:decimal;
121 list-style-type:decimal;
122 }
122 }
123
123
124 div.color {
124 div.color {
125 clear:both;
125 clear:both;
126 overflow:hidden;
126 overflow:hidden;
127 position:absolute;
127 position:absolute;
128 background:#FFF;
128 background:#FFF;
129 margin:7px 0 0 60px;
129 margin:7px 0 0 60px;
130 padding:1px 1px 1px 0;
130 padding:1px 1px 1px 0;
131 }
131 }
132
132
133 div.color a {
133 div.color a {
134 width:15px;
134 width:15px;
135 height:15px;
135 height:15px;
136 display:block;
136 display:block;
137 float:left;
137 float:left;
138 margin:0 0 0 1px;
138 margin:0 0 0 1px;
139 padding:0;
139 padding:0;
140 }
140 }
141
141
142 div.options {
142 div.options {
143 clear:both;
143 clear:both;
144 overflow:hidden;
144 overflow:hidden;
145 position:absolute;
145 position:absolute;
146 background:#FFF;
146 background:#FFF;
147 margin:7px 0 0 162px;
147 margin:7px 0 0 162px;
148 padding:0;
148 padding:0;
149 }
149 }
150
150
151 div.options a {
151 div.options a {
152 height:1%;
152 height:1%;
153 display:block;
153 display:block;
154 text-decoration:none;
154 text-decoration:none;
155 margin:0;
155 margin:0;
156 padding:3px 8px;
156 padding:3px 8px;
157 }
157 }
158
158
159 .top-left-rounded-corner {
159 .top-left-rounded-corner {
160 -webkit-border-top-left-radius: 8px;
160 -webkit-border-top-left-radius: 8px;
161 -khtml-border-radius-topleft: 8px;
161 -khtml-border-radius-topleft: 8px;
162 -moz-border-radius-topleft: 8px;
162 -moz-border-radius-topleft: 8px;
163 border-top-left-radius: 8px;
163 border-top-left-radius: 8px;
164 }
164 }
165
165
166 .top-right-rounded-corner {
166 .top-right-rounded-corner {
167 -webkit-border-top-right-radius: 8px;
167 -webkit-border-top-right-radius: 8px;
168 -khtml-border-radius-topright: 8px;
168 -khtml-border-radius-topright: 8px;
169 -moz-border-radius-topright: 8px;
169 -moz-border-radius-topright: 8px;
170 border-top-right-radius: 8px;
170 border-top-right-radius: 8px;
171 }
171 }
172
172
173 .bottom-left-rounded-corner {
173 .bottom-left-rounded-corner {
174 -webkit-border-bottom-left-radius: 8px;
174 -webkit-border-bottom-left-radius: 8px;
175 -khtml-border-radius-bottomleft: 8px;
175 -khtml-border-radius-bottomleft: 8px;
176 -moz-border-radius-bottomleft: 8px;
176 -moz-border-radius-bottomleft: 8px;
177 border-bottom-left-radius: 8px;
177 border-bottom-left-radius: 8px;
178 }
178 }
179
179
180 .bottom-right-rounded-corner {
180 .bottom-right-rounded-corner {
181 -webkit-border-bottom-right-radius: 8px;
181 -webkit-border-bottom-right-radius: 8px;
182 -khtml-border-radius-bottomright: 8px;
182 -khtml-border-radius-bottomright: 8px;
183 -moz-border-radius-bottomright: 8px;
183 -moz-border-radius-bottomright: 8px;
184 border-bottom-right-radius: 8px;
184 border-bottom-right-radius: 8px;
185 }
185 }
186
186
187
187
188 #header {
188 #header {
189 margin:0;
189 margin:0;
190 padding:0 30px;
190 padding:0 30px;
191 }
191 }
192
192
193
193
194 #header ul#logged-user{
194 #header ul#logged-user{
195 margin-bottom:5px !important;
195 margin-bottom:5px !important;
196 -webkit-border-radius: 0px 0px 8px 8px;
196 -webkit-border-radius: 0px 0px 8px 8px;
197 -khtml-border-radius: 0px 0px 8px 8px;
197 -khtml-border-radius: 0px 0px 8px 8px;
198 -moz-border-radius: 0px 0px 8px 8px;
198 -moz-border-radius: 0px 0px 8px 8px;
199 border-radius: 0px 0px 8px 8px;
199 border-radius: 0px 0px 8px 8px;
200 height:37px;
200 height:37px;
201 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367
201 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367
202 }
202 }
203
203
204 #header ul#logged-user li {
204 #header ul#logged-user li {
205 list-style:none;
205 list-style:none;
206 float:left;
206 float:left;
207 margin:8px 0 0;
207 margin:8px 0 0;
208 padding:4px 12px;
208 padding:4px 12px;
209 border-left: 1px solid #316293;
209 border-left: 1px solid #316293;
210 }
210 }
211
211
212 #header ul#logged-user li.first {
212 #header ul#logged-user li.first {
213 border-left:none;
213 border-left:none;
214 margin:4px;
214 margin:4px;
215 }
215 }
216
216
217 #header ul#logged-user li.first div.gravatar {
217 #header ul#logged-user li.first div.gravatar {
218 margin-top:-2px;
218 margin-top:-2px;
219 }
219 }
220
220
221 #header ul#logged-user li.first div.account {
221 #header ul#logged-user li.first div.account {
222 padding-top:4px;
222 padding-top:4px;
223 float:left;
223 float:left;
224 }
224 }
225
225
226 #header ul#logged-user li.last {
226 #header ul#logged-user li.last {
227 border-right:none;
227 border-right:none;
228 }
228 }
229
229
230 #header ul#logged-user li a {
230 #header ul#logged-user li a {
231 color:#fff;
231 color:#fff;
232 font-weight:700;
232 font-weight:700;
233 text-decoration:none;
233 text-decoration:none;
234 }
234 }
235
235
236 #header ul#logged-user li a:hover {
236 #header ul#logged-user li a:hover {
237 text-decoration:underline;
237 text-decoration:underline;
238 }
238 }
239
239
240 #header ul#logged-user li.highlight a {
240 #header ul#logged-user li.highlight a {
241 color:#fff;
241 color:#fff;
242 }
242 }
243
243
244 #header ul#logged-user li.highlight a:hover {
244 #header ul#logged-user li.highlight a:hover {
245 color:#FFF;
245 color:#FFF;
246 }
246 }
247
247
248 #header #header-inner {
248 #header #header-inner {
249 height:40px;
249 height:40px;
250 clear:both;
250 clear:both;
251 position:relative;
251 position:relative;
252 background:#003367 url("../images/header_inner.png") repeat-x;
252 background:#003367 url("../images/header_inner.png") repeat-x;
253 border-bottom:2px solid #fff;
253 border-bottom:2px solid #fff;
254 margin:0;
254 margin:0;
255 padding:0;
255 padding:0;
256 }
256 }
257
257
258 #header #header-inner #home a {
258 #header #header-inner #home a {
259 height:40px;
259 height:40px;
260 width:46px;
260 width:46px;
261 display:block;
261 display:block;
262 background:url("../images/button_home.png");
262 background:url("../images/button_home.png");
263 background-position:0 0;
263 background-position:0 0;
264 margin:0;
264 margin:0;
265 padding:0;
265 padding:0;
266 }
266 }
267
267
268 #header #header-inner #home a:hover {
268 #header #header-inner #home a:hover {
269 background-position:0 -40px;
269 background-position:0 -40px;
270 }
270 }
271
271
272 #header #header-inner #logo h1 {
272 #header #header-inner #logo h1 {
273 color:#FFF;
273 color:#FFF;
274 font-size:18px;
274 font-size:18px;
275 margin:10px 0 0 13px;
275 margin:10px 0 0 13px;
276 padding:0;
276 padding:0;
277 }
277 }
278
278
279 #header #header-inner #logo a {
279 #header #header-inner #logo a {
280 color:#fff;
280 color:#fff;
281 text-decoration:none;
281 text-decoration:none;
282 }
282 }
283
283
284 #header #header-inner #logo a:hover {
284 #header #header-inner #logo a:hover {
285 color:#bfe3ff;
285 color:#bfe3ff;
286 }
286 }
287
287
288 #header #header-inner #quick,#header #header-inner #quick ul {
288 #header #header-inner #quick,#header #header-inner #quick ul {
289 position:relative;
289 position:relative;
290 float:right;
290 float:right;
291 list-style-type:none;
291 list-style-type:none;
292 list-style-position:outside;
292 list-style-position:outside;
293 margin:10px 5px 0 0;
293 margin:10px 5px 0 0;
294 padding:0;
294 padding:0;
295 }
295 }
296
296
297 #header #header-inner #quick li {
297 #header #header-inner #quick li {
298 position:relative;
298 position:relative;
299 float:left;
299 float:left;
300 margin:0 5px 0 0;
300 margin:0 5px 0 0;
301 padding:0;
301 padding:0;
302 }
302 }
303
303
304 #header #header-inner #quick li a {
304 #header #header-inner #quick li a {
305 top:0;
305 top:0;
306 left:0;
306 left:0;
307 height:1%;
307 height:1%;
308 display:block;
308 display:block;
309 clear:both;
309 clear:both;
310 overflow:hidden;
310 overflow:hidden;
311 color:#FFF;
311 color:#FFF;
312 font-weight:700;
312 font-weight:700;
313 text-decoration:none;
313 text-decoration:none;
314 background:#369 url("../images/quick_l.png") no-repeat top left;
314 background:#369 url("../images/quick_l.png") no-repeat top left;
315 padding:0;
315 padding:0;
316 }
316 }
317
317
318 #header #header-inner #quick li span.short {
318 #header #header-inner #quick li span.short {
319 padding:9px 6px 8px 6px;
319 padding:9px 6px 8px 6px;
320 }
320 }
321
321
322 #header #header-inner #quick li span {
322 #header #header-inner #quick li span {
323 top:0;
323 top:0;
324 right:0;
324 right:0;
325 height:1%;
325 height:1%;
326 display:block;
326 display:block;
327 float:left;
327 float:left;
328 background:url("../images/quick_r.png") no-repeat top right;
328 background:url("../images/quick_r.png") no-repeat top right;
329 border-left:1px solid #3f6f9f;
329 border-left:1px solid #3f6f9f;
330 margin:0;
330 margin:0;
331 padding:10px 12px 8px 10px;
331 padding:10px 12px 8px 10px;
332 }
332 }
333
333
334 #header #header-inner #quick li span.normal {
334 #header #header-inner #quick li span.normal {
335 border:none;
335 border:none;
336 padding:10px 12px 8px;
336 padding:10px 12px 8px;
337 }
337 }
338
338
339 #header #header-inner #quick li span.icon {
339 #header #header-inner #quick li span.icon {
340 top:0;
340 top:0;
341 left:0;
341 left:0;
342 border-left:none;
342 border-left:none;
343 background:url("../images/quick_l.png") no-repeat top left;
343 background:url("../images/quick_l.png") no-repeat top left;
344 border-right:1px solid #2e5c89;
344 border-right:1px solid #2e5c89;
345 padding:8px 8px 4px;
345 padding:8px 8px 4px;
346 }
346 }
347
347
348 #header #header-inner #quick li span.icon_short {
348 #header #header-inner #quick li span.icon_short {
349 top:0;
349 top:0;
350 left:0;
350 left:0;
351 border-left:none;
351 border-left:none;
352 background:url("../images/quick_l.png") no-repeat top left;
352 background:url("../images/quick_l.png") no-repeat top left;
353 border-right:1px solid #2e5c89;
353 border-right:1px solid #2e5c89;
354 padding:9px 4px 4px;
354 padding:9px 4px 4px;
355 }
355 }
356
356
357 #header #header-inner #quick li a:hover {
357 #header #header-inner #quick li a:hover {
358 background:#4e4e4e url("../images/quick_l_selected.png") no-repeat top left;
358 background:#4e4e4e url("../images/quick_l_selected.png") no-repeat top left;
359 }
359 }
360
360
361 #header #header-inner #quick li a:hover span {
361 #header #header-inner #quick li a:hover span {
362 border-left:1px solid #545454;
362 border-left:1px solid #545454;
363 background:url("../images/quick_r_selected.png") no-repeat top right;
363 background:url("../images/quick_r_selected.png") no-repeat top right;
364 }
364 }
365
365
366 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short {
366 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short {
367 border-left:none;
367 border-left:none;
368 border-right:1px solid #464646;
368 border-right:1px solid #464646;
369 background:url("../images/quick_l_selected.png") no-repeat top left;
369 background:url("../images/quick_l_selected.png") no-repeat top left;
370 }
370 }
371
371
372
372
373 #header #header-inner #quick ul {
373 #header #header-inner #quick ul {
374 top:29px;
374 top:29px;
375 right:0;
375 right:0;
376 min-width:200px;
376 min-width:200px;
377 display:none;
377 display:none;
378 position:absolute;
378 position:absolute;
379 background:#FFF;
379 background:#FFF;
380 border:1px solid #666;
380 border:1px solid #666;
381 border-top:1px solid #003367;
381 border-top:1px solid #003367;
382 z-index:100;
382 z-index:100;
383 margin:0;
383 margin:0;
384 padding:0;
384 padding:0;
385 }
385 }
386
386
387 #header #header-inner #quick ul.repo_switcher {
387 #header #header-inner #quick ul.repo_switcher {
388 max-height:275px;
388 max-height:275px;
389 overflow-x:hidden;
389 overflow-x:hidden;
390 overflow-y:auto;
390 overflow-y:auto;
391 }
391 }
392
392
393 #header #header-inner #quick .repo_switcher_type{
393 #header #header-inner #quick .repo_switcher_type{
394 position:absolute;
394 position:absolute;
395 left:0;
395 left:0;
396 top:9px;
396 top:9px;
397
397
398 }
398 }
399 #header #header-inner #quick li ul li {
399 #header #header-inner #quick li ul li {
400 border-bottom:1px solid #ddd;
400 border-bottom:1px solid #ddd;
401 }
401 }
402
402
403 #header #header-inner #quick li ul li a {
403 #header #header-inner #quick li ul li a {
404 width:182px;
404 width:182px;
405 height:auto;
405 height:auto;
406 display:block;
406 display:block;
407 float:left;
407 float:left;
408 background:#FFF;
408 background:#FFF;
409 color:#003367;
409 color:#003367;
410 font-weight:400;
410 font-weight:400;
411 margin:0;
411 margin:0;
412 padding:7px 9px;
412 padding:7px 9px;
413 }
413 }
414
414
415 #header #header-inner #quick li ul li a:hover {
415 #header #header-inner #quick li ul li a:hover {
416 color:#000;
416 color:#000;
417 background:#FFF;
417 background:#FFF;
418 }
418 }
419
419
420 #header #header-inner #quick ul ul {
420 #header #header-inner #quick ul ul {
421 top:auto;
421 top:auto;
422 }
422 }
423
423
424 #header #header-inner #quick li ul ul {
424 #header #header-inner #quick li ul ul {
425 right:200px;
425 right:200px;
426 max-height:275px;
426 max-height:275px;
427 overflow:auto;
427 overflow:auto;
428 overflow-x:hidden;
428 overflow-x:hidden;
429 white-space:normal;
429 white-space:normal;
430 }
430 }
431
431
432 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
432 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
433 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
433 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
434 width:167px;
434 width:167px;
435 margin:0;
435 margin:0;
436 padding:12px 9px 7px 24px;
436 padding:12px 9px 7px 24px;
437 }
437 }
438
438
439 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
439 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
440 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
440 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
441 min-width:167px;
441 min-width:167px;
442 margin:0;
442 margin:0;
443 padding:12px 9px 7px 24px;
443 padding:12px 9px 7px 24px;
444 }
444 }
445
445
446 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
446 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
447 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
447 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
448 min-width:167px;
448 min-width:167px;
449 margin:0;
449 margin:0;
450 padding:12px 9px 7px 24px;
450 padding:12px 9px 7px 24px;
451 }
451 }
452
452
453 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover {
453 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover {
454 background:url("../images/icons/hgicon.png") no-repeat scroll 4px 9px #FFF;
454 background:url("../images/icons/hgicon.png") no-repeat scroll 4px 9px #FFF;
455 min-width:167px;
455 min-width:167px;
456 margin:0 0 0 14px;
456 margin:0 0 0 14px;
457 padding:12px 9px 7px 24px;
457 padding:12px 9px 7px 24px;
458 }
458 }
459
459
460 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover {
460 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover {
461 background:url("../images/icons/giticon.png") no-repeat scroll 4px 9px #FFF;
461 background:url("../images/icons/giticon.png") no-repeat scroll 4px 9px #FFF;
462 min-width:167px;
462 min-width:167px;
463 margin:0 0 0 14px;
463 margin:0 0 0 14px;
464 padding:12px 9px 7px 24px;
464 padding:12px 9px 7px 24px;
465 }
465 }
466
466
467 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
467 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
468 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
468 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
469 width:167px;
469 width:167px;
470 margin:0;
470 margin:0;
471 padding:12px 9px 7px 24px;
471 padding:12px 9px 7px 24px;
472 }
472 }
473
473
474 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
474 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
475 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
475 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
476 width:167px;
476 width:167px;
477 margin:0;
477 margin:0;
478 padding:12px 9px 7px 24px;
478 padding:12px 9px 7px 24px;
479 }
479 }
480
480
481 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover {
481 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover {
482 background:#FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
482 background:#FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
483 width:167px;
483 width:167px;
484 margin:0;
484 margin:0;
485 padding:12px 9px 7px 24px;
485 padding:12px 9px 7px 24px;
486 }
486 }
487
487
488 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
488 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
489 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
489 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
490 width:167px;
490 width:167px;
491 margin:0;
491 margin:0;
492 padding:12px 9px 7px 24px;
492 padding:12px 9px 7px 24px;
493 }
493 }
494
494
495 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
495 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
496 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
496 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
497 width:167px;
497 width:167px;
498 margin:0;
498 margin:0;
499 padding:12px 9px 7px 24px;
499 padding:12px 9px 7px 24px;
500 }
500 }
501
501
502 #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover {
502 #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover {
503 background:#FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
503 background:#FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
504 width:167px;
504 width:167px;
505 margin:0;
505 margin:0;
506 padding:12px 9px 7px 24px;
506 padding:12px 9px 7px 24px;
507 }
507 }
508
508
509 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
509 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
510 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
510 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
511 width:167px;
511 width:167px;
512 margin:0;
512 margin:0;
513 padding:12px 9px 7px 24px;
513 padding:12px 9px 7px 24px;
514 }
514 }
515
515
516 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
516 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
517 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
517 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
518 width:167px;
518 width:167px;
519 margin:0;
519 margin:0;
520 padding:12px 9px 7px 24px;
520 padding:12px 9px 7px 24px;
521 }
521 }
522
522
523 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
523 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
524 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
524 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
525 width:167px;
525 width:167px;
526 margin:0;
526 margin:0;
527 padding:12px 9px 7px 24px;
527 padding:12px 9px 7px 24px;
528 }
528 }
529
529
530 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
530 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
531 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
531 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
532 width:167px;
532 width:167px;
533 margin:0;
533 margin:0;
534 padding:12px 9px 7px 24px;
534 padding:12px 9px 7px 24px;
535 }
535 }
536
536
537 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
537 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
538 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
538 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
539 width:167px;
539 width:167px;
540 margin:0;
540 margin:0;
541 padding:12px 9px 7px 24px;
541 padding:12px 9px 7px 24px;
542 }
542 }
543
543
544 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
544 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
545 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
545 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
546 width:167px;
546 width:167px;
547 margin:0;
547 margin:0;
548 padding:12px 9px 7px 24px;
548 padding:12px 9px 7px 24px;
549 }
549 }
550
550
551 #content #left {
551 #content #left {
552 left:0;
552 left:0;
553 width:280px;
553 width:280px;
554 position:absolute;
554 position:absolute;
555 }
555 }
556
556
557 #content #right {
557 #content #right {
558 margin:0 60px 10px 290px;
558 margin:0 60px 10px 290px;
559 }
559 }
560
560
561 #content div.box {
561 #content div.box {
562 clear:both;
562 clear:both;
563 overflow:hidden;
563 overflow:hidden;
564 background:#fff;
564 background:#fff;
565 margin:0 0 10px;
565 margin:0 0 10px;
566 padding:0 0 10px;
566 padding:0 0 10px;
567 }
567 }
568
568
569 #content div.box-left {
569 #content div.box-left {
570 width:49%;
570 width:49%;
571 clear:none;
571 clear:none;
572 float:left;
572 float:left;
573 margin:0 0 10px;
573 margin:0 0 10px;
574 }
574 }
575
575
576 #content div.box-right {
576 #content div.box-right {
577 width:49%;
577 width:49%;
578 clear:none;
578 clear:none;
579 float:right;
579 float:right;
580 margin:0 0 10px;
580 margin:0 0 10px;
581 }
581 }
582
582
583 #content div.box div.title {
583 #content div.box div.title {
584 clear:both;
584 clear:both;
585 overflow:hidden;
585 overflow:hidden;
586 background:#369 url("../images/header_inner.png") repeat-x;
586 background:#369 url("../images/header_inner.png") repeat-x;
587 margin:0 0 20px;
587 margin:0 0 20px;
588 padding:0;
588 padding:0;
589 }
589 }
590
590
591 #content div.box div.title h5 {
591 #content div.box div.title h5 {
592 float:left;
592 float:left;
593 border:none;
593 border:none;
594 color:#fff;
594 color:#fff;
595 text-transform:uppercase;
595 text-transform:uppercase;
596 margin:0;
596 margin:0;
597 padding:11px 0 11px 10px;
597 padding:11px 0 11px 10px;
598 }
598 }
599
599
600 #content div.box div.title ul.links li {
600 #content div.box div.title ul.links li {
601 list-style:none;
601 list-style:none;
602 float:left;
602 float:left;
603 margin:0;
603 margin:0;
604 padding:0;
604 padding:0;
605 }
605 }
606
606
607 #content div.box div.title ul.links li a {
607 #content div.box div.title ul.links li a {
608 border-left: 1px solid #316293;
608 border-left: 1px solid #316293;
609 color: #FFFFFF;
609 color: #FFFFFF;
610 display: block;
610 display: block;
611 float: left;
611 float: left;
612 font-size: 13px;
612 font-size: 13px;
613 font-weight: 700;
613 font-weight: 700;
614 height: 1%;
614 height: 1%;
615 margin: 0;
615 margin: 0;
616 padding: 11px 22px 12px;
616 padding: 11px 22px 12px;
617 text-decoration: none;
617 text-decoration: none;
618 }
618 }
619
619
620 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
620 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
621 clear:both;
621 clear:both;
622 overflow:hidden;
622 overflow:hidden;
623 border-bottom:1px solid #DDD;
623 border-bottom:1px solid #DDD;
624 margin:10px 20px;
624 margin:10px 20px;
625 padding:0 0 15px;
625 padding:0 0 15px;
626 }
626 }
627
627
628 #content div.box p {
628 #content div.box p {
629 color:#5f5f5f;
629 color:#5f5f5f;
630 font-size:12px;
630 font-size:12px;
631 line-height:150%;
631 line-height:150%;
632 margin:0 24px 10px;
632 margin:0 24px 10px;
633 padding:0;
633 padding:0;
634 }
634 }
635
635
636 #content div.box blockquote {
636 #content div.box blockquote {
637 border-left:4px solid #DDD;
637 border-left:4px solid #DDD;
638 color:#5f5f5f;
638 color:#5f5f5f;
639 font-size:11px;
639 font-size:11px;
640 line-height:150%;
640 line-height:150%;
641 margin:0 34px;
641 margin:0 34px;
642 padding:0 0 0 14px;
642 padding:0 0 0 14px;
643 }
643 }
644
644
645 #content div.box blockquote p {
645 #content div.box blockquote p {
646 margin:10px 0;
646 margin:10px 0;
647 padding:0;
647 padding:0;
648 }
648 }
649
649
650 #content div.box dl {
650 #content div.box dl {
651 margin:10px 24px;
651 margin:10px 24px;
652 }
652 }
653
653
654 #content div.box dt {
654 #content div.box dt {
655 font-size:12px;
655 font-size:12px;
656 margin:0;
656 margin:0;
657 }
657 }
658
658
659 #content div.box dd {
659 #content div.box dd {
660 font-size:12px;
660 font-size:12px;
661 margin:0;
661 margin:0;
662 padding:8px 0 8px 15px;
662 padding:8px 0 8px 15px;
663 }
663 }
664
664
665 #content div.box li {
665 #content div.box li {
666 font-size:12px;
666 font-size:12px;
667 padding:4px 0;
667 padding:4px 0;
668 }
668 }
669
669
670 #content div.box ul.disc,#content div.box ul.circle {
670 #content div.box ul.disc,#content div.box ul.circle {
671 margin:10px 24px 10px 38px;
671 margin:10px 24px 10px 38px;
672 }
672 }
673
673
674 #content div.box ul.square {
674 #content div.box ul.square {
675 margin:10px 24px 10px 40px;
675 margin:10px 24px 10px 40px;
676 }
676 }
677
677
678 #content div.box img.left {
678 #content div.box img.left {
679 border:none;
679 border:none;
680 float:left;
680 float:left;
681 margin:10px 10px 10px 0;
681 margin:10px 10px 10px 0;
682 }
682 }
683
683
684 #content div.box img.right {
684 #content div.box img.right {
685 border:none;
685 border:none;
686 float:right;
686 float:right;
687 margin:10px 0 10px 10px;
687 margin:10px 0 10px 10px;
688 }
688 }
689
689
690 #content div.box div.messages {
690 #content div.box div.messages {
691 clear:both;
691 clear:both;
692 overflow:hidden;
692 overflow:hidden;
693 margin:0 20px;
693 margin:0 20px;
694 padding:0;
694 padding:0;
695 }
695 }
696
696
697 #content div.box div.message {
697 #content div.box div.message {
698 clear:both;
698 clear:both;
699 overflow:hidden;
699 overflow:hidden;
700 margin:0;
700 margin:0;
701 padding:10px 0;
701 padding:10px 0;
702 }
702 }
703
703
704 #content div.box div.message a {
704 #content div.box div.message a {
705 font-weight:400 !important;
705 font-weight:400 !important;
706 }
706 }
707
707
708 #content div.box div.message div.image {
708 #content div.box div.message div.image {
709 float:left;
709 float:left;
710 margin:9px 0 0 5px;
710 margin:9px 0 0 5px;
711 padding:6px;
711 padding:6px;
712 }
712 }
713
713
714 #content div.box div.message div.image img {
714 #content div.box div.message div.image img {
715 vertical-align:middle;
715 vertical-align:middle;
716 margin:0;
716 margin:0;
717 }
717 }
718
718
719 #content div.box div.message div.text {
719 #content div.box div.message div.text {
720 float:left;
720 float:left;
721 margin:0;
721 margin:0;
722 padding:9px 6px;
722 padding:9px 6px;
723 }
723 }
724
724
725 #content div.box div.message div.dismiss a {
725 #content div.box div.message div.dismiss a {
726 height:16px;
726 height:16px;
727 width:16px;
727 width:16px;
728 display:block;
728 display:block;
729 background:url("../images/icons/cross.png") no-repeat;
729 background:url("../images/icons/cross.png") no-repeat;
730 margin:15px 14px 0 0;
730 margin:15px 14px 0 0;
731 padding:0;
731 padding:0;
732 }
732 }
733
733
734 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 {
734 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 {
735 border:none;
735 border:none;
736 margin:0;
736 margin:0;
737 padding:0;
737 padding:0;
738 }
738 }
739
739
740 #content div.box div.message div.text span {
740 #content div.box div.message div.text span {
741 height:1%;
741 height:1%;
742 display:block;
742 display:block;
743 margin:0;
743 margin:0;
744 padding:5px 0 0;
744 padding:5px 0 0;
745 }
745 }
746
746
747 #content div.box div.message-error {
747 #content div.box div.message-error {
748 height:1%;
748 height:1%;
749 clear:both;
749 clear:both;
750 overflow:hidden;
750 overflow:hidden;
751 background:#FBE3E4;
751 background:#FBE3E4;
752 border:1px solid #FBC2C4;
752 border:1px solid #FBC2C4;
753 color:#860006;
753 color:#860006;
754 }
754 }
755
755
756 #content div.box div.message-error h6 {
756 #content div.box div.message-error h6 {
757 color:#860006;
757 color:#860006;
758 }
758 }
759
759
760 #content div.box div.message-warning {
760 #content div.box div.message-warning {
761 height:1%;
761 height:1%;
762 clear:both;
762 clear:both;
763 overflow:hidden;
763 overflow:hidden;
764 background:#FFF6BF;
764 background:#FFF6BF;
765 border:1px solid #FFD324;
765 border:1px solid #FFD324;
766 color:#5f5200;
766 color:#5f5200;
767 }
767 }
768
768
769 #content div.box div.message-warning h6 {
769 #content div.box div.message-warning h6 {
770 color:#5f5200;
770 color:#5f5200;
771 }
771 }
772
772
773 #content div.box div.message-notice {
773 #content div.box div.message-notice {
774 height:1%;
774 height:1%;
775 clear:both;
775 clear:both;
776 overflow:hidden;
776 overflow:hidden;
777 background:#8FBDE0;
777 background:#8FBDE0;
778 border:1px solid #6BACDE;
778 border:1px solid #6BACDE;
779 color:#003863;
779 color:#003863;
780 }
780 }
781
781
782 #content div.box div.message-notice h6 {
782 #content div.box div.message-notice h6 {
783 color:#003863;
783 color:#003863;
784 }
784 }
785
785
786 #content div.box div.message-success {
786 #content div.box div.message-success {
787 height:1%;
787 height:1%;
788 clear:both;
788 clear:both;
789 overflow:hidden;
789 overflow:hidden;
790 background:#E6EFC2;
790 background:#E6EFC2;
791 border:1px solid #C6D880;
791 border:1px solid #C6D880;
792 color:#4e6100;
792 color:#4e6100;
793 }
793 }
794
794
795 #content div.box div.message-success h6 {
795 #content div.box div.message-success h6 {
796 color:#4e6100;
796 color:#4e6100;
797 }
797 }
798
798
799 #content div.box div.form div.fields div.field {
799 #content div.box div.form div.fields div.field {
800 height:1%;
800 height:1%;
801 border-bottom:1px solid #DDD;
801 border-bottom:1px solid #DDD;
802 clear:both;
802 clear:both;
803 margin:0;
803 margin:0;
804 padding:10px 0;
804 padding:10px 0;
805 }
805 }
806
806
807 #content div.box div.form div.fields div.field-first {
807 #content div.box div.form div.fields div.field-first {
808 padding:0 0 10px;
808 padding:0 0 10px;
809 }
809 }
810
810
811 #content div.box div.form div.fields div.field-noborder {
811 #content div.box div.form div.fields div.field-noborder {
812 border-bottom:0 !important;
812 border-bottom:0 !important;
813 }
813 }
814
814
815 #content div.box div.form div.fields div.field span.error-message {
815 #content div.box div.form div.fields div.field span.error-message {
816 height:1%;
816 height:1%;
817 display:inline-block;
817 display:inline-block;
818 color:red;
818 color:red;
819 margin:8px 0 0 4px;
819 margin:8px 0 0 4px;
820 padding:0;
820 padding:0;
821 }
821 }
822
822
823 #content div.box div.form div.fields div.field span.success {
823 #content div.box div.form div.fields div.field span.success {
824 height:1%;
824 height:1%;
825 display:block;
825 display:block;
826 color:#316309;
826 color:#316309;
827 margin:8px 0 0;
827 margin:8px 0 0;
828 padding:0;
828 padding:0;
829 }
829 }
830
830
831 #content div.box div.form div.fields div.field div.label {
831 #content div.box div.form div.fields div.field div.label {
832 left:80px;
832 left:80px;
833 width:auto;
833 width:auto;
834 position:absolute;
834 position:absolute;
835 margin:0;
835 margin:0;
836 padding:8px 0 0 5px;
836 padding:8px 0 0 5px;
837 }
837 }
838
838
839 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
839 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
840 clear:both;
840 clear:both;
841 overflow:hidden;
841 overflow:hidden;
842 left:0;
842 left:0;
843 width:auto;
843 width:auto;
844 position:relative;
844 position:relative;
845 margin:0;
845 margin:0;
846 padding:0 0 8px;
846 padding:0 0 8px;
847 }
847 }
848
848
849 #content div.box div.form div.fields div.field div.label-select {
849 #content div.box div.form div.fields div.field div.label-select {
850 padding:5px 0 0 5px;
850 padding:5px 0 0 5px;
851 }
851 }
852
852
853 #content div.box-left div.form div.fields div.field div.label-select,#content div.box-right div.form div.fields div.field div.label-select {
853 #content div.box-left div.form div.fields div.field div.label-select,#content div.box-right div.form div.fields div.field div.label-select {
854 padding:0 0 8px;
854 padding:0 0 8px;
855 }
855 }
856
856
857 #content div.box-left div.form div.fields div.field div.label-textarea,#content div.box-right div.form div.fields div.field div.label-textarea {
857 #content div.box-left div.form div.fields div.field div.label-textarea,#content div.box-right div.form div.fields div.field div.label-textarea {
858 padding:0 0 8px !important;
858 padding:0 0 8px !important;
859 }
859 }
860
860
861 #content div.box div.form div.fields div.field div.label label {
861 #content div.box div.form div.fields div.field div.label label {
862 color:#393939;
862 color:#393939;
863 font-weight:700;
863 font-weight:700;
864 }
864 }
865
865
866 #content div.box div.form div.fields div.field div.input {
866 #content div.box div.form div.fields div.field div.input {
867 margin:0 0 0 200px;
867 margin:0 0 0 200px;
868 }
868 }
869 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
869 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
870 margin:0 0 0 0px;
870 margin:0 0 0 0px;
871 }
871 }
872
872
873 #content div.box div.form div.fields div.field div.input input {
873 #content div.box div.form div.fields div.field div.input input {
874 background:#FFF;
874 background:#FFF;
875 border-top:1px solid #b3b3b3;
875 border-top:1px solid #b3b3b3;
876 border-left:1px solid #b3b3b3;
876 border-left:1px solid #b3b3b3;
877 border-right:1px solid #eaeaea;
877 border-right:1px solid #eaeaea;
878 border-bottom:1px solid #eaeaea;
878 border-bottom:1px solid #eaeaea;
879 color:#000;
879 color:#000;
880 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
880 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
881 font-size:11px;
881 font-size:11px;
882 margin:0;
882 margin:0;
883 padding:7px 7px 6px;
883 padding:7px 7px 6px;
884 }
884 }
885
885
886
886
887
887
888 #content div.box div.form div.fields div.field div.input input.small {
888 #content div.box div.form div.fields div.field div.input input.small {
889 width:30%;
889 width:30%;
890 }
890 }
891
891
892 #content div.box div.form div.fields div.field div.input input.medium {
892 #content div.box div.form div.fields div.field div.input input.medium {
893 width:55%;
893 width:55%;
894 }
894 }
895
895
896 #content div.box div.form div.fields div.field div.input input.large {
896 #content div.box div.form div.fields div.field div.input input.large {
897 width:85%;
897 width:85%;
898 }
898 }
899
899
900 #content div.box div.form div.fields div.field div.input input.date {
900 #content div.box div.form div.fields div.field div.input input.date {
901 width:177px;
901 width:177px;
902 }
902 }
903
903
904 #content div.box div.form div.fields div.field div.input input.button {
904 #content div.box div.form div.fields div.field div.input input.button {
905 background:#D4D0C8;
905 background:#D4D0C8;
906 border-top:1px solid #FFF;
906 border-top:1px solid #FFF;
907 border-left:1px solid #FFF;
907 border-left:1px solid #FFF;
908 border-right:1px solid #404040;
908 border-right:1px solid #404040;
909 border-bottom:1px solid #404040;
909 border-bottom:1px solid #404040;
910 color:#000;
910 color:#000;
911 margin:0;
911 margin:0;
912 padding:4px 8px;
912 padding:4px 8px;
913 }
913 }
914
914
915 #content div.box div.form div.fields div.field div.textarea {
915 #content div.box div.form div.fields div.field div.textarea {
916 border-top:1px solid #b3b3b3;
916 border-top:1px solid #b3b3b3;
917 border-left:1px solid #b3b3b3;
917 border-left:1px solid #b3b3b3;
918 border-right:1px solid #eaeaea;
918 border-right:1px solid #eaeaea;
919 border-bottom:1px solid #eaeaea;
919 border-bottom:1px solid #eaeaea;
920 margin:0 0 0 200px;
920 margin:0 0 0 200px;
921 padding:10px;
921 padding:10px;
922 }
922 }
923
923
924 #content div.box div.form div.fields div.field div.textarea-editor {
924 #content div.box div.form div.fields div.field div.textarea-editor {
925 border:1px solid #ddd;
925 border:1px solid #ddd;
926 padding:0;
926 padding:0;
927 }
927 }
928
928
929 #content div.box div.form div.fields div.field div.textarea textarea {
929 #content div.box div.form div.fields div.field div.textarea textarea {
930 width:100%;
930 width:100%;
931 height:220px;
931 height:220px;
932 overflow:hidden;
932 overflow:hidden;
933 background:#FFF;
933 background:#FFF;
934 color:#000;
934 color:#000;
935 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
935 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
936 font-size:11px;
936 font-size:11px;
937 outline:none;
937 outline:none;
938 border-width:0;
938 border-width:0;
939 margin:0;
939 margin:0;
940 padding:0;
940 padding:0;
941 }
941 }
942
942
943 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea {
943 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea {
944 width:100%;
944 width:100%;
945 height:100px;
945 height:100px;
946 }
946 }
947
947
948 #content div.box div.form div.fields div.field div.textarea table {
948 #content div.box div.form div.fields div.field div.textarea table {
949 width:100%;
949 width:100%;
950 border:none;
950 border:none;
951 margin:0;
951 margin:0;
952 padding:0;
952 padding:0;
953 }
953 }
954
954
955 #content div.box div.form div.fields div.field div.textarea table td {
955 #content div.box div.form div.fields div.field div.textarea table td {
956 background:#DDD;
956 background:#DDD;
957 border:none;
957 border:none;
958 padding:0;
958 padding:0;
959 }
959 }
960
960
961 #content div.box div.form div.fields div.field div.textarea table td table {
961 #content div.box div.form div.fields div.field div.textarea table td table {
962 width:auto;
962 width:auto;
963 border:none;
963 border:none;
964 margin:0;
964 margin:0;
965 padding:0;
965 padding:0;
966 }
966 }
967
967
968 #content div.box div.form div.fields div.field div.textarea table td table td {
968 #content div.box div.form div.fields div.field div.textarea table td table td {
969 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
969 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
970 font-size:11px;
970 font-size:11px;
971 padding:5px 5px 5px 0;
971 padding:5px 5px 5px 0;
972 }
972 }
973
973
974 #content div.box div.form div.fields div.field input[type=text]:focus,#content div.box div.form div.fields div.field input[type=password]:focus,#content div.box div.form div.fields div.field input[type=file]:focus,#content div.box div.form div.fields div.field textarea:focus,#content div.box div.form div.fields div.field select:focus {
974 #content div.box div.form div.fields div.field input[type=text]:focus,#content div.box div.form div.fields div.field input[type=password]:focus,#content div.box div.form div.fields div.field input[type=file]:focus,#content div.box div.form div.fields div.field textarea:focus,#content div.box div.form div.fields div.field select:focus {
975 background:#f6f6f6;
975 background:#f6f6f6;
976 border-color:#666;
976 border-color:#666;
977 }
977 }
978
978
979 div.form div.fields div.field div.button {
979 div.form div.fields div.field div.button {
980 margin:0;
980 margin:0;
981 padding:0 0 0 8px;
981 padding:0 0 0 8px;
982 }
982 }
983
983
984 div.form div.fields div.field div.highlight .ui-button {
984 div.form div.fields div.field div.highlight .ui-button {
985 background:#4e85bb url("../images/button_highlight.png") repeat-x;
985 background:#4e85bb url("../images/button_highlight.png") repeat-x;
986 border-top:1px solid #5c91a4;
986 border-top:1px solid #5c91a4;
987 border-left:1px solid #2a6f89;
987 border-left:1px solid #2a6f89;
988 border-right:1px solid #2b7089;
988 border-right:1px solid #2b7089;
989 border-bottom:1px solid #1a6480;
989 border-bottom:1px solid #1a6480;
990 color:#FFF;
990 color:#FFF;
991 margin:0;
991 margin:0;
992 padding:6px 12px;
992 padding:6px 12px;
993 }
993 }
994
994
995 div.form div.fields div.field div.highlight .ui-state-hover {
995 div.form div.fields div.field div.highlight .ui-state-hover {
996 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
996 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
997 border-top:1px solid #78acbf;
997 border-top:1px solid #78acbf;
998 border-left:1px solid #34819e;
998 border-left:1px solid #34819e;
999 border-right:1px solid #35829f;
999 border-right:1px solid #35829f;
1000 border-bottom:1px solid #257897;
1000 border-bottom:1px solid #257897;
1001 color:#FFF;
1001 color:#FFF;
1002 margin:0;
1002 margin:0;
1003 padding:6px 12px;
1003 padding:6px 12px;
1004 }
1004 }
1005
1005
1006 #content div.box div.form div.fields div.buttons div.highlight input.ui-button {
1006 #content div.box div.form div.fields div.buttons div.highlight input.ui-button {
1007 background:#4e85bb url("../images/button_highlight.png") repeat-x;
1007 background:#4e85bb url("../images/button_highlight.png") repeat-x;
1008 border-top:1px solid #5c91a4;
1008 border-top:1px solid #5c91a4;
1009 border-left:1px solid #2a6f89;
1009 border-left:1px solid #2a6f89;
1010 border-right:1px solid #2b7089;
1010 border-right:1px solid #2b7089;
1011 border-bottom:1px solid #1a6480;
1011 border-bottom:1px solid #1a6480;
1012 color:#fff;
1012 color:#fff;
1013 margin:0;
1013 margin:0;
1014 padding:6px 12px;
1014 padding:6px 12px;
1015 }
1015 }
1016
1016
1017 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
1017 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
1018 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
1018 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
1019 border-top:1px solid #78acbf;
1019 border-top:1px solid #78acbf;
1020 border-left:1px solid #34819e;
1020 border-left:1px solid #34819e;
1021 border-right:1px solid #35829f;
1021 border-right:1px solid #35829f;
1022 border-bottom:1px solid #257897;
1022 border-bottom:1px solid #257897;
1023 color:#fff;
1023 color:#fff;
1024 margin:0;
1024 margin:0;
1025 padding:6px 12px;
1025 padding:6px 12px;
1026 }
1026 }
1027
1027
1028 #content div.box table {
1028 #content div.box table {
1029 width:100%;
1029 width:100%;
1030 border-collapse:collapse;
1030 border-collapse:collapse;
1031 margin:0;
1031 margin:0;
1032 padding:0;
1032 padding:0;
1033 }
1033 }
1034
1034
1035 #content div.box table th {
1035 #content div.box table th {
1036 background:#eee;
1036 background:#eee;
1037 border-bottom:1px solid #ddd;
1037 border-bottom:1px solid #ddd;
1038 padding:5px 0px 5px 5px;
1038 padding:5px 0px 5px 5px;
1039 }
1039 }
1040
1040
1041 #content div.box table th.left {
1041 #content div.box table th.left {
1042 text-align:left;
1042 text-align:left;
1043 }
1043 }
1044
1044
1045 #content div.box table th.right {
1045 #content div.box table th.right {
1046 text-align:right;
1046 text-align:right;
1047 }
1047 }
1048
1048
1049 #content div.box table th.center {
1049 #content div.box table th.center {
1050 text-align:center;
1050 text-align:center;
1051 }
1051 }
1052
1052
1053 #content div.box table th.selected {
1053 #content div.box table th.selected {
1054 vertical-align:middle;
1054 vertical-align:middle;
1055 padding:0;
1055 padding:0;
1056 }
1056 }
1057
1057
1058 #content div.box table td {
1058 #content div.box table td {
1059 background:#fff;
1059 background:#fff;
1060 border-bottom:1px solid #cdcdcd;
1060 border-bottom:1px solid #cdcdcd;
1061 vertical-align:middle;
1061 vertical-align:middle;
1062 padding:5px;
1062 padding:5px;
1063 }
1063 }
1064
1064
1065 #content div.box table tr.selected td {
1065 #content div.box table tr.selected td {
1066 background:#FFC;
1066 background:#FFC;
1067 }
1067 }
1068
1068
1069 #content div.box table td.selected {
1069 #content div.box table td.selected {
1070 width:3%;
1070 width:3%;
1071 text-align:center;
1071 text-align:center;
1072 vertical-align:middle;
1072 vertical-align:middle;
1073 padding:0;
1073 padding:0;
1074 }
1074 }
1075
1075
1076 #content div.box table td.action {
1076 #content div.box table td.action {
1077 width:45%;
1077 width:45%;
1078 text-align:left;
1078 text-align:left;
1079 }
1079 }
1080
1080
1081 #content div.box table td.date {
1081 #content div.box table td.date {
1082 width:33%;
1082 width:33%;
1083 text-align:center;
1083 text-align:center;
1084 }
1084 }
1085
1085
1086 #content div.box div.action {
1086 #content div.box div.action {
1087 float:right;
1087 float:right;
1088 background:#FFF;
1088 background:#FFF;
1089 text-align:right;
1089 text-align:right;
1090 margin:10px 0 0;
1090 margin:10px 0 0;
1091 padding:0;
1091 padding:0;
1092 }
1092 }
1093
1093
1094 #content div.box div.action select {
1094 #content div.box div.action select {
1095 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1095 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1096 font-size:11px;
1096 font-size:11px;
1097 margin:0;
1097 margin:0;
1098 }
1098 }
1099
1099
1100 #content div.box div.action .ui-selectmenu {
1100 #content div.box div.action .ui-selectmenu {
1101 margin:0;
1101 margin:0;
1102 padding:0;
1102 padding:0;
1103 }
1103 }
1104
1104
1105 #content div.box div.pagination {
1105 #content div.box div.pagination {
1106 height:1%;
1106 height:1%;
1107 clear:both;
1107 clear:both;
1108 overflow:hidden;
1108 overflow:hidden;
1109 margin:10px 0 0;
1109 margin:10px 0 0;
1110 padding:0;
1110 padding:0;
1111 }
1111 }
1112
1112
1113 #content div.box div.pagination ul.pager {
1113 #content div.box div.pagination ul.pager {
1114 float:right;
1114 float:right;
1115 text-align:right;
1115 text-align:right;
1116 margin:0;
1116 margin:0;
1117 padding:0;
1117 padding:0;
1118 }
1118 }
1119
1119
1120 #content div.box div.pagination ul.pager li {
1120 #content div.box div.pagination ul.pager li {
1121 height:1%;
1121 height:1%;
1122 float:left;
1122 float:left;
1123 list-style:none;
1123 list-style:none;
1124 background:#ebebeb url("../images/pager.png") repeat-x;
1124 background:#ebebeb url("../images/pager.png") repeat-x;
1125 border-top:1px solid #dedede;
1125 border-top:1px solid #dedede;
1126 border-left:1px solid #cfcfcf;
1126 border-left:1px solid #cfcfcf;
1127 border-right:1px solid #c4c4c4;
1127 border-right:1px solid #c4c4c4;
1128 border-bottom:1px solid #c4c4c4;
1128 border-bottom:1px solid #c4c4c4;
1129 color:#4A4A4A;
1129 color:#4A4A4A;
1130 font-weight:700;
1130 font-weight:700;
1131 margin:0 0 0 4px;
1131 margin:0 0 0 4px;
1132 padding:0;
1132 padding:0;
1133 }
1133 }
1134
1134
1135 #content div.box div.pagination ul.pager li.separator {
1135 #content div.box div.pagination ul.pager li.separator {
1136 padding:6px;
1136 padding:6px;
1137 }
1137 }
1138
1138
1139 #content div.box div.pagination ul.pager li.current {
1139 #content div.box div.pagination ul.pager li.current {
1140 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1140 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1141 border-top:1px solid #ccc;
1141 border-top:1px solid #ccc;
1142 border-left:1px solid #bebebe;
1142 border-left:1px solid #bebebe;
1143 border-right:1px solid #b1b1b1;
1143 border-right:1px solid #b1b1b1;
1144 border-bottom:1px solid #afafaf;
1144 border-bottom:1px solid #afafaf;
1145 color:#515151;
1145 color:#515151;
1146 padding:6px;
1146 padding:6px;
1147 }
1147 }
1148
1148
1149 #content div.box div.pagination ul.pager li a {
1149 #content div.box div.pagination ul.pager li a {
1150 height:1%;
1150 height:1%;
1151 display:block;
1151 display:block;
1152 float:left;
1152 float:left;
1153 color:#515151;
1153 color:#515151;
1154 text-decoration:none;
1154 text-decoration:none;
1155 margin:0;
1155 margin:0;
1156 padding:6px;
1156 padding:6px;
1157 }
1157 }
1158
1158
1159 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1159 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1160 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1160 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1161 border-top:1px solid #ccc;
1161 border-top:1px solid #ccc;
1162 border-left:1px solid #bebebe;
1162 border-left:1px solid #bebebe;
1163 border-right:1px solid #b1b1b1;
1163 border-right:1px solid #b1b1b1;
1164 border-bottom:1px solid #afafaf;
1164 border-bottom:1px solid #afafaf;
1165 margin:-1px;
1165 margin:-1px;
1166 }
1166 }
1167
1167
1168 #content div.box div.pagination-wh {
1168 #content div.box div.pagination-wh {
1169 height:1%;
1169 height:1%;
1170 clear:both;
1170 clear:both;
1171 overflow:hidden;
1171 overflow:hidden;
1172 text-align:right;
1172 text-align:right;
1173 margin:10px 0 0;
1173 margin:10px 0 0;
1174 padding:0;
1174 padding:0;
1175 }
1175 }
1176
1176
1177 #content div.box div.pagination-right {
1177 #content div.box div.pagination-right {
1178 float:right;
1178 float:right;
1179 }
1179 }
1180
1180
1181 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1181 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1182 height:1%;
1182 height:1%;
1183 float:left;
1183 float:left;
1184 background:#ebebeb url("../images/pager.png") repeat-x;
1184 background:#ebebeb url("../images/pager.png") repeat-x;
1185 border-top:1px solid #dedede;
1185 border-top:1px solid #dedede;
1186 border-left:1px solid #cfcfcf;
1186 border-left:1px solid #cfcfcf;
1187 border-right:1px solid #c4c4c4;
1187 border-right:1px solid #c4c4c4;
1188 border-bottom:1px solid #c4c4c4;
1188 border-bottom:1px solid #c4c4c4;
1189 color:#4A4A4A;
1189 color:#4A4A4A;
1190 font-weight:700;
1190 font-weight:700;
1191 margin:0 0 0 4px;
1191 margin:0 0 0 4px;
1192 padding:6px;
1192 padding:6px;
1193 }
1193 }
1194
1194
1195 #content div.box div.pagination-wh span.pager_curpage {
1195 #content div.box div.pagination-wh span.pager_curpage {
1196 height:1%;
1196 height:1%;
1197 float:left;
1197 float:left;
1198 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1198 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1199 border-top:1px solid #ccc;
1199 border-top:1px solid #ccc;
1200 border-left:1px solid #bebebe;
1200 border-left:1px solid #bebebe;
1201 border-right:1px solid #b1b1b1;
1201 border-right:1px solid #b1b1b1;
1202 border-bottom:1px solid #afafaf;
1202 border-bottom:1px solid #afafaf;
1203 color:#515151;
1203 color:#515151;
1204 font-weight:700;
1204 font-weight:700;
1205 margin:0 0 0 4px;
1205 margin:0 0 0 4px;
1206 padding:6px;
1206 padding:6px;
1207 }
1207 }
1208
1208
1209 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1209 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1210 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1210 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1211 border-top:1px solid #ccc;
1211 border-top:1px solid #ccc;
1212 border-left:1px solid #bebebe;
1212 border-left:1px solid #bebebe;
1213 border-right:1px solid #b1b1b1;
1213 border-right:1px solid #b1b1b1;
1214 border-bottom:1px solid #afafaf;
1214 border-bottom:1px solid #afafaf;
1215 text-decoration:none;
1215 text-decoration:none;
1216 }
1216 }
1217
1217
1218 #content div.box div.traffic div.legend {
1218 #content div.box div.traffic div.legend {
1219 clear:both;
1219 clear:both;
1220 overflow:hidden;
1220 overflow:hidden;
1221 border-bottom:1px solid #ddd;
1221 border-bottom:1px solid #ddd;
1222 margin:0 0 10px;
1222 margin:0 0 10px;
1223 padding:0 0 10px;
1223 padding:0 0 10px;
1224 }
1224 }
1225
1225
1226 #content div.box div.traffic div.legend h6 {
1226 #content div.box div.traffic div.legend h6 {
1227 float:left;
1227 float:left;
1228 border:none;
1228 border:none;
1229 margin:0;
1229 margin:0;
1230 padding:0;
1230 padding:0;
1231 }
1231 }
1232
1232
1233 #content div.box div.traffic div.legend li {
1233 #content div.box div.traffic div.legend li {
1234 list-style:none;
1234 list-style:none;
1235 float:left;
1235 float:left;
1236 font-size:11px;
1236 font-size:11px;
1237 margin:0;
1237 margin:0;
1238 padding:0 8px 0 4px;
1238 padding:0 8px 0 4px;
1239 }
1239 }
1240
1240
1241 #content div.box div.traffic div.legend li.visits {
1241 #content div.box div.traffic div.legend li.visits {
1242 border-left:12px solid #edc240;
1242 border-left:12px solid #edc240;
1243 }
1243 }
1244
1244
1245 #content div.box div.traffic div.legend li.pageviews {
1245 #content div.box div.traffic div.legend li.pageviews {
1246 border-left:12px solid #afd8f8;
1246 border-left:12px solid #afd8f8;
1247 }
1247 }
1248
1248
1249 #content div.box div.traffic table {
1249 #content div.box div.traffic table {
1250 width:auto;
1250 width:auto;
1251 }
1251 }
1252
1252
1253 #content div.box div.traffic table td {
1253 #content div.box div.traffic table td {
1254 background:transparent;
1254 background:transparent;
1255 border:none;
1255 border:none;
1256 padding:2px 3px 3px;
1256 padding:2px 3px 3px;
1257 }
1257 }
1258
1258
1259 #content div.box div.traffic table td.legendLabel {
1259 #content div.box div.traffic table td.legendLabel {
1260 padding:0 3px 2px;
1260 padding:0 3px 2px;
1261 }
1261 }
1262
1262
1263 #footer {
1263 #footer {
1264 clear:both;
1264 clear:both;
1265 overflow:hidden;
1265 overflow:hidden;
1266 text-align:right;
1266 text-align:right;
1267 margin:0;
1267 margin:0;
1268 padding:0 30px 4px;
1268 padding:0 30px 4px;
1269 margin:-10px 0 0;
1269 margin:-10px 0 0;
1270 }
1270 }
1271
1271
1272 #footer div#footer-inner {
1272 #footer div#footer-inner {
1273 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1273 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1274 border-top:2px solid #FFFFFF;
1274 border-top:2px solid #FFFFFF;
1275 }
1275 }
1276
1276
1277 #footer div#footer-inner p {
1277 #footer div#footer-inner p {
1278 padding:15px 25px 15px 0;
1278 padding:15px 25px 15px 0;
1279 color:#FFF;
1279 color:#FFF;
1280 font-weight:700;
1280 font-weight:700;
1281 }
1281 }
1282 #footer div#footer-inner .footer-link {
1282 #footer div#footer-inner .footer-link {
1283 float:left;
1283 float:left;
1284 padding-left:10px;
1284 padding-left:10px;
1285 }
1285 }
1286 #footer div#footer-inner .footer-link a {
1286 #footer div#footer-inner .footer-link a {
1287 color:#FFF;
1287 color:#FFF;
1288 }
1288 }
1289
1289
1290 #login div.title {
1290 #login div.title {
1291 width:420px;
1291 width:420px;
1292 clear:both;
1292 clear:both;
1293 overflow:hidden;
1293 overflow:hidden;
1294 position:relative;
1294 position:relative;
1295 background:#003367 url("../images/header_inner.png") repeat-x;
1295 background:#003367 url("../images/header_inner.png") repeat-x;
1296 margin:0 auto;
1296 margin:0 auto;
1297 padding:0;
1297 padding:0;
1298 }
1298 }
1299
1299
1300 #login div.inner {
1300 #login div.inner {
1301 width:380px;
1301 width:380px;
1302 background:#FFF url("../images/login.png") no-repeat top left;
1302 background:#FFF url("../images/login.png") no-repeat top left;
1303 border-top:none;
1303 border-top:none;
1304 border-bottom:none;
1304 border-bottom:none;
1305 margin:0 auto;
1305 margin:0 auto;
1306 padding:20px;
1306 padding:20px;
1307 }
1307 }
1308
1308
1309 #login div.form div.fields div.field div.label {
1309 #login div.form div.fields div.field div.label {
1310 width:173px;
1310 width:173px;
1311 float:left;
1311 float:left;
1312 text-align:right;
1312 text-align:right;
1313 margin:2px 10px 0 0;
1313 margin:2px 10px 0 0;
1314 padding:5px 0 0 5px;
1314 padding:5px 0 0 5px;
1315 }
1315 }
1316
1316
1317 #login div.form div.fields div.field div.input input {
1317 #login div.form div.fields div.field div.input input {
1318 width:176px;
1318 width:176px;
1319 background:#FFF;
1319 background:#FFF;
1320 border-top:1px solid #b3b3b3;
1320 border-top:1px solid #b3b3b3;
1321 border-left:1px solid #b3b3b3;
1321 border-left:1px solid #b3b3b3;
1322 border-right:1px solid #eaeaea;
1322 border-right:1px solid #eaeaea;
1323 border-bottom:1px solid #eaeaea;
1323 border-bottom:1px solid #eaeaea;
1324 color:#000;
1324 color:#000;
1325 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1325 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1326 font-size:11px;
1326 font-size:11px;
1327 margin:0;
1327 margin:0;
1328 padding:7px 7px 6px;
1328 padding:7px 7px 6px;
1329 }
1329 }
1330
1330
1331 #login div.form div.fields div.buttons {
1331 #login div.form div.fields div.buttons {
1332 clear:both;
1332 clear:both;
1333 overflow:hidden;
1333 overflow:hidden;
1334 border-top:1px solid #DDD;
1334 border-top:1px solid #DDD;
1335 text-align:right;
1335 text-align:right;
1336 margin:0;
1336 margin:0;
1337 padding:10px 0 0;
1337 padding:10px 0 0;
1338 }
1338 }
1339
1339
1340 #login div.form div.links {
1340 #login div.form div.links {
1341 clear:both;
1341 clear:both;
1342 overflow:hidden;
1342 overflow:hidden;
1343 margin:10px 0 0;
1343 margin:10px 0 0;
1344 padding:0 0 2px;
1344 padding:0 0 2px;
1345 }
1345 }
1346
1346
1347 #register div.title {
1347 #register div.title {
1348 clear:both;
1348 clear:both;
1349 overflow:hidden;
1349 overflow:hidden;
1350 position:relative;
1350 position:relative;
1351 background:#003367 url("../images/header_inner.png") repeat-x;
1351 background:#003367 url("../images/header_inner.png") repeat-x;
1352 margin:0 auto;
1352 margin:0 auto;
1353 padding:0;
1353 padding:0;
1354 }
1354 }
1355
1355
1356 #register div.inner {
1356 #register div.inner {
1357 background:#FFF;
1357 background:#FFF;
1358 border-top:none;
1358 border-top:none;
1359 border-bottom:none;
1359 border-bottom:none;
1360 margin:0 auto;
1360 margin:0 auto;
1361 padding:20px;
1361 padding:20px;
1362 }
1362 }
1363
1363
1364 #register div.form div.fields div.field div.label {
1364 #register div.form div.fields div.field div.label {
1365 width:135px;
1365 width:135px;
1366 float:left;
1366 float:left;
1367 text-align:right;
1367 text-align:right;
1368 margin:2px 10px 0 0;
1368 margin:2px 10px 0 0;
1369 padding:5px 0 0 5px;
1369 padding:5px 0 0 5px;
1370 }
1370 }
1371
1371
1372 #register div.form div.fields div.field div.input input {
1372 #register div.form div.fields div.field div.input input {
1373 width:300px;
1373 width:300px;
1374 background:#FFF;
1374 background:#FFF;
1375 border-top:1px solid #b3b3b3;
1375 border-top:1px solid #b3b3b3;
1376 border-left:1px solid #b3b3b3;
1376 border-left:1px solid #b3b3b3;
1377 border-right:1px solid #eaeaea;
1377 border-right:1px solid #eaeaea;
1378 border-bottom:1px solid #eaeaea;
1378 border-bottom:1px solid #eaeaea;
1379 color:#000;
1379 color:#000;
1380 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1380 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1381 font-size:11px;
1381 font-size:11px;
1382 margin:0;
1382 margin:0;
1383 padding:7px 7px 6px;
1383 padding:7px 7px 6px;
1384 }
1384 }
1385
1385
1386 #register div.form div.fields div.buttons {
1386 #register div.form div.fields div.buttons {
1387 clear:both;
1387 clear:both;
1388 overflow:hidden;
1388 overflow:hidden;
1389 border-top:1px solid #DDD;
1389 border-top:1px solid #DDD;
1390 text-align:left;
1390 text-align:left;
1391 margin:0;
1391 margin:0;
1392 padding:10px 0 0 150px;
1392 padding:10px 0 0 150px;
1393 }
1393 }
1394
1394
1395 #register div.form div.fields div.buttons div.highlight input.ui-button {
1395 #register div.form div.fields div.buttons div.highlight input.ui-button {
1396 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1396 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1397 color:#FFF;
1397 color:#FFF;
1398 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1398 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1399 border-style:solid;
1399 border-style:solid;
1400 border-width:1px;
1400 border-width:1px;
1401 }
1401 }
1402
1402
1403 #register div.form div.activation_msg {
1403 #register div.form div.activation_msg {
1404 padding-top:4px;
1404 padding-top:4px;
1405 padding-bottom:4px;
1405 padding-bottom:4px;
1406 }
1406 }
1407
1407
1408 #journal .journal_day{
1408 #journal .journal_day{
1409 font-size:20px;
1409 font-size:20px;
1410 padding:10px 0px;
1410 padding:10px 0px;
1411 border-bottom:2px solid #DDD;
1411 border-bottom:2px solid #DDD;
1412 margin-left:10px;
1412 margin-left:10px;
1413 margin-right:10px;
1413 margin-right:10px;
1414 }
1414 }
1415
1415
1416 #journal .journal_container{
1416 #journal .journal_container{
1417 padding:5px;
1417 padding:5px;
1418 clear:both;
1418 clear:both;
1419 margin:0px 5px 0px 10px;
1419 margin:0px 5px 0px 10px;
1420 }
1420 }
1421
1421
1422 #journal .journal_action_container{
1422 #journal .journal_action_container{
1423 padding-left:38px;
1423 padding-left:38px;
1424 }
1424 }
1425
1425
1426 #journal .journal_user{
1426 #journal .journal_user{
1427 color: #747474;
1427 color: #747474;
1428 font-size: 14px;
1428 font-size: 14px;
1429 font-weight: bold;
1429 font-weight: bold;
1430 height: 30px;
1430 height: 30px;
1431 }
1431 }
1432 #journal .journal_icon{
1432 #journal .journal_icon{
1433 clear: both;
1433 clear: both;
1434 float: left;
1434 float: left;
1435 padding-right: 4px;
1435 padding-right: 4px;
1436 padding-top: 3px;
1436 padding-top: 3px;
1437 }
1437 }
1438 #journal .journal_action{
1438 #journal .journal_action{
1439 padding-top:4px;
1439 padding-top:4px;
1440 min-height:2px;
1440 min-height:2px;
1441 float:left
1441 float:left
1442 }
1442 }
1443 #journal .journal_action_params{
1443 #journal .journal_action_params{
1444 clear: left;
1444 clear: left;
1445 padding-left: 22px;
1445 padding-left: 22px;
1446 }
1446 }
1447 #journal .journal_repo{
1447 #journal .journal_repo{
1448 float: left;
1448 float: left;
1449 margin-left: 6px;
1449 margin-left: 6px;
1450 padding-top: 3px;
1450 padding-top: 3px;
1451 }
1451 }
1452 #journal .date{
1452 #journal .date{
1453 clear: both;
1453 clear: both;
1454 color: #777777;
1454 color: #777777;
1455 font-size: 11px;
1455 font-size: 11px;
1456 padding-left: 22px;
1456 padding-left: 22px;
1457 }
1457 }
1458 #journal .journal_repo .journal_repo_name{
1458 #journal .journal_repo .journal_repo_name{
1459 font-weight: bold;
1459 font-weight: bold;
1460 font-size: 1.1em;
1460 font-size: 1.1em;
1461 }
1461 }
1462 #journal .compare_view{
1462 #journal .compare_view{
1463 padding: 5px 0px 5px 0px;
1463 padding: 5px 0px 5px 0px;
1464 width: 95px;
1464 width: 95px;
1465 }
1465 }
1466 .journal_highlight{
1466 .journal_highlight{
1467 font-weight: bold;
1467 font-weight: bold;
1468 padding: 0 2px;
1468 padding: 0 2px;
1469 vertical-align: bottom;
1469 vertical-align: bottom;
1470 }
1470 }
1471 .trending_language_tbl,.trending_language_tbl td {
1471 .trending_language_tbl,.trending_language_tbl td {
1472 border:0 !important;
1472 border:0 !important;
1473 margin:0 !important;
1473 margin:0 !important;
1474 padding:0 !important;
1474 padding:0 !important;
1475 }
1475 }
1476
1476
1477 .trending_language {
1477 .trending_language {
1478 background-color:#003367;
1478 background-color:#003367;
1479 color:#FFF;
1479 color:#FFF;
1480 display:block;
1480 display:block;
1481 min-width:20px;
1481 min-width:20px;
1482 text-decoration:none;
1482 text-decoration:none;
1483 height:12px;
1483 height:12px;
1484 margin-bottom:4px;
1484 margin-bottom:4px;
1485 margin-left:5px;
1485 margin-left:5px;
1486 white-space:pre;
1486 white-space:pre;
1487 padding:3px;
1487 padding:3px;
1488 }
1488 }
1489
1489
1490 h3.files_location {
1490 h3.files_location {
1491 font-size:1.8em;
1491 font-size:1.8em;
1492 font-weight:700;
1492 font-weight:700;
1493 border-bottom:none !important;
1493 border-bottom:none !important;
1494 margin:10px 0 !important;
1494 margin:10px 0 !important;
1495 }
1495 }
1496
1496
1497 #files_data dl dt {
1497 #files_data dl dt {
1498 float:left;
1498 float:left;
1499 width:115px;
1499 width:115px;
1500 margin:0 !important;
1500 margin:0 !important;
1501 padding:5px;
1501 padding:5px;
1502 }
1502 }
1503
1503
1504 #files_data dl dd {
1504 #files_data dl dd {
1505 margin:0 !important;
1505 margin:0 !important;
1506 padding:5px !important;
1506 padding:5px !important;
1507 }
1507 }
1508
1508
1509 #changeset_content {
1509 #changeset_content {
1510 border:1px solid #CCC;
1510 border:1px solid #CCC;
1511 padding:5px;
1511 padding:5px;
1512 }
1512 }
1513 #changeset_compare_view_content{
1513 #changeset_compare_view_content{
1514 border:1px solid #CCC;
1514 border:1px solid #CCC;
1515 padding:5px;
1515 padding:5px;
1516 }
1516 }
1517
1517
1518 #changeset_content .container {
1518 #changeset_content .container {
1519 min-height:120px;
1519 min-height:120px;
1520 font-size:1.2em;
1520 font-size:1.2em;
1521 overflow:hidden;
1521 overflow:hidden;
1522 }
1522 }
1523
1523
1524 #changeset_compare_view_content .compare_view_commits{
1524 #changeset_compare_view_content .compare_view_commits{
1525 width: auto !important;
1525 width: auto !important;
1526 }
1526 }
1527
1527
1528 #changeset_compare_view_content .compare_view_commits td{
1528 #changeset_compare_view_content .compare_view_commits td{
1529 padding:0px 0px 0px 12px !important;
1529 padding:0px 0px 0px 12px !important;
1530 }
1530 }
1531
1531
1532 #changeset_content .container .right {
1532 #changeset_content .container .right {
1533 float:right;
1533 float:right;
1534 width:25%;
1534 width:25%;
1535 text-align:right;
1535 text-align:right;
1536 }
1536 }
1537
1537
1538 #changeset_content .container .left .message {
1538 #changeset_content .container .left .message {
1539 font-style:italic;
1539 font-style:italic;
1540 color:#556CB5;
1540 color:#556CB5;
1541 white-space:pre-wrap;
1541 white-space:pre-wrap;
1542 }
1542 }
1543
1543
1544 .cs_files .cur_cs{
1544 .cs_files .cur_cs{
1545 margin:10px 2px;
1545 margin:10px 2px;
1546 font-weight: bold;
1546 font-weight: bold;
1547 }
1547 }
1548
1548
1549 .cs_files .cs_added {
1549 .cs_files .cs_added {
1550 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1550 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1551 height:16px;
1551 height:16px;
1552 padding-left:20px;
1552 padding-left:20px;
1553 margin-top:7px;
1553 margin-top:7px;
1554 text-align:left;
1554 text-align:left;
1555 }
1555 }
1556
1556
1557 .cs_files .cs_changed {
1557 .cs_files .cs_changed {
1558 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1558 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1559 height:16px;
1559 height:16px;
1560 padding-left:20px;
1560 padding-left:20px;
1561 margin-top:7px;
1561 margin-top:7px;
1562 text-align:left;
1562 text-align:left;
1563 }
1563 }
1564
1564
1565 .cs_files .cs_removed {
1565 .cs_files .cs_removed {
1566 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1566 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1567 height:16px;
1567 height:16px;
1568 padding-left:20px;
1568 padding-left:20px;
1569 margin-top:7px;
1569 margin-top:7px;
1570 text-align:left;
1570 text-align:left;
1571 }
1571 }
1572
1572
1573 #graph {
1573 #graph {
1574 overflow:hidden;
1574 overflow:hidden;
1575 }
1575 }
1576
1576
1577 #graph_nodes {
1577 #graph_nodes {
1578 width:160px;
1578 width:160px;
1579 float:left;
1579 float:left;
1580 margin-left:-50px;
1580 margin-left:-50px;
1581 margin-top:5px;
1581 margin-top:5px;
1582 }
1582 }
1583
1583
1584 #graph_content {
1584 #graph_content {
1585 width:800px;
1585 width:800px;
1586 float:left;
1586 float:left;
1587 }
1587 }
1588
1588
1589 #graph_content .container_header {
1589 #graph_content .container_header {
1590 border:1px solid #CCC;
1590 border:1px solid #CCC;
1591 padding:10px;
1591 padding:10px;
1592 }
1592 }
1593 #graph_content #rev_range_container{
1593 #graph_content #rev_range_container{
1594 padding:10px 0px;
1594 padding:10px 0px;
1595 }
1595 }
1596 #graph_content .container {
1596 #graph_content .container {
1597 border-bottom:1px solid #CCC;
1597 border-bottom:1px solid #CCC;
1598 border-left:1px solid #CCC;
1598 border-left:1px solid #CCC;
1599 border-right:1px solid #CCC;
1599 border-right:1px solid #CCC;
1600 min-height:80px;
1600 min-height:80px;
1601 overflow:hidden;
1601 overflow:hidden;
1602 font-size:1.2em;
1602 font-size:1.2em;
1603 }
1603 }
1604
1604
1605 #graph_content .container .right {
1605 #graph_content .container .right {
1606 float:right;
1606 float:right;
1607 width:28%;
1607 width:28%;
1608 text-align:right;
1608 text-align:right;
1609 padding-bottom:5px;
1609 padding-bottom:5px;
1610 }
1610 }
1611
1611
1612 #graph_content .container .left .date {
1612 #graph_content .container .left .date {
1613 font-weight:700;
1613 font-weight:700;
1614 padding-bottom:5px;
1614 padding-bottom:5px;
1615 }
1615 }
1616 #graph_content .container .left .date span{
1616 #graph_content .container .left .date span{
1617 vertical-align: text-top;
1617 vertical-align: text-top;
1618 }
1618 }
1619
1619
1620 #graph_content .container .left .message {
1620 #graph_content .container .left .message {
1621 font-size:100%;
1621 font-size:100%;
1622 padding-top:3px;
1622 padding-top:3px;
1623 white-space:pre-wrap;
1623 white-space:pre-wrap;
1624 }
1624 }
1625
1625
1626 .right div {
1626 .right div {
1627 clear:both;
1627 clear:both;
1628 }
1628 }
1629
1629
1630 .right .changes .added,.changed,.removed {
1630 .right .changes .added,.changed,.removed {
1631 border:1px solid #DDD;
1631 border:1px solid #DDD;
1632 display:block;
1632 display:block;
1633 float:right;
1633 float:right;
1634 text-align:center;
1634 text-align:center;
1635 min-width:15px;
1635 min-width:15px;
1636 cursor: help;
1636 cursor: help;
1637 }
1637 }
1638
1638
1639 .right .changes .added {
1639 .right .changes .added {
1640 background:#BFB;
1640 background:#BFB;
1641 }
1641 }
1642
1642
1643 .right .changes .changed {
1643 .right .changes .changed {
1644 background:#FD8;
1644 background:#FD8;
1645 }
1645 }
1646
1646
1647 .right .changes .removed {
1647 .right .changes .removed {
1648 background:#F88;
1648 background:#F88;
1649 }
1649 }
1650
1650
1651 .right .merge {
1651 .right .merge {
1652 vertical-align:top;
1652 vertical-align:top;
1653 font-size:0.75em;
1653 font-size:0.75em;
1654 font-weight:700;
1654 font-weight:700;
1655 }
1655 }
1656
1656
1657 .right .parent {
1657 .right .parent {
1658 font-size:90%;
1658 font-size:90%;
1659 font-family:monospace;
1659 font-family:monospace;
1660 }
1660 }
1661
1661
1662 .right .logtags .branchtag {
1662 .right .logtags .branchtag {
1663 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1663 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1664 display:block;
1664 display:block;
1665 font-size:0.8em;
1665 font-size:0.8em;
1666 padding:11px 16px 0 0;
1666 padding:11px 16px 0 0;
1667 }
1667 }
1668
1668
1669 .right .logtags .tagtag {
1669 .right .logtags .tagtag {
1670 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1670 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1671 display:block;
1671 display:block;
1672 font-size:0.8em;
1672 font-size:0.8em;
1673 padding:11px 16px 0 0;
1673 padding:11px 16px 0 0;
1674 }
1674 }
1675
1675
1676 div.browserblock {
1676 div.browserblock {
1677 overflow:hidden;
1677 overflow:hidden;
1678 border:1px solid #ccc;
1678 border:1px solid #ccc;
1679 background:#f8f8f8;
1679 background:#f8f8f8;
1680 font-size:100%;
1680 font-size:100%;
1681 line-height:125%;
1681 line-height:125%;
1682 padding:0;
1682 padding:0;
1683 }
1683 }
1684
1684
1685 div.browserblock .browser-header {
1685 div.browserblock .browser-header {
1686 background:#FFF;
1686 background:#FFF;
1687 padding:10px 0px 35px 0px;
1687 padding:10px 0px 35px 0px;
1688 width: 100%;
1688 width: 100%;
1689 }
1689 }
1690 div.browserblock .browser-nav {
1690 div.browserblock .browser-nav {
1691 float:left
1691 float:left
1692 }
1692 }
1693
1693
1694 div.browserblock .browser-branch {
1694 div.browserblock .browser-branch {
1695 padding:10px 0 0 0;
1695 padding:10px 0 0 0;
1696 float:left;
1696 float:left;
1697 }
1697 }
1698 div.browserblock .browser-branch label {
1698 div.browserblock .browser-branch label {
1699 color:#4A4A4A;
1699 color:#4A4A4A;
1700 vertical-align:text-top;
1700 vertical-align:text-top;
1701 }
1701 }
1702
1702
1703 div.browserblock .browser-header span {
1703 div.browserblock .browser-header span {
1704 margin-left:25px;
1704 margin-left:25px;
1705 font-weight:700;
1705 font-weight:700;
1706 }
1706 }
1707
1707
1708 div.browserblock .browser-body {
1708 div.browserblock .browser-body {
1709 background:#EEE;
1709 background:#EEE;
1710 border-top:1px solid #CCC;
1710 border-top:1px solid #CCC;
1711 }
1711 }
1712
1712
1713 table.code-browser {
1713 table.code-browser {
1714 border-collapse:collapse;
1714 border-collapse:collapse;
1715 width:100%;
1715 width:100%;
1716 }
1716 }
1717
1717
1718 table.code-browser tr {
1718 table.code-browser tr {
1719 margin:3px;
1719 margin:3px;
1720 }
1720 }
1721
1721
1722 table.code-browser thead th {
1722 table.code-browser thead th {
1723 background-color:#EEE;
1723 background-color:#EEE;
1724 height:20px;
1724 height:20px;
1725 font-size:1.1em;
1725 font-size:1.1em;
1726 font-weight:700;
1726 font-weight:700;
1727 text-align:left;
1727 text-align:left;
1728 padding-left:10px;
1728 padding-left:10px;
1729 }
1729 }
1730
1730
1731 table.code-browser tbody td {
1731 table.code-browser tbody td {
1732 padding-left:10px;
1732 padding-left:10px;
1733 height:20px;
1733 height:20px;
1734 }
1734 }
1735
1735
1736 table.code-browser .browser-file {
1736 table.code-browser .browser-file {
1737 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1737 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1738 height:16px;
1738 height:16px;
1739 padding-left:20px;
1739 padding-left:20px;
1740 text-align:left;
1740 text-align:left;
1741 }
1741 }
1742 .diffblock .changeset_file{
1742 .diffblock .changeset_file{
1743 background:url("../images/icons/file.png") no-repeat scroll 3px;
1743 background:url("../images/icons/file.png") no-repeat scroll 3px;
1744 height:16px;
1744 height:16px;
1745 padding-left:22px;
1745 padding-left:22px;
1746 text-align:left;
1746 text-align:left;
1747 font-size: 14px;
1747 font-size: 14px;
1748 }
1748 }
1749
1749
1750 .diffblock .changeset_header{
1750 .diffblock .changeset_header{
1751 margin-left: 6px !important;
1751 margin-left: 6px !important;
1752 }
1752 }
1753
1753
1754 table.code-browser .browser-dir {
1754 table.code-browser .browser-dir {
1755 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1755 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1756 height:16px;
1756 height:16px;
1757 padding-left:20px;
1757 padding-left:20px;
1758 text-align:left;
1758 text-align:left;
1759 }
1759 }
1760
1760
1761 .box .search {
1761 .box .search {
1762 clear:both;
1762 clear:both;
1763 overflow:hidden;
1763 overflow:hidden;
1764 margin:0;
1764 margin:0;
1765 padding:0 20px 10px;
1765 padding:0 20px 10px;
1766 }
1766 }
1767
1767
1768 .box .search div.search_path {
1768 .box .search div.search_path {
1769 background:none repeat scroll 0 0 #EEE;
1769 background:none repeat scroll 0 0 #EEE;
1770 border:1px solid #CCC;
1770 border:1px solid #CCC;
1771 color:blue;
1771 color:blue;
1772 margin-bottom:10px;
1772 margin-bottom:10px;
1773 padding:10px 0;
1773 padding:10px 0;
1774 }
1774 }
1775
1775
1776 .box .search div.search_path div.link {
1776 .box .search div.search_path div.link {
1777 font-weight:700;
1777 font-weight:700;
1778 margin-left:25px;
1778 margin-left:25px;
1779 }
1779 }
1780
1780
1781 .box .search div.search_path div.link a {
1781 .box .search div.search_path div.link a {
1782 color:#003367;
1782 color:#003367;
1783 cursor:pointer;
1783 cursor:pointer;
1784 text-decoration:none;
1784 text-decoration:none;
1785 }
1785 }
1786
1786
1787 #path_unlock {
1787 #path_unlock {
1788 color:red;
1788 color:red;
1789 font-size:1.2em;
1789 font-size:1.2em;
1790 padding-left:4px;
1790 padding-left:4px;
1791 }
1791 }
1792
1792
1793 .info_box * {
1793 .info_box * {
1794 background:url("../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1794 background:url("../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1795 color:#4A4A4A;
1795 color:#4A4A4A;
1796 font-weight:700;
1796 font-weight:700;
1797 height:1%;
1797 height:1%;
1798 display:inline;
1798 display:inline;
1799 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1799 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1800 border-style:solid;
1800 border-style:solid;
1801 border-width:1px;
1801 border-width:1px;
1802 padding:4px 6px;
1802 padding:4px 6px;
1803 }
1803 }
1804
1804
1805 .info_box span {
1805 .info_box span {
1806 margin-left:3px;
1806 margin-left:3px;
1807 margin-right:3px;
1807 margin-right:3px;
1808 }
1808 }
1809
1809
1810 .info_box input#at_rev {
1810 .info_box input#at_rev {
1811 text-align:center;
1811 text-align:center;
1812 padding:5px 3px 3px 2px;
1812 padding:5px 3px 3px 2px;
1813 }
1813 }
1814
1814
1815 .info_box input#view {
1815 .info_box input#view {
1816 text-align:center;
1816 text-align:center;
1817 padding:4px 3px 2px 2px;
1817 padding:4px 3px 2px 2px;
1818 }
1818 }
1819
1819
1820 .yui-overlay,.yui-panel-container {
1820 .yui-overlay,.yui-panel-container {
1821 visibility:hidden;
1821 visibility:hidden;
1822 position:absolute;
1822 position:absolute;
1823 z-index:2;
1823 z-index:2;
1824 }
1824 }
1825
1825
1826 .yui-tt {
1826 .yui-tt {
1827 visibility:hidden;
1827 visibility:hidden;
1828 position:absolute;
1828 position:absolute;
1829 color:#666;
1829 color:#666;
1830 background-color:#FFF;
1830 background-color:#FFF;
1831 font-family:arial, helvetica, verdana, sans-serif;
1831 font-family:arial, helvetica, verdana, sans-serif;
1832 border:2px solid #003367;
1832 border:2px solid #003367;
1833 font:100% sans-serif;
1833 font:100% sans-serif;
1834 width:auto;
1834 width:auto;
1835 opacity:1px;
1835 opacity:1px;
1836 padding:8px;
1836 padding:8px;
1837 white-space: pre;
1837 white-space: pre;
1838 -webkit-border-radius: 8px 8px 8px 8px;
1838 -webkit-border-radius: 8px 8px 8px 8px;
1839 -khtml-border-radius: 8px 8px 8px 8px;
1839 -khtml-border-radius: 8px 8px 8px 8px;
1840 -moz-border-radius: 8px 8px 8px 8px;
1840 -moz-border-radius: 8px 8px 8px 8px;
1841 border-radius: 8px 8px 8px 8px;
1841 border-radius: 8px 8px 8px 8px;
1842 }
1842 }
1843
1843
1844 .ac {
1844 .ac {
1845 vertical-align:top;
1845 vertical-align:top;
1846 }
1846 }
1847
1847
1848 .ac .yui-ac {
1848 .ac .yui-ac {
1849 position:relative;
1849 position:relative;
1850 font-family:arial;
1850 font-family:arial;
1851 font-size:100%;
1851 font-size:100%;
1852 }
1852 }
1853
1853
1854 .ac .perm_ac {
1854 .ac .perm_ac {
1855 width:15em;
1855 width:15em;
1856 }
1856 }
1857
1857
1858 .ac .yui-ac-input {
1858 .ac .yui-ac-input {
1859 width:100%;
1859 width:100%;
1860 }
1860 }
1861
1861
1862 .ac .yui-ac-container {
1862 .ac .yui-ac-container {
1863 position:absolute;
1863 position:absolute;
1864 top:1.6em;
1864 top:1.6em;
1865 width:100%;
1865 width:100%;
1866 }
1866 }
1867
1867
1868 .ac .yui-ac-content {
1868 .ac .yui-ac-content {
1869 position:absolute;
1869 position:absolute;
1870 width:100%;
1870 width:100%;
1871 border:1px solid gray;
1871 border:1px solid gray;
1872 background:#fff;
1872 background:#fff;
1873 overflow:hidden;
1873 overflow:hidden;
1874 z-index:9050;
1874 z-index:9050;
1875 }
1875 }
1876
1876
1877 .ac .yui-ac-shadow {
1877 .ac .yui-ac-shadow {
1878 position:absolute;
1878 position:absolute;
1879 width:100%;
1879 width:100%;
1880 background:#000;
1880 background:#000;
1881 -moz-opacity:0.1px;
1881 -moz-opacity:0.1px;
1882 opacity:.10;
1882 opacity:.10;
1883 filter:alpha(opacity = 10);
1883 filter:alpha(opacity = 10);
1884 z-index:9049;
1884 z-index:9049;
1885 margin:.3em;
1885 margin:.3em;
1886 }
1886 }
1887
1887
1888 .ac .yui-ac-content ul {
1888 .ac .yui-ac-content ul {
1889 width:100%;
1889 width:100%;
1890 margin:0;
1890 margin:0;
1891 padding:0;
1891 padding:0;
1892 }
1892 }
1893
1893
1894 .ac .yui-ac-content li {
1894 .ac .yui-ac-content li {
1895 cursor:default;
1895 cursor:default;
1896 white-space:nowrap;
1896 white-space:nowrap;
1897 margin:0;
1897 margin:0;
1898 padding:2px 5px;
1898 padding:2px 5px;
1899 }
1899 }
1900
1900
1901 .ac .yui-ac-content li.yui-ac-prehighlight {
1901 .ac .yui-ac-content li.yui-ac-prehighlight {
1902 background:#B3D4FF;
1902 background:#B3D4FF;
1903 }
1903 }
1904
1904
1905 .ac .yui-ac-content li.yui-ac-highlight {
1905 .ac .yui-ac-content li.yui-ac-highlight {
1906 background:#556CB5;
1906 background:#556CB5;
1907 color:#FFF;
1907 color:#FFF;
1908 }
1908 }
1909
1909
1910 .follow{
1910 .follow{
1911 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1911 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1912 height: 16px;
1912 height: 16px;
1913 width: 20px;
1913 width: 20px;
1914 cursor: pointer;
1914 cursor: pointer;
1915 display: block;
1915 display: block;
1916 float: right;
1916 float: right;
1917 margin-top: 2px;
1917 margin-top: 2px;
1918 }
1918 }
1919
1919
1920 .following{
1920 .following{
1921 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
1921 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
1922 height: 16px;
1922 height: 16px;
1923 width: 20px;
1923 width: 20px;
1924 cursor: pointer;
1924 cursor: pointer;
1925 display: block;
1925 display: block;
1926 float: right;
1926 float: right;
1927 margin-top: 2px;
1927 margin-top: 2px;
1928 }
1928 }
1929
1929
1930 .currently_following{
1930 .currently_following{
1931 padding-left: 10px;
1931 padding-left: 10px;
1932 padding-bottom:5px;
1932 padding-bottom:5px;
1933 }
1933 }
1934
1934
1935 .add_icon {
1935 .add_icon {
1936 background:url("../images/icons/add.png") no-repeat scroll 3px;
1936 background:url("../images/icons/add.png") no-repeat scroll 3px;
1937 height:16px;
1937 height:16px;
1938 padding-left:20px;
1938 padding-left:20px;
1939 padding-top:1px;
1939 padding-top:1px;
1940 text-align:left;
1940 text-align:left;
1941 }
1941 }
1942
1942
1943 .edit_icon {
1943 .edit_icon {
1944 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1944 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1945 height:16px;
1945 height:16px;
1946 padding-left:20px;
1946 padding-left:20px;
1947 padding-top:1px;
1947 padding-top:1px;
1948 text-align:left;
1948 text-align:left;
1949 }
1949 }
1950
1950
1951 .delete_icon {
1951 .delete_icon {
1952 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1952 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1953 height:16px;
1953 height:16px;
1954 padding-left:20px;
1954 padding-left:20px;
1955 padding-top:1px;
1955 padding-top:1px;
1956 text-align:left;
1956 text-align:left;
1957 }
1957 }
1958
1958
1959 .refresh_icon {
1959 .refresh_icon {
1960 background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
1960 background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
1961 height:16px;
1961 height:16px;
1962 padding-left:20px;
1962 padding-left:20px;
1963 padding-top:1px;
1963 padding-top:1px;
1964 text-align:left;
1964 text-align:left;
1965 }
1965 }
1966
1966
1967 .pull_icon {
1968 background:url("../images/icons/connect.png") no-repeat scroll 3px;
1969 height:16px;
1970 padding-left:20px;
1971 padding-top:1px;
1972 text-align:left;
1973 }
1974
1967 .rss_icon {
1975 .rss_icon {
1968 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1976 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1969 height:16px;
1977 height:16px;
1970 padding-left:20px;
1978 padding-left:20px;
1971 padding-top:1px;
1979 padding-top:1px;
1972 text-align:left;
1980 text-align:left;
1973 }
1981 }
1974
1982
1975 .atom_icon {
1983 .atom_icon {
1976 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1984 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1977 height:16px;
1985 height:16px;
1978 padding-left:20px;
1986 padding-left:20px;
1979 padding-top:1px;
1987 padding-top:1px;
1980 text-align:left;
1988 text-align:left;
1981 }
1989 }
1982
1990
1983 .archive_icon {
1991 .archive_icon {
1984 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1992 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1985 height:16px;
1993 height:16px;
1986 padding-left:20px;
1994 padding-left:20px;
1987 text-align:left;
1995 text-align:left;
1988 padding-top:1px;
1996 padding-top:1px;
1989 }
1997 }
1990 .start_following_icon {
1998 .start_following_icon {
1991 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1999 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1992 height:16px;
2000 height:16px;
1993 padding-left:20px;
2001 padding-left:20px;
1994 text-align:left;
2002 text-align:left;
1995 padding-top:1px;
2003 padding-top:1px;
1996 }
2004 }
1997 .stop_following_icon {
2005 .stop_following_icon {
1998 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
2006 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
1999 height:16px;
2007 height:16px;
2000 padding-left:20px;
2008 padding-left:20px;
2001 text-align:left;
2009 text-align:left;
2002 padding-top:1px;
2010 padding-top:1px;
2003 }
2011 }
2004
2012
2005 .action_button {
2013 .action_button {
2006 border:0;
2014 border:0;
2007 display:block;
2015 display:block;
2008 }
2016 }
2009
2017
2010 .action_button:hover {
2018 .action_button:hover {
2011 border:0;
2019 border:0;
2012 text-decoration:underline;
2020 text-decoration:underline;
2013 cursor:pointer;
2021 cursor:pointer;
2014 }
2022 }
2015
2023
2016 #switch_repos {
2024 #switch_repos {
2017 position:absolute;
2025 position:absolute;
2018 height:25px;
2026 height:25px;
2019 z-index:1;
2027 z-index:1;
2020 }
2028 }
2021
2029
2022 #switch_repos select {
2030 #switch_repos select {
2023 min-width:150px;
2031 min-width:150px;
2024 max-height:250px;
2032 max-height:250px;
2025 z-index:1;
2033 z-index:1;
2026 }
2034 }
2027
2035
2028 .breadcrumbs {
2036 .breadcrumbs {
2029 border:medium none;
2037 border:medium none;
2030 color:#FFF;
2038 color:#FFF;
2031 float:left;
2039 float:left;
2032 text-transform:uppercase;
2040 text-transform:uppercase;
2033 font-weight:700;
2041 font-weight:700;
2034 font-size:14px;
2042 font-size:14px;
2035 margin:0;
2043 margin:0;
2036 padding:11px 0 11px 10px;
2044 padding:11px 0 11px 10px;
2037 }
2045 }
2038
2046
2039 .breadcrumbs a {
2047 .breadcrumbs a {
2040 color:#FFF;
2048 color:#FFF;
2041 }
2049 }
2042
2050
2043 .flash_msg ul {
2051 .flash_msg ul {
2044 margin:0;
2052 margin:0;
2045 padding:0 0 10px;
2053 padding:0 0 10px;
2046 }
2054 }
2047
2055
2048 .error_msg {
2056 .error_msg {
2049 background-color:#FFCFCF;
2057 background-color:#FFCFCF;
2050 background-image:url("../images/icons/error_msg.png");
2058 background-image:url("../images/icons/error_msg.png");
2051 border:1px solid #FF9595;
2059 border:1px solid #FF9595;
2052 color:#C30;
2060 color:#C30;
2053 }
2061 }
2054
2062
2055 .warning_msg {
2063 .warning_msg {
2056 background-color:#FFFBCC;
2064 background-color:#FFFBCC;
2057 background-image:url("../images/icons/warning_msg.png");
2065 background-image:url("../images/icons/warning_msg.png");
2058 border:1px solid #FFF35E;
2066 border:1px solid #FFF35E;
2059 color:#C69E00;
2067 color:#C69E00;
2060 }
2068 }
2061
2069
2062 .success_msg {
2070 .success_msg {
2063 background-color:#D5FFCF;
2071 background-color:#D5FFCF;
2064 background-image:url("../images/icons/success_msg.png");
2072 background-image:url("../images/icons/success_msg.png");
2065 border:1px solid #97FF88;
2073 border:1px solid #97FF88;
2066 color:#090;
2074 color:#090;
2067 }
2075 }
2068
2076
2069 .notice_msg {
2077 .notice_msg {
2070 background-color:#DCE3FF;
2078 background-color:#DCE3FF;
2071 background-image:url("../images/icons/notice_msg.png");
2079 background-image:url("../images/icons/notice_msg.png");
2072 border:1px solid #93A8FF;
2080 border:1px solid #93A8FF;
2073 color:#556CB5;
2081 color:#556CB5;
2074 }
2082 }
2075
2083
2076 .success_msg,.error_msg,.notice_msg,.warning_msg {
2084 .success_msg,.error_msg,.notice_msg,.warning_msg {
2077 background-position:10px center;
2085 background-position:10px center;
2078 background-repeat:no-repeat;
2086 background-repeat:no-repeat;
2079 font-size:12px;
2087 font-size:12px;
2080 font-weight:700;
2088 font-weight:700;
2081 min-height:14px;
2089 min-height:14px;
2082 line-height:14px;
2090 line-height:14px;
2083 margin-bottom:0;
2091 margin-bottom:0;
2084 margin-top:0;
2092 margin-top:0;
2085 display:block;
2093 display:block;
2086 overflow:auto;
2094 overflow:auto;
2087 padding:6px 10px 6px 40px;
2095 padding:6px 10px 6px 40px;
2088 }
2096 }
2089
2097
2090 #msg_close {
2098 #msg_close {
2091 background:transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
2099 background:transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
2092 cursor:pointer;
2100 cursor:pointer;
2093 height:16px;
2101 height:16px;
2094 position:absolute;
2102 position:absolute;
2095 right:5px;
2103 right:5px;
2096 top:5px;
2104 top:5px;
2097 width:16px;
2105 width:16px;
2098 }
2106 }
2099
2107
2100 div#legend_container table,div#legend_choices table {
2108 div#legend_container table,div#legend_choices table {
2101 width:auto !important;
2109 width:auto !important;
2102 }
2110 }
2103
2111
2104 table#permissions_manage {
2112 table#permissions_manage {
2105 width:0 !important;
2113 width:0 !important;
2106 }
2114 }
2107
2115
2108 table#permissions_manage span.private_repo_msg {
2116 table#permissions_manage span.private_repo_msg {
2109 font-size:0.8em;
2117 font-size:0.8em;
2110 opacity:0.6px;
2118 opacity:0.6px;
2111 }
2119 }
2112
2120
2113 table#permissions_manage td.private_repo_msg {
2121 table#permissions_manage td.private_repo_msg {
2114 font-size:0.8em;
2122 font-size:0.8em;
2115 }
2123 }
2116
2124
2117 table#permissions_manage tr#add_perm_input td {
2125 table#permissions_manage tr#add_perm_input td {
2118 vertical-align:middle;
2126 vertical-align:middle;
2119 }
2127 }
2120
2128
2121 div.gravatar {
2129 div.gravatar {
2122 background-color:#FFF;
2130 background-color:#FFF;
2123 border:1px solid #D0D0D0;
2131 border:1px solid #D0D0D0;
2124 float:left;
2132 float:left;
2125 margin-right:0.7em;
2133 margin-right:0.7em;
2126 padding:2px 2px 0;
2134 padding:2px 2px 0;
2127 }
2135 }
2128
2136
2129 #header,#content,#footer {
2137 #header,#content,#footer {
2130 min-width:1024px;
2138 min-width:1024px;
2131 }
2139 }
2132
2140
2133 #content {
2141 #content {
2134 min-height:100%;
2142 min-height:100%;
2135 clear:both;
2143 clear:both;
2136 overflow:hidden;
2144 overflow:hidden;
2137 padding:14px 30px;
2145 padding:14px 30px;
2138 }
2146 }
2139
2147
2140 #content div.box div.title div.search {
2148 #content div.box div.title div.search {
2141 background:url("../images/title_link.png") no-repeat top left;
2149 background:url("../images/title_link.png") no-repeat top left;
2142 border-left:1px solid #316293;
2150 border-left:1px solid #316293;
2143 }
2151 }
2144
2152
2145 #content div.box div.title div.search div.input input {
2153 #content div.box div.title div.search div.input input {
2146 border:1px solid #316293;
2154 border:1px solid #316293;
2147 }
2155 }
2148
2156
2149 #content div.box div.title div.search div.button input.ui-button {
2157 #content div.box div.title div.search div.button input.ui-button {
2150 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2158 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2151 border:1px solid #316293;
2159 border:1px solid #316293;
2152 border-left:none;
2160 border-left:none;
2153 color:#FFF;
2161 color:#FFF;
2154 }
2162 }
2155
2163
2156 #content div.box div.title div.search div.button input.ui-state-hover {
2164 #content div.box div.title div.search div.button input.ui-state-hover {
2157 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2165 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2158 border:1px solid #316293;
2166 border:1px solid #316293;
2159 border-left:none;
2167 border-left:none;
2160 color:#FFF;
2168 color:#FFF;
2161 }
2169 }
2162
2170
2163 #content div.box div.form div.fields div.field div.highlight .ui-button {
2171 #content div.box div.form div.fields div.field div.highlight .ui-button {
2164 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2172 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2165 border-top:1px solid #5c91a4;
2173 border-top:1px solid #5c91a4;
2166 border-left:1px solid #2a6f89;
2174 border-left:1px solid #2a6f89;
2167 border-right:1px solid #2b7089;
2175 border-right:1px solid #2b7089;
2168 border-bottom:1px solid #1a6480;
2176 border-bottom:1px solid #1a6480;
2169 color:#fff;
2177 color:#fff;
2170 }
2178 }
2171
2179
2172 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
2180 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
2173 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2181 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2174 border-top:1px solid #78acbf;
2182 border-top:1px solid #78acbf;
2175 border-left:1px solid #34819e;
2183 border-left:1px solid #34819e;
2176 border-right:1px solid #35829f;
2184 border-right:1px solid #35829f;
2177 border-bottom:1px solid #257897;
2185 border-bottom:1px solid #257897;
2178 color:#fff;
2186 color:#fff;
2179 }
2187 }
2180
2188
2181 ins,div.options a:hover {
2189 ins,div.options a:hover {
2182 text-decoration:none;
2190 text-decoration:none;
2183 }
2191 }
2184
2192
2185 img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
2193 img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
2186 border:none;
2194 border:none;
2187 }
2195 }
2188
2196
2189 img.icon,.right .merge img {
2197 img.icon,.right .merge img {
2190 vertical-align:bottom;
2198 vertical-align:bottom;
2191 }
2199 }
2192
2200
2193 #header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
2201 #header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
2194 float:right;
2202 float:right;
2195 margin:0;
2203 margin:0;
2196 padding:0;
2204 padding:0;
2197 }
2205 }
2198
2206
2199 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
2207 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
2200 float:left;
2208 float:left;
2201 }
2209 }
2202
2210
2203 #header #header-inner #quick li:hover ul ul,#header #header-inner #quick li:hover ul ul ul,#header #header-inner #quick li:hover ul ul ul ul,#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow {
2211 #header #header-inner #quick li:hover ul ul,#header #header-inner #quick li:hover ul ul ul,#header #header-inner #quick li:hover ul ul ul ul,#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow {
2204 display:none;
2212 display:none;
2205 }
2213 }
2206
2214
2207 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded {
2215 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded {
2208 display:block;
2216 display:block;
2209 }
2217 }
2210
2218
2211 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2219 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2212 color:#bfe3ff;
2220 color:#bfe3ff;
2213 }
2221 }
2214
2222
2215 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal {
2223 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal {
2216 margin:10px 24px 10px 44px;
2224 margin:10px 24px 10px 44px;
2217 }
2225 }
2218
2226
2219 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2227 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2220 clear:both;
2228 clear:both;
2221 overflow:hidden;
2229 overflow:hidden;
2222 margin:0;
2230 margin:0;
2223 padding:0 20px 10px;
2231 padding:0 20px 10px;
2224 }
2232 }
2225
2233
2226 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2234 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2227 clear:both;
2235 clear:both;
2228 overflow:hidden;
2236 overflow:hidden;
2229 margin:0;
2237 margin:0;
2230 padding:0;
2238 padding:0;
2231 }
2239 }
2232
2240
2233 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span {
2241 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span {
2234 height:1%;
2242 height:1%;
2235 display:block;
2243 display:block;
2236 color:#363636;
2244 color:#363636;
2237 margin:0;
2245 margin:0;
2238 padding:2px 0 0;
2246 padding:2px 0 0;
2239 }
2247 }
2240
2248
2241 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error {
2249 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error {
2242 background:#FBE3E4;
2250 background:#FBE3E4;
2243 border-top:1px solid #e1b2b3;
2251 border-top:1px solid #e1b2b3;
2244 border-left:1px solid #e1b2b3;
2252 border-left:1px solid #e1b2b3;
2245 border-right:1px solid #FBC2C4;
2253 border-right:1px solid #FBC2C4;
2246 border-bottom:1px solid #FBC2C4;
2254 border-bottom:1px solid #FBC2C4;
2247 }
2255 }
2248
2256
2249 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success {
2257 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success {
2250 background:#E6EFC2;
2258 background:#E6EFC2;
2251 border-top:1px solid #cebb98;
2259 border-top:1px solid #cebb98;
2252 border-left:1px solid #cebb98;
2260 border-left:1px solid #cebb98;
2253 border-right:1px solid #c6d880;
2261 border-right:1px solid #c6d880;
2254 border-bottom:1px solid #c6d880;
2262 border-bottom:1px solid #c6d880;
2255 }
2263 }
2256
2264
2257 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input {
2265 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input {
2258 margin:0;
2266 margin:0;
2259 }
2267 }
2260
2268
2261 #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios{
2269 #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios{
2262 margin:0 0 0 0px !important;
2270 margin:0 0 0 0px !important;
2263 padding:0;
2271 padding:0;
2264 }
2272 }
2265
2273
2266 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios {
2274 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios {
2267 margin:0 0 0 200px;
2275 margin:0 0 0 200px;
2268 padding:0;
2276 padding:0;
2269 }
2277 }
2270
2278
2271
2279
2272 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover {
2280 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover {
2273 color:#000;
2281 color:#000;
2274 text-decoration:none;
2282 text-decoration:none;
2275 }
2283 }
2276
2284
2277 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2285 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2278 border:1px solid #666;
2286 border:1px solid #666;
2279 }
2287 }
2280
2288
2281 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio {
2289 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio {
2282 clear:both;
2290 clear:both;
2283 overflow:hidden;
2291 overflow:hidden;
2284 margin:0;
2292 margin:0;
2285 padding:8px 0 2px;
2293 padding:8px 0 2px;
2286 }
2294 }
2287
2295
2288 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
2296 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
2289 float:left;
2297 float:left;
2290 margin:0;
2298 margin:0;
2291 }
2299 }
2292
2300
2293 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label {
2301 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label {
2294 height:1%;
2302 height:1%;
2295 display:block;
2303 display:block;
2296 float:left;
2304 float:left;
2297 margin:2px 0 0 4px;
2305 margin:2px 0 0 4px;
2298 }
2306 }
2299
2307
2300 div.form div.fields div.field div.button input,#content div.box div.form div.fields div.buttons input,div.form div.fields div.buttons input,#content div.box div.action div.button input {
2308 div.form div.fields div.field div.button input,#content div.box div.form div.fields div.buttons input,div.form div.fields div.buttons input,#content div.box div.action div.button input {
2301 color:#000;
2309 color:#000;
2302 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2310 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2303 font-size:11px;
2311 font-size:11px;
2304 font-weight:700;
2312 font-weight:700;
2305 margin:0;
2313 margin:0;
2306 }
2314 }
2307
2315
2308 div.form div.fields div.field div.button .ui-button,#content div.box div.form div.fields div.buttons input.ui-button {
2316 div.form div.fields div.field div.button .ui-button,#content div.box div.form div.fields div.buttons input.ui-button {
2309 background:#e5e3e3 url("../images/button.png") repeat-x;
2317 background:#e5e3e3 url("../images/button.png") repeat-x;
2310 border-top:1px solid #DDD;
2318 border-top:1px solid #DDD;
2311 border-left:1px solid #c6c6c6;
2319 border-left:1px solid #c6c6c6;
2312 border-right:1px solid #DDD;
2320 border-right:1px solid #DDD;
2313 border-bottom:1px solid #c6c6c6;
2321 border-bottom:1px solid #c6c6c6;
2314 color:#515151;
2322 color:#515151;
2315 outline:none;
2323 outline:none;
2316 margin:0;
2324 margin:0;
2317 padding:6px 12px;
2325 padding:6px 12px;
2318 }
2326 }
2319
2327
2320 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2328 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2321 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2329 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2322 border-top:1px solid #ccc;
2330 border-top:1px solid #ccc;
2323 border-left:1px solid #bebebe;
2331 border-left:1px solid #bebebe;
2324 border-right:1px solid #b1b1b1;
2332 border-right:1px solid #b1b1b1;
2325 border-bottom:1px solid #afafaf;
2333 border-bottom:1px solid #afafaf;
2326 color:#515151;
2334 color:#515151;
2327 outline:none;
2335 outline:none;
2328 margin:0;
2336 margin:0;
2329 padding:6px 12px;
2337 padding:6px 12px;
2330 }
2338 }
2331
2339
2332 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2340 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2333 display:inline;
2341 display:inline;
2334 }
2342 }
2335
2343
2336 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2344 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2337 margin:10px 0 0 200px;
2345 margin:10px 0 0 200px;
2338 padding:0;
2346 padding:0;
2339 }
2347 }
2340
2348
2341 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons {
2349 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons {
2342 margin:10px 0 0;
2350 margin:10px 0 0;
2343 }
2351 }
2344
2352
2345 #content div.box table td.user,#content div.box table td.address {
2353 #content div.box table td.user,#content div.box table td.address {
2346 width:10%;
2354 width:10%;
2347 text-align:center;
2355 text-align:center;
2348 }
2356 }
2349
2357
2350 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link {
2358 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link {
2351 text-align:right;
2359 text-align:right;
2352 margin:6px 0 0;
2360 margin:6px 0 0;
2353 padding:0;
2361 padding:0;
2354 }
2362 }
2355
2363
2356 #content div.box div.action div.button input.ui-button,#login div.form div.fields div.buttons input.ui-button,#register div.form div.fields div.buttons input.ui-button {
2364 #content div.box div.action div.button input.ui-button,#login div.form div.fields div.buttons input.ui-button,#register div.form div.fields div.buttons input.ui-button {
2357 background:#e5e3e3 url("../images/button.png") repeat-x;
2365 background:#e5e3e3 url("../images/button.png") repeat-x;
2358 border-top:1px solid #DDD;
2366 border-top:1px solid #DDD;
2359 border-left:1px solid #c6c6c6;
2367 border-left:1px solid #c6c6c6;
2360 border-right:1px solid #DDD;
2368 border-right:1px solid #DDD;
2361 border-bottom:1px solid #c6c6c6;
2369 border-bottom:1px solid #c6c6c6;
2362 color:#515151;
2370 color:#515151;
2363 margin:0;
2371 margin:0;
2364 padding:6px 12px;
2372 padding:6px 12px;
2365 }
2373 }
2366
2374
2367 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
2375 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
2368 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2376 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2369 border-top:1px solid #ccc;
2377 border-top:1px solid #ccc;
2370 border-left:1px solid #bebebe;
2378 border-left:1px solid #bebebe;
2371 border-right:1px solid #b1b1b1;
2379 border-right:1px solid #b1b1b1;
2372 border-bottom:1px solid #afafaf;
2380 border-bottom:1px solid #afafaf;
2373 color:#515151;
2381 color:#515151;
2374 margin:0;
2382 margin:0;
2375 padding:6px 12px;
2383 padding:6px 12px;
2376 }
2384 }
2377
2385
2378 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2386 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2379 text-align:left;
2387 text-align:left;
2380 float:left;
2388 float:left;
2381 margin:0;
2389 margin:0;
2382 padding:0;
2390 padding:0;
2383 }
2391 }
2384
2392
2385 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2393 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2386 height:1%;
2394 height:1%;
2387 display:block;
2395 display:block;
2388 float:left;
2396 float:left;
2389 background:#ebebeb url("../images/pager.png") repeat-x;
2397 background:#ebebeb url("../images/pager.png") repeat-x;
2390 border-top:1px solid #dedede;
2398 border-top:1px solid #dedede;
2391 border-left:1px solid #cfcfcf;
2399 border-left:1px solid #cfcfcf;
2392 border-right:1px solid #c4c4c4;
2400 border-right:1px solid #c4c4c4;
2393 border-bottom:1px solid #c4c4c4;
2401 border-bottom:1px solid #c4c4c4;
2394 color:#4A4A4A;
2402 color:#4A4A4A;
2395 font-weight:700;
2403 font-weight:700;
2396 margin:0;
2404 margin:0;
2397 padding:6px 8px;
2405 padding:6px 8px;
2398 }
2406 }
2399
2407
2400 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2408 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2401 color:#B4B4B4;
2409 color:#B4B4B4;
2402 padding:6px;
2410 padding:6px;
2403 }
2411 }
2404
2412
2405 #login,#register {
2413 #login,#register {
2406 width:520px;
2414 width:520px;
2407 margin:10% auto 0;
2415 margin:10% auto 0;
2408 padding:0;
2416 padding:0;
2409 }
2417 }
2410
2418
2411 #login div.color,#register div.color {
2419 #login div.color,#register div.color {
2412 clear:both;
2420 clear:both;
2413 overflow:hidden;
2421 overflow:hidden;
2414 background:#FFF;
2422 background:#FFF;
2415 margin:10px auto 0;
2423 margin:10px auto 0;
2416 padding:3px 3px 3px 0;
2424 padding:3px 3px 3px 0;
2417 }
2425 }
2418
2426
2419 #login div.color a,#register div.color a {
2427 #login div.color a,#register div.color a {
2420 width:20px;
2428 width:20px;
2421 height:20px;
2429 height:20px;
2422 display:block;
2430 display:block;
2423 float:left;
2431 float:left;
2424 margin:0 0 0 3px;
2432 margin:0 0 0 3px;
2425 padding:0;
2433 padding:0;
2426 }
2434 }
2427
2435
2428 #login div.title h5,#register div.title h5 {
2436 #login div.title h5,#register div.title h5 {
2429 color:#fff;
2437 color:#fff;
2430 margin:10px;
2438 margin:10px;
2431 padding:0;
2439 padding:0;
2432 }
2440 }
2433
2441
2434 #login div.form div.fields div.field,#register div.form div.fields div.field {
2442 #login div.form div.fields div.field,#register div.form div.fields div.field {
2435 clear:both;
2443 clear:both;
2436 overflow:hidden;
2444 overflow:hidden;
2437 margin:0;
2445 margin:0;
2438 padding:0 0 10px;
2446 padding:0 0 10px;
2439 }
2447 }
2440
2448
2441 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2449 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2442 height:1%;
2450 height:1%;
2443 display:block;
2451 display:block;
2444 color:red;
2452 color:red;
2445 margin:8px 0 0;
2453 margin:8px 0 0;
2446 padding:0;
2454 padding:0;
2447 max-width: 320px;
2455 max-width: 320px;
2448 }
2456 }
2449
2457
2450 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2458 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2451 color:#000;
2459 color:#000;
2452 font-weight:700;
2460 font-weight:700;
2453 }
2461 }
2454
2462
2455 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2463 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2456 float:left;
2464 float:left;
2457 margin:0;
2465 margin:0;
2458 padding:0;
2466 padding:0;
2459 }
2467 }
2460
2468
2461 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2469 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2462 margin:0 0 0 184px;
2470 margin:0 0 0 184px;
2463 padding:0;
2471 padding:0;
2464 }
2472 }
2465
2473
2466 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2474 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2467 color:#565656;
2475 color:#565656;
2468 font-weight:700;
2476 font-weight:700;
2469 }
2477 }
2470
2478
2471 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2479 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2472 color:#000;
2480 color:#000;
2473 font-size:1em;
2481 font-size:1em;
2474 font-weight:700;
2482 font-weight:700;
2475 font-family:Verdana, Helvetica, Sans-Serif;
2483 font-family:Verdana, Helvetica, Sans-Serif;
2476 margin:0;
2484 margin:0;
2477 }
2485 }
2478
2486
2479 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2487 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2480 width:600px;
2488 width:600px;
2481 }
2489 }
2482
2490
2483 #changeset_content .container .left,#graph_content .container .left {
2491 #changeset_content .container .left,#graph_content .container .left {
2484 float:left;
2492 float:left;
2485 width:70%;
2493 width:70%;
2486 padding-left:5px;
2494 padding-left:5px;
2487 }
2495 }
2488
2496
2489 #changeset_content .container .left .date,.ac .match {
2497 #changeset_content .container .left .date,.ac .match {
2490 font-weight:700;
2498 font-weight:700;
2491 padding-top: 5px;
2499 padding-top: 5px;
2492 padding-bottom:5px;
2500 padding-bottom:5px;
2493 }
2501 }
2494
2502
2495 div#legend_container table td,div#legend_choices table td {
2503 div#legend_container table td,div#legend_choices table td {
2496 border:none !important;
2504 border:none !important;
2497 height:20px !important;
2505 height:20px !important;
2498 padding:0 !important;
2506 padding:0 !important;
2499 }
2507 }
2500
2508
2501 #q_filter{
2509 #q_filter{
2502 border:0 none;
2510 border:0 none;
2503 color:#AAAAAA;
2511 color:#AAAAAA;
2504 margin-bottom:-4px;
2512 margin-bottom:-4px;
2505 margin-top:-4px;
2513 margin-top:-4px;
2506 padding-left:3px;
2514 padding-left:3px;
2507 }
2515 }
2508
2516
@@ -1,368 +1,383 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name}
5 ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('Repositories'),h.url('repos'))}
11 ${h.link_to(_('Repositories'),h.url('repos'))}
12 &raquo;
12 &raquo;
13 ${_('edit')} &raquo; ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
13 ${_('edit')} &raquo; ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box box-left">
21 <div class="box box-left">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
26 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
27 <div class="form">
27 <div class="form">
28 <!-- fields -->
28 <!-- fields -->
29 <div class="fields">
29 <div class="fields">
30 <div class="field">
30 <div class="field">
31 <div class="label">
31 <div class="label">
32 <label for="repo_name">${_('Name')}:</label>
32 <label for="repo_name">${_('Name')}:</label>
33 </div>
33 </div>
34 <div class="input">
34 <div class="input">
35 ${h.text('repo_name',class_="medium")}
35 ${h.text('repo_name',class_="medium")}
36 </div>
36 </div>
37 </div>
37 </div>
38 <div class="field">
38 <div class="field">
39 <div class="label">
39 <div class="label">
40 <label for="clone_uri">${_('Clone uri')}:</label>
40 <label for="clone_uri">${_('Clone uri')}:</label>
41 </div>
41 </div>
42 <div class="input">
42 <div class="input">
43 ${h.text('clone_uri',class_="small")}
43 ${h.text('clone_uri',class_="small")}
44 </div>
44 </div>
45 </div>
45 </div>
46 <div class="field">
46 <div class="field">
47 <div class="label">
47 <div class="label">
48 <label for="repo_group">${_('Repository group')}:</label>
48 <label for="repo_group">${_('Repository group')}:</label>
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>
52 <span>${h.link_to(_('add new group'),h.url(''))}</span>
53 </div>
53 </div>
54 </div>
54 </div>
55 <div class="field">
55 <div class="field">
56 <div class="label">
56 <div class="label">
57 <label for="repo_type">${_('Type')}:</label>
57 <label for="repo_type">${_('Type')}:</label>
58 </div>
58 </div>
59 <div class="input">
59 <div class="input">
60 ${h.select('repo_type','hg',c.backends,class_="medium")}
60 ${h.select('repo_type','hg',c.backends,class_="medium")}
61 </div>
61 </div>
62 </div>
62 </div>
63 <div class="field">
63 <div class="field">
64 <div class="label label-textarea">
64 <div class="label label-textarea">
65 <label for="description">${_('Description')}:</label>
65 <label for="description">${_('Description')}:</label>
66 </div>
66 </div>
67 <div class="textarea text-area editor">
67 <div class="textarea text-area editor">
68 ${h.textarea('description',cols=23,rows=5)}
68 ${h.textarea('description',cols=23,rows=5)}
69 </div>
69 </div>
70 </div>
70 </div>
71
71
72 <div class="field">
72 <div class="field">
73 <div class="label label-checkbox">
73 <div class="label label-checkbox">
74 <label for="private">${_('Private')}:</label>
74 <label for="private">${_('Private')}:</label>
75 </div>
75 </div>
76 <div class="checkboxes">
76 <div class="checkboxes">
77 ${h.checkbox('private',value="True")}
77 ${h.checkbox('private',value="True")}
78 </div>
78 </div>
79 </div>
79 </div>
80 <div class="field">
80 <div class="field">
81 <div class="label label-checkbox">
81 <div class="label label-checkbox">
82 <label for="enable_statistics">${_('Enable statistics')}:</label>
82 <label for="enable_statistics">${_('Enable statistics')}:</label>
83 </div>
83 </div>
84 <div class="checkboxes">
84 <div class="checkboxes">
85 ${h.checkbox('enable_statistics',value="True")}
85 ${h.checkbox('enable_statistics',value="True")}
86 </div>
86 </div>
87 </div>
87 </div>
88 <div class="field">
88 <div class="field">
89 <div class="label label-checkbox">
89 <div class="label label-checkbox">
90 <label for="enable_downloads">${_('Enable downloads')}:</label>
90 <label for="enable_downloads">${_('Enable downloads')}:</label>
91 </div>
91 </div>
92 <div class="checkboxes">
92 <div class="checkboxes">
93 ${h.checkbox('enable_downloads',value="True")}
93 ${h.checkbox('enable_downloads',value="True")}
94 </div>
94 </div>
95 </div>
95 </div>
96 <div class="field">
96 <div class="field">
97 <div class="label">
97 <div class="label">
98 <label for="user">${_('Owner')}:</label>
98 <label for="user">${_('Owner')}:</label>
99 </div>
99 </div>
100 <div class="input input-small ac">
100 <div class="input input-small ac">
101 <div class="perm_ac">
101 <div class="perm_ac">
102 ${h.text('user',class_='yui-ac-input')}
102 ${h.text('user',class_='yui-ac-input')}
103 <div id="owner_container"></div>
103 <div id="owner_container"></div>
104 </div>
104 </div>
105 </div>
105 </div>
106 </div>
106 </div>
107
107
108 <div class="field">
108 <div class="field">
109 <div class="label">
109 <div class="label">
110 <label for="input">${_('Permissions')}:</label>
110 <label for="input">${_('Permissions')}:</label>
111 </div>
111 </div>
112 <div class="input">
112 <div class="input">
113 <%include file="repo_edit_perms.html"/>
113 <%include file="repo_edit_perms.html"/>
114 </div>
114 </div>
115
115
116 <div class="buttons">
116 <div class="buttons">
117 ${h.submit('save','Save',class_="ui-button")}
117 ${h.submit('save','Save',class_="ui-button")}
118 ${h.reset('reset','Reset',class_="ui-button")}
118 ${h.reset('reset','Reset',class_="ui-button")}
119 </div>
119 </div>
120 </div>
120 </div>
121 </div>
121 </div>
122 </div>
122 </div>
123 ${h.end_form()}
123 ${h.end_form()}
124 <script type="text/javascript">
124 <script type="text/javascript">
125 YAHOO.util.Event.onDOMReady(function(){
125 YAHOO.util.Event.onDOMReady(function(){
126 var D = YAHOO.util.Dom;
126 var D = YAHOO.util.Dom;
127 if(!D.hasClass('perm_new_member_name','error')){
127 if(!D.hasClass('perm_new_member_name','error')){
128 D.setStyle('add_perm_input','display','none');
128 D.setStyle('add_perm_input','display','none');
129 }
129 }
130 YAHOO.util.Event.addListener('add_perm','click',function(){
130 YAHOO.util.Event.addListener('add_perm','click',function(){
131 D.setStyle('add_perm_input','display','');
131 D.setStyle('add_perm_input','display','');
132 D.setStyle('add_perm','opacity','0.6');
132 D.setStyle('add_perm','opacity','0.6');
133 D.setStyle('add_perm','cursor','default');
133 D.setStyle('add_perm','cursor','default');
134 });
134 });
135 });
135 });
136 </script>
136 </script>
137 <script type="text/javascript">
137 <script type="text/javascript">
138 YAHOO.example.FnMultipleFields = function(){
138 YAHOO.example.FnMultipleFields = function(){
139 var myUsers = ${c.users_array|n};
139 var myUsers = ${c.users_array|n};
140 var myGroups = ${c.users_groups_array|n};
140 var myGroups = ${c.users_groups_array|n};
141
141
142 // Define a custom search function for the DataSource of users
142 // Define a custom search function for the DataSource of users
143 var matchUsers = function(sQuery) {
143 var matchUsers = function(sQuery) {
144 // Case insensitive matching
144 // Case insensitive matching
145 var query = sQuery.toLowerCase();
145 var query = sQuery.toLowerCase();
146 var i=0;
146 var i=0;
147 var l=myUsers.length;
147 var l=myUsers.length;
148 var matches = [];
148 var matches = [];
149
149
150 // Match against each name of each contact
150 // Match against each name of each contact
151 for(; i<l; i++) {
151 for(; i<l; i++) {
152 contact = myUsers[i];
152 contact = myUsers[i];
153 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
153 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
154 (contact.lname.toLowerCase().indexOf(query) > -1) ||
154 (contact.lname.toLowerCase().indexOf(query) > -1) ||
155 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
155 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
156 matches[matches.length] = contact;
156 matches[matches.length] = contact;
157 }
157 }
158 }
158 }
159 return matches;
159 return matches;
160 };
160 };
161
161
162 // Define a custom search function for the DataSource of usersGroups
162 // Define a custom search function for the DataSource of usersGroups
163 var matchGroups = function(sQuery) {
163 var matchGroups = function(sQuery) {
164 // Case insensitive matching
164 // Case insensitive matching
165 var query = sQuery.toLowerCase();
165 var query = sQuery.toLowerCase();
166 var i=0;
166 var i=0;
167 var l=myGroups.length;
167 var l=myGroups.length;
168 var matches = [];
168 var matches = [];
169
169
170 // Match against each name of each contact
170 // Match against each name of each contact
171 for(; i<l; i++) {
171 for(; i<l; i++) {
172 matched_group = myGroups[i];
172 matched_group = myGroups[i];
173 if(matched_group.grname.toLowerCase().indexOf(query) > -1) {
173 if(matched_group.grname.toLowerCase().indexOf(query) > -1) {
174 matches[matches.length] = matched_group;
174 matches[matches.length] = matched_group;
175 }
175 }
176 }
176 }
177 return matches;
177 return matches;
178 };
178 };
179
179
180 //match all
180 //match all
181 var matchAll = function(sQuery){
181 var matchAll = function(sQuery){
182 u = matchUsers(sQuery);
182 u = matchUsers(sQuery);
183 g = matchGroups(sQuery);
183 g = matchGroups(sQuery);
184 return u.concat(g);
184 return u.concat(g);
185 };
185 };
186
186
187 // DataScheme for members
187 // DataScheme for members
188 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
188 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
189 memberDS.responseSchema = {
189 memberDS.responseSchema = {
190 fields: ["id", "fname", "lname", "nname", "grname", "grmembers"]
190 fields: ["id", "fname", "lname", "nname", "grname", "grmembers"]
191 };
191 };
192
192
193 // DataScheme for owner
193 // DataScheme for owner
194 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
194 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
195 ownerDS.responseSchema = {
195 ownerDS.responseSchema = {
196 fields: ["id", "fname", "lname", "nname"]
196 fields: ["id", "fname", "lname", "nname"]
197 };
197 };
198
198
199 // Instantiate AutoComplete for perms
199 // Instantiate AutoComplete for perms
200 var membersAC = new YAHOO.widget.AutoComplete("perm_new_member_name", "perm_container", memberDS);
200 var membersAC = new YAHOO.widget.AutoComplete("perm_new_member_name", "perm_container", memberDS);
201 membersAC.useShadow = false;
201 membersAC.useShadow = false;
202 membersAC.resultTypeList = false;
202 membersAC.resultTypeList = false;
203
203
204 // Instantiate AutoComplete for owner
204 // Instantiate AutoComplete for owner
205 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
205 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
206 ownerAC.useShadow = false;
206 ownerAC.useShadow = false;
207 ownerAC.resultTypeList = false;
207 ownerAC.resultTypeList = false;
208
208
209
209
210 // Helper highlight function for the formatter
210 // Helper highlight function for the formatter
211 var highlightMatch = function(full, snippet, matchindex) {
211 var highlightMatch = function(full, snippet, matchindex) {
212 return full.substring(0, matchindex) +
212 return full.substring(0, matchindex) +
213 "<span class='match'>" +
213 "<span class='match'>" +
214 full.substr(matchindex, snippet.length) +
214 full.substr(matchindex, snippet.length) +
215 "</span>" +
215 "</span>" +
216 full.substring(matchindex + snippet.length);
216 full.substring(matchindex + snippet.length);
217 };
217 };
218
218
219 // Custom formatter to highlight the matching letters
219 // Custom formatter to highlight the matching letters
220 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
220 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
221 var query = sQuery.toLowerCase();
221 var query = sQuery.toLowerCase();
222
222
223 if (oResultData.grname != undefined){
223 if (oResultData.grname != undefined){
224 var grname = oResultData.grname;
224 var grname = oResultData.grname;
225 var grmembers = oResultData.grmembers;
225 var grmembers = oResultData.grmembers;
226 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
226 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
227 var grprefix = "${_('Group')}: ";
227 var grprefix = "${_('Group')}: ";
228 var grsuffix = " ("+grmembers+" ${_('members')})";
228 var grsuffix = " ("+grmembers+" ${_('members')})";
229
229
230 if (grnameMatchIndex > -1){
230 if (grnameMatchIndex > -1){
231 return grprefix+highlightMatch(grname,query,grnameMatchIndex)+grsuffix;
231 return grprefix+highlightMatch(grname,query,grnameMatchIndex)+grsuffix;
232 }
232 }
233
233
234 return grprefix+oResultData.grname+grsuffix;
234 return grprefix+oResultData.grname+grsuffix;
235 }
235 }
236 else if(oResultData.fname != undefined){
236 else if(oResultData.fname != undefined){
237
237
238 var fname = oResultData.fname,
238 var fname = oResultData.fname,
239 lname = oResultData.lname,
239 lname = oResultData.lname,
240 nname = oResultData.nname || "", // Guard against null value
240 nname = oResultData.nname || "", // Guard against null value
241 fnameMatchIndex = fname.toLowerCase().indexOf(query),
241 fnameMatchIndex = fname.toLowerCase().indexOf(query),
242 lnameMatchIndex = lname.toLowerCase().indexOf(query),
242 lnameMatchIndex = lname.toLowerCase().indexOf(query),
243 nnameMatchIndex = nname.toLowerCase().indexOf(query),
243 nnameMatchIndex = nname.toLowerCase().indexOf(query),
244 displayfname, displaylname, displaynname;
244 displayfname, displaylname, displaynname;
245
245
246 if(fnameMatchIndex > -1) {
246 if(fnameMatchIndex > -1) {
247 displayfname = highlightMatch(fname, query, fnameMatchIndex);
247 displayfname = highlightMatch(fname, query, fnameMatchIndex);
248 }
248 }
249 else {
249 else {
250 displayfname = fname;
250 displayfname = fname;
251 }
251 }
252
252
253 if(lnameMatchIndex > -1) {
253 if(lnameMatchIndex > -1) {
254 displaylname = highlightMatch(lname, query, lnameMatchIndex);
254 displaylname = highlightMatch(lname, query, lnameMatchIndex);
255 }
255 }
256 else {
256 else {
257 displaylname = lname;
257 displaylname = lname;
258 }
258 }
259
259
260 if(nnameMatchIndex > -1) {
260 if(nnameMatchIndex > -1) {
261 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
261 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
262 }
262 }
263 else {
263 else {
264 displaynname = nname ? "(" + nname + ")" : "";
264 displaynname = nname ? "(" + nname + ")" : "";
265 }
265 }
266
266
267 return displayfname + " " + displaylname + " " + displaynname;
267 return displayfname + " " + displaylname + " " + displaynname;
268 }
268 }
269 else{
269 else{
270 return '';
270 return '';
271 }
271 }
272 };
272 };
273 membersAC.formatResult = custom_formatter;
273 membersAC.formatResult = custom_formatter;
274 ownerAC.formatResult = custom_formatter;
274 ownerAC.formatResult = custom_formatter;
275
275
276 var myHandler = function(sType, aArgs) {
276 var myHandler = function(sType, aArgs) {
277
277
278 var myAC = aArgs[0]; // reference back to the AC instance
278 var myAC = aArgs[0]; // reference back to the AC instance
279 var elLI = aArgs[1]; // reference to the selected LI element
279 var elLI = aArgs[1]; // reference to the selected LI element
280 var oData = aArgs[2]; // object literal of selected item's result data
280 var oData = aArgs[2]; // object literal of selected item's result data
281
281
282 //fill the autocomplete with value
282 //fill the autocomplete with value
283 if(oData.nname != undefined){
283 if(oData.nname != undefined){
284 //users
284 //users
285 myAC.getInputEl().value = oData.nname;
285 myAC.getInputEl().value = oData.nname;
286 YUD.get('perm_new_member_type').value = 'user';
286 YUD.get('perm_new_member_type').value = 'user';
287 }
287 }
288 else{
288 else{
289 //groups
289 //groups
290 myAC.getInputEl().value = oData.grname;
290 myAC.getInputEl().value = oData.grname;
291 YUD.get('perm_new_member_type').value = 'users_group';
291 YUD.get('perm_new_member_type').value = 'users_group';
292 }
292 }
293
293
294 };
294 };
295
295
296 membersAC.itemSelectEvent.subscribe(myHandler);
296 membersAC.itemSelectEvent.subscribe(myHandler);
297 ownerAC.itemSelectEvent.subscribe(myHandler);
297 ownerAC.itemSelectEvent.subscribe(myHandler);
298
298
299 return {
299 return {
300 memberDS: memberDS,
300 memberDS: memberDS,
301 ownerDS: ownerDS,
301 ownerDS: ownerDS,
302 membersAC: membersAC,
302 membersAC: membersAC,
303 ownerAC: ownerAC,
303 ownerAC: ownerAC,
304 };
304 };
305 }();
305 }();
306
306
307 </script>
307 </script>
308
308
309 </div>
309 </div>
310
310
311 <div class="box box-right">
311 <div class="box box-right">
312 <div class="title">
312 <div class="title">
313 <h5>${_('Administration')}</h5>
313 <h5>${_('Administration')}</h5>
314 </div>
314 </div>
315
315
316 <h3>${_('Statistics')}</h3>
316 <h3>${_('Statistics')}</h3>
317
318 ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')}
317 ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')}
319 <div class="form">
318 <div class="form">
320 <div class="fields">
319 <div class="fields">
321 ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('Confirm to remove current statistics');")}
320 ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('Confirm to remove current statistics');")}
322 <div class="field">
321 <div class="field" style="border:none">
323 <ul>
322 <ul>
324 <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
323 <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
325 <li>${_('Percentage of stats gathered')}: ${c.stats_percentage} %</li>
324 <li>${_('Percentage of stats gathered')}: ${c.stats_percentage} %</li>
326 </ul>
325 </ul>
327 </div>
326 </div>
328
327
329 </div>
328 </div>
330 </div>
329 </div>
331 ${h.end_form()}
330 ${h.end_form()}
332
331
332 %if c.repo_info.clone_uri:
333 <h3>${_('Remote')}</h3>
334 ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')}
335 <div class="form">
336 <div class="fields">
337 ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="pull_icon action_button",onclick="return confirm('Confirm to pull changes from remote side');")}
338 <div class="field" style="border:none">
339 <ul>
340 <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li>
341 </ul>
342 </div>
343 </div>
344 </div>
345 ${h.end_form()}
346 %endif
347
333 <h3>${_('Cache')}</h3>
348 <h3>${_('Cache')}</h3>
334 ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')}
349 ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')}
335 <div class="form">
350 <div class="form">
336 <div class="fields">
351 <div class="fields">
337 ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="refresh_icon action_button",onclick="return confirm('Confirm to invalidate repository cache');")}
352 ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="refresh_icon action_button",onclick="return confirm('Confirm to invalidate repository cache');")}
338 </div>
353 </div>
339 </div>
354 </div>
340 ${h.end_form()}
355 ${h.end_form()}
341
356
342 <h3>${_('Public journal')}</h3>
357 <h3>${_('Public journal')}</h3>
343 ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
358 ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
344 <div class="form">
359 <div class="form">
345 <div class="fields">
360 <div class="fields">
346 ${h.hidden('auth_token',str(h.get_token()))}
361 ${h.hidden('auth_token',str(h.get_token()))}
347 %if c.in_public_journal:
362 %if c.in_public_journal:
348 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="stop_following_icon action_button")}
363 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="stop_following_icon action_button")}
349 %else:
364 %else:
350 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="start_following_icon action_button")}
365 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="start_following_icon action_button")}
351 %endif
366 %endif
352 </div>
367 </div>
353 </div>
368 </div>
354 ${h.end_form()}
369 ${h.end_form()}
355
370
356 <h3>${_('Delete')}</h3>
371 <h3>${_('Delete')}</h3>
357 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
372 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
358 <div class="form">
373 <div class="form">
359 <div class="fields">
374 <div class="fields">
360 ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
375 ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
361 </div>
376 </div>
362 </div>
377 </div>
363 ${h.end_form()}
378 ${h.end_form()}
364
379
365 </div>
380 </div>
366
381
367
382
368 </%def> No newline at end of file
383 </%def>
General Comments 0
You need to be logged in to leave comments. Login now