##// END OF EJS Templates
implemented user dashboards, and following system.
marcink -
r734:49eb69d7 beta
parent child Browse files
Show More
@@ -0,0 +1,84 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # journal controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
20 """
21 Created on November 21, 2010
22 journal controller for pylons
23 @author: marcink
24 """
25
26 from pylons import request, response, session, tmpl_context as c, url
27 from pylons.controllers.util import abort, redirect
28 from rhodecode.lib.auth import LoginRequired
29 from rhodecode.lib.base import BaseController, render
30 from rhodecode.lib.helpers import get_token
31 from rhodecode.model.db import UserLog, UserFollowing
32 from rhodecode.model.scm import ScmModel
33 import logging
34 from paste.httpexceptions import HTTPInternalServerError, HTTPNotFound
35
36 log = logging.getLogger(__name__)
37
38 class JournalController(BaseController):
39
40
41 @LoginRequired()
42 def __before__(self):
43 super(JournalController, self).__before__()
44
45 def index(self):
46 # Return a rendered template
47
48 c.following = self.sa.query(UserFollowing)\
49 .filter(UserFollowing.user_id == c.rhodecode_user.user_id).all()
50
51
52 c.journal = self.sa.query(UserLog)\
53 .order_by(UserLog.action_date.desc())\
54 .all()
55 return render('/journal.html')
56
57
58 def toggle_following(self):
59 print c.rhodecode_user
60
61 if request.POST.get('auth_token') == get_token():
62 scm_model = ScmModel()
63
64 user_id = request.POST.get('follows_user_id')
65 if user_id:
66 try:
67 scm_model.toggle_following_user(user_id,
68 c.rhodecode_user.user_id)
69 return 'ok'
70 except:
71 raise HTTPInternalServerError()
72
73 repo_id = request.POST.get('follows_repo_id')
74 if repo_id:
75 try:
76 scm_model.toggle_following_repo(repo_id,
77 c.rhodecode_user.user_id)
78 return 'ok'
79 except:
80 raise HTTPInternalServerError()
81
82
83
84 raise HTTPInternalServerError()
@@ -0,0 +1,80 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/base.html"/>
3 <%def name="title()">
4 ${_('Journal')} - ${c.rhodecode_name}
5 </%def>
6 <%def name="breadcrumbs()">
7 ${c.rhodecode_name}
8 </%def>
9 <%def name="page_nav()">
10 ${self.menu('home')}
11 </%def>
12 <%def name="main()">
13
14 <div class="box box-left">
15 <!-- box / title -->
16 <div class="title">
17 <h5>${_('Journal')}</h5>
18 </div>
19 <div>
20 %if c.journal:
21 %for entry in c.journal:
22 <div style="padding:10px">
23 <div class="gravatar">
24 <img alt="gravatar" src="${h.gravatar_url(entry.user.email)}"/>
25 </div>
26 <div>${entry.user.name} ${entry.user.lastname}</div>
27 <div style="padding-left: 45px;">${h.action_parser(entry)} <br/>
28 <b>
29 %if entry.repository:
30 ${h.link_to(entry.repository.repo_name,
31 h.url('summary_home',repo_name=entry.repository.repo_name))}
32 %else:
33 ${entry.repository_name}
34 %endif
35 </b> - <span title="${entry.action_date}">${h.age(entry.action_date)}</span>
36 </div>
37 </div>
38 <div style="clear:both;border-bottom:1px dashed #DDD;padding:3px 3px;margin:0px 10px 0px 10px"></div>
39 %endfor
40 %else:
41 ${_('No entries yet')}
42 %endif
43 </div>
44 </div>
45
46 <div class="box box-right">
47 <!-- box / title -->
48 <div class="title">
49 <h5>${_('Following')}</h5>
50 </div>
51 <div>
52 %if c.following:
53 %for entry in c.following:
54 <div>
55 %if entry.follows_user_id:
56 <img alt="" src="/images/icons/user.png"/>
57
58 ${entry.follows_user.username}
59 %endif
60
61 %if entry.follows_repo_id:
62
63 %if entry.follows_repository.private:
64 <img alt="" src="/images/icons/lock_closed.png"/>
65 %else:
66 <img alt="" src="/images/icons/lock_open.png"/>
67 %endif
68
69 ${h.link_to(entry.follows_repository.repo_name,h.url('summary_home',
70 repo_name=entry.follows_repository.repo_name))}
71
72 %endif
73 </div>
74 %endfor
75 %else:
76 ${_('You are not following any users or repositories')}
77 %endif
78 </div>
79 </div>
80 </%def>
@@ -0,0 +1,7 b''
1 from rhodecode.tests import *
2
3 class TestJournalController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url(controller='journal', action='index'))
7 # Test response...
@@ -1,198 +1,206 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 map = Mapper(directory=config['pylons.paths']['controllers'],
14 map = Mapper(directory=config['pylons.paths']['controllers'],
15 always_scan=config['debug'])
15 always_scan=config['debug'])
16 map.minimization = False
16 map.minimization = False
17 map.explicit = False
17 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 :param environ:
22 :param environ:
23 :param match_dict:
23 :param match_dict:
24 """
24 """
25 repo_name = match_dict.get('repo_name')
25 repo_name = match_dict.get('repo_name')
26 return not cr(repo_name, config['base_path'])
26 return not cr(repo_name, config['base_path'])
27
27
28 # The ErrorController route (handles 404/500 error pages); it should
28 # The ErrorController route (handles 404/500 error pages); it should
29 # likely stay at the top, ensuring it can always be resolved
29 # likely stay at the top, ensuring it can always be resolved
30 map.connect('/error/{action}', controller='error')
30 map.connect('/error/{action}', controller='error')
31 map.connect('/error/{action}/{id}', controller='error')
31 map.connect('/error/{action}/{id}', controller='error')
32
32
33 #==========================================================================
33 #==========================================================================
34 # CUSTOM ROUTES HERE
34 # CUSTOM ROUTES HERE
35 #==========================================================================
35 #==========================================================================
36
36
37 #MAIN PAGE
37 #MAIN PAGE
38 map.connect('home', '/', controller='home', action='index')
38 map.connect('home', '/', controller='home', action='index')
39 map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
39 map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
40 map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
40 map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
41 #ADMIN REPOSITORY REST ROUTES
41 #ADMIN REPOSITORY REST ROUTES
42 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
42 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
43 m.connect("repos", "/repos",
43 m.connect("repos", "/repos",
44 action="create", conditions=dict(method=["POST"]))
44 action="create", conditions=dict(method=["POST"]))
45 m.connect("repos", "/repos",
45 m.connect("repos", "/repos",
46 action="index", conditions=dict(method=["GET"]))
46 action="index", conditions=dict(method=["GET"]))
47 m.connect("formatted_repos", "/repos.{format}",
47 m.connect("formatted_repos", "/repos.{format}",
48 action="index",
48 action="index",
49 conditions=dict(method=["GET"]))
49 conditions=dict(method=["GET"]))
50 m.connect("new_repo", "/repos/new",
50 m.connect("new_repo", "/repos/new",
51 action="new", conditions=dict(method=["GET"]))
51 action="new", conditions=dict(method=["GET"]))
52 m.connect("formatted_new_repo", "/repos/new.{format}",
52 m.connect("formatted_new_repo", "/repos/new.{format}",
53 action="new", conditions=dict(method=["GET"]))
53 action="new", conditions=dict(method=["GET"]))
54 m.connect("/repos/{repo_name:.*}",
54 m.connect("/repos/{repo_name:.*}",
55 action="update", conditions=dict(method=["PUT"],
55 action="update", conditions=dict(method=["PUT"],
56 function=check_repo))
56 function=check_repo))
57 m.connect("/repos/{repo_name:.*}",
57 m.connect("/repos/{repo_name:.*}",
58 action="delete", conditions=dict(method=["DELETE"],
58 action="delete", conditions=dict(method=["DELETE"],
59 function=check_repo))
59 function=check_repo))
60 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
60 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
61 action="edit", conditions=dict(method=["GET"],
61 action="edit", conditions=dict(method=["GET"],
62 function=check_repo))
62 function=check_repo))
63 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
63 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
64 action="edit", conditions=dict(method=["GET"],
64 action="edit", conditions=dict(method=["GET"],
65 function=check_repo))
65 function=check_repo))
66 m.connect("repo", "/repos/{repo_name:.*}",
66 m.connect("repo", "/repos/{repo_name:.*}",
67 action="show", conditions=dict(method=["GET"],
67 action="show", conditions=dict(method=["GET"],
68 function=check_repo))
68 function=check_repo))
69 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
69 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
70 action="show", conditions=dict(method=["GET"],
70 action="show", conditions=dict(method=["GET"],
71 function=check_repo))
71 function=check_repo))
72 #ajax delete repo perm user
72 #ajax delete repo perm user
73 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
73 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
74 action="delete_perm_user", conditions=dict(method=["DELETE"],
74 action="delete_perm_user", conditions=dict(method=["DELETE"],
75 function=check_repo))
75 function=check_repo))
76 #settings actions
76 #settings actions
77 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
77 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
78 action="repo_stats", conditions=dict(method=["DELETE"],
78 action="repo_stats", conditions=dict(method=["DELETE"],
79 function=check_repo))
79 function=check_repo))
80 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
80 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
81 action="repo_cache", conditions=dict(method=["DELETE"],
81 action="repo_cache", conditions=dict(method=["DELETE"],
82 function=check_repo))
82 function=check_repo))
83 #ADMIN USER REST ROUTES
83 #ADMIN USER REST ROUTES
84 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
84 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
85
85
86 #ADMIN PERMISSIONS REST ROUTES
86 #ADMIN PERMISSIONS REST ROUTES
87 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
87 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
88 map.connect('permissions_ldap', '/_admin/permissions_ldap', controller='admin/permissions', action='ldap')
88 map.connect('permissions_ldap', '/_admin/permissions_ldap', controller='admin/permissions', action='ldap')
89
89
90
90
91 #ADMIN SETTINGS REST ROUTES
91 #ADMIN SETTINGS REST ROUTES
92 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
92 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
93 m.connect("admin_settings", "/settings",
93 m.connect("admin_settings", "/settings",
94 action="create", conditions=dict(method=["POST"]))
94 action="create", conditions=dict(method=["POST"]))
95 m.connect("admin_settings", "/settings",
95 m.connect("admin_settings", "/settings",
96 action="index", conditions=dict(method=["GET"]))
96 action="index", conditions=dict(method=["GET"]))
97 m.connect("formatted_admin_settings", "/settings.{format}",
97 m.connect("formatted_admin_settings", "/settings.{format}",
98 action="index", conditions=dict(method=["GET"]))
98 action="index", conditions=dict(method=["GET"]))
99 m.connect("admin_new_setting", "/settings/new",
99 m.connect("admin_new_setting", "/settings/new",
100 action="new", conditions=dict(method=["GET"]))
100 action="new", conditions=dict(method=["GET"]))
101 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
101 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
102 action="new", conditions=dict(method=["GET"]))
102 action="new", conditions=dict(method=["GET"]))
103 m.connect("/settings/{setting_id}",
103 m.connect("/settings/{setting_id}",
104 action="update", conditions=dict(method=["PUT"]))
104 action="update", conditions=dict(method=["PUT"]))
105 m.connect("/settings/{setting_id}",
105 m.connect("/settings/{setting_id}",
106 action="delete", conditions=dict(method=["DELETE"]))
106 action="delete", conditions=dict(method=["DELETE"]))
107 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
107 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
108 action="edit", conditions=dict(method=["GET"]))
108 action="edit", conditions=dict(method=["GET"]))
109 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
109 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
110 action="edit", conditions=dict(method=["GET"]))
110 action="edit", conditions=dict(method=["GET"]))
111 m.connect("admin_setting", "/settings/{setting_id}",
111 m.connect("admin_setting", "/settings/{setting_id}",
112 action="show", conditions=dict(method=["GET"]))
112 action="show", conditions=dict(method=["GET"]))
113 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
113 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
114 action="show", conditions=dict(method=["GET"]))
114 action="show", conditions=dict(method=["GET"]))
115 m.connect("admin_settings_my_account", "/my_account",
115 m.connect("admin_settings_my_account", "/my_account",
116 action="my_account", conditions=dict(method=["GET"]))
116 action="my_account", conditions=dict(method=["GET"]))
117 m.connect("admin_settings_my_account_update", "/my_account_update",
117 m.connect("admin_settings_my_account_update", "/my_account_update",
118 action="my_account_update", conditions=dict(method=["PUT"]))
118 action="my_account_update", conditions=dict(method=["PUT"]))
119 m.connect("admin_settings_create_repository", "/create_repository",
119 m.connect("admin_settings_create_repository", "/create_repository",
120 action="create_repository", conditions=dict(method=["GET"]))
120 action="create_repository", conditions=dict(method=["GET"]))
121
121
122 #ADMIN MAIN PAGES
122 #ADMIN MAIN PAGES
123 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
123 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
124 m.connect('admin_home', '', action='index')#main page
124 m.connect('admin_home', '', action='index')#main page
125 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
125 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
126 action='add_repo')
126 action='add_repo')
127
128
129 #USER JOURNAL
130 map.connect('journal', '/_admin/journal', controller='journal',)
131 map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
132 action='toggle_following', conditions=dict(method=["POST"]))
133
134
127 #SEARCH
135 #SEARCH
128 map.connect('search', '/_admin/search', controller='search',)
136 map.connect('search', '/_admin/search', controller='search',)
129 map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
137 map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
130
138
131 #LOGIN/LOGOUT/REGISTER/SIGN IN
139 #LOGIN/LOGOUT/REGISTER/SIGN IN
132 map.connect('login_home', '/_admin/login', controller='login')
140 map.connect('login_home', '/_admin/login', controller='login')
133 map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
141 map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
134 map.connect('register', '/_admin/register', controller='login', action='register')
142 map.connect('register', '/_admin/register', controller='login', action='register')
135 map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
143 map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
136
144
137 #FEEDS
145 #FEEDS
138 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
146 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
139 controller='feed', action='rss',
147 controller='feed', action='rss',
140 conditions=dict(function=check_repo))
148 conditions=dict(function=check_repo))
141 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
149 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
142 controller='feed', action='atom',
150 controller='feed', action='atom',
143 conditions=dict(function=check_repo))
151 conditions=dict(function=check_repo))
144
152
145
153
146 #REPOSITORY ROUTES
154 #REPOSITORY ROUTES
147 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
155 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
148 controller='changeset', revision='tip',
156 controller='changeset', revision='tip',
149 conditions=dict(function=check_repo))
157 conditions=dict(function=check_repo))
150 map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
158 map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
151 controller='changeset', action='raw_changeset', revision='tip',
159 controller='changeset', action='raw_changeset', revision='tip',
152 conditions=dict(function=check_repo))
160 conditions=dict(function=check_repo))
153 map.connect('summary_home', '/{repo_name:.*}/summary',
161 map.connect('summary_home', '/{repo_name:.*}/summary',
154 controller='summary', conditions=dict(function=check_repo))
162 controller='summary', conditions=dict(function=check_repo))
155 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
163 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
156 controller='shortlog', conditions=dict(function=check_repo))
164 controller='shortlog', conditions=dict(function=check_repo))
157 map.connect('branches_home', '/{repo_name:.*}/branches',
165 map.connect('branches_home', '/{repo_name:.*}/branches',
158 controller='branches', conditions=dict(function=check_repo))
166 controller='branches', conditions=dict(function=check_repo))
159 map.connect('tags_home', '/{repo_name:.*}/tags',
167 map.connect('tags_home', '/{repo_name:.*}/tags',
160 controller='tags', conditions=dict(function=check_repo))
168 controller='tags', conditions=dict(function=check_repo))
161 map.connect('changelog_home', '/{repo_name:.*}/changelog',
169 map.connect('changelog_home', '/{repo_name:.*}/changelog',
162 controller='changelog', conditions=dict(function=check_repo))
170 controller='changelog', conditions=dict(function=check_repo))
163 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
171 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
164 controller='files', revision='tip', f_path='',
172 controller='files', revision='tip', f_path='',
165 conditions=dict(function=check_repo))
173 conditions=dict(function=check_repo))
166 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
174 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
167 controller='files', action='diff', revision='tip', f_path='',
175 controller='files', action='diff', revision='tip', f_path='',
168 conditions=dict(function=check_repo))
176 conditions=dict(function=check_repo))
169 map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
177 map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
170 controller='files', action='rawfile', revision='tip', f_path='',
178 controller='files', action='rawfile', revision='tip', f_path='',
171 conditions=dict(function=check_repo))
179 conditions=dict(function=check_repo))
172 map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
180 map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
173 controller='files', action='raw', revision='tip', f_path='',
181 controller='files', action='raw', revision='tip', f_path='',
174 conditions=dict(function=check_repo))
182 conditions=dict(function=check_repo))
175 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
183 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
176 controller='files', action='annotate', revision='tip', f_path='',
184 controller='files', action='annotate', revision='tip', f_path='',
177 conditions=dict(function=check_repo))
185 conditions=dict(function=check_repo))
178 map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
186 map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
179 controller='files', action='archivefile', revision='tip',
187 controller='files', action='archivefile', revision='tip',
180 conditions=dict(function=check_repo))
188 conditions=dict(function=check_repo))
181 map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
189 map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
182 controller='settings', action="delete",
190 controller='settings', action="delete",
183 conditions=dict(method=["DELETE"], function=check_repo))
191 conditions=dict(method=["DELETE"], function=check_repo))
184 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
192 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
185 controller='settings', action="update",
193 controller='settings', action="update",
186 conditions=dict(method=["PUT"], function=check_repo))
194 conditions=dict(method=["PUT"], function=check_repo))
187 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
195 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
188 controller='settings', action='index',
196 controller='settings', action='index',
189 conditions=dict(function=check_repo))
197 conditions=dict(function=check_repo))
190
198
191 map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
199 map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
192 controller='settings', action='fork_create',
200 controller='settings', action='fork_create',
193 conditions=dict(function=check_repo, method=["POST"]))
201 conditions=dict(function=check_repo, method=["POST"]))
194 map.connect('repo_fork_home', '/{repo_name:.*}/fork',
202 map.connect('repo_fork_home', '/{repo_name:.*}/fork',
195 controller='settings', action='fork',
203 controller='settings', action='fork',
196 conditions=dict(function=check_repo))
204 conditions=dict(function=check_repo))
197
205
198 return map
206 return map
@@ -1,126 +1,128 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # summary controller for pylons
3 # summary controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 18, 2010
21 Created on April 18, 2010
22 summary controller for pylons
22 summary controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from pylons import tmpl_context as c, request, url
25 from pylons import tmpl_context as c, request, url
26 from vcs.exceptions import ChangesetError
26 from vcs.exceptions import ChangesetError
27 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
27 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
28 from rhodecode.lib.base import BaseController, render
28 from rhodecode.lib.base import BaseController, render
29 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
29 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
30 from rhodecode.model.scm import ScmModel
30 from rhodecode.model.scm import ScmModel
31 from rhodecode.model.db import Statistics
31 from rhodecode.model.db import Statistics
32 from webhelpers.paginate import Page
32 from webhelpers.paginate import Page
33 from rhodecode.lib.celerylib import run_task
33 from rhodecode.lib.celerylib import run_task
34 from rhodecode.lib.celerylib.tasks import get_commits_stats
34 from rhodecode.lib.celerylib.tasks import get_commits_stats
35 from datetime import datetime, timedelta
35 from datetime import datetime, timedelta
36 from time import mktime
36 from time import mktime
37 import calendar
37 import calendar
38 import logging
38 import logging
39 try:
39 try:
40 import json
40 import json
41 except ImportError:
41 except ImportError:
42 #python 2.5 compatibility
42 #python 2.5 compatibility
43 import simplejson as json
43 import simplejson as json
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46 class SummaryController(BaseController):
46 class SummaryController(BaseController):
47
47
48 @LoginRequired()
48 @LoginRequired()
49 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
49 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
50 'repository.admin')
50 'repository.admin')
51 def __before__(self):
51 def __before__(self):
52 super(SummaryController, self).__before__()
52 super(SummaryController, self).__before__()
53
53
54 def index(self):
54 def index(self):
55 hg_model = ScmModel()
55 scm_model = ScmModel()
56 c.repo_info = hg_model.get_repo(c.repo_name)
56 c.repo_info = scm_model.get_repo(c.repo_name)
57 c.following = scm_model.is_following_repo(c.repo_name,
58 c.rhodecode_user.user_id)
57 def url_generator(**kw):
59 def url_generator(**kw):
58 return url('shortlog_home', repo_name=c.repo_name, **kw)
60 return url('shortlog_home', repo_name=c.repo_name, **kw)
59
61
60 c.repo_changesets = Page(c.repo_info, page=1, items_per_page=10,
62 c.repo_changesets = Page(c.repo_info, page=1, items_per_page=10,
61 url=url_generator)
63 url=url_generator)
62
64
63 e = request.environ
65 e = request.environ
64
66
65 if self.rhodecode_user.username == 'default':
67 if self.rhodecode_user.username == 'default':
66 password = ':default'
68 password = ':default'
67 else:
69 else:
68 password = ''
70 password = ''
69
71
70 uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
72 uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
71 'protocol': e.get('wsgi.url_scheme'),
73 'protocol': e.get('wsgi.url_scheme'),
72 'user':str(c.rhodecode_user.username),
74 'user':str(c.rhodecode_user.username),
73 'password':password,
75 'password':password,
74 'host':e.get('HTTP_HOST'),
76 'host':e.get('HTTP_HOST'),
75 'prefix':e.get('SCRIPT_NAME'),
77 'prefix':e.get('SCRIPT_NAME'),
76 'repo_name':c.repo_name, }
78 'repo_name':c.repo_name, }
77 c.clone_repo_url = uri
79 c.clone_repo_url = uri
78 c.repo_tags = OrderedDict()
80 c.repo_tags = OrderedDict()
79 for name, hash in c.repo_info.tags.items()[:10]:
81 for name, hash in c.repo_info.tags.items()[:10]:
80 try:
82 try:
81 c.repo_tags[name] = c.repo_info.get_changeset(hash)
83 c.repo_tags[name] = c.repo_info.get_changeset(hash)
82 except ChangesetError:
84 except ChangesetError:
83 c.repo_tags[name] = EmptyChangeset(hash)
85 c.repo_tags[name] = EmptyChangeset(hash)
84
86
85 c.repo_branches = OrderedDict()
87 c.repo_branches = OrderedDict()
86 for name, hash in c.repo_info.branches.items()[:10]:
88 for name, hash in c.repo_info.branches.items()[:10]:
87 try:
89 try:
88 c.repo_branches[name] = c.repo_info.get_changeset(hash)
90 c.repo_branches[name] = c.repo_info.get_changeset(hash)
89 except ChangesetError:
91 except ChangesetError:
90 c.repo_branches[name] = EmptyChangeset(hash)
92 c.repo_branches[name] = EmptyChangeset(hash)
91
93
92 td = datetime.today() + timedelta(days=1)
94 td = datetime.today() + timedelta(days=1)
93 y, m, d = td.year, td.month, td.day
95 y, m, d = td.year, td.month, td.day
94
96
95 ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
97 ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
96 d, 0, 0, 0, 0, 0, 0,))
98 d, 0, 0, 0, 0, 0, 0,))
97 ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
99 ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
98 d, 0, 0, 0, 0, 0, 0,))
100 d, 0, 0, 0, 0, 0, 0,))
99
101
100 ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
102 ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
101
103
102 run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
104 run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
103 c.ts_min = ts_min_m
105 c.ts_min = ts_min_m
104 c.ts_max = ts_max_y
106 c.ts_max = ts_max_y
105
107
106 stats = self.sa.query(Statistics)\
108 stats = self.sa.query(Statistics)\
107 .filter(Statistics.repository == c.repo_info.dbrepo)\
109 .filter(Statistics.repository == c.repo_info.dbrepo)\
108 .scalar()
110 .scalar()
109
111
110
112
111 if stats and stats.languages:
113 if stats and stats.languages:
112 lang_stats = json.loads(stats.languages)
114 lang_stats = json.loads(stats.languages)
113 c.commit_data = stats.commit_activity
115 c.commit_data = stats.commit_activity
114 c.overview_data = stats.commit_activity_combined
116 c.overview_data = stats.commit_activity_combined
115 c.trending_languages = json.dumps(OrderedDict(
117 c.trending_languages = json.dumps(OrderedDict(
116 sorted(lang_stats.items(), reverse=True,
118 sorted(lang_stats.items(), reverse=True,
117 key=lambda k: k[1])[:2]
119 key=lambda k: k[1])[:2]
118 )
120 )
119 )
121 )
120 else:
122 else:
121 c.commit_data = json.dumps({})
123 c.commit_data = json.dumps({})
122 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 0] ])
124 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 0] ])
123 c.trending_languages = json.dumps({})
125 c.trending_languages = json.dumps({})
124
126
125 return render('summary/summary.html')
127 return render('summary/summary.html')
126
128
@@ -1,488 +1,508 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
7 import hashlib
6 from pygments.formatters import HtmlFormatter
8 from pygments.formatters import HtmlFormatter
7 from pygments import highlight as code_highlight
9 from pygments import highlight as code_highlight
8 from pylons import url, app_globals as g
10 from pylons import url, app_globals as g
9 from pylons.i18n.translation import _, ungettext
11 from pylons.i18n.translation import _, ungettext
10 from vcs.utils.annotate import annotate_highlight
12 from vcs.utils.annotate import annotate_highlight
11 from webhelpers.html import literal, HTML, escape
13 from webhelpers.html import literal, HTML, escape
12 from webhelpers.html.tools import *
14 from webhelpers.html.tools import *
13 from webhelpers.html.builder import make_tag
15 from webhelpers.html.builder import make_tag
14 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
16 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
15 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
17 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
16 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
18 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
17 password, textarea, title, ul, xml_declaration, radio
19 password, textarea, title, ul, xml_declaration, radio
18 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
20 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
19 mail_to, strip_links, strip_tags, tag_re
21 mail_to, strip_links, strip_tags, tag_re
20 from webhelpers.number import format_byte_size, format_bit_size
22 from webhelpers.number import format_byte_size, format_bit_size
21 from webhelpers.pylonslib import Flash as _Flash
23 from webhelpers.pylonslib import Flash as _Flash
22 from webhelpers.pylonslib.secure_form import secure_form
24 from webhelpers.pylonslib.secure_form import secure_form
23 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
25 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
24 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
26 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
25 replace_whitespace, urlify, truncate, wrap_paragraphs
27 replace_whitespace, urlify, truncate, wrap_paragraphs
26 from webhelpers.date import time_ago_in_words
28 from webhelpers.date import time_ago_in_words
27
29
28 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
30 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
29 convert_boolean_attrs, NotGiven
31 convert_boolean_attrs, NotGiven
30
32
31 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
33 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
32 _set_input_attrs(attrs, type, name, value)
34 _set_input_attrs(attrs, type, name, value)
33 _set_id_attr(attrs, id, name)
35 _set_id_attr(attrs, id, name)
34 convert_boolean_attrs(attrs, ["disabled"])
36 convert_boolean_attrs(attrs, ["disabled"])
35 return HTML.input(**attrs)
37 return HTML.input(**attrs)
36
38
37 reset = _reset
39 reset = _reset
38
40
41
42 def get_token():
43 """Return the current authentication token, creating one if one doesn't
44 already exist.
45 """
46 token_key = "_authentication_token"
47 from pylons import session
48 if not token_key in session:
49 try:
50 token = hashlib.sha1(str(random.getrandbits(128))).hexdigest()
51 except AttributeError: # Python < 2.4
52 token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest()
53 session[token_key] = token
54 if hasattr(session, 'save'):
55 session.save()
56 return session[token_key]
57
58
39 #Custom helpers here :)
59 #Custom helpers here :)
40 class _Link(object):
60 class _Link(object):
41 '''
61 '''
42 Make a url based on label and url with help of url_for
62 Make a url based on label and url with help of url_for
43 :param label:name of link if not defined url is used
63 :param label:name of link if not defined url is used
44 :param url: the url for link
64 :param url: the url for link
45 '''
65 '''
46
66
47 def __call__(self, label='', *url_, **urlargs):
67 def __call__(self, label='', *url_, **urlargs):
48 if label is None or '':
68 if label is None or '':
49 label = url
69 label = url
50 link_fn = link_to(label, url(*url_, **urlargs))
70 link_fn = link_to(label, url(*url_, **urlargs))
51 return link_fn
71 return link_fn
52
72
53 link = _Link()
73 link = _Link()
54
74
55 class _GetError(object):
75 class _GetError(object):
56
76
57 def __call__(self, field_name, form_errors):
77 def __call__(self, field_name, form_errors):
58 tmpl = """<span class="error_msg">%s</span>"""
78 tmpl = """<span class="error_msg">%s</span>"""
59 if form_errors and form_errors.has_key(field_name):
79 if form_errors and form_errors.has_key(field_name):
60 return literal(tmpl % form_errors.get(field_name))
80 return literal(tmpl % form_errors.get(field_name))
61
81
62 get_error = _GetError()
82 get_error = _GetError()
63
83
64 def recursive_replace(str, replace=' '):
84 def recursive_replace(str, replace=' '):
65 """
85 """
66 Recursive replace of given sign to just one instance
86 Recursive replace of given sign to just one instance
67 :param str: given string
87 :param str: given string
68 :param replace:char to find and replace multiple instances
88 :param replace:char to find and replace multiple instances
69
89
70 Examples::
90 Examples::
71 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
91 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
72 'Mighty-Mighty-Bo-sstones'
92 'Mighty-Mighty-Bo-sstones'
73 """
93 """
74
94
75 if str.find(replace * 2) == -1:
95 if str.find(replace * 2) == -1:
76 return str
96 return str
77 else:
97 else:
78 str = str.replace(replace * 2, replace)
98 str = str.replace(replace * 2, replace)
79 return recursive_replace(str, replace)
99 return recursive_replace(str, replace)
80
100
81 class _ToolTip(object):
101 class _ToolTip(object):
82
102
83 def __call__(self, tooltip_title, trim_at=50):
103 def __call__(self, tooltip_title, trim_at=50):
84 """
104 """
85 Special function just to wrap our text into nice formatted autowrapped
105 Special function just to wrap our text into nice formatted autowrapped
86 text
106 text
87 :param tooltip_title:
107 :param tooltip_title:
88 """
108 """
89
109
90 return wrap_paragraphs(escape(tooltip_title), trim_at)\
110 return wrap_paragraphs(escape(tooltip_title), trim_at)\
91 .replace('\n', '<br/>')
111 .replace('\n', '<br/>')
92
112
93 def activate(self):
113 def activate(self):
94 """
114 """
95 Adds tooltip mechanism to the given Html all tooltips have to have
115 Adds tooltip mechanism to the given Html all tooltips have to have
96 set class tooltip and set attribute tooltip_title.
116 set class tooltip and set attribute tooltip_title.
97 Then a tooltip will be generated based on that
117 Then a tooltip will be generated based on that
98 All with yui js tooltip
118 All with yui js tooltip
99 """
119 """
100
120
101 js = '''
121 js = '''
102 YAHOO.util.Event.onDOMReady(function(){
122 YAHOO.util.Event.onDOMReady(function(){
103 function toolTipsId(){
123 function toolTipsId(){
104 var ids = [];
124 var ids = [];
105 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
125 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
106
126
107 for (var i = 0; i < tts.length; i++) {
127 for (var i = 0; i < tts.length; i++) {
108 //if element doesn't not have and id autgenerate one for tooltip
128 //if element doesn't not have and id autgenerate one for tooltip
109
129
110 if (!tts[i].id){
130 if (!tts[i].id){
111 tts[i].id='tt'+i*100;
131 tts[i].id='tt'+i*100;
112 }
132 }
113 ids.push(tts[i].id);
133 ids.push(tts[i].id);
114 }
134 }
115 return ids
135 return ids
116 };
136 };
117 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
137 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
118 context: toolTipsId(),
138 context: toolTipsId(),
119 monitorresize:false,
139 monitorresize:false,
120 xyoffset :[0,0],
140 xyoffset :[0,0],
121 autodismissdelay:300000,
141 autodismissdelay:300000,
122 hidedelay:5,
142 hidedelay:5,
123 showdelay:20,
143 showdelay:20,
124 });
144 });
125
145
126 //Mouse Over event disabled for new repositories since they don't
146 //Mouse Over event disabled for new repositories since they don't
127 //have last commit message
147 //have last commit message
128 myToolTips.contextMouseOverEvent.subscribe(
148 myToolTips.contextMouseOverEvent.subscribe(
129 function(type, args) {
149 function(type, args) {
130 var context = args[0];
150 var context = args[0];
131 var txt = context.getAttribute('tooltip_title');
151 var txt = context.getAttribute('tooltip_title');
132 if(txt){
152 if(txt){
133 return true;
153 return true;
134 }
154 }
135 else{
155 else{
136 return false;
156 return false;
137 }
157 }
138 });
158 });
139
159
140
160
141 // Set the text for the tooltip just before we display it. Lazy method
161 // Set the text for the tooltip just before we display it. Lazy method
142 myToolTips.contextTriggerEvent.subscribe(
162 myToolTips.contextTriggerEvent.subscribe(
143 function(type, args) {
163 function(type, args) {
144
164
145
165
146 var context = args[0];
166 var context = args[0];
147
167
148 var txt = context.getAttribute('tooltip_title');
168 var txt = context.getAttribute('tooltip_title');
149 this.cfg.setProperty("text", txt);
169 this.cfg.setProperty("text", txt);
150
170
151
171
152 // positioning of tooltip
172 // positioning of tooltip
153 var tt_w = this.element.clientWidth;
173 var tt_w = this.element.clientWidth;
154 var tt_h = this.element.clientHeight;
174 var tt_h = this.element.clientHeight;
155
175
156 var context_w = context.offsetWidth;
176 var context_w = context.offsetWidth;
157 var context_h = context.offsetHeight;
177 var context_h = context.offsetHeight;
158
178
159 var pos_x = YAHOO.util.Dom.getX(context);
179 var pos_x = YAHOO.util.Dom.getX(context);
160 var pos_y = YAHOO.util.Dom.getY(context);
180 var pos_y = YAHOO.util.Dom.getY(context);
161
181
162 var display_strategy = 'top';
182 var display_strategy = 'top';
163 var xy_pos = [0,0];
183 var xy_pos = [0,0];
164 switch (display_strategy){
184 switch (display_strategy){
165
185
166 case 'top':
186 case 'top':
167 var cur_x = (pos_x+context_w/2)-(tt_w/2);
187 var cur_x = (pos_x+context_w/2)-(tt_w/2);
168 var cur_y = pos_y-tt_h-4;
188 var cur_y = pos_y-tt_h-4;
169 xy_pos = [cur_x,cur_y];
189 xy_pos = [cur_x,cur_y];
170 break;
190 break;
171 case 'bottom':
191 case 'bottom':
172 var cur_x = (pos_x+context_w/2)-(tt_w/2);
192 var cur_x = (pos_x+context_w/2)-(tt_w/2);
173 var cur_y = pos_y+context_h+4;
193 var cur_y = pos_y+context_h+4;
174 xy_pos = [cur_x,cur_y];
194 xy_pos = [cur_x,cur_y];
175 break;
195 break;
176 case 'left':
196 case 'left':
177 var cur_x = (pos_x-tt_w-4);
197 var cur_x = (pos_x-tt_w-4);
178 var cur_y = pos_y-((tt_h/2)-context_h/2);
198 var cur_y = pos_y-((tt_h/2)-context_h/2);
179 xy_pos = [cur_x,cur_y];
199 xy_pos = [cur_x,cur_y];
180 break;
200 break;
181 case 'right':
201 case 'right':
182 var cur_x = (pos_x+context_w+4);
202 var cur_x = (pos_x+context_w+4);
183 var cur_y = pos_y-((tt_h/2)-context_h/2);
203 var cur_y = pos_y-((tt_h/2)-context_h/2);
184 xy_pos = [cur_x,cur_y];
204 xy_pos = [cur_x,cur_y];
185 break;
205 break;
186 default:
206 default:
187 var cur_x = (pos_x+context_w/2)-(tt_w/2);
207 var cur_x = (pos_x+context_w/2)-(tt_w/2);
188 var cur_y = pos_y-tt_h-4;
208 var cur_y = pos_y-tt_h-4;
189 xy_pos = [cur_x,cur_y];
209 xy_pos = [cur_x,cur_y];
190 break;
210 break;
191
211
192 }
212 }
193
213
194 this.cfg.setProperty("xy",xy_pos);
214 this.cfg.setProperty("xy",xy_pos);
195
215
196 });
216 });
197
217
198 //Mouse out
218 //Mouse out
199 myToolTips.contextMouseOutEvent.subscribe(
219 myToolTips.contextMouseOutEvent.subscribe(
200 function(type, args) {
220 function(type, args) {
201 var context = args[0];
221 var context = args[0];
202
222
203 });
223 });
204 });
224 });
205 '''
225 '''
206 return literal(js)
226 return literal(js)
207
227
208 tooltip = _ToolTip()
228 tooltip = _ToolTip()
209
229
210 class _FilesBreadCrumbs(object):
230 class _FilesBreadCrumbs(object):
211
231
212 def __call__(self, repo_name, rev, paths):
232 def __call__(self, repo_name, rev, paths):
213 url_l = [link_to(repo_name, url('files_home',
233 url_l = [link_to(repo_name, url('files_home',
214 repo_name=repo_name,
234 repo_name=repo_name,
215 revision=rev, f_path=''))]
235 revision=rev, f_path=''))]
216 paths_l = paths.split('/')
236 paths_l = paths.split('/')
217
237
218 for cnt, p in enumerate(paths_l, 1):
238 for cnt, p in enumerate(paths_l, 1):
219 if p != '':
239 if p != '':
220 url_l.append(link_to(p, url('files_home',
240 url_l.append(link_to(p, url('files_home',
221 repo_name=repo_name,
241 repo_name=repo_name,
222 revision=rev,
242 revision=rev,
223 f_path='/'.join(paths_l[:cnt]))))
243 f_path='/'.join(paths_l[:cnt]))))
224
244
225 return literal('/'.join(url_l))
245 return literal('/'.join(url_l))
226
246
227 files_breadcrumbs = _FilesBreadCrumbs()
247 files_breadcrumbs = _FilesBreadCrumbs()
228 class CodeHtmlFormatter(HtmlFormatter):
248 class CodeHtmlFormatter(HtmlFormatter):
229
249
230 def wrap(self, source, outfile):
250 def wrap(self, source, outfile):
231 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
251 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
232
252
233 def _wrap_code(self, source):
253 def _wrap_code(self, source):
234 for cnt, it in enumerate(source, 1):
254 for cnt, it in enumerate(source, 1):
235 i, t = it
255 i, t = it
236 t = '<div id="#S-%s">%s</div>' % (cnt, t)
256 t = '<div id="#S-%s">%s</div>' % (cnt, t)
237 yield i, t
257 yield i, t
238 def pygmentize(filenode, **kwargs):
258 def pygmentize(filenode, **kwargs):
239 """
259 """
240 pygmentize function using pygments
260 pygmentize function using pygments
241 :param filenode:
261 :param filenode:
242 """
262 """
243 return literal(code_highlight(filenode.content,
263 return literal(code_highlight(filenode.content,
244 filenode.lexer, CodeHtmlFormatter(**kwargs)))
264 filenode.lexer, CodeHtmlFormatter(**kwargs)))
245
265
246 def pygmentize_annotation(filenode, **kwargs):
266 def pygmentize_annotation(filenode, **kwargs):
247 """
267 """
248 pygmentize function for annotation
268 pygmentize function for annotation
249 :param filenode:
269 :param filenode:
250 """
270 """
251
271
252 color_dict = {}
272 color_dict = {}
253 def gen_color():
273 def gen_color():
254 """generator for getting 10k of evenly distibuted colors using hsv color
274 """generator for getting 10k of evenly distibuted colors using hsv color
255 and golden ratio.
275 and golden ratio.
256 """
276 """
257 import colorsys
277 import colorsys
258 n = 10000
278 n = 10000
259 golden_ratio = 0.618033988749895
279 golden_ratio = 0.618033988749895
260 h = 0.22717784590367374
280 h = 0.22717784590367374
261 #generate 10k nice web friendly colors in the same order
281 #generate 10k nice web friendly colors in the same order
262 for c in xrange(n):
282 for c in xrange(n):
263 h += golden_ratio
283 h += golden_ratio
264 h %= 1
284 h %= 1
265 HSV_tuple = [h, 0.95, 0.95]
285 HSV_tuple = [h, 0.95, 0.95]
266 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
286 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
267 yield map(lambda x:str(int(x * 256)), RGB_tuple)
287 yield map(lambda x:str(int(x * 256)), RGB_tuple)
268
288
269 cgenerator = gen_color()
289 cgenerator = gen_color()
270
290
271 def get_color_string(cs):
291 def get_color_string(cs):
272 if color_dict.has_key(cs):
292 if color_dict.has_key(cs):
273 col = color_dict[cs]
293 col = color_dict[cs]
274 else:
294 else:
275 col = color_dict[cs] = cgenerator.next()
295 col = color_dict[cs] = cgenerator.next()
276 return "color: rgb(%s)! important;" % (', '.join(col))
296 return "color: rgb(%s)! important;" % (', '.join(col))
277
297
278 def url_func(changeset):
298 def url_func(changeset):
279 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
299 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
280 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
300 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
281
301
282 tooltip_html = tooltip_html % (changeset.author,
302 tooltip_html = tooltip_html % (changeset.author,
283 changeset.date,
303 changeset.date,
284 tooltip(changeset.message))
304 tooltip(changeset.message))
285 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
305 lnk_format = '%5s:%s' % ('r%s' % changeset.revision,
286 short_id(changeset.raw_id))
306 short_id(changeset.raw_id))
287 uri = link_to(
307 uri = link_to(
288 lnk_format,
308 lnk_format,
289 url('changeset_home', repo_name=changeset.repository.name,
309 url('changeset_home', repo_name=changeset.repository.name,
290 revision=changeset.raw_id),
310 revision=changeset.raw_id),
291 style=get_color_string(changeset.raw_id),
311 style=get_color_string(changeset.raw_id),
292 class_='tooltip',
312 class_='tooltip',
293 tooltip_title=tooltip_html
313 tooltip_title=tooltip_html
294 )
314 )
295
315
296 uri += '\n'
316 uri += '\n'
297 return uri
317 return uri
298 return literal(annotate_highlight(filenode, url_func, **kwargs))
318 return literal(annotate_highlight(filenode, url_func, **kwargs))
299
319
300 def repo_name_slug(value):
320 def repo_name_slug(value):
301 """Return slug of name of repository
321 """Return slug of name of repository
302 This function is called on each creation/modification
322 This function is called on each creation/modification
303 of repository to prevent bad names in repo
323 of repository to prevent bad names in repo
304 """
324 """
305 slug = remove_formatting(value)
325 slug = remove_formatting(value)
306 slug = strip_tags(slug)
326 slug = strip_tags(slug)
307
327
308 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
328 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
309 slug = slug.replace(c, '-')
329 slug = slug.replace(c, '-')
310 slug = recursive_replace(slug, '-')
330 slug = recursive_replace(slug, '-')
311 slug = collapse(slug, '-')
331 slug = collapse(slug, '-')
312 return slug
332 return slug
313
333
314 def get_changeset_safe(repo, rev):
334 def get_changeset_safe(repo, rev):
315 from vcs.backends.base import BaseRepository
335 from vcs.backends.base import BaseRepository
316 from vcs.exceptions import RepositoryError
336 from vcs.exceptions import RepositoryError
317 if not isinstance(repo, BaseRepository):
337 if not isinstance(repo, BaseRepository):
318 raise Exception('You must pass an Repository '
338 raise Exception('You must pass an Repository '
319 'object as first argument got %s', type(repo))
339 'object as first argument got %s', type(repo))
320
340
321 try:
341 try:
322 cs = repo.get_changeset(rev)
342 cs = repo.get_changeset(rev)
323 except RepositoryError:
343 except RepositoryError:
324 from rhodecode.lib.utils import EmptyChangeset
344 from rhodecode.lib.utils import EmptyChangeset
325 cs = EmptyChangeset()
345 cs = EmptyChangeset()
326 return cs
346 return cs
327
347
328
348
329 flash = _Flash()
349 flash = _Flash()
330
350
331
351
332 #==============================================================================
352 #==============================================================================
333 # MERCURIAL FILTERS available via h.
353 # MERCURIAL FILTERS available via h.
334 #==============================================================================
354 #==============================================================================
335 from mercurial import util
355 from mercurial import util
336 from mercurial.templatefilters import person as _person
356 from mercurial.templatefilters import person as _person
337
357
338
358
339
359
340 def _age(curdate):
360 def _age(curdate):
341 """turns a datetime into an age string."""
361 """turns a datetime into an age string."""
342
362
343 if not curdate:
363 if not curdate:
344 return ''
364 return ''
345
365
346 from datetime import timedelta, datetime
366 from datetime import timedelta, datetime
347
367
348 agescales = [("year", 3600 * 24 * 365),
368 agescales = [("year", 3600 * 24 * 365),
349 ("month", 3600 * 24 * 30),
369 ("month", 3600 * 24 * 30),
350 ("day", 3600 * 24),
370 ("day", 3600 * 24),
351 ("hour", 3600),
371 ("hour", 3600),
352 ("minute", 60),
372 ("minute", 60),
353 ("second", 1), ]
373 ("second", 1), ]
354
374
355 age = datetime.now() - curdate
375 age = datetime.now() - curdate
356 age_seconds = (age.days * agescales[2][1]) + age.seconds
376 age_seconds = (age.days * agescales[2][1]) + age.seconds
357 pos = 1
377 pos = 1
358 for scale in agescales:
378 for scale in agescales:
359 if scale[1] <= age_seconds:
379 if scale[1] <= age_seconds:
360 if pos == 6:pos = 5
380 if pos == 6:pos = 5
361 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
381 return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
362 pos += 1
382 pos += 1
363
383
364 return _('just now')
384 return _('just now')
365
385
366 age = lambda x:_age(x)
386 age = lambda x:_age(x)
367 capitalize = lambda x: x.capitalize()
387 capitalize = lambda x: x.capitalize()
368 email = util.email
388 email = util.email
369 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
389 email_or_none = lambda x: util.email(x) if util.email(x) != x else None
370 person = lambda x: _person(x)
390 person = lambda x: _person(x)
371 short_id = lambda x: x[:12]
391 short_id = lambda x: x[:12]
372
392
373
393
374 def bool2icon(value):
394 def bool2icon(value):
375 """
395 """
376 Returns True/False values represented as small html image of true/false
396 Returns True/False values represented as small html image of true/false
377 icons
397 icons
378 :param value: bool value
398 :param value: bool value
379 """
399 """
380
400
381 if value is True:
401 if value is True:
382 return HTML.tag('img', src="/images/icons/accept.png", alt=_('True'))
402 return HTML.tag('img', src="/images/icons/accept.png", alt=_('True'))
383
403
384 if value is False:
404 if value is False:
385 return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False'))
405 return HTML.tag('img', src="/images/icons/cancel.png", alt=_('False'))
386
406
387 return value
407 return value
388
408
389
409
390 def action_parser(user_log):
410 def action_parser(user_log):
391 """
411 """
392 This helper will map the specified string action into translated
412 This helper will map the specified string action into translated
393 fancy names with icons and links
413 fancy names with icons and links
394
414
395 @param action:
415 @param action:
396 """
416 """
397 action = user_log.action
417 action = user_log.action
398 action_params = None
418 action_params = None
399
419
400 x = action.split(':')
420 x = action.split(':')
401
421
402 if len(x) > 1:
422 if len(x) > 1:
403 action, action_params = x
423 action, action_params = x
404
424
405 def get_cs_links():
425 def get_cs_links():
406 if action == 'push':
426 if action == 'push':
407 revs_limit = 5
427 revs_limit = 5
408 revs = action_params.split(',')
428 revs = action_params.split(',')
409 cs_links = " " + ', '.join ([link(rev,
429 cs_links = " " + ', '.join ([link(rev,
410 url('changeset_home',
430 url('changeset_home',
411 repo_name=user_log.repository.repo_name,
431 repo_name=user_log.repository.repo_name,
412 revision=rev)) for rev in revs[:revs_limit] ])
432 revision=rev)) for rev in revs[:revs_limit] ])
413 if len(revs) > revs_limit:
433 if len(revs) > revs_limit:
414 html_tmpl = '<span title="%s"> %s </span>'
434 html_tmpl = '<span title="%s"> %s </span>'
415 cs_links += html_tmpl % (', '.join(r for r in revs[revs_limit:]),
435 cs_links += html_tmpl % (', '.join(r for r in revs[revs_limit:]),
416 _('and %s more revisions') \
436 _('and %s more revisions') \
417 % (len(revs) - revs_limit))
437 % (len(revs) - revs_limit))
418
438
419 return literal(cs_links)
439 return literal(cs_links)
420 return ''
440 return ''
421
441
422 def get_fork_name():
442 def get_fork_name():
423 if action == 'user_forked_repo':
443 if action == 'user_forked_repo':
424 from rhodecode.model.scm import ScmModel
444 from rhodecode.model.scm import ScmModel
425 repo_name = action_params
445 repo_name = action_params
426 repo = ScmModel().get(repo_name)
446 repo = ScmModel().get(repo_name)
427 if repo is None:
447 if repo is None:
428 return repo_name
448 return repo_name
429 return link_to(action_params, url('summary_home',
449 return link_to(action_params, url('summary_home',
430 repo_name=repo.name,),
450 repo_name=repo.name,),
431 title=repo.dbrepo.description)
451 title=repo.dbrepo.description)
432 return ''
452 return ''
433 map = {'user_deleted_repo':_('User deleted repository'),
453 map = {'user_deleted_repo':_('User deleted repository'),
434 'user_created_repo':_('User created repository'),
454 'user_created_repo':_('User created repository'),
435 'user_forked_repo':_('User forked repository as: ') + get_fork_name(),
455 'user_forked_repo':_('User forked repository as: ') + get_fork_name(),
436 'user_updated_repo':_('User updated repository'),
456 'user_updated_repo':_('User updated repository'),
437 'admin_deleted_repo':_('Admin delete repository'),
457 'admin_deleted_repo':_('Admin delete repository'),
438 'admin_created_repo':_('Admin created repository'),
458 'admin_created_repo':_('Admin created repository'),
439 'admin_forked_repo':_('Admin forked repository'),
459 'admin_forked_repo':_('Admin forked repository'),
440 'admin_updated_repo':_('Admin updated repository'),
460 'admin_updated_repo':_('Admin updated repository'),
441 'push':_('Pushed') + get_cs_links(),
461 'push':_('Pushed') + get_cs_links(),
442 'pull':_('Pulled'), }
462 'pull':_('Pulled'), }
443
463
444 return map.get(action, action)
464 return map.get(action, action)
445
465
446
466
447 #==============================================================================
467 #==============================================================================
448 # PERMS
468 # PERMS
449 #==============================================================================
469 #==============================================================================
450 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
470 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
451 HasRepoPermissionAny, HasRepoPermissionAll
471 HasRepoPermissionAny, HasRepoPermissionAll
452
472
453 #==============================================================================
473 #==============================================================================
454 # GRAVATAR URL
474 # GRAVATAR URL
455 #==============================================================================
475 #==============================================================================
456 import hashlib
476 import hashlib
457 import urllib
477 import urllib
458 from pylons import request
478 from pylons import request
459
479
460 def gravatar_url(email_address, size=30):
480 def gravatar_url(email_address, size=30):
461 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
481 ssl_enabled = 'https' == request.environ.get('HTTP_X_URL_SCHEME')
462 default = 'identicon'
482 default = 'identicon'
463 baseurl_nossl = "http://www.gravatar.com/avatar/"
483 baseurl_nossl = "http://www.gravatar.com/avatar/"
464 baseurl_ssl = "https://secure.gravatar.com/avatar/"
484 baseurl_ssl = "https://secure.gravatar.com/avatar/"
465 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
485 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
466
486
467
487
468 # construct the url
488 # construct the url
469 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
489 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
470 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
490 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
471
491
472 return gravatar_url
492 return gravatar_url
473
493
474 def safe_unicode(str):
494 def safe_unicode(str):
475 """safe unicode function. In case of UnicodeDecode error we try to return
495 """safe unicode function. In case of UnicodeDecode error we try to return
476 unicode with errors replace, if this failes we return unicode with
496 unicode with errors replace, if this failes we return unicode with
477 string_escape decoding """
497 string_escape decoding """
478
498
479 try:
499 try:
480 u_str = unicode(str)
500 u_str = unicode(str)
481 except UnicodeDecodeError:
501 except UnicodeDecodeError:
482 try:
502 try:
483 u_str = unicode(str, 'utf-8', 'replace')
503 u_str = unicode(str, 'utf-8', 'replace')
484 except UnicodeDecodeError:
504 except UnicodeDecodeError:
485 #incase we have a decode error just represent as byte string
505 #incase we have a decode error just represent as byte string
486 u_str = unicode(str(str).encode('string_escape'))
506 u_str = unicode(str(str).encode('string_escape'))
487
507
488 return u_str
508 return u_str
@@ -1,166 +1,187 b''
1 from rhodecode.model.meta import Base
1 from rhodecode.model.meta import Base
2 from sqlalchemy import *
2 from sqlalchemy import *
3 from sqlalchemy.orm import relation, backref
3 from sqlalchemy.orm import relation, backref
4 from sqlalchemy.orm.session import Session
4 from sqlalchemy.orm.session import Session
5 from vcs.utils.lazy import LazyProperty
5 from vcs.utils.lazy import LazyProperty
6 import logging
6 import logging
7 log = logging.getLogger(__name__)
7 log = logging.getLogger(__name__)
8
8
9 class RhodeCodeSettings(Base):
9 class RhodeCodeSettings(Base):
10 __tablename__ = 'rhodecode_settings'
10 __tablename__ = 'rhodecode_settings'
11 __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
11 __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
12 app_settings_id = Column("app_settings_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
12 app_settings_id = Column("app_settings_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
13 app_settings_name = Column("app_settings_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
13 app_settings_name = Column("app_settings_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
14 app_settings_value = Column("app_settings_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
14 app_settings_value = Column("app_settings_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
15
15
16 def __init__(self, k, v):
16 def __init__(self, k, v):
17 self.app_settings_name = k
17 self.app_settings_name = k
18 self.app_settings_value = v
18 self.app_settings_value = v
19
19
20 def __repr__(self):
20 def __repr__(self):
21 return "<RhodeCodeSetting('%s:%s')>" % (self.app_settings_name,
21 return "<RhodeCodeSetting('%s:%s')>" % (self.app_settings_name,
22 self.app_settings_value)
22 self.app_settings_value)
23
23
24 class RhodeCodeUi(Base):
24 class RhodeCodeUi(Base):
25 __tablename__ = 'rhodecode_ui'
25 __tablename__ = 'rhodecode_ui'
26 __table_args__ = {'useexisting':True}
26 __table_args__ = {'useexisting':True}
27 ui_id = Column("ui_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
27 ui_id = Column("ui_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
28 ui_section = Column("ui_section", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
28 ui_section = Column("ui_section", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
29 ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
29 ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
30 ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
30 ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
31 ui_active = Column("ui_active", BOOLEAN(), nullable=True, unique=None, default=True)
31 ui_active = Column("ui_active", BOOLEAN(), nullable=True, unique=None, default=True)
32
32
33
33
34 class User(Base):
34 class User(Base):
35 __tablename__ = 'users'
35 __tablename__ = 'users'
36 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
36 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
37 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
37 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
38 username = Column("username", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
38 username = Column("username", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
39 password = Column("password", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
39 password = Column("password", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
40 active = Column("active", BOOLEAN(), nullable=True, unique=None, default=None)
40 active = Column("active", BOOLEAN(), nullable=True, unique=None, default=None)
41 admin = Column("admin", BOOLEAN(), nullable=True, unique=None, default=False)
41 admin = Column("admin", BOOLEAN(), nullable=True, unique=None, default=False)
42 name = Column("name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
42 name = Column("name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
43 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
43 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
44 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
44 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
45 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
45 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
46 is_ldap = Column("is_ldap", BOOLEAN(), nullable=False, unique=None, default=False)
46 is_ldap = Column("is_ldap", BOOLEAN(), nullable=False, unique=None, default=False)
47
47
48 user_log = relation('UserLog', cascade='all')
48 user_log = relation('UserLog', cascade='all')
49 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
49 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
50
50
51 repositories = relation('Repository')
51 repositories = relation('Repository')
52 user_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
52
53
53 @LazyProperty
54 @LazyProperty
54 def full_contact(self):
55 def full_contact(self):
55 return '%s %s <%s>' % (self.name, self.lastname, self.email)
56 return '%s %s <%s>' % (self.name, self.lastname, self.email)
56
57
57 def __repr__(self):
58 def __repr__(self):
58 return "<User('id:%s:%s')>" % (self.user_id, self.username)
59 return "<User('id:%s:%s')>" % (self.user_id, self.username)
59
60
60 def update_lastlogin(self):
61 def update_lastlogin(self):
61 """Update user lastlogin"""
62 """Update user lastlogin"""
62 import datetime
63 import datetime
63
64
64 try:
65 try:
65 session = Session.object_session(self)
66 session = Session.object_session(self)
66 self.last_login = datetime.datetime.now()
67 self.last_login = datetime.datetime.now()
67 session.add(self)
68 session.add(self)
68 session.commit()
69 session.commit()
69 log.debug('updated user %s lastlogin', self.username)
70 log.debug('updated user %s lastlogin', self.username)
70 except Exception:
71 except Exception:
71 session.rollback()
72 session.rollback()
72
73
73
74
74 class UserLog(Base):
75 class UserLog(Base):
75 __tablename__ = 'user_logs'
76 __tablename__ = 'user_logs'
76 __table_args__ = {'useexisting':True}
77 __table_args__ = {'useexisting':True}
77 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
78 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
78 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
79 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
79 repository_id = Column("repository_id", INTEGER(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
80 repository_id = Column("repository_id", INTEGER(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
80 repository_name = Column("repository_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
81 repository_name = Column("repository_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
81 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
82 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
82 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
83 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
83 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
84 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
84
85
85 user = relation('User')
86 user = relation('User')
86 repository = relation('Repository')
87 repository = relation('Repository')
87
88
88 class Repository(Base):
89 class Repository(Base):
89 __tablename__ = 'repositories'
90 __tablename__ = 'repositories'
90 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
91 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
91 repo_id = Column("repo_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
92 repo_id = Column("repo_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
92 repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
93 repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
93 repo_type = Column("repo_type", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
94 repo_type = Column("repo_type", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
94 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
95 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
95 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
96 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
96 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
97 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
97 fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
98 fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
98
99
99 user = relation('User')
100 user = relation('User')
100 fork = relation('Repository', remote_side=repo_id)
101 fork = relation('Repository', remote_side=repo_id)
101 repo_to_perm = relation('RepoToPerm', cascade='all')
102 repo_to_perm = relation('RepoToPerm', cascade='all')
102 stats = relation('Statistics', cascade='all', uselist=False)
103 stats = relation('Statistics', cascade='all', uselist=False)
103
104
105 repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
106
107
104 def __repr__(self):
108 def __repr__(self):
105 return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
109 return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
106
110
107 class Permission(Base):
111 class Permission(Base):
108 __tablename__ = 'permissions'
112 __tablename__ = 'permissions'
109 __table_args__ = {'useexisting':True}
113 __table_args__ = {'useexisting':True}
110 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
114 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
111 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
115 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
112 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
116 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
113
117
114 def __repr__(self):
118 def __repr__(self):
115 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
119 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
116
120
117 class RepoToPerm(Base):
121 class RepoToPerm(Base):
118 __tablename__ = 'repo_to_perm'
122 __tablename__ = 'repo_to_perm'
119 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
123 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
120 repo_to_perm_id = Column("repo_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
124 repo_to_perm_id = Column("repo_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
121 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
125 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
122 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
126 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
123 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
127 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
124
128
125 user = relation('User')
129 user = relation('User')
126 permission = relation('Permission')
130 permission = relation('Permission')
127 repository = relation('Repository')
131 repository = relation('Repository')
128
132
129 class UserToPerm(Base):
133 class UserToPerm(Base):
130 __tablename__ = 'user_to_perm'
134 __tablename__ = 'user_to_perm'
131 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
135 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
132 user_to_perm_id = Column("user_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
136 user_to_perm_id = Column("user_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
133 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
137 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
134 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
138 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
135
139
136 user = relation('User')
140 user = relation('User')
137 permission = relation('Permission')
141 permission = relation('Permission')
138
142
139 class Statistics(Base):
143 class Statistics(Base):
140 __tablename__ = 'statistics'
144 __tablename__ = 'statistics'
141 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
145 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
142 stat_id = Column("stat_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
146 stat_id = Column("stat_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
143 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=True, default=None)
147 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=True, default=None)
144 stat_on_revision = Column("stat_on_revision", INTEGER(), nullable=False)
148 stat_on_revision = Column("stat_on_revision", INTEGER(), nullable=False)
145 commit_activity = Column("commit_activity", BLOB(), nullable=False)#JSON data
149 commit_activity = Column("commit_activity", BLOB(), nullable=False)#JSON data
146 commit_activity_combined = Column("commit_activity_combined", BLOB(), nullable=False)#JSON data
150 commit_activity_combined = Column("commit_activity_combined", BLOB(), nullable=False)#JSON data
147 languages = Column("languages", BLOB(), nullable=False)#JSON data
151 languages = Column("languages", BLOB(), nullable=False)#JSON data
148
152
149 repository = relation('Repository', single_parent=True)
153 repository = relation('Repository', single_parent=True)
150
154
155 class UserFollowing(Base):
156 __tablename__ = 'user_followings'
157 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
158 UniqueConstraint('user_id', 'follows_user_id')
159 , {'useexisting':True})
160
161 user_following_id = Column("user_following_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
162 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
163 follows_repo_id = Column("follows_repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=None, default=None)
164 follows_user_id = Column("follows_user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=True, unique=None, default=None)
165
166 user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
167
168 follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
169 follows_repository = relation('Repository')
170
171
151 class CacheInvalidation(Base):
172 class CacheInvalidation(Base):
152 __tablename__ = 'cache_invalidation'
173 __tablename__ = 'cache_invalidation'
153 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
174 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
154 cache_id = Column("cache_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
175 cache_id = Column("cache_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
155 cache_key = Column("cache_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
176 cache_key = Column("cache_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
156 cache_args = Column("cache_args", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
177 cache_args = Column("cache_args", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
157 cache_active = Column("cache_active", BOOLEAN(), nullable=True, unique=None, default=False)
178 cache_active = Column("cache_active", BOOLEAN(), nullable=True, unique=None, default=False)
158
179
159
180
160 def __init__(self, cache_key, cache_args=''):
181 def __init__(self, cache_key, cache_args=''):
161 self.cache_key = cache_key
182 self.cache_key = cache_key
162 self.cache_args = cache_args
183 self.cache_args = cache_args
163 self.cache_active = False
184 self.cache_active = False
164
185
165 def __repr__(self):
186 def __repr__(self):
166 return "<CacheInvaidation('%s:%s')>" % (self.cache_id, self.cache_key)
187 return "<CacheInvalidation('%s:%s')>" % (self.cache_id, self.cache_key)
@@ -1,254 +1,327 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Model for RhodeCode
3 # Model for RhodeCode
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 9, 2010
21 Created on April 9, 2010
22 Model for RhodeCode
22 Model for RhodeCode
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from beaker.cache import cache_region, region_invalidate
25 from beaker.cache import cache_region, region_invalidate
26 from mercurial import ui
26 from mercurial import ui
27 from rhodecode import BACKENDS
27 from rhodecode import BACKENDS
28 from rhodecode.lib import helpers as h
28 from rhodecode.lib import helpers as h
29 from rhodecode.lib.auth import HasRepoPermissionAny
29 from rhodecode.lib.auth import HasRepoPermissionAny
30 from rhodecode.lib.utils import get_repos, make_ui
30 from rhodecode.lib.utils import get_repos, make_ui
31 from rhodecode.model import meta
31 from rhodecode.model import meta
32 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
32 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation, \
33 UserFollowing
33 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.caching_query import FromCache
34 from sqlalchemy.orm import joinedload
35 from sqlalchemy.orm import joinedload
35 from sqlalchemy.orm.session import make_transient
36 from sqlalchemy.orm.session import make_transient
36 from vcs import get_backend
37 from vcs import get_backend
37 from vcs.utils.helpers import get_scm
38 from vcs.utils.helpers import get_scm
38 from vcs.exceptions import RepositoryError, VCSError
39 from vcs.exceptions import RepositoryError, VCSError
39 from vcs.utils.lazy import LazyProperty
40 from vcs.utils.lazy import LazyProperty
40 import traceback
41 import traceback
41 import logging
42 import logging
42 import os
43 import os
43 import time
44 import time
44
45
45 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
46
47
47 class ScmModel(object):
48 class ScmModel(object):
48 """
49 """
49 Mercurial Model
50 Mercurial Model
50 """
51 """
51
52
52 def __init__(self):
53 def __init__(self):
53 self.sa = meta.Session()
54 self.sa = meta.Session()
54
55
55 @LazyProperty
56 @LazyProperty
56 def repos_path(self):
57 def repos_path(self):
57 """
58 """
58 Get's the repositories root path from database
59 Get's the repositories root path from database
59 """
60 """
60 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
61 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
61
62
62 return q.ui_value
63 return q.ui_value
63
64
64 def repo_scan(self, repos_path, baseui, initial=False):
65 def repo_scan(self, repos_path, baseui, initial=False):
65 """
66 """
66 Listing of repositories in given path. This path should not be a
67 Listing of repositories in given path. This path should not be a
67 repository itself. Return a dictionary of repository objects
68 repository itself. Return a dictionary of repository objects
68
69
69 :param repos_path: path to directory containing repositories
70 :param repos_path: path to directory containing repositories
70 :param baseui
71 :param baseui
71 :param initial: initial scan
72 :param initial: initial scan
72 """
73 """
73 log.info('scanning for repositories in %s', repos_path)
74 log.info('scanning for repositories in %s', repos_path)
74
75
75 if not isinstance(baseui, ui.ui):
76 if not isinstance(baseui, ui.ui):
76 baseui = make_ui('db')
77 baseui = make_ui('db')
77 repos_list = {}
78 repos_list = {}
78
79
79 for name, path in get_repos(repos_path):
80 for name, path in get_repos(repos_path):
80 try:
81 try:
81 if repos_list.has_key(name):
82 if repos_list.has_key(name):
82 raise RepositoryError('Duplicate repository name %s '
83 raise RepositoryError('Duplicate repository name %s '
83 'found in %s' % (name, path))
84 'found in %s' % (name, path))
84 else:
85 else:
85
86
86 klass = get_backend(path[0])
87 klass = get_backend(path[0])
87
88
88 if path[0] == 'hg' and path[0] in BACKENDS.keys():
89 if path[0] == 'hg' and path[0] in BACKENDS.keys():
89 repos_list[name] = klass(path[1], baseui=baseui)
90 repos_list[name] = klass(path[1], baseui=baseui)
90
91
91 if path[0] == 'git' and path[0] in BACKENDS.keys():
92 if path[0] == 'git' and path[0] in BACKENDS.keys():
92 repos_list[name] = klass(path[1])
93 repos_list[name] = klass(path[1])
93 except OSError:
94 except OSError:
94 continue
95 continue
95
96
96 return repos_list
97 return repos_list
97
98
98 def get_repos(self, all_repos=None):
99 def get_repos(self, all_repos=None):
99 """
100 """
100 Get all repos from db and for each repo create it's backend instance.
101 Get all repos from db and for each repo create it's backend instance.
101 and fill that backed with information from database
102 and fill that backed with information from database
102
103
103 :param all_repos: give specific repositories list, good for filtering
104 :param all_repos: give specific repositories list, good for filtering
104 """
105 """
105 if not all_repos:
106 if not all_repos:
106 all_repos = self.sa.query(Repository)\
107 all_repos = self.sa.query(Repository)\
107 .order_by(Repository.repo_name).all()
108 .order_by(Repository.repo_name).all()
108
109
109 invalidation_list = [str(x.cache_key) for x in \
110 invalidation_list = [str(x.cache_key) for x in \
110 self.sa.query(CacheInvalidation.cache_key)\
111 self.sa.query(CacheInvalidation.cache_key)\
111 .filter(CacheInvalidation.cache_active == False)\
112 .filter(CacheInvalidation.cache_active == False)\
112 .all()]
113 .all()]
113
114
114 for r in all_repos:
115 for r in all_repos:
115
116
116 repo = self.get(r.repo_name, invalidation_list)
117 repo = self.get(r.repo_name, invalidation_list)
117
118
118 if repo is not None:
119 if repo is not None:
119 last_change = repo.last_change
120 last_change = repo.last_change
120 tip = h.get_changeset_safe(repo, 'tip')
121 tip = h.get_changeset_safe(repo, 'tip')
121
122
122 tmp_d = {}
123 tmp_d = {}
123 tmp_d['name'] = repo.name
124 tmp_d['name'] = repo.name
124 tmp_d['name_sort'] = tmp_d['name'].lower()
125 tmp_d['name_sort'] = tmp_d['name'].lower()
125 tmp_d['description'] = repo.dbrepo.description
126 tmp_d['description'] = repo.dbrepo.description
126 tmp_d['description_sort'] = tmp_d['description']
127 tmp_d['description_sort'] = tmp_d['description']
127 tmp_d['last_change'] = last_change
128 tmp_d['last_change'] = last_change
128 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
129 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
129 tmp_d['tip'] = tip.raw_id
130 tmp_d['tip'] = tip.raw_id
130 tmp_d['tip_sort'] = tip.revision
131 tmp_d['tip_sort'] = tip.revision
131 tmp_d['rev'] = tip.revision
132 tmp_d['rev'] = tip.revision
132 tmp_d['contact'] = repo.dbrepo.user.full_contact
133 tmp_d['contact'] = repo.dbrepo.user.full_contact
133 tmp_d['contact_sort'] = tmp_d['contact']
134 tmp_d['contact_sort'] = tmp_d['contact']
134 tmp_d['repo_archives'] = list(repo._get_archives())
135 tmp_d['repo_archives'] = list(repo._get_archives())
135 tmp_d['last_msg'] = tip.message
136 tmp_d['last_msg'] = tip.message
136 tmp_d['repo'] = repo
137 tmp_d['repo'] = repo
137 yield tmp_d
138 yield tmp_d
138
139
139 def get_repo(self, repo_name):
140 def get_repo(self, repo_name):
140 return self.get(repo_name)
141 return self.get(repo_name)
141
142
142 def get(self, repo_name, invalidation_list=None):
143 def get(self, repo_name, invalidation_list=None):
143 """
144 """
144 Get's repository from given name, creates BackendInstance and
145 Get's repository from given name, creates BackendInstance and
145 propagates it's data from database with all additional information
146 propagates it's data from database with all additional information
146 :param repo_name:
147 :param repo_name:
147 """
148 """
148 if not HasRepoPermissionAny('repository.read', 'repository.write',
149 if not HasRepoPermissionAny('repository.read', 'repository.write',
149 'repository.admin')(repo_name, 'get repo check'):
150 'repository.admin')(repo_name, 'get repo check'):
150 return
151 return
151
152
152 @cache_region('long_term')
153 @cache_region('long_term')
153 def _get_repo(repo_name):
154 def _get_repo(repo_name):
154
155
155 repo_path = os.path.join(self.repos_path, repo_name)
156 repo_path = os.path.join(self.repos_path, repo_name)
156 alias = get_scm(repo_path)[0]
157 alias = get_scm(repo_path)[0]
157
158
158 log.debug('Creating instance of %s repository', alias)
159 log.debug('Creating instance of %s repository', alias)
159 backend = get_backend(alias)
160 backend = get_backend(alias)
160
161
161 #TODO: get the baseui from somewhere for this
162 #TODO: get the baseui from somewhere for this
162 if alias == 'hg':
163 if alias == 'hg':
163 from pylons import app_globals as g
164 from pylons import app_globals as g
164 repo = backend(repo_path, create=False, baseui=g.baseui)
165 repo = backend(repo_path, create=False, baseui=g.baseui)
165 #skip hidden web repository
166 #skip hidden web repository
166 if repo._get_hidden():
167 if repo._get_hidden():
167 return
168 return
168 else:
169 else:
169 repo = backend(repo_path, create=False)
170 repo = backend(repo_path, create=False)
170
171
171 dbrepo = self.sa.query(Repository)\
172 dbrepo = self.sa.query(Repository)\
172 .options(joinedload(Repository.fork))\
173 .options(joinedload(Repository.fork))\
173 .options(joinedload(Repository.user))\
174 .options(joinedload(Repository.user))\
174 .filter(Repository.repo_name == repo_name)\
175 .filter(Repository.repo_name == repo_name)\
175 .scalar()
176 .scalar()
176 make_transient(dbrepo)
177 make_transient(dbrepo)
177 repo.dbrepo = dbrepo
178 repo.dbrepo = dbrepo
178 return repo
179 return repo
179
180
180 pre_invalidate = True
181 pre_invalidate = True
181 if invalidation_list:
182 if invalidation_list:
182 pre_invalidate = repo_name in invalidation_list
183 pre_invalidate = repo_name in invalidation_list
183
184
184 if pre_invalidate:
185 if pre_invalidate:
185 invalidate = self._should_invalidate(repo_name)
186 invalidate = self._should_invalidate(repo_name)
186
187
187 if invalidate:
188 if invalidate:
188 log.info('invalidating cache for repository %s', repo_name)
189 log.info('invalidating cache for repository %s', repo_name)
189 region_invalidate(_get_repo, None, repo_name)
190 region_invalidate(_get_repo, None, repo_name)
190 self._mark_invalidated(invalidate)
191 self._mark_invalidated(invalidate)
191
192
192 return _get_repo(repo_name)
193 return _get_repo(repo_name)
193
194
194
195
195
196
196 def mark_for_invalidation(self, repo_name):
197 def mark_for_invalidation(self, repo_name):
197 """
198 """
198 Puts cache invalidation task into db for
199 Puts cache invalidation task into db for
199 further global cache invalidation
200 further global cache invalidation
200
201
201 :param repo_name: this repo that should invalidation take place
202 :param repo_name: this repo that should invalidation take place
202 """
203 """
203 log.debug('marking %s for invalidation', repo_name)
204 log.debug('marking %s for invalidation', repo_name)
204 cache = self.sa.query(CacheInvalidation)\
205 cache = self.sa.query(CacheInvalidation)\
205 .filter(CacheInvalidation.cache_key == repo_name).scalar()
206 .filter(CacheInvalidation.cache_key == repo_name).scalar()
206
207
207 if cache:
208 if cache:
208 #mark this cache as inactive
209 #mark this cache as inactive
209 cache.cache_active = False
210 cache.cache_active = False
210 else:
211 else:
211 log.debug('cache key not found in invalidation db -> creating one')
212 log.debug('cache key not found in invalidation db -> creating one')
212 cache = CacheInvalidation(repo_name)
213 cache = CacheInvalidation(repo_name)
213
214
214 try:
215 try:
215 self.sa.add(cache)
216 self.sa.add(cache)
216 self.sa.commit()
217 self.sa.commit()
217 except:
218 except:
218 log.error(traceback.format_exc())
219 log.error(traceback.format_exc())
219 self.sa.rollback()
220 self.sa.rollback()
220
221
221
222
223 def toggle_following_repo(self, follow_repo_id, user_id):
222
224
225 f = self.sa.query(UserFollowing)\
226 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
227 .filter(UserFollowing.user_id == user_id).scalar()
228
229 if f is not None:
230 try:
231 self.sa.delete(f)
232 self.sa.commit()
233 return
234 except:
235 log.error(traceback.format_exc())
236 self.sa.rollback()
237 raise
238
239
240 try:
241 f = UserFollowing()
242 f.user_id = user_id
243 f.follows_repo_id = follow_repo_id
244 self.sa.add(f)
245 self.sa.commit()
246 except:
247 log.error(traceback.format_exc())
248 self.sa.rollback()
249 raise
250
251 def toggle_following_user(self, follow_user_id , user_id):
252 f = self.sa.query(UserFollowing)\
253 .filter(UserFollowing.follows_user_id == follow_user_id)\
254 .filter(UserFollowing.user_id == user_id).scalar()
255
256 if f is not None:
257 try:
258 self.sa.delete(f)
259 self.sa.commit()
260 return
261 except:
262 log.error(traceback.format_exc())
263 self.sa.rollback()
264 raise
265
266 try:
267 f = UserFollowing()
268 f.user_id = user_id
269 f.follows_user_id = follow_user_id
270 self.sa.add(f)
271 self.sa.commit()
272 except:
273 log.error(traceback.format_exc())
274 self.sa.rollback()
275 raise
276
277 def is_following_repo(self, repo_name, user_id):
278 r = self.sa.query(Repository)\
279 .filter(Repository.repo_name == repo_name).scalar()
280
281 f = self.sa.query(UserFollowing)\
282 .filter(UserFollowing.follows_repository == r)\
283 .filter(UserFollowing.user_id == user_id).scalar()
284
285 return f is not None
286
287 def is_following_user(self, username, user_id):
288 u = self.sa.query(User)\
289 .filter(User.username == username).scalar()
290
291 f = self.sa.query(UserFollowing)\
292 .filter(UserFollowing.follows_user == u)\
293 .filter(UserFollowing.user_id == user_id).scalar()
294
295 return f is not None
223
296
224
297
225 def _should_invalidate(self, repo_name):
298 def _should_invalidate(self, repo_name):
226 """
299 """
227 Looks up database for invalidation signals for this repo_name
300 Looks up database for invalidation signals for this repo_name
228 :param repo_name:
301 :param repo_name:
229 """
302 """
230
303
231 ret = self.sa.query(CacheInvalidation)\
304 ret = self.sa.query(CacheInvalidation)\
232 .options(FromCache('sql_cache_short',
305 .options(FromCache('sql_cache_short',
233 'get_invalidation_%s' % repo_name))\
306 'get_invalidation_%s' % repo_name))\
234 .filter(CacheInvalidation.cache_key == repo_name)\
307 .filter(CacheInvalidation.cache_key == repo_name)\
235 .filter(CacheInvalidation.cache_active == False)\
308 .filter(CacheInvalidation.cache_active == False)\
236 .scalar()
309 .scalar()
237
310
238 return ret
311 return ret
239
312
240 def _mark_invalidated(self, cache_key):
313 def _mark_invalidated(self, cache_key):
241 """
314 """
242 Marks all occurences of cache to invaldation as already invalidated
315 Marks all occurences of cache to invaldation as already invalidated
243 @param repo_name:
316 @param repo_name:
244 """
317 """
245 if cache_key:
318 if cache_key:
246 log.debug('marking %s as already invalidated', cache_key)
319 log.debug('marking %s as already invalidated', cache_key)
247 try:
320 try:
248 cache_key.cache_active = True
321 cache_key.cache_active = True
249 self.sa.add(cache_key)
322 self.sa.add(cache_key)
250 self.sa.commit()
323 self.sa.commit()
251 except:
324 except:
252 log.error(traceback.format_exc())
325 log.error(traceback.format_exc())
253 self.sa.rollback()
326 self.sa.rollback()
254
327
@@ -1,2337 +1,2357 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 #header ul#logged-user li {
193 #header ul#logged-user li {
194 list-style:none;
194 list-style:none;
195 float:left;
195 float:left;
196 border-left:1px solid #bbb;
196 border-left:1px solid #bbb;
197 border-right:1px solid #a5a5a5;
197 border-right:1px solid #a5a5a5;
198 margin:-2px 0 0;
198 margin:-2px 0 0;
199 padding:10px 12px;
199 padding:10px 12px;
200 }
200 }
201
201
202 #header ul#logged-user li.first {
202 #header ul#logged-user li.first {
203 border-left:none;
203 border-left:none;
204 margin:-6px;
204 margin:-6px;
205 }
205 }
206
206
207 #header ul#logged-user li.first div.account {
207 #header ul#logged-user li.first div.account {
208 padding-top:4px;
208 padding-top:4px;
209 float:left;
209 float:left;
210 }
210 }
211
211
212 #header ul#logged-user li.last {
212 #header ul#logged-user li.last {
213 border-right:none;
213 border-right:none;
214 }
214 }
215
215
216 #header ul#logged-user li a {
216 #header ul#logged-user li a {
217 color:#4e4e4e;
217 color:#4e4e4e;
218 font-weight:700;
218 font-weight:700;
219 text-decoration:none;
219 text-decoration:none;
220 }
220 }
221
221
222 #header ul#logged-user li a:hover {
222 #header ul#logged-user li a:hover {
223 color:#376ea6;
223 color:#376ea6;
224 text-decoration:underline;
224 text-decoration:underline;
225 }
225 }
226
226
227 #header ul#logged-user li.highlight a {
227 #header ul#logged-user li.highlight a {
228 color:#fff;
228 color:#fff;
229 }
229 }
230
230
231 #header ul#logged-user li.highlight a:hover {
231 #header ul#logged-user li.highlight a:hover {
232 color:#376ea6;
232 color:#376ea6;
233 }
233 }
234
234
235 #header #header-inner {
235 #header #header-inner {
236 height:40px;
236 height:40px;
237 clear:both;
237 clear:both;
238 position:relative;
238 position:relative;
239 background:#003367 url("../images/header_inner.png") repeat-x;
239 background:#003367 url("../images/header_inner.png") repeat-x;
240 border-bottom:2px solid #fff;
240 border-bottom:2px solid #fff;
241 margin:0;
241 margin:0;
242 padding:0;
242 padding:0;
243 }
243 }
244
244
245 #header #header-inner #home a {
245 #header #header-inner #home a {
246 height:40px;
246 height:40px;
247 width:46px;
247 width:46px;
248 display:block;
248 display:block;
249 background:url("../images/button_home.png");
249 background:url("../images/button_home.png");
250 background-position:0 0;
250 background-position:0 0;
251 margin:0;
251 margin:0;
252 padding:0;
252 padding:0;
253 }
253 }
254
254
255 #header #header-inner #home a:hover {
255 #header #header-inner #home a:hover {
256 background-position:0 -40px;
256 background-position:0 -40px;
257 }
257 }
258
258
259 #header #header-inner #logo h1 {
259 #header #header-inner #logo h1 {
260 color:#FFF;
260 color:#FFF;
261 font-size:18px;
261 font-size:18px;
262 margin:10px 0 0 13px;
262 margin:10px 0 0 13px;
263 padding:0;
263 padding:0;
264 }
264 }
265
265
266 #header #header-inner #logo a {
266 #header #header-inner #logo a {
267 color:#fff;
267 color:#fff;
268 text-decoration:none;
268 text-decoration:none;
269 }
269 }
270
270
271 #header #header-inner #logo a:hover {
271 #header #header-inner #logo a:hover {
272 color:#bfe3ff;
272 color:#bfe3ff;
273 }
273 }
274
274
275 #header #header-inner #quick,#header #header-inner #quick ul {
275 #header #header-inner #quick,#header #header-inner #quick ul {
276 position:relative;
276 position:relative;
277 float:right;
277 float:right;
278 list-style-type:none;
278 list-style-type:none;
279 list-style-position:outside;
279 list-style-position:outside;
280 margin:10px 5px 0 0;
280 margin:10px 5px 0 0;
281 padding:0;
281 padding:0;
282 }
282 }
283
283
284 #header #header-inner #quick li {
284 #header #header-inner #quick li {
285 position:relative;
285 position:relative;
286 float:left;
286 float:left;
287 margin:0 5px 0 0;
287 margin:0 5px 0 0;
288 padding:0;
288 padding:0;
289 }
289 }
290
290
291 #header #header-inner #quick li a {
291 #header #header-inner #quick li a {
292 top:0;
292 top:0;
293 left:0;
293 left:0;
294 height:1%;
294 height:1%;
295 display:block;
295 display:block;
296 clear:both;
296 clear:both;
297 overflow:hidden;
297 overflow:hidden;
298 color:#FFF;
298 color:#FFF;
299 font-weight:700;
299 font-weight:700;
300 text-decoration:none;
300 text-decoration:none;
301 background:#369 url("../../images/quick_l.png") no-repeat top left;
301 background:#369 url("../../images/quick_l.png") no-repeat top left;
302 padding:0;
302 padding:0;
303 }
303 }
304
304
305 #header #header-inner #quick li span {
305 #header #header-inner #quick li span {
306 top:0;
306 top:0;
307 right:0;
307 right:0;
308 height:1%;
308 height:1%;
309 display:block;
309 display:block;
310 float:left;
310 float:left;
311 background:url("../../images/quick_r.png") no-repeat top right;
311 background:url("../../images/quick_r.png") no-repeat top right;
312 border-left:1px solid #3f6f9f;
312 border-left:1px solid #3f6f9f;
313 margin:0;
313 margin:0;
314 padding:10px 12px 8px 10px;
314 padding:10px 12px 8px 10px;
315 }
315 }
316
316
317 #header #header-inner #quick li span.normal {
317 #header #header-inner #quick li span.normal {
318 border:none;
318 border:none;
319 padding:10px 12px 8px;
319 padding:10px 12px 8px;
320 }
320 }
321
321
322 #header #header-inner #quick li span.icon {
322 #header #header-inner #quick li span.icon {
323 top:0;
323 top:0;
324 left:0;
324 left:0;
325 border-left:none;
325 border-left:none;
326 background:url("../../images/quick_l.png") no-repeat top left;
326 background:url("../../images/quick_l.png") no-repeat top left;
327 border-right:1px solid #2e5c89;
327 border-right:1px solid #2e5c89;
328 padding:8px 8px 4px;
328 padding:8px 8px 4px;
329 }
329 }
330
330
331 #header #header-inner #quick li a:hover {
331 #header #header-inner #quick li a:hover {
332 background:#4e4e4e url("../../images/quick_l_selected.png") no-repeat top left;
332 background:#4e4e4e url("../../images/quick_l_selected.png") no-repeat top left;
333 }
333 }
334
334
335 #header #header-inner #quick li a:hover span {
335 #header #header-inner #quick li a:hover span {
336 border-left:1px solid #545454;
336 border-left:1px solid #545454;
337 background:url("../../images/quick_r_selected.png") no-repeat top right;
337 background:url("../../images/quick_r_selected.png") no-repeat top right;
338 }
338 }
339
339
340 #header #header-inner #quick li a:hover span.icon {
340 #header #header-inner #quick li a:hover span.icon {
341 border-left:none;
341 border-left:none;
342 border-right:1px solid #464646;
342 border-right:1px solid #464646;
343 background:url("../../images/quick_l_selected.png") no-repeat top left;
343 background:url("../../images/quick_l_selected.png") no-repeat top left;
344 }
344 }
345
345
346 #header #header-inner #quick ul {
346 #header #header-inner #quick ul {
347 top:29px;
347 top:29px;
348 right:0;
348 right:0;
349 min-width:200px;
349 min-width:200px;
350 display:none;
350 display:none;
351 position:absolute;
351 position:absolute;
352 background:#FFF;
352 background:#FFF;
353 border:1px solid #666;
353 border:1px solid #666;
354 border-top:1px solid #003367;
354 border-top:1px solid #003367;
355 z-index:100;
355 z-index:100;
356 margin:0;
356 margin:0;
357 padding:0;
357 padding:0;
358 }
358 }
359
359
360 #header #header-inner #quick ul.repo_switcher {
360 #header #header-inner #quick ul.repo_switcher {
361 max-height:275px;
361 max-height:275px;
362 overflow-x:hidden;
362 overflow-x:hidden;
363 overflow-y:auto;
363 overflow-y:auto;
364 }
364 }
365
365
366 #header #header-inner #quick .repo_switcher_type{
366 #header #header-inner #quick .repo_switcher_type{
367 position:absolute;
367 position:absolute;
368 left:0;
368 left:0;
369 top:9px;
369 top:9px;
370
370
371 }
371 }
372 #header #header-inner #quick li ul li {
372 #header #header-inner #quick li ul li {
373 border-bottom:1px solid #ddd;
373 border-bottom:1px solid #ddd;
374 }
374 }
375
375
376 #header #header-inner #quick li ul li a {
376 #header #header-inner #quick li ul li a {
377 width:182px;
377 width:182px;
378 height:auto;
378 height:auto;
379 display:block;
379 display:block;
380 float:left;
380 float:left;
381 background:#FFF;
381 background:#FFF;
382 color:#003367;
382 color:#003367;
383 font-weight:400;
383 font-weight:400;
384 margin:0;
384 margin:0;
385 padding:7px 9px;
385 padding:7px 9px;
386 }
386 }
387
387
388 #header #header-inner #quick li ul li a:hover {
388 #header #header-inner #quick li ul li a:hover {
389 color:#000;
389 color:#000;
390 background:#FFF;
390 background:#FFF;
391 }
391 }
392
392
393 #header #header-inner #quick ul ul {
393 #header #header-inner #quick ul ul {
394 top:auto;
394 top:auto;
395 }
395 }
396
396
397 #header #header-inner #quick li ul ul {
397 #header #header-inner #quick li ul ul {
398 right:200px;
398 right:200px;
399 max-height:275px;
399 max-height:275px;
400 overflow:auto;
400 overflow:auto;
401 overflow-x:hidden;
401 overflow-x:hidden;
402 white-space:normal;
402 white-space:normal;
403 }
403 }
404
404
405 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
405 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
406 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
406 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
407 width:167px;
407 width:167px;
408 margin:0;
408 margin:0;
409 padding:12px 9px 7px 24px;
409 padding:12px 9px 7px 24px;
410 }
410 }
411
411
412 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
412 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
413 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
413 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
414 min-width:167px;
414 min-width:167px;
415 margin:0;
415 margin:0;
416 padding:12px 9px 7px 24px;
416 padding:12px 9px 7px 24px;
417 }
417 }
418
418
419 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
419 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
420 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
420 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
421 min-width:167px;
421 min-width:167px;
422 margin:0;
422 margin:0;
423 padding:12px 9px 7px 24px;
423 padding:12px 9px 7px 24px;
424 }
424 }
425
425
426 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover {
426 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover {
427 background:url("../images/icons/hgicon.png") no-repeat scroll 4px 9px #FFF;
427 background:url("../images/icons/hgicon.png") no-repeat scroll 4px 9px #FFF;
428 min-width:167px;
428 min-width:167px;
429 margin:0 0 0 14px;
429 margin:0 0 0 14px;
430 padding:12px 9px 7px 24px;
430 padding:12px 9px 7px 24px;
431 }
431 }
432
432
433 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover {
433 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover {
434 background:url("../images/icons/giticon.png") no-repeat scroll 4px 9px #FFF;
434 background:url("../images/icons/giticon.png") no-repeat scroll 4px 9px #FFF;
435 min-width:167px;
435 min-width:167px;
436 margin:0 0 0 14px;
436 margin:0 0 0 14px;
437 padding:12px 9px 7px 24px;
437 padding:12px 9px 7px 24px;
438 }
438 }
439
439
440 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
440 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
441 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
441 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
442 width:167px;
442 width:167px;
443 margin:0;
443 margin:0;
444 padding:12px 9px 7px 24px;
444 padding:12px 9px 7px 24px;
445 }
445 }
446
446
447 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
447 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
448 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
448 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
449 width:167px;
449 width:167px;
450 margin:0;
450 margin:0;
451 padding:12px 9px 7px 24px;
451 padding:12px 9px 7px 24px;
452 }
452 }
453
453
454 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
454 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
455 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
455 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
456 width:167px;
456 width:167px;
457 margin:0;
457 margin:0;
458 padding:12px 9px 7px 24px;
458 padding:12px 9px 7px 24px;
459 }
459 }
460
460
461 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
461 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
462 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
462 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
463 width:167px;
463 width:167px;
464 margin:0;
464 margin:0;
465 padding:12px 9px 7px 24px;
465 padding:12px 9px 7px 24px;
466 }
466 }
467
467
468 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
468 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
469 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
469 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
470 width:167px;
470 width:167px;
471 margin:0;
471 margin:0;
472 padding:12px 9px 7px 24px;
472 padding:12px 9px 7px 24px;
473 }
473 }
474
474
475 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
475 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
476 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
476 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
477 width:167px;
477 width:167px;
478 margin:0;
478 margin:0;
479 padding:12px 9px 7px 24px;
479 padding:12px 9px 7px 24px;
480 }
480 }
481
481
482 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
482 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
483 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
483 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
484 width:167px;
484 width:167px;
485 margin:0;
485 margin:0;
486 padding:12px 9px 7px 24px;
486 padding:12px 9px 7px 24px;
487 }
487 }
488
488
489 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
489 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
490 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
490 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
491 width:167px;
491 width:167px;
492 margin:0;
492 margin:0;
493 padding:12px 9px 7px 24px;
493 padding:12px 9px 7px 24px;
494 }
494 }
495
495
496 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
496 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
497 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
497 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
498 width:167px;
498 width:167px;
499 margin:0;
499 margin:0;
500 padding:12px 9px 7px 24px;
500 padding:12px 9px 7px 24px;
501 }
501 }
502
502
503 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
503 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
504 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
504 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
505 width:167px;
505 width:167px;
506 margin:0;
506 margin:0;
507 padding:12px 9px 7px 24px;
507 padding:12px 9px 7px 24px;
508 }
508 }
509
509
510 #content #left {
510 #content #left {
511 left:0;
511 left:0;
512 width:280px;
512 width:280px;
513 position:absolute;
513 position:absolute;
514 }
514 }
515
515
516 #content #right {
516 #content #right {
517 margin:0 60px 10px 290px;
517 margin:0 60px 10px 290px;
518 }
518 }
519
519
520 #content div.box {
520 #content div.box {
521 clear:both;
521 clear:both;
522 overflow:hidden;
522 overflow:hidden;
523 background:#fff;
523 background:#fff;
524 margin:0 0 10px;
524 margin:0 0 10px;
525 padding:0 0 10px;
525 padding:0 0 10px;
526 }
526 }
527
527
528 #content div.box-left {
528 #content div.box-left {
529 width:49%;
529 width:49%;
530 clear:none;
530 clear:none;
531 float:left;
531 float:left;
532 margin:0 0 10px;
532 margin:0 0 10px;
533 }
533 }
534
534
535 #content div.box-right {
535 #content div.box-right {
536 width:49%;
536 width:49%;
537 clear:none;
537 clear:none;
538 float:right;
538 float:right;
539 margin:0 0 10px;
539 margin:0 0 10px;
540 }
540 }
541
541
542 #content div.box div.title {
542 #content div.box div.title {
543 clear:both;
543 clear:both;
544 overflow:hidden;
544 overflow:hidden;
545 background:#369 url("../images/header_inner.png") repeat-x;
545 background:#369 url("../images/header_inner.png") repeat-x;
546 margin:0 0 20px;
546 margin:0 0 20px;
547 padding:0;
547 padding:0;
548 }
548 }
549
549
550 #content div.box div.title h5 {
550 #content div.box div.title h5 {
551 float:left;
551 float:left;
552 border:none;
552 border:none;
553 color:#fff;
553 color:#fff;
554 text-transform:uppercase;
554 text-transform:uppercase;
555 margin:0;
555 margin:0;
556 padding:11px 0 11px 10px;
556 padding:11px 0 11px 10px;
557 }
557 }
558
558
559 #content div.box div.title ul.links li {
559 #content div.box div.title ul.links li {
560 list-style:none;
560 list-style:none;
561 float:left;
561 float:left;
562 margin:0;
562 margin:0;
563 padding:0;
563 padding:0;
564 }
564 }
565
565
566 #content div.box div.title ul.links li a {
566 #content div.box div.title ul.links li a {
567 height:1%;
567 height:1%;
568 display:block;
568 display:block;
569 float:left;
569 float:left;
570 border-left:1px solid #316293;
570 border-left:1px solid #316293;
571 color:#fff;
571 color:#fff;
572 font-size:11px;
572 font-size:11px;
573 font-weight:700;
573 font-weight:700;
574 text-decoration:none;
574 text-decoration:none;
575 margin:0;
575 margin:0;
576 padding:13px 16px 12px;
576 padding:13px 16px 12px;
577 }
577 }
578
578
579 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
579 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
580 clear:both;
580 clear:both;
581 overflow:hidden;
581 overflow:hidden;
582 border-bottom:1px solid #DDD;
582 border-bottom:1px solid #DDD;
583 margin:10px 20px;
583 margin:10px 20px;
584 padding:0 0 15px;
584 padding:0 0 15px;
585 }
585 }
586
586
587 #content div.box p {
587 #content div.box p {
588 color:#5f5f5f;
588 color:#5f5f5f;
589 font-size:12px;
589 font-size:12px;
590 line-height:150%;
590 line-height:150%;
591 margin:0 24px 10px;
591 margin:0 24px 10px;
592 padding:0;
592 padding:0;
593 }
593 }
594
594
595 #content div.box blockquote {
595 #content div.box blockquote {
596 border-left:4px solid #DDD;
596 border-left:4px solid #DDD;
597 color:#5f5f5f;
597 color:#5f5f5f;
598 font-size:11px;
598 font-size:11px;
599 line-height:150%;
599 line-height:150%;
600 margin:0 34px;
600 margin:0 34px;
601 padding:0 0 0 14px;
601 padding:0 0 0 14px;
602 }
602 }
603
603
604 #content div.box blockquote p {
604 #content div.box blockquote p {
605 margin:10px 0;
605 margin:10px 0;
606 padding:0;
606 padding:0;
607 }
607 }
608
608
609 #content div.box dl {
609 #content div.box dl {
610 margin:10px 24px;
610 margin:10px 24px;
611 }
611 }
612
612
613 #content div.box dt {
613 #content div.box dt {
614 font-size:12px;
614 font-size:12px;
615 margin:0;
615 margin:0;
616 }
616 }
617
617
618 #content div.box dd {
618 #content div.box dd {
619 font-size:12px;
619 font-size:12px;
620 margin:0;
620 margin:0;
621 padding:8px 0 8px 15px;
621 padding:8px 0 8px 15px;
622 }
622 }
623
623
624 #content div.box li {
624 #content div.box li {
625 font-size:12px;
625 font-size:12px;
626 padding:4px 0;
626 padding:4px 0;
627 }
627 }
628
628
629 #content div.box ul.disc,#content div.box ul.circle {
629 #content div.box ul.disc,#content div.box ul.circle {
630 margin:10px 24px 10px 38px;
630 margin:10px 24px 10px 38px;
631 }
631 }
632
632
633 #content div.box ul.square {
633 #content div.box ul.square {
634 margin:10px 24px 10px 40px;
634 margin:10px 24px 10px 40px;
635 }
635 }
636
636
637 #content div.box img.left {
637 #content div.box img.left {
638 border:none;
638 border:none;
639 float:left;
639 float:left;
640 margin:10px 10px 10px 0;
640 margin:10px 10px 10px 0;
641 }
641 }
642
642
643 #content div.box img.right {
643 #content div.box img.right {
644 border:none;
644 border:none;
645 float:right;
645 float:right;
646 margin:10px 0 10px 10px;
646 margin:10px 0 10px 10px;
647 }
647 }
648
648
649 #content div.box div.messages {
649 #content div.box div.messages {
650 clear:both;
650 clear:both;
651 overflow:hidden;
651 overflow:hidden;
652 margin:0 20px;
652 margin:0 20px;
653 padding:0;
653 padding:0;
654 }
654 }
655
655
656 #content div.box div.message {
656 #content div.box div.message {
657 clear:both;
657 clear:both;
658 overflow:hidden;
658 overflow:hidden;
659 margin:0;
659 margin:0;
660 padding:10px 0;
660 padding:10px 0;
661 }
661 }
662
662
663 #content div.box div.message a {
663 #content div.box div.message a {
664 font-weight:400 !important;
664 font-weight:400 !important;
665 }
665 }
666
666
667 #content div.box div.message div.image {
667 #content div.box div.message div.image {
668 float:left;
668 float:left;
669 margin:9px 0 0 5px;
669 margin:9px 0 0 5px;
670 padding:6px;
670 padding:6px;
671 }
671 }
672
672
673 #content div.box div.message div.image img {
673 #content div.box div.message div.image img {
674 vertical-align:middle;
674 vertical-align:middle;
675 margin:0;
675 margin:0;
676 }
676 }
677
677
678 #content div.box div.message div.text {
678 #content div.box div.message div.text {
679 float:left;
679 float:left;
680 margin:0;
680 margin:0;
681 padding:9px 6px;
681 padding:9px 6px;
682 }
682 }
683
683
684 #content div.box div.message div.dismiss a {
684 #content div.box div.message div.dismiss a {
685 height:16px;
685 height:16px;
686 width:16px;
686 width:16px;
687 display:block;
687 display:block;
688 background:url("../images/icons/cross.png") no-repeat;
688 background:url("../images/icons/cross.png") no-repeat;
689 margin:15px 14px 0 0;
689 margin:15px 14px 0 0;
690 padding:0;
690 padding:0;
691 }
691 }
692
692
693 #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 {
693 #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 {
694 border:none;
694 border:none;
695 margin:0;
695 margin:0;
696 padding:0;
696 padding:0;
697 }
697 }
698
698
699 #content div.box div.message div.text span {
699 #content div.box div.message div.text span {
700 height:1%;
700 height:1%;
701 display:block;
701 display:block;
702 margin:0;
702 margin:0;
703 padding:5px 0 0;
703 padding:5px 0 0;
704 }
704 }
705
705
706 #content div.box div.message-error {
706 #content div.box div.message-error {
707 height:1%;
707 height:1%;
708 clear:both;
708 clear:both;
709 overflow:hidden;
709 overflow:hidden;
710 background:#FBE3E4;
710 background:#FBE3E4;
711 border:1px solid #FBC2C4;
711 border:1px solid #FBC2C4;
712 color:#860006;
712 color:#860006;
713 }
713 }
714
714
715 #content div.box div.message-error h6 {
715 #content div.box div.message-error h6 {
716 color:#860006;
716 color:#860006;
717 }
717 }
718
718
719 #content div.box div.message-warning {
719 #content div.box div.message-warning {
720 height:1%;
720 height:1%;
721 clear:both;
721 clear:both;
722 overflow:hidden;
722 overflow:hidden;
723 background:#FFF6BF;
723 background:#FFF6BF;
724 border:1px solid #FFD324;
724 border:1px solid #FFD324;
725 color:#5f5200;
725 color:#5f5200;
726 }
726 }
727
727
728 #content div.box div.message-warning h6 {
728 #content div.box div.message-warning h6 {
729 color:#5f5200;
729 color:#5f5200;
730 }
730 }
731
731
732 #content div.box div.message-notice {
732 #content div.box div.message-notice {
733 height:1%;
733 height:1%;
734 clear:both;
734 clear:both;
735 overflow:hidden;
735 overflow:hidden;
736 background:#8FBDE0;
736 background:#8FBDE0;
737 border:1px solid #6BACDE;
737 border:1px solid #6BACDE;
738 color:#003863;
738 color:#003863;
739 }
739 }
740
740
741 #content div.box div.message-notice h6 {
741 #content div.box div.message-notice h6 {
742 color:#003863;
742 color:#003863;
743 }
743 }
744
744
745 #content div.box div.message-success {
745 #content div.box div.message-success {
746 height:1%;
746 height:1%;
747 clear:both;
747 clear:both;
748 overflow:hidden;
748 overflow:hidden;
749 background:#E6EFC2;
749 background:#E6EFC2;
750 border:1px solid #C6D880;
750 border:1px solid #C6D880;
751 color:#4e6100;
751 color:#4e6100;
752 }
752 }
753
753
754 #content div.box div.message-success h6 {
754 #content div.box div.message-success h6 {
755 color:#4e6100;
755 color:#4e6100;
756 }
756 }
757
757
758 #content div.box div.form div.fields div.field {
758 #content div.box div.form div.fields div.field {
759 height:1%;
759 height:1%;
760 border-bottom:1px solid #DDD;
760 border-bottom:1px solid #DDD;
761 clear:both;
761 clear:both;
762 margin:0;
762 margin:0;
763 padding:10px 0;
763 padding:10px 0;
764 }
764 }
765
765
766 #content div.box div.form div.fields div.field-first {
766 #content div.box div.form div.fields div.field-first {
767 padding:0 0 10px;
767 padding:0 0 10px;
768 }
768 }
769
769
770 #content div.box div.form div.fields div.field-noborder {
770 #content div.box div.form div.fields div.field-noborder {
771 border-bottom:0 !important;
771 border-bottom:0 !important;
772 }
772 }
773
773
774 #content div.box div.form div.fields div.field span.error-message {
774 #content div.box div.form div.fields div.field span.error-message {
775 height:1%;
775 height:1%;
776 display:inline-block;
776 display:inline-block;
777 color:red;
777 color:red;
778 margin:8px 0 0 4px;
778 margin:8px 0 0 4px;
779 padding:0;
779 padding:0;
780 }
780 }
781
781
782 #content div.box div.form div.fields div.field span.success {
782 #content div.box div.form div.fields div.field span.success {
783 height:1%;
783 height:1%;
784 display:block;
784 display:block;
785 color:#316309;
785 color:#316309;
786 margin:8px 0 0;
786 margin:8px 0 0;
787 padding:0;
787 padding:0;
788 }
788 }
789
789
790 #content div.box div.form div.fields div.field div.label {
790 #content div.box div.form div.fields div.field div.label {
791 left:80px;
791 left:80px;
792 width:auto;
792 width:auto;
793 position:absolute;
793 position:absolute;
794 margin:0;
794 margin:0;
795 padding:8px 0 0 5px;
795 padding:8px 0 0 5px;
796 }
796 }
797
797
798 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
798 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
799 clear:both;
799 clear:both;
800 overflow:hidden;
800 overflow:hidden;
801 left:0;
801 left:0;
802 width:auto;
802 width:auto;
803 position:relative;
803 position:relative;
804 margin:0;
804 margin:0;
805 padding:0 0 8px;
805 padding:0 0 8px;
806 }
806 }
807
807
808 #content div.box div.form div.fields div.field div.label-select {
808 #content div.box div.form div.fields div.field div.label-select {
809 padding:5px 0 0 5px;
809 padding:5px 0 0 5px;
810 }
810 }
811
811
812 #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 {
812 #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 {
813 padding:0 0 8px;
813 padding:0 0 8px;
814 }
814 }
815
815
816 #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 {
816 #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 {
817 padding:0 0 8px !important;
817 padding:0 0 8px !important;
818 }
818 }
819
819
820 #content div.box div.form div.fields div.field div.label label {
820 #content div.box div.form div.fields div.field div.label label {
821 color:#393939;
821 color:#393939;
822 font-weight:700;
822 font-weight:700;
823 }
823 }
824
824
825 #content div.box div.form div.fields div.field div.input {
825 #content div.box div.form div.fields div.field div.input {
826 margin:0 0 0 200px;
826 margin:0 0 0 200px;
827 }
827 }
828 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
828 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
829 margin:0 0 0 0px;
829 margin:0 0 0 0px;
830 }
830 }
831
831
832 #content div.box div.form div.fields div.field div.input input {
832 #content div.box div.form div.fields div.field div.input input {
833 background:#FFF;
833 background:#FFF;
834 border-top:1px solid #b3b3b3;
834 border-top:1px solid #b3b3b3;
835 border-left:1px solid #b3b3b3;
835 border-left:1px solid #b3b3b3;
836 border-right:1px solid #eaeaea;
836 border-right:1px solid #eaeaea;
837 border-bottom:1px solid #eaeaea;
837 border-bottom:1px solid #eaeaea;
838 color:#000;
838 color:#000;
839 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
839 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
840 font-size:11px;
840 font-size:11px;
841 margin:0;
841 margin:0;
842 padding:7px 7px 6px;
842 padding:7px 7px 6px;
843 }
843 }
844
844
845
845
846
846
847 #content div.box div.form div.fields div.field div.input input.small {
847 #content div.box div.form div.fields div.field div.input input.small {
848 width:30%;
848 width:30%;
849 }
849 }
850
850
851 #content div.box div.form div.fields div.field div.input input.medium {
851 #content div.box div.form div.fields div.field div.input input.medium {
852 width:55%;
852 width:55%;
853 }
853 }
854
854
855 #content div.box div.form div.fields div.field div.input input.large {
855 #content div.box div.form div.fields div.field div.input input.large {
856 width:85%;
856 width:85%;
857 }
857 }
858
858
859 #content div.box div.form div.fields div.field div.input input.date {
859 #content div.box div.form div.fields div.field div.input input.date {
860 width:177px;
860 width:177px;
861 }
861 }
862
862
863 #content div.box div.form div.fields div.field div.input input.button {
863 #content div.box div.form div.fields div.field div.input input.button {
864 background:#D4D0C8;
864 background:#D4D0C8;
865 border-top:1px solid #FFF;
865 border-top:1px solid #FFF;
866 border-left:1px solid #FFF;
866 border-left:1px solid #FFF;
867 border-right:1px solid #404040;
867 border-right:1px solid #404040;
868 border-bottom:1px solid #404040;
868 border-bottom:1px solid #404040;
869 color:#000;
869 color:#000;
870 margin:0;
870 margin:0;
871 padding:4px 8px;
871 padding:4px 8px;
872 }
872 }
873
873
874 #content div.box div.form div.fields div.field div.input a.ui-input-file {
874 #content div.box div.form div.fields div.field div.input a.ui-input-file {
875 width:28px;
875 width:28px;
876 height:28px;
876 height:28px;
877 display:inline;
877 display:inline;
878 position:absolute;
878 position:absolute;
879 overflow:hidden;
879 overflow:hidden;
880 cursor:pointer;
880 cursor:pointer;
881 background:#e5e3e3 url("../images/button_browse.png") no-repeat;
881 background:#e5e3e3 url("../images/button_browse.png") no-repeat;
882 border:none;
882 border:none;
883 text-decoration:none;
883 text-decoration:none;
884 margin:0 0 0 6px;
884 margin:0 0 0 6px;
885 padding:0;
885 padding:0;
886 }
886 }
887
887
888 #content div.box div.form div.fields div.field div.textarea {
888 #content div.box div.form div.fields div.field div.textarea {
889 border-top:1px solid #b3b3b3;
889 border-top:1px solid #b3b3b3;
890 border-left:1px solid #b3b3b3;
890 border-left:1px solid #b3b3b3;
891 border-right:1px solid #eaeaea;
891 border-right:1px solid #eaeaea;
892 border-bottom:1px solid #eaeaea;
892 border-bottom:1px solid #eaeaea;
893 margin:0 0 0 200px;
893 margin:0 0 0 200px;
894 padding:10px;
894 padding:10px;
895 }
895 }
896
896
897 #content div.box div.form div.fields div.field div.textarea-editor {
897 #content div.box div.form div.fields div.field div.textarea-editor {
898 border:1px solid #ddd;
898 border:1px solid #ddd;
899 padding:0;
899 padding:0;
900 }
900 }
901
901
902 #content div.box div.form div.fields div.field div.textarea textarea {
902 #content div.box div.form div.fields div.field div.textarea textarea {
903 width:100%;
903 width:100%;
904 height:220px;
904 height:220px;
905 overflow:hidden;
905 overflow:hidden;
906 background:#FFF;
906 background:#FFF;
907 color:#000;
907 color:#000;
908 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
908 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
909 font-size:11px;
909 font-size:11px;
910 outline:none;
910 outline:none;
911 border-width:0;
911 border-width:0;
912 margin:0;
912 margin:0;
913 padding:0;
913 padding:0;
914 }
914 }
915
915
916 #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 {
916 #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 {
917 width:100%;
917 width:100%;
918 height:100px;
918 height:100px;
919 }
919 }
920
920
921 #content div.box div.form div.fields div.field div.textarea table {
921 #content div.box div.form div.fields div.field div.textarea table {
922 width:100%;
922 width:100%;
923 border:none;
923 border:none;
924 margin:0;
924 margin:0;
925 padding:0;
925 padding:0;
926 }
926 }
927
927
928 #content div.box div.form div.fields div.field div.textarea table td {
928 #content div.box div.form div.fields div.field div.textarea table td {
929 background:#DDD;
929 background:#DDD;
930 border:none;
930 border:none;
931 padding:0;
931 padding:0;
932 }
932 }
933
933
934 #content div.box div.form div.fields div.field div.textarea table td table {
934 #content div.box div.form div.fields div.field div.textarea table td table {
935 width:auto;
935 width:auto;
936 border:none;
936 border:none;
937 margin:0;
937 margin:0;
938 padding:0;
938 padding:0;
939 }
939 }
940
940
941 #content div.box div.form div.fields div.field div.textarea table td table td {
941 #content div.box div.form div.fields div.field div.textarea table td table td {
942 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
942 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
943 font-size:11px;
943 font-size:11px;
944 padding:5px 5px 5px 0;
944 padding:5px 5px 5px 0;
945 }
945 }
946
946
947 #content div.box div.form div.fields div.field div.textarea table td table td a.mceButtonActive {
947 #content div.box div.form div.fields div.field div.textarea table td table td a.mceButtonActive {
948 background:#b1b1b1;
948 background:#b1b1b1;
949 }
949 }
950
950
951 #content div.box div.form div.fields div.field div.select a.ui-selectmenu {
951 #content div.box div.form div.fields div.field div.select a.ui-selectmenu {
952 color:#565656;
952 color:#565656;
953 text-decoration:none;
953 text-decoration:none;
954 }
954 }
955
955
956 #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 {
956 #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 {
957 background:#f6f6f6;
957 background:#f6f6f6;
958 border-color:#666;
958 border-color:#666;
959 }
959 }
960
960
961 div.form div.fields div.field div.button {
961 div.form div.fields div.field div.button {
962 margin:0;
962 margin:0;
963 padding:0 0 0 8px;
963 padding:0 0 0 8px;
964 }
964 }
965
965
966 div.form div.fields div.field div.highlight .ui-state-default {
966 div.form div.fields div.field div.highlight .ui-state-default {
967 background:#4e85bb url("../images/button_highlight.png") repeat-x;
967 background:#4e85bb url("../images/button_highlight.png") repeat-x;
968 border-top:1px solid #5c91a4;
968 border-top:1px solid #5c91a4;
969 border-left:1px solid #2a6f89;
969 border-left:1px solid #2a6f89;
970 border-right:1px solid #2b7089;
970 border-right:1px solid #2b7089;
971 border-bottom:1px solid #1a6480;
971 border-bottom:1px solid #1a6480;
972 color:#FFF;
972 color:#FFF;
973 margin:0;
973 margin:0;
974 padding:6px 12px;
974 padding:6px 12px;
975 }
975 }
976
976
977 div.form div.fields div.field div.highlight .ui-state-hover {
977 div.form div.fields div.field div.highlight .ui-state-hover {
978 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
978 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
979 border-top:1px solid #78acbf;
979 border-top:1px solid #78acbf;
980 border-left:1px solid #34819e;
980 border-left:1px solid #34819e;
981 border-right:1px solid #35829f;
981 border-right:1px solid #35829f;
982 border-bottom:1px solid #257897;
982 border-bottom:1px solid #257897;
983 color:#FFF;
983 color:#FFF;
984 margin:0;
984 margin:0;
985 padding:6px 12px;
985 padding:6px 12px;
986 }
986 }
987
987
988 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-default {
988 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-default {
989 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
989 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
990 border-top:1px solid #5c91a4;
990 border-top:1px solid #5c91a4;
991 border-left:1px solid #2a6f89;
991 border-left:1px solid #2a6f89;
992 border-right:1px solid #2b7089;
992 border-right:1px solid #2b7089;
993 border-bottom:1px solid #1a6480;
993 border-bottom:1px solid #1a6480;
994 color:#fff;
994 color:#fff;
995 margin:0;
995 margin:0;
996 padding:6px 12px;
996 padding:6px 12px;
997 }
997 }
998
998
999 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
999 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
1000 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1000 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1001 border-top:1px solid #78acbf;
1001 border-top:1px solid #78acbf;
1002 border-left:1px solid #34819e;
1002 border-left:1px solid #34819e;
1003 border-right:1px solid #35829f;
1003 border-right:1px solid #35829f;
1004 border-bottom:1px solid #257897;
1004 border-bottom:1px solid #257897;
1005 color:#fff;
1005 color:#fff;
1006 margin:0;
1006 margin:0;
1007 padding:6px 12px;
1007 padding:6px 12px;
1008 }
1008 }
1009
1009
1010 #content div.box table {
1010 #content div.box table {
1011 width:100%;
1011 width:100%;
1012 border-collapse:collapse;
1012 border-collapse:collapse;
1013 margin:0;
1013 margin:0;
1014 padding:0;
1014 padding:0;
1015 }
1015 }
1016
1016
1017 #content div.box table th {
1017 #content div.box table th {
1018 background:#eee;
1018 background:#eee;
1019 border-bottom:1px solid #ddd;
1019 border-bottom:1px solid #ddd;
1020 padding:5px 0px 5px 5px;
1020 padding:5px 0px 5px 5px;
1021 }
1021 }
1022
1022
1023 #content div.box table th.left {
1023 #content div.box table th.left {
1024 text-align:left;
1024 text-align:left;
1025 }
1025 }
1026
1026
1027 #content div.box table th.right {
1027 #content div.box table th.right {
1028 text-align:right;
1028 text-align:right;
1029 }
1029 }
1030
1030
1031 #content div.box table th.center {
1031 #content div.box table th.center {
1032 text-align:center;
1032 text-align:center;
1033 }
1033 }
1034
1034
1035 #content div.box table th.selected {
1035 #content div.box table th.selected {
1036 vertical-align:middle;
1036 vertical-align:middle;
1037 padding:0;
1037 padding:0;
1038 }
1038 }
1039
1039
1040 #content div.box table td {
1040 #content div.box table td {
1041 background:#fff;
1041 background:#fff;
1042 border-bottom:1px solid #cdcdcd;
1042 border-bottom:1px solid #cdcdcd;
1043 vertical-align:middle;
1043 vertical-align:middle;
1044 padding:5px;
1044 padding:5px;
1045 }
1045 }
1046
1046
1047 #content div.box table tr.selected td {
1047 #content div.box table tr.selected td {
1048 background:#FFC;
1048 background:#FFC;
1049 }
1049 }
1050
1050
1051 #content div.box table td.selected {
1051 #content div.box table td.selected {
1052 width:3%;
1052 width:3%;
1053 text-align:center;
1053 text-align:center;
1054 vertical-align:middle;
1054 vertical-align:middle;
1055 padding:0;
1055 padding:0;
1056 }
1056 }
1057
1057
1058 #content div.box table td.action {
1058 #content div.box table td.action {
1059 width:45%;
1059 width:45%;
1060 text-align:left;
1060 text-align:left;
1061 }
1061 }
1062
1062
1063 #content div.box table td.date {
1063 #content div.box table td.date {
1064 width:33%;
1064 width:33%;
1065 text-align:center;
1065 text-align:center;
1066 }
1066 }
1067
1067
1068 #content div.box div.action {
1068 #content div.box div.action {
1069 float:right;
1069 float:right;
1070 background:#FFF;
1070 background:#FFF;
1071 text-align:right;
1071 text-align:right;
1072 margin:10px 0 0;
1072 margin:10px 0 0;
1073 padding:0;
1073 padding:0;
1074 }
1074 }
1075
1075
1076 #content div.box div.action select {
1076 #content div.box div.action select {
1077 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1077 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1078 font-size:11px;
1078 font-size:11px;
1079 margin:0;
1079 margin:0;
1080 }
1080 }
1081
1081
1082 #content div.box div.action .ui-selectmenu {
1082 #content div.box div.action .ui-selectmenu {
1083 margin:0;
1083 margin:0;
1084 padding:0;
1084 padding:0;
1085 }
1085 }
1086
1086
1087 #content div.box div.pagination {
1087 #content div.box div.pagination {
1088 height:1%;
1088 height:1%;
1089 clear:both;
1089 clear:both;
1090 overflow:hidden;
1090 overflow:hidden;
1091 margin:10px 0 0;
1091 margin:10px 0 0;
1092 padding:0;
1092 padding:0;
1093 }
1093 }
1094
1094
1095 #content div.box div.pagination ul.pager {
1095 #content div.box div.pagination ul.pager {
1096 float:right;
1096 float:right;
1097 text-align:right;
1097 text-align:right;
1098 margin:0;
1098 margin:0;
1099 padding:0;
1099 padding:0;
1100 }
1100 }
1101
1101
1102 #content div.box div.pagination ul.pager li {
1102 #content div.box div.pagination ul.pager li {
1103 height:1%;
1103 height:1%;
1104 float:left;
1104 float:left;
1105 list-style:none;
1105 list-style:none;
1106 background:#ebebeb url("../images/pager.png") repeat-x;
1106 background:#ebebeb url("../images/pager.png") repeat-x;
1107 border-top:1px solid #dedede;
1107 border-top:1px solid #dedede;
1108 border-left:1px solid #cfcfcf;
1108 border-left:1px solid #cfcfcf;
1109 border-right:1px solid #c4c4c4;
1109 border-right:1px solid #c4c4c4;
1110 border-bottom:1px solid #c4c4c4;
1110 border-bottom:1px solid #c4c4c4;
1111 color:#4A4A4A;
1111 color:#4A4A4A;
1112 font-weight:700;
1112 font-weight:700;
1113 margin:0 0 0 4px;
1113 margin:0 0 0 4px;
1114 padding:0;
1114 padding:0;
1115 }
1115 }
1116
1116
1117 #content div.box div.pagination ul.pager li.separator {
1117 #content div.box div.pagination ul.pager li.separator {
1118 padding:6px;
1118 padding:6px;
1119 }
1119 }
1120
1120
1121 #content div.box div.pagination ul.pager li.current {
1121 #content div.box div.pagination ul.pager li.current {
1122 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1122 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1123 border-top:1px solid #ccc;
1123 border-top:1px solid #ccc;
1124 border-left:1px solid #bebebe;
1124 border-left:1px solid #bebebe;
1125 border-right:1px solid #b1b1b1;
1125 border-right:1px solid #b1b1b1;
1126 border-bottom:1px solid #afafaf;
1126 border-bottom:1px solid #afafaf;
1127 color:#515151;
1127 color:#515151;
1128 padding:6px;
1128 padding:6px;
1129 }
1129 }
1130
1130
1131 #content div.box div.pagination ul.pager li a {
1131 #content div.box div.pagination ul.pager li a {
1132 height:1%;
1132 height:1%;
1133 display:block;
1133 display:block;
1134 float:left;
1134 float:left;
1135 color:#515151;
1135 color:#515151;
1136 text-decoration:none;
1136 text-decoration:none;
1137 margin:0;
1137 margin:0;
1138 padding:6px;
1138 padding:6px;
1139 }
1139 }
1140
1140
1141 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1141 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1142 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1142 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1143 border-top:1px solid #ccc;
1143 border-top:1px solid #ccc;
1144 border-left:1px solid #bebebe;
1144 border-left:1px solid #bebebe;
1145 border-right:1px solid #b1b1b1;
1145 border-right:1px solid #b1b1b1;
1146 border-bottom:1px solid #afafaf;
1146 border-bottom:1px solid #afafaf;
1147 margin:-1px;
1147 margin:-1px;
1148 }
1148 }
1149
1149
1150 #content div.box div.pagination-wh {
1150 #content div.box div.pagination-wh {
1151 height:1%;
1151 height:1%;
1152 clear:both;
1152 clear:both;
1153 overflow:hidden;
1153 overflow:hidden;
1154 text-align:right;
1154 text-align:right;
1155 margin:10px 0 0;
1155 margin:10px 0 0;
1156 padding:0;
1156 padding:0;
1157 }
1157 }
1158
1158
1159 #content div.box div.pagination-right {
1159 #content div.box div.pagination-right {
1160 float:right;
1160 float:right;
1161 }
1161 }
1162
1162
1163 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1163 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1164 height:1%;
1164 height:1%;
1165 float:left;
1165 float:left;
1166 background:#ebebeb url("../images/pager.png") repeat-x;
1166 background:#ebebeb url("../images/pager.png") repeat-x;
1167 border-top:1px solid #dedede;
1167 border-top:1px solid #dedede;
1168 border-left:1px solid #cfcfcf;
1168 border-left:1px solid #cfcfcf;
1169 border-right:1px solid #c4c4c4;
1169 border-right:1px solid #c4c4c4;
1170 border-bottom:1px solid #c4c4c4;
1170 border-bottom:1px solid #c4c4c4;
1171 color:#4A4A4A;
1171 color:#4A4A4A;
1172 font-weight:700;
1172 font-weight:700;
1173 margin:0 0 0 4px;
1173 margin:0 0 0 4px;
1174 padding:6px;
1174 padding:6px;
1175 }
1175 }
1176
1176
1177 #content div.box div.pagination-wh span.pager_curpage {
1177 #content div.box div.pagination-wh span.pager_curpage {
1178 height:1%;
1178 height:1%;
1179 float:left;
1179 float:left;
1180 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1180 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1181 border-top:1px solid #ccc;
1181 border-top:1px solid #ccc;
1182 border-left:1px solid #bebebe;
1182 border-left:1px solid #bebebe;
1183 border-right:1px solid #b1b1b1;
1183 border-right:1px solid #b1b1b1;
1184 border-bottom:1px solid #afafaf;
1184 border-bottom:1px solid #afafaf;
1185 color:#515151;
1185 color:#515151;
1186 font-weight:700;
1186 font-weight:700;
1187 margin:0 0 0 4px;
1187 margin:0 0 0 4px;
1188 padding:6px;
1188 padding:6px;
1189 }
1189 }
1190
1190
1191 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1191 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1192 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1192 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1193 border-top:1px solid #ccc;
1193 border-top:1px solid #ccc;
1194 border-left:1px solid #bebebe;
1194 border-left:1px solid #bebebe;
1195 border-right:1px solid #b1b1b1;
1195 border-right:1px solid #b1b1b1;
1196 border-bottom:1px solid #afafaf;
1196 border-bottom:1px solid #afafaf;
1197 text-decoration:none;
1197 text-decoration:none;
1198 }
1198 }
1199
1199
1200 #content div.box div.traffic div.legend {
1200 #content div.box div.traffic div.legend {
1201 clear:both;
1201 clear:both;
1202 overflow:hidden;
1202 overflow:hidden;
1203 border-bottom:1px solid #ddd;
1203 border-bottom:1px solid #ddd;
1204 margin:0 0 10px;
1204 margin:0 0 10px;
1205 padding:0 0 10px;
1205 padding:0 0 10px;
1206 }
1206 }
1207
1207
1208 #content div.box div.traffic div.legend h6 {
1208 #content div.box div.traffic div.legend h6 {
1209 float:left;
1209 float:left;
1210 border:none;
1210 border:none;
1211 margin:0;
1211 margin:0;
1212 padding:0;
1212 padding:0;
1213 }
1213 }
1214
1214
1215 #content div.box div.traffic div.legend li {
1215 #content div.box div.traffic div.legend li {
1216 list-style:none;
1216 list-style:none;
1217 float:left;
1217 float:left;
1218 font-size:11px;
1218 font-size:11px;
1219 margin:0;
1219 margin:0;
1220 padding:0 8px 0 4px;
1220 padding:0 8px 0 4px;
1221 }
1221 }
1222
1222
1223 #content div.box div.traffic div.legend li.visits {
1223 #content div.box div.traffic div.legend li.visits {
1224 border-left:12px solid #edc240;
1224 border-left:12px solid #edc240;
1225 }
1225 }
1226
1226
1227 #content div.box div.traffic div.legend li.pageviews {
1227 #content div.box div.traffic div.legend li.pageviews {
1228 border-left:12px solid #afd8f8;
1228 border-left:12px solid #afd8f8;
1229 }
1229 }
1230
1230
1231 #content div.box div.traffic table {
1231 #content div.box div.traffic table {
1232 width:auto;
1232 width:auto;
1233 }
1233 }
1234
1234
1235 #content div.box div.traffic table td {
1235 #content div.box div.traffic table td {
1236 background:transparent;
1236 background:transparent;
1237 border:none;
1237 border:none;
1238 padding:2px 3px 3px;
1238 padding:2px 3px 3px;
1239 }
1239 }
1240
1240
1241 #content div.box div.traffic table td.legendLabel {
1241 #content div.box div.traffic table td.legendLabel {
1242 padding:0 3px 2px;
1242 padding:0 3px 2px;
1243 }
1243 }
1244
1244
1245 #footer {
1245 #footer {
1246 clear:both;
1246 clear:both;
1247 overflow:hidden;
1247 overflow:hidden;
1248 text-align:right;
1248 text-align:right;
1249 margin:0;
1249 margin:0;
1250 padding:0 30px 4px;
1250 padding:0 30px 4px;
1251 margin:-10px 0 0;
1251 margin:-10px 0 0;
1252 }
1252 }
1253
1253
1254 #footer div#footer-inner {
1254 #footer div#footer-inner {
1255 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1255 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1256 border-top:2px solid #FFFFFF;
1256 border-top:2px solid #FFFFFF;
1257 }
1257 }
1258
1258
1259 #footer div#footer-inner p {
1259 #footer div#footer-inner p {
1260 padding:15px 25px 15px 0;
1260 padding:15px 25px 15px 0;
1261 color:#FFF;
1261 color:#FFF;
1262 font-weight:700;
1262 font-weight:700;
1263 }
1263 }
1264 #footer div#footer-inner .footer-link {
1264 #footer div#footer-inner .footer-link {
1265 float:left;
1265 float:left;
1266 padding-left:10px;
1266 padding-left:10px;
1267 }
1267 }
1268 #footer div#footer-inner .footer-link a {
1268 #footer div#footer-inner .footer-link a {
1269 color:#FFF;
1269 color:#FFF;
1270 }
1270 }
1271
1271
1272 #login div.title {
1272 #login div.title {
1273 width:420px;
1273 width:420px;
1274 clear:both;
1274 clear:both;
1275 overflow:hidden;
1275 overflow:hidden;
1276 position:relative;
1276 position:relative;
1277 background:#003367 url("../../images/header_inner.png") repeat-x;
1277 background:#003367 url("../../images/header_inner.png") repeat-x;
1278 margin:0 auto;
1278 margin:0 auto;
1279 padding:0;
1279 padding:0;
1280 }
1280 }
1281
1281
1282 #login div.inner {
1282 #login div.inner {
1283 width:380px;
1283 width:380px;
1284 background:#FFF url("../images/login.png") no-repeat top left;
1284 background:#FFF url("../images/login.png") no-repeat top left;
1285 border-top:none;
1285 border-top:none;
1286 border-bottom:none;
1286 border-bottom:none;
1287 margin:0 auto;
1287 margin:0 auto;
1288 padding:20px;
1288 padding:20px;
1289 }
1289 }
1290
1290
1291 #login div.form div.fields div.field div.label {
1291 #login div.form div.fields div.field div.label {
1292 width:173px;
1292 width:173px;
1293 float:left;
1293 float:left;
1294 text-align:right;
1294 text-align:right;
1295 margin:2px 10px 0 0;
1295 margin:2px 10px 0 0;
1296 padding:5px 0 0 5px;
1296 padding:5px 0 0 5px;
1297 }
1297 }
1298
1298
1299 #login div.form div.fields div.field div.input input {
1299 #login div.form div.fields div.field div.input input {
1300 width:176px;
1300 width:176px;
1301 background:#FFF;
1301 background:#FFF;
1302 border-top:1px solid #b3b3b3;
1302 border-top:1px solid #b3b3b3;
1303 border-left:1px solid #b3b3b3;
1303 border-left:1px solid #b3b3b3;
1304 border-right:1px solid #eaeaea;
1304 border-right:1px solid #eaeaea;
1305 border-bottom:1px solid #eaeaea;
1305 border-bottom:1px solid #eaeaea;
1306 color:#000;
1306 color:#000;
1307 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1307 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1308 font-size:11px;
1308 font-size:11px;
1309 margin:0;
1309 margin:0;
1310 padding:7px 7px 6px;
1310 padding:7px 7px 6px;
1311 }
1311 }
1312
1312
1313 #login div.form div.fields div.buttons {
1313 #login div.form div.fields div.buttons {
1314 clear:both;
1314 clear:both;
1315 overflow:hidden;
1315 overflow:hidden;
1316 border-top:1px solid #DDD;
1316 border-top:1px solid #DDD;
1317 text-align:right;
1317 text-align:right;
1318 margin:0;
1318 margin:0;
1319 padding:10px 0 0;
1319 padding:10px 0 0;
1320 }
1320 }
1321
1321
1322 #login div.form div.links {
1322 #login div.form div.links {
1323 clear:both;
1323 clear:both;
1324 overflow:hidden;
1324 overflow:hidden;
1325 margin:10px 0 0;
1325 margin:10px 0 0;
1326 padding:0 0 2px;
1326 padding:0 0 2px;
1327 }
1327 }
1328
1328
1329 #register div.title {
1329 #register div.title {
1330 clear:both;
1330 clear:both;
1331 overflow:hidden;
1331 overflow:hidden;
1332 position:relative;
1332 position:relative;
1333 background:#003367 url("../images/header_inner.png") repeat-x;
1333 background:#003367 url("../images/header_inner.png") repeat-x;
1334 margin:0 auto;
1334 margin:0 auto;
1335 padding:0;
1335 padding:0;
1336 }
1336 }
1337
1337
1338 #register div.inner {
1338 #register div.inner {
1339 background:#FFF;
1339 background:#FFF;
1340 border-top:none;
1340 border-top:none;
1341 border-bottom:none;
1341 border-bottom:none;
1342 margin:0 auto;
1342 margin:0 auto;
1343 padding:20px;
1343 padding:20px;
1344 }
1344 }
1345
1345
1346 #register div.form div.fields div.field div.label {
1346 #register div.form div.fields div.field div.label {
1347 width:135px;
1347 width:135px;
1348 float:left;
1348 float:left;
1349 text-align:right;
1349 text-align:right;
1350 margin:2px 10px 0 0;
1350 margin:2px 10px 0 0;
1351 padding:5px 0 0 5px;
1351 padding:5px 0 0 5px;
1352 }
1352 }
1353
1353
1354 #register div.form div.fields div.field div.input input {
1354 #register div.form div.fields div.field div.input input {
1355 width:300px;
1355 width:300px;
1356 background:#FFF;
1356 background:#FFF;
1357 border-top:1px solid #b3b3b3;
1357 border-top:1px solid #b3b3b3;
1358 border-left:1px solid #b3b3b3;
1358 border-left:1px solid #b3b3b3;
1359 border-right:1px solid #eaeaea;
1359 border-right:1px solid #eaeaea;
1360 border-bottom:1px solid #eaeaea;
1360 border-bottom:1px solid #eaeaea;
1361 color:#000;
1361 color:#000;
1362 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1362 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1363 font-size:11px;
1363 font-size:11px;
1364 margin:0;
1364 margin:0;
1365 padding:7px 7px 6px;
1365 padding:7px 7px 6px;
1366 }
1366 }
1367
1367
1368 #register div.form div.fields div.buttons {
1368 #register div.form div.fields div.buttons {
1369 clear:both;
1369 clear:both;
1370 overflow:hidden;
1370 overflow:hidden;
1371 border-top:1px solid #DDD;
1371 border-top:1px solid #DDD;
1372 text-align:left;
1372 text-align:left;
1373 margin:0;
1373 margin:0;
1374 padding:10px 0 0 114px;
1374 padding:10px 0 0 114px;
1375 }
1375 }
1376
1376
1377 #register div.form div.fields div.buttons div.highlight input.ui-state-default {
1377 #register div.form div.fields div.buttons div.highlight input.ui-state-default {
1378 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1378 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1379 color:#FFF;
1379 color:#FFF;
1380 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1380 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1381 border-style:solid;
1381 border-style:solid;
1382 border-width:1px;
1382 border-width:1px;
1383 }
1383 }
1384
1384
1385 #register div.form div.activation_msg {
1385 #register div.form div.activation_msg {
1386 padding-top:4px;
1386 padding-top:4px;
1387 padding-bottom:4px;
1387 padding-bottom:4px;
1388 }
1388 }
1389
1389
1390 .trending_language_tbl,.trending_language_tbl td {
1390 .trending_language_tbl,.trending_language_tbl td {
1391 border:0 !important;
1391 border:0 !important;
1392 margin:0 !important;
1392 margin:0 !important;
1393 padding:0 !important;
1393 padding:0 !important;
1394 }
1394 }
1395
1395
1396 .trending_language {
1396 .trending_language {
1397 background-color:#003367;
1397 background-color:#003367;
1398 color:#FFF;
1398 color:#FFF;
1399 display:block;
1399 display:block;
1400 min-width:20px;
1400 min-width:20px;
1401 text-decoration:none;
1401 text-decoration:none;
1402 height:12px;
1402 height:12px;
1403 margin-bottom:4px;
1403 margin-bottom:4px;
1404 margin-left:5px;
1404 margin-left:5px;
1405 white-space:pre;
1405 white-space:pre;
1406 padding:3px;
1406 padding:3px;
1407 }
1407 }
1408
1408
1409 h3.files_location {
1409 h3.files_location {
1410 font-size:1.8em;
1410 font-size:1.8em;
1411 font-weight:700;
1411 font-weight:700;
1412 border-bottom:none !important;
1412 border-bottom:none !important;
1413 margin:10px 0 !important;
1413 margin:10px 0 !important;
1414 }
1414 }
1415
1415
1416 #files_data dl dt {
1416 #files_data dl dt {
1417 float:left;
1417 float:left;
1418 width:115px;
1418 width:115px;
1419 margin:0 !important;
1419 margin:0 !important;
1420 padding:5px;
1420 padding:5px;
1421 }
1421 }
1422
1422
1423 #files_data dl dd {
1423 #files_data dl dd {
1424 margin:0 !important;
1424 margin:0 !important;
1425 padding:5px !important;
1425 padding:5px !important;
1426 }
1426 }
1427
1427
1428 #changeset_content {
1428 #changeset_content {
1429 border:1px solid #CCC;
1429 border:1px solid #CCC;
1430 padding:5px;
1430 padding:5px;
1431 }
1431 }
1432
1432
1433 #changeset_content .container {
1433 #changeset_content .container {
1434 min-height:120px;
1434 min-height:120px;
1435 font-size:1.2em;
1435 font-size:1.2em;
1436 overflow:hidden;
1436 overflow:hidden;
1437 }
1437 }
1438
1438
1439 #changeset_content .container .right {
1439 #changeset_content .container .right {
1440 float:right;
1440 float:right;
1441 width:25%;
1441 width:25%;
1442 text-align:right;
1442 text-align:right;
1443 }
1443 }
1444
1444
1445 #changeset_content .container .left .message {
1445 #changeset_content .container .left .message {
1446 font-style:italic;
1446 font-style:italic;
1447 color:#556CB5;
1447 color:#556CB5;
1448 white-space:pre-wrap;
1448 white-space:pre-wrap;
1449 }
1449 }
1450
1450
1451 .cs_files .cs_added {
1451 .cs_files .cs_added {
1452 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1452 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1453 height:16px;
1453 height:16px;
1454 padding-left:20px;
1454 padding-left:20px;
1455 margin-top:7px;
1455 margin-top:7px;
1456 text-align:left;
1456 text-align:left;
1457 }
1457 }
1458
1458
1459 .cs_files .cs_changed {
1459 .cs_files .cs_changed {
1460 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1460 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1461 height:16px;
1461 height:16px;
1462 padding-left:20px;
1462 padding-left:20px;
1463 margin-top:7px;
1463 margin-top:7px;
1464 text-align:left;
1464 text-align:left;
1465 }
1465 }
1466
1466
1467 .cs_files .cs_removed {
1467 .cs_files .cs_removed {
1468 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1468 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1469 height:16px;
1469 height:16px;
1470 padding-left:20px;
1470 padding-left:20px;
1471 margin-top:7px;
1471 margin-top:7px;
1472 text-align:left;
1472 text-align:left;
1473 }
1473 }
1474
1474
1475 #graph {
1475 #graph {
1476 overflow:hidden;
1476 overflow:hidden;
1477 }
1477 }
1478
1478
1479 #graph_nodes {
1479 #graph_nodes {
1480 width:160px;
1480 width:160px;
1481 float:left;
1481 float:left;
1482 margin-left:-50px;
1482 margin-left:-50px;
1483 margin-top:5px;
1483 margin-top:5px;
1484 }
1484 }
1485
1485
1486 #graph_content {
1486 #graph_content {
1487 width:800px;
1487 width:800px;
1488 float:left;
1488 float:left;
1489 }
1489 }
1490
1490
1491 #graph_content .container_header {
1491 #graph_content .container_header {
1492 border:1px solid #CCC;
1492 border:1px solid #CCC;
1493 padding:10px;
1493 padding:10px;
1494 }
1494 }
1495
1495
1496 #graph_content .container {
1496 #graph_content .container {
1497 border-bottom:1px solid #CCC;
1497 border-bottom:1px solid #CCC;
1498 border-left:1px solid #CCC;
1498 border-left:1px solid #CCC;
1499 border-right:1px solid #CCC;
1499 border-right:1px solid #CCC;
1500 min-height:80px;
1500 min-height:80px;
1501 overflow:hidden;
1501 overflow:hidden;
1502 font-size:1.2em;
1502 font-size:1.2em;
1503 }
1503 }
1504
1504
1505 #graph_content .container .right {
1505 #graph_content .container .right {
1506 float:right;
1506 float:right;
1507 width:28%;
1507 width:28%;
1508 text-align:right;
1508 text-align:right;
1509 padding-bottom:5px;
1509 padding-bottom:5px;
1510 }
1510 }
1511
1511
1512 #graph_content .container .left .date {
1512 #graph_content .container .left .date {
1513 font-weight:700;
1513 font-weight:700;
1514 padding-bottom:5px;
1514 padding-bottom:5px;
1515 }
1515 }
1516
1516
1517 #graph_content .container .left .message {
1517 #graph_content .container .left .message {
1518 font-size:100%;
1518 font-size:100%;
1519 padding-top:3px;
1519 padding-top:3px;
1520 white-space:pre-wrap;
1520 white-space:pre-wrap;
1521 }
1521 }
1522
1522
1523 .right div {
1523 .right div {
1524 clear:both;
1524 clear:both;
1525 }
1525 }
1526
1526
1527 .right .changes .added,.changed,.removed {
1527 .right .changes .added,.changed,.removed {
1528 border:1px solid #DDD;
1528 border:1px solid #DDD;
1529 display:block;
1529 display:block;
1530 float:right;
1530 float:right;
1531 text-align:center;
1531 text-align:center;
1532 min-width:15px;
1532 min-width:15px;
1533 }
1533 }
1534
1534
1535 .right .changes .added {
1535 .right .changes .added {
1536 background:#BFB;
1536 background:#BFB;
1537 }
1537 }
1538
1538
1539 .right .changes .changed {
1539 .right .changes .changed {
1540 background:#FD8;
1540 background:#FD8;
1541 }
1541 }
1542
1542
1543 .right .changes .removed {
1543 .right .changes .removed {
1544 background:#F88;
1544 background:#F88;
1545 }
1545 }
1546
1546
1547 .right .merge {
1547 .right .merge {
1548 vertical-align:top;
1548 vertical-align:top;
1549 font-size:0.75em;
1549 font-size:0.75em;
1550 font-weight:700;
1550 font-weight:700;
1551 }
1551 }
1552
1552
1553 .right .parent {
1553 .right .parent {
1554 font-size:90%;
1554 font-size:90%;
1555 font-family:monospace;
1555 font-family:monospace;
1556 }
1556 }
1557
1557
1558 .right .logtags .branchtag {
1558 .right .logtags .branchtag {
1559 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1559 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1560 display:block;
1560 display:block;
1561 font-size:0.8em;
1561 font-size:0.8em;
1562 padding:11px 16px 0 0;
1562 padding:11px 16px 0 0;
1563 }
1563 }
1564
1564
1565 .right .logtags .tagtag {
1565 .right .logtags .tagtag {
1566 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1566 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1567 display:block;
1567 display:block;
1568 font-size:0.8em;
1568 font-size:0.8em;
1569 padding:11px 16px 0 0;
1569 padding:11px 16px 0 0;
1570 }
1570 }
1571
1571
1572 div.browserblock {
1572 div.browserblock {
1573 overflow:hidden;
1573 overflow:hidden;
1574 border:1px solid #ccc;
1574 border:1px solid #ccc;
1575 background:#f8f8f8;
1575 background:#f8f8f8;
1576 font-size:100%;
1576 font-size:100%;
1577 line-height:125%;
1577 line-height:125%;
1578 padding:0;
1578 padding:0;
1579 }
1579 }
1580
1580
1581 div.browserblock .browser-header {
1581 div.browserblock .browser-header {
1582 border-bottom:1px solid #CCC;
1582 border-bottom:1px solid #CCC;
1583 background:#FFF;
1583 background:#FFF;
1584 color:blue;
1584 color:blue;
1585 padding:10px 0;
1585 padding:10px 0;
1586 }
1586 }
1587
1587
1588 div.browserblock .browser-header span {
1588 div.browserblock .browser-header span {
1589 margin-left:25px;
1589 margin-left:25px;
1590 font-weight:700;
1590 font-weight:700;
1591 }
1591 }
1592
1592
1593 div.browserblock .browser-body {
1593 div.browserblock .browser-body {
1594 background:#EEE;
1594 background:#EEE;
1595 }
1595 }
1596
1596
1597 table.code-browser {
1597 table.code-browser {
1598 border-collapse:collapse;
1598 border-collapse:collapse;
1599 width:100%;
1599 width:100%;
1600 }
1600 }
1601
1601
1602 table.code-browser tr {
1602 table.code-browser tr {
1603 margin:3px;
1603 margin:3px;
1604 }
1604 }
1605
1605
1606 table.code-browser thead th {
1606 table.code-browser thead th {
1607 background-color:#EEE;
1607 background-color:#EEE;
1608 height:20px;
1608 height:20px;
1609 font-size:1.1em;
1609 font-size:1.1em;
1610 font-weight:700;
1610 font-weight:700;
1611 text-align:left;
1611 text-align:left;
1612 padding-left:10px;
1612 padding-left:10px;
1613 }
1613 }
1614
1614
1615 table.code-browser tbody td {
1615 table.code-browser tbody td {
1616 padding-left:10px;
1616 padding-left:10px;
1617 height:20px;
1617 height:20px;
1618 }
1618 }
1619
1619
1620 table.code-browser .browser-file {
1620 table.code-browser .browser-file {
1621 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1621 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1622 height:16px;
1622 height:16px;
1623 padding-left:20px;
1623 padding-left:20px;
1624 text-align:left;
1624 text-align:left;
1625 }
1625 }
1626
1626
1627 table.code-browser .browser-dir {
1627 table.code-browser .browser-dir {
1628 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1628 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1629 height:16px;
1629 height:16px;
1630 padding-left:20px;
1630 padding-left:20px;
1631 text-align:left;
1631 text-align:left;
1632 }
1632 }
1633
1633
1634 .box .search {
1634 .box .search {
1635 clear:both;
1635 clear:both;
1636 overflow:hidden;
1636 overflow:hidden;
1637 margin:0;
1637 margin:0;
1638 padding:0 20px 10px;
1638 padding:0 20px 10px;
1639 }
1639 }
1640
1640
1641 .box .search div.search_path {
1641 .box .search div.search_path {
1642 background:none repeat scroll 0 0 #EEE;
1642 background:none repeat scroll 0 0 #EEE;
1643 border:1px solid #CCC;
1643 border:1px solid #CCC;
1644 color:blue;
1644 color:blue;
1645 margin-bottom:10px;
1645 margin-bottom:10px;
1646 padding:10px 0;
1646 padding:10px 0;
1647 }
1647 }
1648
1648
1649 .box .search div.search_path div.link {
1649 .box .search div.search_path div.link {
1650 font-weight:700;
1650 font-weight:700;
1651 margin-left:25px;
1651 margin-left:25px;
1652 }
1652 }
1653
1653
1654 .box .search div.search_path div.link a {
1654 .box .search div.search_path div.link a {
1655 color:#003367;
1655 color:#003367;
1656 cursor:pointer;
1656 cursor:pointer;
1657 text-decoration:none;
1657 text-decoration:none;
1658 }
1658 }
1659
1659
1660 #path_unlock {
1660 #path_unlock {
1661 color:red;
1661 color:red;
1662 font-size:1.2em;
1662 font-size:1.2em;
1663 padding-left:4px;
1663 padding-left:4px;
1664 }
1664 }
1665
1665
1666 .info_box * {
1666 .info_box * {
1667 background:url("../../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1667 background:url("../../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1668 color:#4A4A4A;
1668 color:#4A4A4A;
1669 font-weight:700;
1669 font-weight:700;
1670 height:1%;
1670 height:1%;
1671 display:inline;
1671 display:inline;
1672 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1672 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1673 border-style:solid;
1673 border-style:solid;
1674 border-width:1px;
1674 border-width:1px;
1675 padding:4px 6px;
1675 padding:4px 6px;
1676 }
1676 }
1677
1677
1678 .info_box span {
1678 .info_box span {
1679 margin-left:3px;
1679 margin-left:3px;
1680 margin-right:3px;
1680 margin-right:3px;
1681 }
1681 }
1682
1682
1683 .info_box input#at_rev {
1683 .info_box input#at_rev {
1684 text-align:center;
1684 text-align:center;
1685 padding:5px 3px 3px 2px;
1685 padding:5px 3px 3px 2px;
1686 }
1686 }
1687
1687
1688 .info_box input#view {
1688 .info_box input#view {
1689 text-align:center;
1689 text-align:center;
1690 padding:4px 3px 2px 2px;
1690 padding:4px 3px 2px 2px;
1691 }
1691 }
1692
1692
1693 .yui-overlay,.yui-panel-container {
1693 .yui-overlay,.yui-panel-container {
1694 visibility:hidden;
1694 visibility:hidden;
1695 position:absolute;
1695 position:absolute;
1696 z-index:2;
1696 z-index:2;
1697 }
1697 }
1698
1698
1699 .yui-tt {
1699 .yui-tt {
1700 visibility:hidden;
1700 visibility:hidden;
1701 position:absolute;
1701 position:absolute;
1702 color:#666;
1702 color:#666;
1703 background-color:#FFF;
1703 background-color:#FFF;
1704 font-family:arial, helvetica, verdana, sans-serif;
1704 font-family:arial, helvetica, verdana, sans-serif;
1705 border:2px solid #003367;
1705 border:2px solid #003367;
1706 font:100% sans-serif;
1706 font:100% sans-serif;
1707 width:auto;
1707 width:auto;
1708 opacity:1px;
1708 opacity:1px;
1709 padding:8px;
1709 padding:8px;
1710 white-space: pre;
1710 white-space: pre;
1711 }
1711 }
1712
1712
1713 .ac {
1713 .ac {
1714 vertical-align:top;
1714 vertical-align:top;
1715 }
1715 }
1716
1716
1717 .ac .yui-ac {
1717 .ac .yui-ac {
1718 position:relative;
1718 position:relative;
1719 font-family:arial;
1719 font-family:arial;
1720 font-size:100%;
1720 font-size:100%;
1721 }
1721 }
1722
1722
1723 .ac .perm_ac {
1723 .ac .perm_ac {
1724 width:15em;
1724 width:15em;
1725 }
1725 }
1726
1726
1727 .ac .yui-ac-input {
1727 .ac .yui-ac-input {
1728 width:100%;
1728 width:100%;
1729 }
1729 }
1730
1730
1731 .ac .yui-ac-container {
1731 .ac .yui-ac-container {
1732 position:absolute;
1732 position:absolute;
1733 top:1.6em;
1733 top:1.6em;
1734 width:100%;
1734 width:100%;
1735 }
1735 }
1736
1736
1737 .ac .yui-ac-content {
1737 .ac .yui-ac-content {
1738 position:absolute;
1738 position:absolute;
1739 width:100%;
1739 width:100%;
1740 border:1px solid gray;
1740 border:1px solid gray;
1741 background:#fff;
1741 background:#fff;
1742 overflow:hidden;
1742 overflow:hidden;
1743 z-index:9050;
1743 z-index:9050;
1744 }
1744 }
1745
1745
1746 .ac .yui-ac-shadow {
1746 .ac .yui-ac-shadow {
1747 position:absolute;
1747 position:absolute;
1748 width:100%;
1748 width:100%;
1749 background:#000;
1749 background:#000;
1750 -moz-opacity:0.1px;
1750 -moz-opacity:0.1px;
1751 opacity:.10;
1751 opacity:.10;
1752 filter:alpha(opacity = 10);
1752 filter:alpha(opacity = 10);
1753 z-index:9049;
1753 z-index:9049;
1754 margin:.3em;
1754 margin:.3em;
1755 }
1755 }
1756
1756
1757 .ac .yui-ac-content ul {
1757 .ac .yui-ac-content ul {
1758 width:100%;
1758 width:100%;
1759 margin:0;
1759 margin:0;
1760 padding:0;
1760 padding:0;
1761 }
1761 }
1762
1762
1763 .ac .yui-ac-content li {
1763 .ac .yui-ac-content li {
1764 cursor:default;
1764 cursor:default;
1765 white-space:nowrap;
1765 white-space:nowrap;
1766 margin:0;
1766 margin:0;
1767 padding:2px 5px;
1767 padding:2px 5px;
1768 }
1768 }
1769
1769
1770 .ac .yui-ac-content li.yui-ac-prehighlight {
1770 .ac .yui-ac-content li.yui-ac-prehighlight {
1771 background:#B3D4FF;
1771 background:#B3D4FF;
1772 }
1772 }
1773
1773
1774 .ac .yui-ac-content li.yui-ac-highlight {
1774 .ac .yui-ac-content li.yui-ac-highlight {
1775 background:#556CB5;
1775 background:#556CB5;
1776 color:#FFF;
1776 color:#FFF;
1777 }
1777 }
1778
1778
1779 .follow{
1780 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1781 height: 16px;
1782 width: 20px;
1783 cursor: pointer;
1784 display: block;
1785 float: right;
1786 margin-top: 2px;
1787 }
1788
1789 .following{
1790 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
1791 height: 16px;
1792 width: 20px;
1793 cursor: pointer;
1794 display: block;
1795 float: right;
1796 margin-top: 2px;
1797 }
1798
1779 .add_icon {
1799 .add_icon {
1780 background:url("../images/icons/add.png") no-repeat scroll 3px;
1800 background:url("../images/icons/add.png") no-repeat scroll 3px;
1781 height:16px;
1801 height:16px;
1782 padding-left:20px;
1802 padding-left:20px;
1783 padding-top:1px;
1803 padding-top:1px;
1784 text-align:left;
1804 text-align:left;
1785 }
1805 }
1786
1806
1787 .edit_icon {
1807 .edit_icon {
1788 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1808 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1789 height:16px;
1809 height:16px;
1790 padding-left:20px;
1810 padding-left:20px;
1791 padding-top:1px;
1811 padding-top:1px;
1792 text-align:left;
1812 text-align:left;
1793 }
1813 }
1794
1814
1795 .delete_icon {
1815 .delete_icon {
1796 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1816 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1797 height:16px;
1817 height:16px;
1798 padding-left:20px;
1818 padding-left:20px;
1799 padding-top:1px;
1819 padding-top:1px;
1800 text-align:left;
1820 text-align:left;
1801 }
1821 }
1802
1822
1803 .refresh_icon {
1823 .refresh_icon {
1804 background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
1824 background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
1805 height:16px;
1825 height:16px;
1806 padding-left:20px;
1826 padding-left:20px;
1807 padding-top:1px;
1827 padding-top:1px;
1808 text-align:left;
1828 text-align:left;
1809 }
1829 }
1810
1830
1811 .rss_icon {
1831 .rss_icon {
1812 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1832 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1813 height:16px;
1833 height:16px;
1814 padding-left:20px;
1834 padding-left:20px;
1815 padding-top:1px;
1835 padding-top:1px;
1816 text-align:left;
1836 text-align:left;
1817 }
1837 }
1818
1838
1819 .atom_icon {
1839 .atom_icon {
1820 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1840 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1821 height:16px;
1841 height:16px;
1822 padding-left:20px;
1842 padding-left:20px;
1823 padding-top:1px;
1843 padding-top:1px;
1824 text-align:left;
1844 text-align:left;
1825 }
1845 }
1826
1846
1827 .archive_icon {
1847 .archive_icon {
1828 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1848 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1829 height:16px;
1849 height:16px;
1830 padding-left:20px;
1850 padding-left:20px;
1831 text-align:left;
1851 text-align:left;
1832 padding-top:1px;
1852 padding-top:1px;
1833 }
1853 }
1834
1854
1835 .action_button {
1855 .action_button {
1836 border:0;
1856 border:0;
1837 display:block;
1857 display:block;
1838 }
1858 }
1839
1859
1840 .action_button:hover {
1860 .action_button:hover {
1841 border:0;
1861 border:0;
1842 text-decoration:underline;
1862 text-decoration:underline;
1843 cursor:pointer;
1863 cursor:pointer;
1844 }
1864 }
1845
1865
1846 #switch_repos {
1866 #switch_repos {
1847 position:absolute;
1867 position:absolute;
1848 height:25px;
1868 height:25px;
1849 z-index:1;
1869 z-index:1;
1850 }
1870 }
1851
1871
1852 #switch_repos select {
1872 #switch_repos select {
1853 min-width:150px;
1873 min-width:150px;
1854 max-height:250px;
1874 max-height:250px;
1855 z-index:1;
1875 z-index:1;
1856 }
1876 }
1857
1877
1858 .breadcrumbs {
1878 .breadcrumbs {
1859 border:medium none;
1879 border:medium none;
1860 color:#FFF;
1880 color:#FFF;
1861 float:left;
1881 float:left;
1862 text-transform:uppercase;
1882 text-transform:uppercase;
1863 font-weight:700;
1883 font-weight:700;
1864 font-size:14px;
1884 font-size:14px;
1865 margin:0;
1885 margin:0;
1866 padding:11px 0 11px 10px;
1886 padding:11px 0 11px 10px;
1867 }
1887 }
1868
1888
1869 .breadcrumbs a {
1889 .breadcrumbs a {
1870 color:#FFF;
1890 color:#FFF;
1871 }
1891 }
1872
1892
1873 .flash_msg ul {
1893 .flash_msg ul {
1874 margin:0;
1894 margin:0;
1875 padding:0 0 10px;
1895 padding:0 0 10px;
1876 }
1896 }
1877
1897
1878 .error_msg {
1898 .error_msg {
1879 background-color:#FFCFCF;
1899 background-color:#FFCFCF;
1880 background-image:url("../../images/icons/error_msg.png");
1900 background-image:url("../../images/icons/error_msg.png");
1881 border:1px solid #FF9595;
1901 border:1px solid #FF9595;
1882 color:#C30;
1902 color:#C30;
1883 }
1903 }
1884
1904
1885 .warning_msg {
1905 .warning_msg {
1886 background-color:#FFFBCC;
1906 background-color:#FFFBCC;
1887 background-image:url("../../images/icons/warning_msg.png");
1907 background-image:url("../../images/icons/warning_msg.png");
1888 border:1px solid #FFF35E;
1908 border:1px solid #FFF35E;
1889 color:#C69E00;
1909 color:#C69E00;
1890 }
1910 }
1891
1911
1892 .success_msg {
1912 .success_msg {
1893 background-color:#D5FFCF;
1913 background-color:#D5FFCF;
1894 background-image:url("../../images/icons/success_msg.png");
1914 background-image:url("../../images/icons/success_msg.png");
1895 border:1px solid #97FF88;
1915 border:1px solid #97FF88;
1896 color:#090;
1916 color:#090;
1897 }
1917 }
1898
1918
1899 .notice_msg {
1919 .notice_msg {
1900 background-color:#DCE3FF;
1920 background-color:#DCE3FF;
1901 background-image:url("../../images/icons/notice_msg.png");
1921 background-image:url("../../images/icons/notice_msg.png");
1902 border:1px solid #93A8FF;
1922 border:1px solid #93A8FF;
1903 color:#556CB5;
1923 color:#556CB5;
1904 }
1924 }
1905
1925
1906 .success_msg,.error_msg,.notice_msg,.warning_msg {
1926 .success_msg,.error_msg,.notice_msg,.warning_msg {
1907 background-position:10px center;
1927 background-position:10px center;
1908 background-repeat:no-repeat;
1928 background-repeat:no-repeat;
1909 font-size:12px;
1929 font-size:12px;
1910 font-weight:700;
1930 font-weight:700;
1911 min-height:14px;
1931 min-height:14px;
1912 line-height:14px;
1932 line-height:14px;
1913 margin-bottom:0;
1933 margin-bottom:0;
1914 margin-top:0;
1934 margin-top:0;
1915 display:block;
1935 display:block;
1916 overflow:auto;
1936 overflow:auto;
1917 padding:6px 10px 6px 40px;
1937 padding:6px 10px 6px 40px;
1918 }
1938 }
1919
1939
1920 #msg_close {
1940 #msg_close {
1921 background:transparent url("../../icons/cross_grey_small.png") no-repeat scroll 0 0;
1941 background:transparent url("../../icons/cross_grey_small.png") no-repeat scroll 0 0;
1922 cursor:pointer;
1942 cursor:pointer;
1923 height:16px;
1943 height:16px;
1924 position:absolute;
1944 position:absolute;
1925 right:5px;
1945 right:5px;
1926 top:5px;
1946 top:5px;
1927 width:16px;
1947 width:16px;
1928 }
1948 }
1929
1949
1930 div#legend_container table,div#legend_choices table {
1950 div#legend_container table,div#legend_choices table {
1931 width:auto !important;
1951 width:auto !important;
1932 }
1952 }
1933
1953
1934 table#permissions_manage {
1954 table#permissions_manage {
1935 width:0 !important;
1955 width:0 !important;
1936 }
1956 }
1937
1957
1938 table#permissions_manage span.private_repo_msg {
1958 table#permissions_manage span.private_repo_msg {
1939 font-size:0.8em;
1959 font-size:0.8em;
1940 opacity:0.6px;
1960 opacity:0.6px;
1941 }
1961 }
1942
1962
1943 table#permissions_manage td.private_repo_msg {
1963 table#permissions_manage td.private_repo_msg {
1944 font-size:0.8em;
1964 font-size:0.8em;
1945 }
1965 }
1946
1966
1947 table#permissions_manage tr#add_perm_input td {
1967 table#permissions_manage tr#add_perm_input td {
1948 vertical-align:middle;
1968 vertical-align:middle;
1949 }
1969 }
1950
1970
1951 div.gravatar {
1971 div.gravatar {
1952 background-color:#FFF;
1972 background-color:#FFF;
1953 border:1px solid #D0D0D0;
1973 border:1px solid #D0D0D0;
1954 float:left;
1974 float:left;
1955 margin-right:0.7em;
1975 margin-right:0.7em;
1956 padding:2px 2px 0;
1976 padding:2px 2px 0;
1957 }
1977 }
1958
1978
1959 #header,#content,#footer {
1979 #header,#content,#footer {
1960 min-width:1024px;
1980 min-width:1024px;
1961 }
1981 }
1962
1982
1963 #content {
1983 #content {
1964 min-height:100%;
1984 min-height:100%;
1965 clear:both;
1985 clear:both;
1966 overflow:hidden;
1986 overflow:hidden;
1967 padding:14px 30px;
1987 padding:14px 30px;
1968 }
1988 }
1969
1989
1970 #content div.box div.title div.search {
1990 #content div.box div.title div.search {
1971 background:url("../../images/title_link.png") no-repeat top left;
1991 background:url("../../images/title_link.png") no-repeat top left;
1972 border-left:1px solid #316293;
1992 border-left:1px solid #316293;
1973 }
1993 }
1974
1994
1975 #content div.box div.title div.search div.input input {
1995 #content div.box div.title div.search div.input input {
1976 border:1px solid #316293;
1996 border:1px solid #316293;
1977 }
1997 }
1978
1998
1979 #content div.box div.title div.search div.button input.ui-state-default {
1999 #content div.box div.title div.search div.button input.ui-state-default {
1980 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
2000 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
1981 border:1px solid #316293;
2001 border:1px solid #316293;
1982 border-left:none;
2002 border-left:none;
1983 color:#FFF;
2003 color:#FFF;
1984 }
2004 }
1985
2005
1986 #content div.box div.title div.search div.button input.ui-state-hover {
2006 #content div.box div.title div.search div.button input.ui-state-hover {
1987 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
2007 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1988 border:1px solid #316293;
2008 border:1px solid #316293;
1989 border-left:none;
2009 border-left:none;
1990 color:#FFF;
2010 color:#FFF;
1991 }
2011 }
1992
2012
1993 #content div.box div.form div.fields div.field div.highlight .ui-state-default {
2013 #content div.box div.form div.fields div.field div.highlight .ui-state-default {
1994 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
2014 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
1995 border-top:1px solid #5c91a4;
2015 border-top:1px solid #5c91a4;
1996 border-left:1px solid #2a6f89;
2016 border-left:1px solid #2a6f89;
1997 border-right:1px solid #2b7089;
2017 border-right:1px solid #2b7089;
1998 border-bottom:1px solid #1a6480;
2018 border-bottom:1px solid #1a6480;
1999 color:#fff;
2019 color:#fff;
2000 }
2020 }
2001
2021
2002 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
2022 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
2003 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
2023 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
2004 border-top:1px solid #78acbf;
2024 border-top:1px solid #78acbf;
2005 border-left:1px solid #34819e;
2025 border-left:1px solid #34819e;
2006 border-right:1px solid #35829f;
2026 border-right:1px solid #35829f;
2007 border-bottom:1px solid #257897;
2027 border-bottom:1px solid #257897;
2008 color:#fff;
2028 color:#fff;
2009 }
2029 }
2010
2030
2011 ins,div.options a:hover {
2031 ins,div.options a:hover {
2012 text-decoration:none;
2032 text-decoration:none;
2013 }
2033 }
2014
2034
2015 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 {
2035 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 {
2016 border:none;
2036 border:none;
2017 }
2037 }
2018
2038
2019 img.icon,.right .merge img {
2039 img.icon,.right .merge img {
2020 vertical-align:bottom;
2040 vertical-align:bottom;
2021 }
2041 }
2022
2042
2023 #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 {
2043 #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 {
2024 float:right;
2044 float:right;
2025 margin:0;
2045 margin:0;
2026 padding:0;
2046 padding:0;
2027 }
2047 }
2028
2048
2029 #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 {
2049 #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 {
2030 float:left;
2050 float:left;
2031 }
2051 }
2032
2052
2033 #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 {
2053 #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 {
2034 display:none;
2054 display:none;
2035 }
2055 }
2036
2056
2037 #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 {
2057 #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 {
2038 display:block;
2058 display:block;
2039 }
2059 }
2040
2060
2041 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2061 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2042 color:#bfe3ff;
2062 color:#bfe3ff;
2043 }
2063 }
2044
2064
2045 #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 {
2065 #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 {
2046 margin:10px 24px 10px 44px;
2066 margin:10px 24px 10px 44px;
2047 }
2067 }
2048
2068
2049 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2069 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2050 clear:both;
2070 clear:both;
2051 overflow:hidden;
2071 overflow:hidden;
2052 margin:0;
2072 margin:0;
2053 padding:0 20px 10px;
2073 padding:0 20px 10px;
2054 }
2074 }
2055
2075
2056 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2076 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2057 clear:both;
2077 clear:both;
2058 overflow:hidden;
2078 overflow:hidden;
2059 margin:0;
2079 margin:0;
2060 padding:0;
2080 padding:0;
2061 }
2081 }
2062
2082
2063 #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 {
2083 #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 {
2064 height:1%;
2084 height:1%;
2065 display:block;
2085 display:block;
2066 color:#363636;
2086 color:#363636;
2067 margin:0;
2087 margin:0;
2068 padding:2px 0 0;
2088 padding:2px 0 0;
2069 }
2089 }
2070
2090
2071 #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 {
2091 #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 {
2072 background:#FBE3E4;
2092 background:#FBE3E4;
2073 border-top:1px solid #e1b2b3;
2093 border-top:1px solid #e1b2b3;
2074 border-left:1px solid #e1b2b3;
2094 border-left:1px solid #e1b2b3;
2075 border-right:1px solid #FBC2C4;
2095 border-right:1px solid #FBC2C4;
2076 border-bottom:1px solid #FBC2C4;
2096 border-bottom:1px solid #FBC2C4;
2077 }
2097 }
2078
2098
2079 #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 {
2099 #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 {
2080 background:#E6EFC2;
2100 background:#E6EFC2;
2081 border-top:1px solid #cebb98;
2101 border-top:1px solid #cebb98;
2082 border-left:1px solid #cebb98;
2102 border-left:1px solid #cebb98;
2083 border-right:1px solid #c6d880;
2103 border-right:1px solid #c6d880;
2084 border-bottom:1px solid #c6d880;
2104 border-bottom:1px solid #c6d880;
2085 }
2105 }
2086
2106
2087 #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 {
2107 #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 {
2088 margin:0;
2108 margin:0;
2089 }
2109 }
2090
2110
2091 #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{
2111 #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{
2092 margin:0 0 0 0px !important;
2112 margin:0 0 0 0px !important;
2093 padding:0;
2113 padding:0;
2094 }
2114 }
2095
2115
2096 #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 {
2116 #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 {
2097 margin:0 0 0 200px;
2117 margin:0 0 0 200px;
2098 padding:0;
2118 padding:0;
2099 }
2119 }
2100
2120
2101
2121
2102 #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 {
2122 #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 {
2103 color:#000;
2123 color:#000;
2104 text-decoration:none;
2124 text-decoration:none;
2105 }
2125 }
2106
2126
2107 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2127 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2108 border:1px solid #666;
2128 border:1px solid #666;
2109 }
2129 }
2110
2130
2111 #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 {
2131 #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 {
2112 clear:both;
2132 clear:both;
2113 overflow:hidden;
2133 overflow:hidden;
2114 margin:0;
2134 margin:0;
2115 padding:8px 0 2px;
2135 padding:8px 0 2px;
2116 }
2136 }
2117
2137
2118 #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 {
2138 #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 {
2119 float:left;
2139 float:left;
2120 margin:0;
2140 margin:0;
2121 }
2141 }
2122
2142
2123 #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 {
2143 #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 {
2124 height:1%;
2144 height:1%;
2125 display:block;
2145 display:block;
2126 float:left;
2146 float:left;
2127 margin:2px 0 0 4px;
2147 margin:2px 0 0 4px;
2128 }
2148 }
2129
2149
2130 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 {
2150 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 {
2131 color:#000;
2151 color:#000;
2132 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2152 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2133 font-size:11px;
2153 font-size:11px;
2134 font-weight:700;
2154 font-weight:700;
2135 margin:0;
2155 margin:0;
2136 }
2156 }
2137
2157
2138 div.form div.fields div.field div.button .ui-state-default,#content div.box div.form div.fields div.buttons input.ui-state-default {
2158 div.form div.fields div.field div.button .ui-state-default,#content div.box div.form div.fields div.buttons input.ui-state-default {
2139 background:#e5e3e3 url("../images/button.png") repeat-x;
2159 background:#e5e3e3 url("../images/button.png") repeat-x;
2140 border-top:1px solid #DDD;
2160 border-top:1px solid #DDD;
2141 border-left:1px solid #c6c6c6;
2161 border-left:1px solid #c6c6c6;
2142 border-right:1px solid #DDD;
2162 border-right:1px solid #DDD;
2143 border-bottom:1px solid #c6c6c6;
2163 border-bottom:1px solid #c6c6c6;
2144 color:#515151;
2164 color:#515151;
2145 outline:none;
2165 outline:none;
2146 margin:0;
2166 margin:0;
2147 padding:6px 12px;
2167 padding:6px 12px;
2148 }
2168 }
2149
2169
2150 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2170 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2151 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2171 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2152 border-top:1px solid #ccc;
2172 border-top:1px solid #ccc;
2153 border-left:1px solid #bebebe;
2173 border-left:1px solid #bebebe;
2154 border-right:1px solid #b1b1b1;
2174 border-right:1px solid #b1b1b1;
2155 border-bottom:1px solid #afafaf;
2175 border-bottom:1px solid #afafaf;
2156 color:#515151;
2176 color:#515151;
2157 outline:none;
2177 outline:none;
2158 margin:0;
2178 margin:0;
2159 padding:6px 12px;
2179 padding:6px 12px;
2160 }
2180 }
2161
2181
2162 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2182 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2163 display:inline;
2183 display:inline;
2164 }
2184 }
2165
2185
2166 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2186 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2167 margin:10px 0 0 200px;
2187 margin:10px 0 0 200px;
2168 padding:0;
2188 padding:0;
2169 }
2189 }
2170
2190
2171 #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 {
2191 #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 {
2172 margin:10px 0 0;
2192 margin:10px 0 0;
2173 }
2193 }
2174
2194
2175 #content div.box table td.user,#content div.box table td.address {
2195 #content div.box table td.user,#content div.box table td.address {
2176 width:10%;
2196 width:10%;
2177 text-align:center;
2197 text-align:center;
2178 }
2198 }
2179
2199
2180 #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 {
2200 #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 {
2181 text-align:right;
2201 text-align:right;
2182 margin:6px 0 0;
2202 margin:6px 0 0;
2183 padding:0;
2203 padding:0;
2184 }
2204 }
2185
2205
2186 #content div.box div.action div.button input.ui-state-default,#login div.form div.fields div.buttons input.ui-state-default,#register div.form div.fields div.buttons input.ui-state-default {
2206 #content div.box div.action div.button input.ui-state-default,#login div.form div.fields div.buttons input.ui-state-default,#register div.form div.fields div.buttons input.ui-state-default {
2187 background:#e5e3e3 url("../images/button.png") repeat-x;
2207 background:#e5e3e3 url("../images/button.png") repeat-x;
2188 border-top:1px solid #DDD;
2208 border-top:1px solid #DDD;
2189 border-left:1px solid #c6c6c6;
2209 border-left:1px solid #c6c6c6;
2190 border-right:1px solid #DDD;
2210 border-right:1px solid #DDD;
2191 border-bottom:1px solid #c6c6c6;
2211 border-bottom:1px solid #c6c6c6;
2192 color:#515151;
2212 color:#515151;
2193 margin:0;
2213 margin:0;
2194 padding:6px 12px;
2214 padding:6px 12px;
2195 }
2215 }
2196
2216
2197 #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 {
2217 #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 {
2198 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2218 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2199 border-top:1px solid #ccc;
2219 border-top:1px solid #ccc;
2200 border-left:1px solid #bebebe;
2220 border-left:1px solid #bebebe;
2201 border-right:1px solid #b1b1b1;
2221 border-right:1px solid #b1b1b1;
2202 border-bottom:1px solid #afafaf;
2222 border-bottom:1px solid #afafaf;
2203 color:#515151;
2223 color:#515151;
2204 margin:0;
2224 margin:0;
2205 padding:6px 12px;
2225 padding:6px 12px;
2206 }
2226 }
2207
2227
2208 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2228 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2209 text-align:left;
2229 text-align:left;
2210 float:left;
2230 float:left;
2211 margin:0;
2231 margin:0;
2212 padding:0;
2232 padding:0;
2213 }
2233 }
2214
2234
2215 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2235 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2216 height:1%;
2236 height:1%;
2217 display:block;
2237 display:block;
2218 float:left;
2238 float:left;
2219 background:#ebebeb url("../images/pager.png") repeat-x;
2239 background:#ebebeb url("../images/pager.png") repeat-x;
2220 border-top:1px solid #dedede;
2240 border-top:1px solid #dedede;
2221 border-left:1px solid #cfcfcf;
2241 border-left:1px solid #cfcfcf;
2222 border-right:1px solid #c4c4c4;
2242 border-right:1px solid #c4c4c4;
2223 border-bottom:1px solid #c4c4c4;
2243 border-bottom:1px solid #c4c4c4;
2224 color:#4A4A4A;
2244 color:#4A4A4A;
2225 font-weight:700;
2245 font-weight:700;
2226 margin:0;
2246 margin:0;
2227 padding:6px 8px;
2247 padding:6px 8px;
2228 }
2248 }
2229
2249
2230 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2250 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2231 color:#B4B4B4;
2251 color:#B4B4B4;
2232 padding:6px;
2252 padding:6px;
2233 }
2253 }
2234
2254
2235 #login,#register {
2255 #login,#register {
2236 width:520px;
2256 width:520px;
2237 margin:10% auto 0;
2257 margin:10% auto 0;
2238 padding:0;
2258 padding:0;
2239 }
2259 }
2240
2260
2241 #login div.color,#register div.color {
2261 #login div.color,#register div.color {
2242 clear:both;
2262 clear:both;
2243 overflow:hidden;
2263 overflow:hidden;
2244 background:#FFF;
2264 background:#FFF;
2245 margin:10px auto 0;
2265 margin:10px auto 0;
2246 padding:3px 3px 3px 0;
2266 padding:3px 3px 3px 0;
2247 }
2267 }
2248
2268
2249 #login div.color a,#register div.color a {
2269 #login div.color a,#register div.color a {
2250 width:20px;
2270 width:20px;
2251 height:20px;
2271 height:20px;
2252 display:block;
2272 display:block;
2253 float:left;
2273 float:left;
2254 margin:0 0 0 3px;
2274 margin:0 0 0 3px;
2255 padding:0;
2275 padding:0;
2256 }
2276 }
2257
2277
2258 #login div.title h5,#register div.title h5 {
2278 #login div.title h5,#register div.title h5 {
2259 color:#fff;
2279 color:#fff;
2260 margin:10px;
2280 margin:10px;
2261 padding:0;
2281 padding:0;
2262 }
2282 }
2263
2283
2264 #login div.form div.fields div.field,#register div.form div.fields div.field {
2284 #login div.form div.fields div.field,#register div.form div.fields div.field {
2265 clear:both;
2285 clear:both;
2266 overflow:hidden;
2286 overflow:hidden;
2267 margin:0;
2287 margin:0;
2268 padding:0 0 10px;
2288 padding:0 0 10px;
2269 }
2289 }
2270
2290
2271 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2291 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2272 height:1%;
2292 height:1%;
2273 display:block;
2293 display:block;
2274 color:red;
2294 color:red;
2275 margin:8px 0 0;
2295 margin:8px 0 0;
2276 padding:0;
2296 padding:0;
2277 }
2297 }
2278
2298
2279 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2299 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2280 color:#000;
2300 color:#000;
2281 font-weight:700;
2301 font-weight:700;
2282 }
2302 }
2283
2303
2284 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2304 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2285 float:left;
2305 float:left;
2286 margin:0;
2306 margin:0;
2287 padding:0;
2307 padding:0;
2288 }
2308 }
2289
2309
2290 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2310 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2291 margin:0 0 0 184px;
2311 margin:0 0 0 184px;
2292 padding:0;
2312 padding:0;
2293 }
2313 }
2294
2314
2295 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2315 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2296 color:#565656;
2316 color:#565656;
2297 font-weight:700;
2317 font-weight:700;
2298 }
2318 }
2299
2319
2300 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2320 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2301 color:#000;
2321 color:#000;
2302 font-size:1em;
2322 font-size:1em;
2303 font-weight:700;
2323 font-weight:700;
2304 font-family:Verdana, Helvetica, Sans-Serif;
2324 font-family:Verdana, Helvetica, Sans-Serif;
2305 margin:0;
2325 margin:0;
2306 }
2326 }
2307
2327
2308 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2328 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2309 width:600px;
2329 width:600px;
2310 }
2330 }
2311
2331
2312 #changeset_content .container .left,#graph_content .container .left {
2332 #changeset_content .container .left,#graph_content .container .left {
2313 float:left;
2333 float:left;
2314 width:70%;
2334 width:70%;
2315 padding-left:5px;
2335 padding-left:5px;
2316 }
2336 }
2317
2337
2318 #changeset_content .container .left .date,.ac .match {
2338 #changeset_content .container .left .date,.ac .match {
2319 font-weight:700;
2339 font-weight:700;
2320 padding-top: 5px;
2340 padding-top: 5px;
2321 padding-bottom:5px;
2341 padding-bottom:5px;
2322 }
2342 }
2323
2343
2324 div#legend_container table td,div#legend_choices table td {
2344 div#legend_container table td,div#legend_choices table td {
2325 border:none !important;
2345 border:none !important;
2326 height:20px !important;
2346 height:20px !important;
2327 padding:0 !important;
2347 padding:0 !important;
2328 }
2348 }
2329
2349
2330 #q_filter{
2350 #q_filter{
2331 border:0 none;
2351 border:0 none;
2332 color:#AAAAAA;
2352 color:#AAAAAA;
2333 margin-bottom:-4px;
2353 margin-bottom:-4px;
2334 margin-top:-4px;
2354 margin-top:-4px;
2335 padding-left:3px;
2355 padding-left:3px;
2336 }
2356 }
2337
2357
@@ -1,295 +1,348 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
4 <head>
4 <head>
5 <title>${next.title()}</title>
5 <title>${next.title()}</title>
6 <link rel="icon" href="/images/icons/database_gear.png" type="image/png" />
6 <link rel="icon" href="/images/icons/database_gear.png" type="image/png" />
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 <meta name="robots" content="index, nofollow"/>
8 <meta name="robots" content="index, nofollow"/>
9 <!-- stylesheets -->
9 <!-- stylesheets -->
10 ${self.css()}
10 ${self.css()}
11 <!-- scripts -->
11 <!-- scripts -->
12 ${self.js()}
12 ${self.js()}
13 </head>
13 </head>
14 <body>
14 <body>
15 <!-- header -->
15 <!-- header -->
16 <div id="header">
16 <div id="header">
17 <!-- user -->
17 <!-- user -->
18 <ul id="logged-user">
18 <ul id="logged-user">
19 <li class="first">
19 <li class="first">
20 <div class="gravatar">
20 <div class="gravatar">
21 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,24)}" />
21 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,24)}" />
22 </div>
22 </div>
23 %if c.rhodecode_user.username == 'default':
23 %if c.rhodecode_user.username == 'default':
24 <div class="account">
24 <div class="account">
25 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('#'))}<br/>
25 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('#'))}<br/>
26 ${h.link_to(c.rhodecode_user.username,h.url('#'))}
26 ${h.link_to(c.rhodecode_user.username,h.url('#'))}
27 </div>
27 </div>
28 </li>
28 </li>
29 <li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
29 <li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
30 %else:
30 %else:
31
31
32 <div class="account">
32 <div class="account">
33 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('admin_settings_my_account'))}<br/>
33 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('admin_settings_my_account'))}<br/>
34 ${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'))}
34 ${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'))}
35 </div>
35 </div>
36 </li>
36 </li>
37 <li class="last highlight">${h.link_to(u'Logout',h.url('logout_home'))}</li>
37 <li class="last highlight">${h.link_to(u'Logout',h.url('logout_home'))}</li>
38 %endif
38 %endif
39 </ul>
39 </ul>
40 <!-- end user -->
40 <!-- end user -->
41 <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
41 <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
42 <!-- logo -->
42 <!-- logo -->
43 <div id="logo">
43 <div id="logo">
44 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
44 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
45 </div>
45 </div>
46 <!-- end logo -->
46 <!-- end logo -->
47 <!-- menu -->
47 <!-- menu -->
48 ${self.page_nav()}
48 ${self.page_nav()}
49 <!-- quick -->
49 <!-- quick -->
50 </div>
50 </div>
51 </div>
51 </div>
52 <!-- end header -->
52 <!-- end header -->
53
53
54 <!-- CONTENT -->
54 <!-- CONTENT -->
55 <div id="content">
55 <div id="content">
56 <div class="flash_msg">
56 <div class="flash_msg">
57 <% messages = h.flash.pop_messages() %>
57 <% messages = h.flash.pop_messages() %>
58 % if messages:
58 % if messages:
59 <ul id="flash-messages">
59 <ul id="flash-messages">
60 % for message in messages:
60 % for message in messages:
61 <li class="${message.category}_msg">${message}</li>
61 <li class="${message.category}_msg">${message}</li>
62 % endfor
62 % endfor
63 </ul>
63 </ul>
64 % endif
64 % endif
65 </div>
65 </div>
66 <div id="main">
66 <div id="main">
67 ${next.main()}
67 ${next.main()}
68 </div>
68 </div>
69 </div>
69 </div>
70 <!-- END CONTENT -->
70 <!-- END CONTENT -->
71
71
72 <!-- footer -->
72 <!-- footer -->
73 <div id="footer">
73 <div id="footer">
74 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
74 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
75 <div>
75 <div>
76 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
76 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
77 <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
77 <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
78 <p>RhodeCode ${c.rhodecode_version} &copy; 2010 by Marcin Kuzminski</p>
78 <p>RhodeCode ${c.rhodecode_version} &copy; 2010 by Marcin Kuzminski</p>
79 </div>
79 </div>
80 </div>
80 </div>
81 <script type="text/javascript">${h.tooltip.activate()}</script>
81 <script type="text/javascript">${h.tooltip.activate()}</script>
82 </div>
82 </div>
83 <!-- end footer -->
83 <!-- end footer -->
84 </body>
84 </body>
85
85
86 </html>
86 </html>
87
87
88 ### MAKO DEFS ###
88 ### MAKO DEFS ###
89 <%def name="page_nav()">
89 <%def name="page_nav()">
90 ${self.menu()}
90 ${self.menu()}
91 </%def>
91 </%def>
92
92
93 <%def name="menu(current=None)">
93 <%def name="menu(current=None)">
94 <%
94 <%
95 def is_current(selected):
95 def is_current(selected):
96 if selected == current:
96 if selected == current:
97 return h.literal('class="current"')
97 return h.literal('class="current"')
98 %>
98 %>
99 %if current not in ['home','admin']:
99 %if current not in ['home','admin']:
100 ##REGULAR MENU
100 ##REGULAR MENU
101 <ul id="quick">
101 <ul id="quick">
102 <!-- repo switcher -->
102 <!-- repo switcher -->
103 <li>
103 <li>
104 <a id="repo_switcher" title="${_('Switch repository')}" href="#">
104 <a id="repo_switcher" title="${_('Switch repository')}" href="#">
105 <span class="icon">
105 <span class="icon">
106 <img src="/images/icons/database.png" alt="${_('Products')}" />
106 <img src="/images/icons/database.png" alt="${_('Products')}" />
107 </span>
107 </span>
108 <span>&darr;</span>
108 <span>&darr;</span>
109 </a>
109 </a>
110 <ul class="repo_switcher">
110 <ul class="repo_switcher">
111 %for repo in c.cached_repo_list:
111 %for repo in c.cached_repo_list:
112
112
113 %if repo['repo'].dbrepo.private:
113 %if repo['repo'].dbrepo.private:
114 <li><img src="/images/icons/lock.png" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
114 <li><img src="/images/icons/lock.png" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
115 %else:
115 %else:
116 <li><img src="/images/icons/lock_open.png" alt="${_('Public repository')}" class="repo_switcher_type" />${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
116 <li><img src="/images/icons/lock_open.png" alt="${_('Public repository')}" class="repo_switcher_type" />${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['repo'].dbrepo.repo_type)}</li>
117 %endif
117 %endif
118 %endfor
118 %endfor
119 </ul>
119 </ul>
120 </li>
120 </li>
121
121
122 <li ${is_current('summary')}>
122 <li ${is_current('summary')}>
123 <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
123 <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
124 <span class="icon">
124 <span class="icon">
125 <img src="/images/icons/clipboard_16.png" alt="${_('Summary')}" />
125 <img src="/images/icons/clipboard_16.png" alt="${_('Summary')}" />
126 </span>
126 </span>
127 <span>${_('Summary')}</span>
127 <span>${_('Summary')}</span>
128 </a>
128 </a>
129 </li>
129 </li>
130 ##<li ${is_current('shortlog')}>
130 ##<li ${is_current('shortlog')}>
131 ## <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
131 ## <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
132 ## <span class="icon">
132 ## <span class="icon">
133 ## <img src="/images/icons/application_view_list.png" alt="${_('Shortlog')}" />
133 ## <img src="/images/icons/application_view_list.png" alt="${_('Shortlog')}" />
134 ## </span>
134 ## </span>
135 ## <span>${_('Shortlog')}</span>
135 ## <span>${_('Shortlog')}</span>
136 ## </a>
136 ## </a>
137 ##</li>
137 ##</li>
138 <li ${is_current('changelog')}>
138 <li ${is_current('changelog')}>
139 <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
139 <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
140 <span class="icon">
140 <span class="icon">
141 <img src="/images/icons/time.png" alt="${_('Changelog')}" />
141 <img src="/images/icons/time.png" alt="${_('Changelog')}" />
142 </span>
142 </span>
143 <span>${_('Changelog')}</span>
143 <span>${_('Changelog')}</span>
144 </a>
144 </a>
145 </li>
145 </li>
146
146
147 <li ${is_current('switch_to')}>
147 <li ${is_current('switch_to')}>
148 <a title="${_('Switch to')}" href="#">
148 <a title="${_('Switch to')}" href="#">
149 <span class="icon">
149 <span class="icon">
150 <img src="/images/icons/arrow_switch.png" alt="${_('Switch to')}" />
150 <img src="/images/icons/arrow_switch.png" alt="${_('Switch to')}" />
151 </span>
151 </span>
152 <span>${_('Switch to')}</span>
152 <span>${_('Switch to')}</span>
153 </a>
153 </a>
154 <ul>
154 <ul>
155 <li>
155 <li>
156 ${h.link_to('%s (%s)' % (_('branches'),len(c.repository_branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
156 ${h.link_to('%s (%s)' % (_('branches'),len(c.repository_branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
157 <ul>
157 <ul>
158 %if c.repository_branches.values():
158 %if c.repository_branches.values():
159 %for cnt,branch in enumerate(c.repository_branches.items()):
159 %for cnt,branch in enumerate(c.repository_branches.items()):
160 <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
160 <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
161 %endfor
161 %endfor
162 %else:
162 %else:
163 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
163 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
164 %endif
164 %endif
165 </ul>
165 </ul>
166 </li>
166 </li>
167 <li>
167 <li>
168 ${h.link_to('%s (%s)' % (_('tags'),len(c.repository_tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
168 ${h.link_to('%s (%s)' % (_('tags'),len(c.repository_tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
169 <ul>
169 <ul>
170 %if c.repository_tags.values():
170 %if c.repository_tags.values():
171 %for cnt,tag in enumerate(c.repository_tags.items()):
171 %for cnt,tag in enumerate(c.repository_tags.items()):
172 <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
172 <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
173 %endfor
173 %endfor
174 %else:
174 %else:
175 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
175 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
176 %endif
176 %endif
177 </ul>
177 </ul>
178 </li>
178 </li>
179 </ul>
179 </ul>
180 </li>
180 </li>
181 <li ${is_current('files')}>
181 <li ${is_current('files')}>
182 <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
182 <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
183 <span class="icon">
183 <span class="icon">
184 <img src="/images/icons/file.png" alt="${_('Files')}" />
184 <img src="/images/icons/file.png" alt="${_('Files')}" />
185 </span>
185 </span>
186 <span>${_('Files')}</span>
186 <span>${_('Files')}</span>
187 </a>
187 </a>
188 </li>
188 </li>
189
189
190 <li ${is_current('options')}>
190 <li ${is_current('options')}>
191 <a title="${_('Options')}" href="#">
191 <a title="${_('Options')}" href="#">
192 <span class="icon">
192 <span class="icon">
193 <img src="/images/icons/table_gear.png" alt="${_('Admin')}" />
193 <img src="/images/icons/table_gear.png" alt="${_('Admin')}" />
194 </span>
194 </span>
195 <span>${_('Options')}</span>
195 <span>${_('Options')}</span>
196 </a>
196 </a>
197 <ul>
197 <ul>
198 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
198 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
199 <li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
199 <li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
200 %endif
200 %endif
201 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
201 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
202 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
202 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
203
203
204 %if h.HasPermissionAll('hg.admin')('access admin main page'):
204 %if h.HasPermissionAll('hg.admin')('access admin main page'):
205 <li>
205 <li>
206 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
206 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
207 <ul>
207 <ul>
208 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
208 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
209 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
209 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
210 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
210 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
211 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
211 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
212 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
212 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
213 </ul>
213 </ul>
214 </li>
214 </li>
215 %endif
215 %endif
216
216
217
217
218 ## %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
218 ## %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
219 ## <li class="last">
219 ## <li class="last">
220 ## ${h.link_to(_('delete'),'#',class_='delete')}
220 ## ${h.link_to(_('delete'),'#',class_='delete')}
221 ## ${h.form(url('repo_settings_delete', repo_name=c.repo_name),method='delete')}
221 ## ${h.form(url('repo_settings_delete', repo_name=c.repo_name),method='delete')}
222 ## ${h.submit('remove_%s' % c.repo_name,'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
222 ## ${h.submit('remove_%s' % c.repo_name,'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
223 ## ${h.end_form()}
223 ## ${h.end_form()}
224 ## </li>
224 ## </li>
225 ## %endif
225 ## %endif
226 </ul>
226 </ul>
227 </li>
227 </li>
228 </ul>
228 </ul>
229 %else:
229 %else:
230 ##ROOT MENU
230 ##ROOT MENU
231 <ul id="quick">
231 <ul id="quick">
232 <li>
232 <li>
233 <a title="${_('Home')}" href="${h.url('home')}">
233 <a title="${_('Home')}" href="${h.url('home')}">
234 <span class="icon">
234 <span class="icon">
235 <img src="/images/icons/home_16.png" alt="${_('Home')}" />
235 <img src="/images/icons/home_16.png" alt="${_('Home')}" />
236 </span>
236 </span>
237 <span>${_('Home')}</span>
237 <span>${_('Home')}</span>
238 </a>
238 </a>
239 </li>
239 </li>
240
240
241 <li>
241 <li>
242 <a title="${_('Journal')}" href="${h.url('journal')}">
243 <span class="icon">
244 <img src="/images/icons/book.png" alt="${_('Journal')}" />
245 </span>
246 <span>${_('Journal')}</span>
247 </a>
248 </li>
249
250 <li>
242 <a title="${_('Search')}" href="${h.url('search')}">
251 <a title="${_('Search')}" href="${h.url('search')}">
243 <span class="icon">
252 <span class="icon">
244 <img src="/images/icons/search_16.png" alt="${_('Search')}" />
253 <img src="/images/icons/search_16.png" alt="${_('Search')}" />
245 </span>
254 </span>
246 <span>${_('Search')}</span>
255 <span>${_('Search')}</span>
247 </a>
256 </a>
248 </li>
257 </li>
249
258
250 %if h.HasPermissionAll('hg.admin')('access admin main page'):
259 %if h.HasPermissionAll('hg.admin')('access admin main page'):
251 <li ${is_current('admin')}>
260 <li ${is_current('admin')}>
252 <a title="${_('Admin')}" href="${h.url('admin_home')}">
261 <a title="${_('Admin')}" href="${h.url('admin_home')}">
253 <span class="icon">
262 <span class="icon">
254 <img src="/images/icons/cog_edit.png" alt="${_('Admin')}" />
263 <img src="/images/icons/cog_edit.png" alt="${_('Admin')}" />
255 </span>
264 </span>
256 <span>${_('Admin')}</span>
265 <span>${_('Admin')}</span>
257 </a>
266 </a>
258 <ul>
267 <ul>
259 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
268 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
260 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
269 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
261 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
270 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
262 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
271 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
263 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
272 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
264 </ul>
273 </ul>
265 </li>
274 </li>
266 %endif
275 %endif
267
276
268 </ul>
277 </ul>
269 %endif
278 %endif
270 </%def>
279 </%def>
271
280
272
281
273 <%def name="css()">
282 <%def name="css()">
274 <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
283 <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
275 <link rel="stylesheet" type="text/css" href="/css/pygments.css" />
284 <link rel="stylesheet" type="text/css" href="/css/pygments.css" />
276 <link rel="stylesheet" type="text/css" href="/css/diff.css" />
285 <link rel="stylesheet" type="text/css" href="/css/diff.css" />
277 </%def>
286 </%def>
278
287
279 <%def name="js()">
288 <%def name="js()">
280 ##<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
289 ##<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
281 ##<script type="text/javascript" src="/js/yui/container/container.js"></script>
290 ##<script type="text/javascript" src="/js/yui/container/container.js"></script>
282 ##<script type="text/javascript" src="/js/yui/datasource/datasource.js"></script>
291 ##<script type="text/javascript" src="/js/yui/datasource/datasource.js"></script>
283 ##<script type="text/javascript" src="/js/yui/autocomplete/autocomplete.js"></script>
292 ##<script type="text/javascript" src="/js/yui/autocomplete/autocomplete.js"></script>
284 ##<script type="text/javascript" src="/js/yui/selector/selector-min.js"></script>
293 ##<script type="text/javascript" src="/js/yui/selector/selector-min.js"></script>
285
294
286 <script type="text/javascript" src="/js/yui2a.js"></script>
295 <script type="text/javascript" src="/js/yui2a.js"></script>
287 <!--[if IE]><script language="javascript" type="text/javascript" src="/js/excanvas.min.js"></script><![endif]-->
296 <!--[if IE]><script language="javascript" type="text/javascript" src="/js/excanvas.min.js"></script><![endif]-->
288 <script type="text/javascript" src="/js/yui.flot.js"></script>
297 <script type="text/javascript" src="/js/yui.flot.js"></script>
298
299 <script type="text/javascript">
300 var base_url ='/_admin/toggle_following';
301 var YUC = YAHOO.util.Connect;
302 var YUD = YAHOO.util.Dom;
303
304
305 function onSuccess(){
306
307 var f = YUD.get('follow_toggle');
308 if(f.getAttribute('class')=='follow'){
309 f.setAttribute('class','following');
310 f.setAttribute('title',"${_('Stop following this repository')}");
311
312 }
313 else{
314 f.setAttribute('class','follow');
315 f.setAttribute('title',"${_('Start following this repository')}");
316 }
317 }
318
319 function toggleFollowingUser(fallows_user_id,token){
320 args = 'follows_user_id='+fallows_user_id;
321 args+= '&auth_token='+token;
322 YUC.asyncRequest('POST',base_url,{
323 success:function(o){
324 onSuccess();
325 }
326 },args); return false;
327 }
328
329
330 function toggleFollowingRepo(fallows_repo_id,token){
331 args = 'follows_repo_id='+fallows_repo_id;
332 args+= '&auth_token='+token;
333 YUC.asyncRequest('POST',base_url,{
334 success:function(o){
335 onSuccess();
336 }
337 },args); return false;
338 }
339 </script>
340
341
289 </%def>
342 </%def>
290
343
291 <%def name="breadcrumbs()">
344 <%def name="breadcrumbs()">
292 <div class="breadcrumbs">
345 <div class="breadcrumbs">
293 ${self.breadcrumbs_links()}
346 ${self.breadcrumbs_links()}
294 </div>
347 </div>
295 </%def> No newline at end of file
348 </%def>
@@ -1,596 +1,606 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('Summary')} - ${c.rhodecode_name}
4 ${c.repo_name} ${_('Summary')} - ${c.rhodecode_name}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(u'Home',h.url('/'))}
8 ${h.link_to(u'Home',h.url('/'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 &raquo;
11 &raquo;
12 ${_('summary')}
12 ${_('summary')}
13 </%def>
13 </%def>
14
14
15 <%def name="page_nav()">
15 <%def name="page_nav()">
16 ${self.menu('summary')}
16 ${self.menu('summary')}
17 </%def>
17 </%def>
18
18
19 <%def name="main()">
19 <%def name="main()">
20 <script type="text/javascript">
20 <script type="text/javascript">
21 var E = YAHOO.util.Event;
21 var E = YAHOO.util.Event;
22 var D = YAHOO.util.Dom;
22 var D = YAHOO.util.Dom;
23
23
24 E.onDOMReady(function(e){
24 E.onDOMReady(function(e){
25 id = 'clone_url';
25 id = 'clone_url';
26 E.addListener(id,'click',function(e){
26 E.addListener(id,'click',function(e){
27 D.get('clone_url').select();
27 D.get('clone_url').select();
28 })
28 })
29 })
29 })
30 </script>
30 </script>
31 <div class="box box-left">
31 <div class="box box-left">
32 <!-- box / title -->
32 <!-- box / title -->
33 <div class="title">
33 <div class="title">
34 ${self.breadcrumbs()}
34 ${self.breadcrumbs()}
35 </div>
35 </div>
36 <!-- end box / title -->
36 <!-- end box / title -->
37 <div class="form">
37 <div class="form">
38 <div class="fields">
38 <div class="fields">
39
39
40 <div class="field">
40 <div class="field">
41 <div class="label">
41 <div class="label">
42 <label>${_('Name')}:</label>
42 <label>${_('Name')}:</label>
43 </div>
43 </div>
44 <div class="input-short">
44 <div class="input-short">
45 %if c.repo_info.dbrepo.repo_type =='hg':
45 %if c.repo_info.dbrepo.repo_type =='hg':
46 <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
46 <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
47 %endif
47 %endif
48 %if c.repo_info.dbrepo.repo_type =='git':
48 %if c.repo_info.dbrepo.repo_type =='git':
49 <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
49 <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
50 %endif
50 %endif
51
51
52 %if c.repo_info.dbrepo.private:
52 %if c.repo_info.dbrepo.private:
53 <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
53 <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
54 %else:
54 %else:
55 <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
55 <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
56 %endif
56 %endif
57 <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
57 <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
58
59 %if c.following:
60 <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
61 onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
62 </span>
63 %else:
64 <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
65 onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
66 </span>
67 %endif
58 <br/>
68 <br/>
59 %if c.repo_info.dbrepo.fork:
69 %if c.repo_info.dbrepo.fork:
60 <span style="margin-top:5px">
70 <span style="margin-top:5px">
61 <a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
71 <a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
62 <img class="icon" alt="${_('public')}"
72 <img class="icon" alt="${_('public')}"
63 title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}"
73 title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}"
64 src="/images/icons/arrow_divide.png"/>
74 src="/images/icons/arrow_divide.png"/>
65 ${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
75 ${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
66 </a>
76 </a>
67 </span>
77 </span>
68 %endif
78 %endif
69 </div>
79 </div>
70 </div>
80 </div>
71
81
72
82
73 <div class="field">
83 <div class="field">
74 <div class="label">
84 <div class="label">
75 <label>${_('Description')}:</label>
85 <label>${_('Description')}:</label>
76 </div>
86 </div>
77 <div class="input-short">
87 <div class="input-short">
78 ${c.repo_info.dbrepo.description}
88 ${c.repo_info.dbrepo.description}
79 </div>
89 </div>
80 </div>
90 </div>
81
91
82
92
83 <div class="field">
93 <div class="field">
84 <div class="label">
94 <div class="label">
85 <label>${_('Contact')}:</label>
95 <label>${_('Contact')}:</label>
86 </div>
96 </div>
87 <div class="input-short">
97 <div class="input-short">
88 <div class="gravatar">
98 <div class="gravatar">
89 <img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
99 <img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
90 </div>
100 </div>
91 ${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
101 ${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
92 ${_('Name')}: ${c.repo_info.dbrepo.user.name} ${c.repo_info.dbrepo.user.lastname}<br/>
102 ${_('Name')}: ${c.repo_info.dbrepo.user.name} ${c.repo_info.dbrepo.user.lastname}<br/>
93 ${_('Email')}: <a href="mailto:${c.repo_info.dbrepo.user.email}">${c.repo_info.dbrepo.user.email}</a>
103 ${_('Email')}: <a href="mailto:${c.repo_info.dbrepo.user.email}">${c.repo_info.dbrepo.user.email}</a>
94 </div>
104 </div>
95 </div>
105 </div>
96
106
97 <div class="field">
107 <div class="field">
98 <div class="label">
108 <div class="label">
99 <label>${_('Last change')}:</label>
109 <label>${_('Last change')}:</label>
100 </div>
110 </div>
101 <div class="input-short">
111 <div class="input-short">
102 ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change}
112 ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change}
103 ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author}
113 ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author}
104
114
105 </div>
115 </div>
106 </div>
116 </div>
107
117
108 <div class="field">
118 <div class="field">
109 <div class="label">
119 <div class="label">
110 <label>${_('Clone url')}:</label>
120 <label>${_('Clone url')}:</label>
111 </div>
121 </div>
112 <div class="input-short">
122 <div class="input-short">
113 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
123 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
114 </div>
124 </div>
115 </div>
125 </div>
116
126
117 <div class="field">
127 <div class="field">
118 <div class="label">
128 <div class="label">
119 <label>${_('Trending languages')}:</label>
129 <label>${_('Trending languages')}:</label>
120 </div>
130 </div>
121 <div class="input-short">
131 <div class="input-short">
122 <div id="lang_stats">
132 <div id="lang_stats">
123
133
124 </div>
134 </div>
125 <script type="text/javascript">
135 <script type="text/javascript">
126 var data = ${c.trending_languages|n};
136 var data = ${c.trending_languages|n};
127 var total = 0;
137 var total = 0;
128 var no_data = true;
138 var no_data = true;
129 for (k in data){
139 for (k in data){
130 total += data[k];
140 total += data[k];
131 no_data = false;
141 no_data = false;
132 }
142 }
133 var tbl = document.createElement('table');
143 var tbl = document.createElement('table');
134 tbl.setAttribute('class','trending_language_tbl');
144 tbl.setAttribute('class','trending_language_tbl');
135 for (k in data){
145 for (k in data){
136 var tr = document.createElement('tr');
146 var tr = document.createElement('tr');
137 var percentage = Math.round((data[k]/total*100),2);
147 var percentage = Math.round((data[k]/total*100),2);
138 var value = data[k];
148 var value = data[k];
139 var td1 = document.createElement('td');
149 var td1 = document.createElement('td');
140 td1.width=150;
150 td1.width=150;
141 var trending_language_label = document.createElement('div');
151 var trending_language_label = document.createElement('div');
142 trending_language_label.innerHTML = k;
152 trending_language_label.innerHTML = k;
143 td1.appendChild(trending_language_label);
153 td1.appendChild(trending_language_label);
144
154
145 var td2 = document.createElement('td');
155 var td2 = document.createElement('td');
146 td2.setAttribute('style','padding-right:14px !important');
156 td2.setAttribute('style','padding-right:14px !important');
147 var trending_language = document.createElement('div');
157 var trending_language = document.createElement('div');
148 trending_language.title = k;
158 trending_language.title = k;
149 trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";
159 trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";
150 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
160 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
151 trending_language.style.width=percentage+"%";
161 trending_language.style.width=percentage+"%";
152 td2.appendChild(trending_language);
162 td2.appendChild(trending_language);
153
163
154 tr.appendChild(td1);
164 tr.appendChild(td1);
155 tr.appendChild(td2);
165 tr.appendChild(td2);
156 tbl.appendChild(tr);
166 tbl.appendChild(tr);
157
167
158 }
168 }
159 if(no_data){
169 if(no_data){
160 var tr = document.createElement('tr');
170 var tr = document.createElement('tr');
161 var td1 = document.createElement('td');
171 var td1 = document.createElement('td');
162 td1.innerHTML = "${_('No data loaded yet')}";
172 td1.innerHTML = "${_('No data loaded yet')}";
163 tr.appendChild(td1);
173 tr.appendChild(td1);
164 tbl.appendChild(tr);
174 tbl.appendChild(tr);
165 }
175 }
166 YAHOO.util.Dom.get('lang_stats').appendChild(tbl);
176 YAHOO.util.Dom.get('lang_stats').appendChild(tbl);
167 </script>
177 </script>
168
178
169 </div>
179 </div>
170 </div>
180 </div>
171
181
172 <div class="field">
182 <div class="field">
173 <div class="label">
183 <div class="label">
174 <label>${_('Download')}:</label>
184 <label>${_('Download')}:</label>
175 </div>
185 </div>
176 <div class="input-short">
186 <div class="input-short">
177 %for cnt,archive in enumerate(c.repo_info._get_archives()):
187 %for cnt,archive in enumerate(c.repo_info._get_archives()):
178 %if cnt >=1:
188 %if cnt >=1:
179 |
189 |
180 %endif
190 %endif
181 ${h.link_to(c.repo_info.name+'.'+archive['type'],
191 ${h.link_to(c.repo_info.name+'.'+archive['type'],
182 h.url('files_archive_home',repo_name=c.repo_info.name,
192 h.url('files_archive_home',repo_name=c.repo_info.name,
183 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
193 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
184 %endfor
194 %endfor
185 </div>
195 </div>
186 </div>
196 </div>
187
197
188 <div class="field">
198 <div class="field">
189 <div class="label">
199 <div class="label">
190 <label>${_('Feeds')}:</label>
200 <label>${_('Feeds')}:</label>
191 </div>
201 </div>
192 <div class="input-short">
202 <div class="input-short">
193 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
203 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
194 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
204 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
195 </div>
205 </div>
196 </div>
206 </div>
197 </div>
207 </div>
198 </div>
208 </div>
199 </div>
209 </div>
200
210
201 <div class="box box-right" style="min-height:455px">
211 <div class="box box-right" style="min-height:455px">
202 <!-- box / title -->
212 <!-- box / title -->
203 <div class="title">
213 <div class="title">
204 <h5>${_('Commit activity by day / author')}</h5>
214 <h5>${_('Commit activity by day / author')}</h5>
205 </div>
215 </div>
206
216
207 <div class="table">
217 <div class="table">
208 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
218 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
209 <div style="clear: both;height: 10px"></div>
219 <div style="clear: both;height: 10px"></div>
210 <div id="overview" style="width:460px;height:100px;float:left"></div>
220 <div id="overview" style="width:460px;height:100px;float:left"></div>
211
221
212 <div id="legend_data" style="clear:both;margin-top:10px;">
222 <div id="legend_data" style="clear:both;margin-top:10px;">
213 <div id="legend_container"></div>
223 <div id="legend_container"></div>
214 <div id="legend_choices">
224 <div id="legend_choices">
215 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
225 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
216 </div>
226 </div>
217 </div>
227 </div>
218 <script type="text/javascript">
228 <script type="text/javascript">
219 /**
229 /**
220 * Plots summary graph
230 * Plots summary graph
221 *
231 *
222 * @class SummaryPlot
232 * @class SummaryPlot
223 * @param {from} initial from for detailed graph
233 * @param {from} initial from for detailed graph
224 * @param {to} initial to for detailed graph
234 * @param {to} initial to for detailed graph
225 * @param {dataset}
235 * @param {dataset}
226 * @param {overview_dataset}
236 * @param {overview_dataset}
227 */
237 */
228 function SummaryPlot(from,to,dataset,overview_dataset) {
238 function SummaryPlot(from,to,dataset,overview_dataset) {
229 var initial_ranges = {
239 var initial_ranges = {
230 "xaxis":{
240 "xaxis":{
231 "from":from,
241 "from":from,
232 "to":to,
242 "to":to,
233 },
243 },
234 };
244 };
235 var dataset = dataset;
245 var dataset = dataset;
236 var overview_dataset = [overview_dataset];
246 var overview_dataset = [overview_dataset];
237 var choiceContainer = YAHOO.util.Dom.get("legend_choices");
247 var choiceContainer = YAHOO.util.Dom.get("legend_choices");
238 var choiceContainerTable = YAHOO.util.Dom.get("legend_choices_tables");
248 var choiceContainerTable = YAHOO.util.Dom.get("legend_choices_tables");
239 var plotContainer = YAHOO.util.Dom.get('commit_history');
249 var plotContainer = YAHOO.util.Dom.get('commit_history');
240 var overviewContainer = YAHOO.util.Dom.get('overview');
250 var overviewContainer = YAHOO.util.Dom.get('overview');
241
251
242 var plot_options = {
252 var plot_options = {
243 bars: {show:true,align:'center',lineWidth:4},
253 bars: {show:true,align:'center',lineWidth:4},
244 legend: {show:true, container:"legend_container"},
254 legend: {show:true, container:"legend_container"},
245 points: {show:true,radius:0,fill:false},
255 points: {show:true,radius:0,fill:false},
246 yaxis: {tickDecimals:0,},
256 yaxis: {tickDecimals:0,},
247 xaxis: {
257 xaxis: {
248 mode: "time",
258 mode: "time",
249 timeformat: "%d/%m",
259 timeformat: "%d/%m",
250 min:from,
260 min:from,
251 max:to,
261 max:to,
252 },
262 },
253 grid: {
263 grid: {
254 hoverable: true,
264 hoverable: true,
255 clickable: true,
265 clickable: true,
256 autoHighlight:true,
266 autoHighlight:true,
257 color: "#999"
267 color: "#999"
258 },
268 },
259 //selection: {mode: "x"}
269 //selection: {mode: "x"}
260 };
270 };
261 var overview_options = {
271 var overview_options = {
262 legend:{show:false},
272 legend:{show:false},
263 bars: {show:true,barWidth: 2,},
273 bars: {show:true,barWidth: 2,},
264 shadowSize: 0,
274 shadowSize: 0,
265 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
275 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
266 yaxis: {ticks: 3, min: 0,},
276 yaxis: {ticks: 3, min: 0,},
267 grid: {color: "#999",},
277 grid: {color: "#999",},
268 selection: {mode: "x"}
278 selection: {mode: "x"}
269 };
279 };
270
280
271 /**
281 /**
272 *get dummy data needed in few places
282 *get dummy data needed in few places
273 */
283 */
274 function getDummyData(label){
284 function getDummyData(label){
275 return {"label":label,
285 return {"label":label,
276 "data":[{"time":0,
286 "data":[{"time":0,
277 "commits":0,
287 "commits":0,
278 "added":0,
288 "added":0,
279 "changed":0,
289 "changed":0,
280 "removed":0,
290 "removed":0,
281 }],
291 }],
282 "schema":["commits"],
292 "schema":["commits"],
283 "color":'#ffffff',
293 "color":'#ffffff',
284 }
294 }
285 }
295 }
286
296
287 /**
297 /**
288 * generate checkboxes accordindly to data
298 * generate checkboxes accordindly to data
289 * @param keys
299 * @param keys
290 * @returns
300 * @returns
291 */
301 */
292 function generateCheckboxes(data) {
302 function generateCheckboxes(data) {
293 //append checkboxes
303 //append checkboxes
294 var i = 0;
304 var i = 0;
295 choiceContainerTable.innerHTML = '';
305 choiceContainerTable.innerHTML = '';
296 for(var pos in data) {
306 for(var pos in data) {
297
307
298 data[pos].color = i;
308 data[pos].color = i;
299 i++;
309 i++;
300 if(data[pos].label != ''){
310 if(data[pos].label != ''){
301 choiceContainerTable.innerHTML += '<tr><td>'+
311 choiceContainerTable.innerHTML += '<tr><td>'+
302 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
312 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
303 +data[pos].label+
313 +data[pos].label+
304 '</td></tr>';
314 '</td></tr>';
305 }
315 }
306 }
316 }
307 }
317 }
308
318
309 /**
319 /**
310 * ToolTip show
320 * ToolTip show
311 */
321 */
312 function showTooltip(x, y, contents) {
322 function showTooltip(x, y, contents) {
313 var div=document.getElementById('tooltip');
323 var div=document.getElementById('tooltip');
314 if(!div) {
324 if(!div) {
315 div = document.createElement('div');
325 div = document.createElement('div');
316 div.id="tooltip";
326 div.id="tooltip";
317 div.style.position="absolute";
327 div.style.position="absolute";
318 div.style.border='1px solid #fdd';
328 div.style.border='1px solid #fdd';
319 div.style.padding='2px';
329 div.style.padding='2px';
320 div.style.backgroundColor='#fee';
330 div.style.backgroundColor='#fee';
321 document.body.appendChild(div);
331 document.body.appendChild(div);
322 }
332 }
323 YAHOO.util.Dom.setStyle(div, 'opacity', 0);
333 YAHOO.util.Dom.setStyle(div, 'opacity', 0);
324 div.innerHTML = contents;
334 div.innerHTML = contents;
325 div.style.top=(y + 5) + "px";
335 div.style.top=(y + 5) + "px";
326 div.style.left=(x + 5) + "px";
336 div.style.left=(x + 5) + "px";
327
337
328 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
338 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
329 anim.animate();
339 anim.animate();
330 }
340 }
331
341
332 /**
342 /**
333 * This function will detect if selected period has some changesets
343 * This function will detect if selected period has some changesets
334 for this user if it does this data is then pushed for displaying
344 for this user if it does this data is then pushed for displaying
335 Additionally it will only display users that are selected by the checkbox
345 Additionally it will only display users that are selected by the checkbox
336 */
346 */
337 function getDataAccordingToRanges(ranges) {
347 function getDataAccordingToRanges(ranges) {
338
348
339 var data = [];
349 var data = [];
340 var keys = [];
350 var keys = [];
341 for(var key in dataset){
351 for(var key in dataset){
342 var push = false;
352 var push = false;
343
353
344 //method1 slow !!
354 //method1 slow !!
345 //*
355 //*
346 for(var ds in dataset[key].data){
356 for(var ds in dataset[key].data){
347 commit_data = dataset[key].data[ds];
357 commit_data = dataset[key].data[ds];
348 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
358 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
349 push = true;
359 push = true;
350 break;
360 break;
351 }
361 }
352 }
362 }
353 //*/
363 //*/
354
364
355 /*//method2 sorted commit data !!!
365 /*//method2 sorted commit data !!!
356
366
357 var first_commit = dataset[key].data[0].time;
367 var first_commit = dataset[key].data[0].time;
358 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
368 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
359
369
360 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
370 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
361 push = true;
371 push = true;
362 }
372 }
363 //*/
373 //*/
364
374
365 if(push){
375 if(push){
366 data.push(dataset[key]);
376 data.push(dataset[key]);
367 }
377 }
368 }
378 }
369 if(data.length >= 1){
379 if(data.length >= 1){
370 return data;
380 return data;
371 }
381 }
372 else{
382 else{
373 //just return dummy data for graph to plot itself
383 //just return dummy data for graph to plot itself
374 return [getDummyData('')];
384 return [getDummyData('')];
375 }
385 }
376
386
377 }
387 }
378
388
379 /**
389 /**
380 * redraw using new checkbox data
390 * redraw using new checkbox data
381 */
391 */
382 function plotchoiced(e,args){
392 function plotchoiced(e,args){
383 var cur_data = args[0];
393 var cur_data = args[0];
384 var cur_ranges = args[1];
394 var cur_ranges = args[1];
385
395
386 var new_data = [];
396 var new_data = [];
387 var inputs = choiceContainer.getElementsByTagName("input");
397 var inputs = choiceContainer.getElementsByTagName("input");
388
398
389 //show only checked labels
399 //show only checked labels
390 for(var i=0; i<inputs.length; i++) {
400 for(var i=0; i<inputs.length; i++) {
391 var checkbox_key = inputs[i].name;
401 var checkbox_key = inputs[i].name;
392
402
393 if(inputs[i].checked){
403 if(inputs[i].checked){
394 for(var d in cur_data){
404 for(var d in cur_data){
395 if(cur_data[d].label == checkbox_key){
405 if(cur_data[d].label == checkbox_key){
396 new_data.push(cur_data[d]);
406 new_data.push(cur_data[d]);
397 }
407 }
398 }
408 }
399 }
409 }
400 else{
410 else{
401 //push dummy data to not hide the label
411 //push dummy data to not hide the label
402 new_data.push(getDummyData(checkbox_key));
412 new_data.push(getDummyData(checkbox_key));
403 }
413 }
404 }
414 }
405
415
406 var new_options = YAHOO.lang.merge(plot_options, {
416 var new_options = YAHOO.lang.merge(plot_options, {
407 xaxis: {
417 xaxis: {
408 min: cur_ranges.xaxis.from,
418 min: cur_ranges.xaxis.from,
409 max: cur_ranges.xaxis.to,
419 max: cur_ranges.xaxis.to,
410 mode:"time",
420 mode:"time",
411 timeformat: "%d/%m",
421 timeformat: "%d/%m",
412 },
422 },
413 });
423 });
414 if (!new_data){
424 if (!new_data){
415 new_data = [[0,1]];
425 new_data = [[0,1]];
416 }
426 }
417 // do the zooming
427 // do the zooming
418 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
428 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
419
429
420 plot.subscribe("plotselected", plotselected);
430 plot.subscribe("plotselected", plotselected);
421
431
422 //resubscribe plothover
432 //resubscribe plothover
423 plot.subscribe("plothover", plothover);
433 plot.subscribe("plothover", plothover);
424
434
425 // don't fire event on the overview to prevent eternal loop
435 // don't fire event on the overview to prevent eternal loop
426 overview.setSelection(cur_ranges, true);
436 overview.setSelection(cur_ranges, true);
427
437
428 }
438 }
429
439
430 /**
440 /**
431 * plot only selected items from overview
441 * plot only selected items from overview
432 * @param ranges
442 * @param ranges
433 * @returns
443 * @returns
434 */
444 */
435 function plotselected(ranges,cur_data) {
445 function plotselected(ranges,cur_data) {
436 //updates the data for new plot
446 //updates the data for new plot
437 data = getDataAccordingToRanges(ranges);
447 data = getDataAccordingToRanges(ranges);
438 generateCheckboxes(data);
448 generateCheckboxes(data);
439
449
440 var new_options = YAHOO.lang.merge(plot_options, {
450 var new_options = YAHOO.lang.merge(plot_options, {
441 xaxis: {
451 xaxis: {
442 min: ranges.xaxis.from,
452 min: ranges.xaxis.from,
443 max: ranges.xaxis.to,
453 max: ranges.xaxis.to,
444 mode:"time",
454 mode:"time",
445 timeformat: "%d/%m",
455 timeformat: "%d/%m",
446 },
456 },
447 yaxis: {
457 yaxis: {
448 min: ranges.yaxis.from,
458 min: ranges.yaxis.from,
449 max: ranges.yaxis.to,
459 max: ranges.yaxis.to,
450 },
460 },
451
461
452 });
462 });
453 // do the zooming
463 // do the zooming
454 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
464 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
455
465
456 plot.subscribe("plotselected", plotselected);
466 plot.subscribe("plotselected", plotselected);
457
467
458 //resubscribe plothover
468 //resubscribe plothover
459 plot.subscribe("plothover", plothover);
469 plot.subscribe("plothover", plothover);
460
470
461 // don't fire event on the overview to prevent eternal loop
471 // don't fire event on the overview to prevent eternal loop
462 overview.setSelection(ranges, true);
472 overview.setSelection(ranges, true);
463
473
464 //resubscribe choiced
474 //resubscribe choiced
465 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
475 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
466 }
476 }
467
477
468 var previousPoint = null;
478 var previousPoint = null;
469
479
470 function plothover(o) {
480 function plothover(o) {
471 var pos = o.pos;
481 var pos = o.pos;
472 var item = o.item;
482 var item = o.item;
473
483
474 //YAHOO.util.Dom.get("x").innerHTML = pos.x.toFixed(2);
484 //YAHOO.util.Dom.get("x").innerHTML = pos.x.toFixed(2);
475 //YAHOO.util.Dom.get("y").innerHTML = pos.y.toFixed(2);
485 //YAHOO.util.Dom.get("y").innerHTML = pos.y.toFixed(2);
476 if (item) {
486 if (item) {
477 if (previousPoint != item.datapoint) {
487 if (previousPoint != item.datapoint) {
478 previousPoint = item.datapoint;
488 previousPoint = item.datapoint;
479
489
480 var tooltip = YAHOO.util.Dom.get("tooltip");
490 var tooltip = YAHOO.util.Dom.get("tooltip");
481 if(tooltip) {
491 if(tooltip) {
482 tooltip.parentNode.removeChild(tooltip);
492 tooltip.parentNode.removeChild(tooltip);
483 }
493 }
484 var x = item.datapoint.x.toFixed(2);
494 var x = item.datapoint.x.toFixed(2);
485 var y = item.datapoint.y.toFixed(2);
495 var y = item.datapoint.y.toFixed(2);
486
496
487 if (!item.series.label){
497 if (!item.series.label){
488 item.series.label = 'commits';
498 item.series.label = 'commits';
489 }
499 }
490 var d = new Date(x*1000);
500 var d = new Date(x*1000);
491 var fd = d.toDateString()
501 var fd = d.toDateString()
492 var nr_commits = parseInt(y);
502 var nr_commits = parseInt(y);
493
503
494 var cur_data = dataset[item.series.label].data[item.dataIndex];
504 var cur_data = dataset[item.series.label].data[item.dataIndex];
495 var added = cur_data.added;
505 var added = cur_data.added;
496 var changed = cur_data.changed;
506 var changed = cur_data.changed;
497 var removed = cur_data.removed;
507 var removed = cur_data.removed;
498
508
499 var nr_commits_suffix = " ${_('commits')} ";
509 var nr_commits_suffix = " ${_('commits')} ";
500 var added_suffix = " ${_('files added')} ";
510 var added_suffix = " ${_('files added')} ";
501 var changed_suffix = " ${_('files changed')} ";
511 var changed_suffix = " ${_('files changed')} ";
502 var removed_suffix = " ${_('files removed')} ";
512 var removed_suffix = " ${_('files removed')} ";
503
513
504
514
505 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
515 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
506 if(added==1){added_suffix=" ${_('file added')} ";}
516 if(added==1){added_suffix=" ${_('file added')} ";}
507 if(changed==1){changed_suffix=" ${_('file changed')} ";}
517 if(changed==1){changed_suffix=" ${_('file changed')} ";}
508 if(removed==1){removed_suffix=" ${_('file removed')} ";}
518 if(removed==1){removed_suffix=" ${_('file removed')} ";}
509
519
510 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
520 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
511 +'<br/>'+
521 +'<br/>'+
512 nr_commits + nr_commits_suffix+'<br/>'+
522 nr_commits + nr_commits_suffix+'<br/>'+
513 added + added_suffix +'<br/>'+
523 added + added_suffix +'<br/>'+
514 changed + changed_suffix + '<br/>'+
524 changed + changed_suffix + '<br/>'+
515 removed + removed_suffix + '<br/>');
525 removed + removed_suffix + '<br/>');
516 }
526 }
517 }
527 }
518 else {
528 else {
519 var tooltip = YAHOO.util.Dom.get("tooltip");
529 var tooltip = YAHOO.util.Dom.get("tooltip");
520
530
521 if(tooltip) {
531 if(tooltip) {
522 tooltip.parentNode.removeChild(tooltip);
532 tooltip.parentNode.removeChild(tooltip);
523 }
533 }
524 previousPoint = null;
534 previousPoint = null;
525 }
535 }
526 }
536 }
527
537
528 /**
538 /**
529 * MAIN EXECUTION
539 * MAIN EXECUTION
530 */
540 */
531
541
532 var data = getDataAccordingToRanges(initial_ranges);
542 var data = getDataAccordingToRanges(initial_ranges);
533 generateCheckboxes(data);
543 generateCheckboxes(data);
534
544
535 //main plot
545 //main plot
536 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
546 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
537
547
538 //overview
548 //overview
539 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
549 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
540
550
541 //show initial selection on overview
551 //show initial selection on overview
542 overview.setSelection(initial_ranges);
552 overview.setSelection(initial_ranges);
543
553
544 plot.subscribe("plotselected", plotselected);
554 plot.subscribe("plotselected", plotselected);
545
555
546 overview.subscribe("plotselected", function (ranges) {
556 overview.subscribe("plotselected", function (ranges) {
547 plot.setSelection(ranges);
557 plot.setSelection(ranges);
548 });
558 });
549
559
550 plot.subscribe("plothover", plothover);
560 plot.subscribe("plothover", plothover);
551
561
552 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
562 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
553 }
563 }
554 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
564 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
555 </script>
565 </script>
556
566
557 </div>
567 </div>
558 </div>
568 </div>
559
569
560 <div class="box">
570 <div class="box">
561 <div class="title">
571 <div class="title">
562 <div class="breadcrumbs">${h.link_to(_('Last ten changes'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
572 <div class="breadcrumbs">${h.link_to(_('Last ten changes'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
563 </div>
573 </div>
564 <div class="table">
574 <div class="table">
565 <div id="shortlog_data">
575 <div id="shortlog_data">
566 <%include file='../shortlog/shortlog_data.html'/>
576 <%include file='../shortlog/shortlog_data.html'/>
567 </div>
577 </div>
568 ##%if c.repo_changesets:
578 ##%if c.repo_changesets:
569 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
579 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
570 ##%endif
580 ##%endif
571 </div>
581 </div>
572 </div>
582 </div>
573 <div class="box">
583 <div class="box">
574 <div class="title">
584 <div class="title">
575 <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
585 <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
576 </div>
586 </div>
577 <div class="table">
587 <div class="table">
578 <%include file='../tags/tags_data.html'/>
588 <%include file='../tags/tags_data.html'/>
579 %if c.repo_changesets:
589 %if c.repo_changesets:
580 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
590 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
581 %endif
591 %endif
582 </div>
592 </div>
583 </div>
593 </div>
584 <div class="box">
594 <div class="box">
585 <div class="title">
595 <div class="title">
586 <div class="breadcrumbs">${h.link_to(_('Last ten branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
596 <div class="breadcrumbs">${h.link_to(_('Last ten branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
587 </div>
597 </div>
588 <div class="table">
598 <div class="table">
589 <%include file='../branches/branches_data.html'/>
599 <%include file='../branches/branches_data.html'/>
590 %if c.repo_changesets:
600 %if c.repo_changesets:
591 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
601 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
592 %endif
602 %endif
593 </div>
603 </div>
594 </div>
604 </div>
595
605
596 </%def> No newline at end of file
606 </%def>
@@ -1,175 +1,165 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2
2
3 class TestFilesController(TestController):
3 class TestFilesController(TestController):
4
4
5 def test_index(self):
5 def test_index(self):
6 self.log_user()
6 self.log_user()
7 response = self.app.get(url(controller='files', action='index',
7 response = self.app.get(url(controller='files', action='index',
8 repo_name=HG_REPO,
8 repo_name=HG_REPO,
9 revision='tip',
9 revision='tip',
10 f_path='/'))
10 f_path='/'))
11 # Test response...
11 # Test response...
12 assert '<a class="browser-dir" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/docs">docs</a>' in response.body, 'missing dir'
12 assert '<a class="browser-dir" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/docs">docs</a>' in response.body, 'missing dir'
13 assert '<a class="browser-dir" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/tests">tests</a>' in response.body, 'missing dir'
13 assert '<a class="browser-dir" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/tests">tests</a>' in response.body, 'missing dir'
14 assert '<a class="browser-dir" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/vcs">vcs</a>' in response.body, 'missing dir'
14 assert '<a class="browser-dir" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/vcs">vcs</a>' in response.body, 'missing dir'
15 assert '<a class="browser-file" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/.hgignore">.hgignore</a>' in response.body, 'missing file'
15 assert '<a class="browser-file" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/.hgignore">.hgignore</a>' in response.body, 'missing file'
16 assert '<a class="browser-file" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/MANIFEST.in">MANIFEST.in</a>' in response.body, 'missing file'
16 assert '<a class="browser-file" href="/vcs_test_hg/files/27cd5cce30c96924232dffcd24178a07ffeb5dfc/MANIFEST.in">MANIFEST.in</a>' in response.body, 'missing file'
17
17
18
18
19 def test_index_revision(self):
19 def test_index_revision(self):
20 self.log_user()
20 self.log_user()
21
21
22 response = self.app.get(url(controller='files', action='index',
22 response = self.app.get(url(controller='files', action='index',
23 repo_name=HG_REPO,
23 repo_name=HG_REPO,
24 revision='7ba66bec8d6dbba14a2155be32408c435c5f4492',
24 revision='7ba66bec8d6dbba14a2155be32408c435c5f4492',
25 f_path='/'))
25 f_path='/'))
26
26
27
27
28
28
29 #Test response...
29 #Test response...
30
30
31 assert '<a class="browser-dir" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/docs">docs</a>' in response.body, 'missing dir'
31 assert '<a class="browser-dir" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/docs">docs</a>' in response.body, 'missing dir'
32 assert '<a class="browser-dir" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/tests">tests</a>' in response.body, 'missing dir'
32 assert '<a class="browser-dir" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/tests">tests</a>' in response.body, 'missing dir'
33 assert '<a class="browser-file" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/README.rst">README.rst</a>' in response.body, 'missing file'
33 assert '<a class="browser-file" href="/vcs_test_hg/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/README.rst">README.rst</a>' in response.body, 'missing file'
34 assert '1.1 KiB' in response.body, 'missing size of setup.py'
34 assert '1.1 KiB' in response.body, 'missing size of setup.py'
35 assert 'text/x-python' in response.body, 'missing mimetype of setup.py'
35 assert 'text/x-python' in response.body, 'missing mimetype of setup.py'
36
36
37
37
38
38
39 def test_index_different_branch(self):
39 def test_index_different_branch(self):
40 self.log_user()
40 self.log_user()
41
41
42 response = self.app.get(url(controller='files', action='index',
42 response = self.app.get(url(controller='files', action='index',
43 repo_name=HG_REPO,
43 repo_name=HG_REPO,
44 revision='97e8b885c04894463c51898e14387d80c30ed1ee',
44 revision='97e8b885c04894463c51898e14387d80c30ed1ee',
45 f_path='/'))
45 f_path='/'))
46
46
47
47
48
48
49 assert """<span style="text-transform: uppercase;"><a href="#">branch: git</a></span>""" in response.body, 'missing or wrong branch info'
49 assert """<span style="text-transform: uppercase;"><a href="#">branch: git</a></span>""" in response.body, 'missing or wrong branch info'
50
50
51
51
52
52
53 def test_index_paging(self):
53 def test_index_paging(self):
54 self.log_user()
54 self.log_user()
55
55
56 for r in [(73, 'a066b25d5df7016b45a41b7e2a78c33b57adc235'),
56 for r in [(73, 'a066b25d5df7016b45a41b7e2a78c33b57adc235'),
57 (92, 'cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e'),
57 (92, 'cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e'),
58 (109, '75feb4c33e81186c87eac740cee2447330288412'),
58 (109, '75feb4c33e81186c87eac740cee2447330288412'),
59 (1, '3d8f361e72ab303da48d799ff1ac40d5ac37c67e'),
59 (1, '3d8f361e72ab303da48d799ff1ac40d5ac37c67e'),
60 (0, 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]:
60 (0, 'b986218ba1c9b0d6a259fac9b050b1724ed8e545')]:
61
61
62 response = self.app.get(url(controller='files', action='index',
62 response = self.app.get(url(controller='files', action='index',
63 repo_name=HG_REPO,
63 repo_name=HG_REPO,
64 revision=r[1],
64 revision=r[1],
65 f_path='/'))
65 f_path='/'))
66
66
67 assert """@ r%s:%s""" % (r[0], r[1][:12]) in response.body, 'missing info about current revision'
67 assert """@ r%s:%s""" % (r[0], r[1][:12]) in response.body, 'missing info about current revision'
68
68
69 def test_file_source(self):
69 def test_file_source(self):
70 self.log_user()
70 self.log_user()
71 response = self.app.get(url(controller='files', action='index',
71 response = self.app.get(url(controller='files', action='index',
72 repo_name=HG_REPO,
72 repo_name=HG_REPO,
73 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
73 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
74 f_path='vcs/nodes.py'))
74 f_path='vcs/nodes.py'))
75
75
76
77
78 #tests...
79
80 #test or history
76 #test or history
81 assert """<select id="diff1" name="diff1">
77 assert """<select id="diff1" name="diff1">
82 <option selected="selected" value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776</option>
78 <option selected="selected" value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776</option>
83 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35</option>
79 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35</option>
84 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c</option>
80 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c</option>
85 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329</option>
81 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329</option>
86 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf</option>
82 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf</option>
87 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81</option>
83 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81</option>
88 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc</option>
84 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc</option>
89 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21</option>
85 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21</option>
90 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2</option>
86 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2</option>
91 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85</option>
87 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85</option>
92 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2</option>
88 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2</option>
93 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93</option>
89 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93</option>
94 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b</option>
90 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b</option>
95 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455</option>
91 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455</option>
96 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32</option>
92 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32</option>
97 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0</option>
93 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0</option>
98 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081</option>
94 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081</option>
99 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad</option>
95 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad</option>
100 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7</option>
96 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7</option>
101 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059</option>
97 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059</option>
102 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb</option>
98 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb</option>
103 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1</option>
99 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1</option>
104 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71</option>
100 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71</option>
105 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771</option>
101 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771</option>
106 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526</option>
102 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526</option>
107 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4</option>
103 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4</option>
108 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b</option>
104 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b</option>
109 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c</option>
105 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c</option>
110 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1</option>
106 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1</option>
111 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5</option>
107 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5</option>
112 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283</option>
108 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283</option>
113 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6</option>
109 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6</option>
114 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3</option>
110 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3</option>
115 </select>""" in response.body
111 </select>""" in response.body
116
112
117
113
118 assert """<div class="commit">"Partially implemented #16. filecontent/commit message/author/node name are safe_unicode now.
114 assert """<div class="commit">"Partially implemented #16. filecontent/commit message/author/node name are safe_unicode now.
119 In addition some other __str__ are unicode as well
115 In addition some other __str__ are unicode as well
120 Added test for unicode
116 Added test for unicode
121 Improved test to clone into uniq repository.
117 Improved test to clone into uniq repository.
122 removed extra unicode conversion in diff."</div>""" in response.body
118 removed extra unicode conversion in diff."</div>""" in response.body
123
119
124 assert """<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""" in response.body, 'missing or wrong branch info'
120 assert """<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""" in response.body, 'missing or wrong branch info'
125
121
126 def test_file_annotation(self):
122 def test_file_annotation(self):
127 self.log_user()
123 self.log_user()
128 response = self.app.get(url(controller='files', action='annotate',
124 response = self.app.get(url(controller='files', action='annotate',
129 repo_name=HG_REPO,
125 repo_name=HG_REPO,
130 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
126 revision='27cd5cce30c96924232dffcd24178a07ffeb5dfc',
131 f_path='vcs/nodes.py'))
127 f_path='vcs/nodes.py'))
132
128
133
129
134
135
136
137
138 print response.body
139
140 assert """<option selected="selected" value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776</option>
130 assert """<option selected="selected" value="8911406ad776fdd3d0b9932a2e89677e57405a48">r167:8911406ad776</option>
141 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35</option>
131 <option value="aa957ed78c35a1541f508d2ec90e501b0a9e3167">r165:aa957ed78c35</option>
142 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c</option>
132 <option value="48e11b73e94c0db33e736eaeea692f990cb0b5f1">r140:48e11b73e94c</option>
143 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329</option>
133 <option value="adf3cbf483298563b968a6c673cd5bde5f7d5eea">r126:adf3cbf48329</option>
144 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf</option>
134 <option value="6249fd0fb2cfb1411e764129f598e2cf0de79a6f">r113:6249fd0fb2cf</option>
145 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81</option>
135 <option value="75feb4c33e81186c87eac740cee2447330288412">r109:75feb4c33e81</option>
146 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc</option>
136 <option value="9a4dc232ecdc763ef2e98ae2238cfcbba4f6ad8d">r108:9a4dc232ecdc</option>
147 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21</option>
137 <option value="595cce4efa21fda2f2e4eeb4fe5f2a6befe6fa2d">r107:595cce4efa21</option>
148 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2</option>
138 <option value="4a8bd421fbc2dfbfb70d85a3fe064075ab2c49da">r104:4a8bd421fbc2</option>
149 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85</option>
139 <option value="57be63fc8f85e65a0106a53187f7316f8c487ffa">r102:57be63fc8f85</option>
150 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2</option>
140 <option value="5530bd87f7e2e124a64d07cb2654c997682128be">r101:5530bd87f7e2</option>
151 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93</option>
141 <option value="e516008b1c93f142263dc4b7961787cbad654ce1">r99:e516008b1c93</option>
152 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b</option>
142 <option value="41f43fc74b8b285984554532eb105ac3be5c434f">r93:41f43fc74b8b</option>
153 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455</option>
143 <option value="cc66b61b8455b264a7a8a2d8ddc80fcfc58c221e">r92:cc66b61b8455</option>
154 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32</option>
144 <option value="73ab5b616b3271b0518682fb4988ce421de8099f">r91:73ab5b616b32</option>
155 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0</option>
145 <option value="e0da75f308c0f18f98e9ce6257626009fdda2b39">r82:e0da75f308c0</option>
156 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081</option>
146 <option value="fb2e41e0f0810be4d7103bc2a4c7be16ee3ec611">r81:fb2e41e0f081</option>
157 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad</option>
147 <option value="602ae2f5e7ade70b3b66a58cdd9e3e613dc8a028">r76:602ae2f5e7ad</option>
158 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7</option>
148 <option value="a066b25d5df7016b45a41b7e2a78c33b57adc235">r73:a066b25d5df7</option>
159 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059</option>
149 <option value="637a933c905958ce5151f154147c25c1c7b68832">r61:637a933c9059</option>
160 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb</option>
150 <option value="0c21004effeb8ce2d2d5b4a8baf6afa8394b6fbc">r60:0c21004effeb</option>
161 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1</option>
151 <option value="a1f39c56d3f1d52d5fb5920370a2a2716cd9a444">r59:a1f39c56d3f1</option>
162 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71</option>
152 <option value="97d32df05c715a3bbf936bf3cc4e32fb77fe1a7f">r58:97d32df05c71</option>
163 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771</option>
153 <option value="08eaf14517718dccea4b67755a93368341aca919">r57:08eaf1451771</option>
164 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526</option>
154 <option value="22f71ad265265a53238359c883aa976e725aa07d">r56:22f71ad26526</option>
165 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4</option>
155 <option value="97501f02b7b4330924b647755663a2d90a5e638d">r49:97501f02b7b4</option>
166 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b</option>
156 <option value="86ede6754f2b27309452bb11f997386ae01d0e5a">r47:86ede6754f2b</option>
167 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c</option>
157 <option value="014c40c0203c423dc19ecf94644f7cac9d4cdce0">r45:014c40c0203c</option>
168 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1</option>
158 <option value="ee87846a61c12153b51543bf860e1026c6d3dcba">r30:ee87846a61c1</option>
169 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5</option>
159 <option value="9bb326a04ae5d98d437dece54be04f830cf1edd9">r26:9bb326a04ae5</option>
170 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283</option>
160 <option value="536c1a19428381cfea92ac44985304f6a8049569">r24:536c1a194283</option>
171 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6</option>
161 <option value="dc5d2c0661b61928834a785d3e64a3f80d3aad9c">r8:dc5d2c0661b6</option>
172 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3</option>
162 <option value="3803844fdbd3b711175fc3da9bdacfcd6d29a6fb">r7:3803844fdbd3</option>
173 </select>""" in response.body, 'missing history in annotation'
163 </select>""" in response.body, 'missing history in annotation'
174
164
175 assert """<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""" in response.body, 'missing or wrong branch info'
165 assert """<span style="text-transform: uppercase;"><a href="#">branch: default</a></span>""" in response.body, 'missing or wrong branch info'
General Comments 0
You need to be logged in to leave comments. Login now