##// END OF EJS Templates
fixed sorting for repo switcher, fixed length for code stats
marcink -
r693:90ac3255 beta
parent child Browse files
Show More
@@ -1,239 +1,240 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.lib import helpers as h
27 from rhodecode.lib import helpers as h
28 from rhodecode.lib.auth import HasRepoPermissionAny
28 from rhodecode.lib.auth import HasRepoPermissionAny
29 from rhodecode.lib.utils import get_repos
29 from rhodecode.lib.utils import get_repos
30 from rhodecode.model import meta
30 from rhodecode.model import meta
31 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
31 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
32 from rhodecode.model.caching_query import FromCache
32 from rhodecode.model.caching_query import FromCache
33 from sqlalchemy.orm import joinedload
33 from sqlalchemy.orm import joinedload
34 from sqlalchemy.orm.session import make_transient
34 from sqlalchemy.orm.session import make_transient
35 from vcs import get_backend
35 from vcs import get_backend
36 from vcs.utils.helpers import get_scm
36 from vcs.utils.helpers import get_scm
37 from vcs.exceptions import RepositoryError, VCSError
37 from vcs.exceptions import RepositoryError, VCSError
38 from vcs.utils.lazy import LazyProperty
38 from vcs.utils.lazy import LazyProperty
39 import traceback
39 import traceback
40 import logging
40 import logging
41 import os
41 import os
42 import time
42 import time
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46 class ScmModel(object):
46 class ScmModel(object):
47 """
47 """
48 Mercurial Model
48 Mercurial Model
49 """
49 """
50
50
51 def __init__(self):
51 def __init__(self):
52 self.sa = meta.Session()
52 self.sa = meta.Session()
53
53
54 @LazyProperty
54 @LazyProperty
55 def repos_path(self):
55 def repos_path(self):
56 """
56 """
57 Get's the repositories root path from database
57 Get's the repositories root path from database
58 """
58 """
59 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
59 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
60
60
61 return q.ui_value
61 return q.ui_value
62
62
63 def repo_scan(self, repos_path, baseui, initial=False):
63 def repo_scan(self, repos_path, baseui, initial=False):
64 """
64 """
65 Listing of repositories in given path. This path should not be a
65 Listing of repositories in given path. This path should not be a
66 repository itself. Return a dictionary of repository objects
66 repository itself. Return a dictionary of repository objects
67
67
68 :param repos_path: path to directory containing repositories
68 :param repos_path: path to directory containing repositories
69 :param baseui
69 :param baseui
70 :param initial: initial scan
70 :param initial: initial scan
71 """
71 """
72 log.info('scanning for repositories in %s', repos_path)
72 log.info('scanning for repositories in %s', repos_path)
73
73
74 if not isinstance(baseui, ui.ui):
74 if not isinstance(baseui, ui.ui):
75 baseui = ui.ui()
75 baseui = ui.ui()
76 repos_list = {}
76 repos_list = {}
77
77
78 for name, path in get_repos(repos_path):
78 for name, path in get_repos(repos_path):
79 try:
79 try:
80 if repos_list.has_key(name):
80 if repos_list.has_key(name):
81 raise RepositoryError('Duplicate repository name %s '
81 raise RepositoryError('Duplicate repository name %s '
82 'found in %s' % (name, path))
82 'found in %s' % (name, path))
83 else:
83 else:
84
84
85 klass = get_backend(path[0])
85 klass = get_backend(path[0])
86
86
87 if path[0] == 'hg':
87 if path[0] == 'hg':
88 repos_list[name] = klass(path[1], baseui=baseui)
88 repos_list[name] = klass(path[1], baseui=baseui)
89
89
90 if path[0] == 'git':
90 if path[0] == 'git':
91 repos_list[name] = klass(path[1])
91 repos_list[name] = klass(path[1])
92 except OSError:
92 except OSError:
93 continue
93 continue
94
94
95 return repos_list
95 return repos_list
96
96
97 def get_repos(self, all_repos=None):
97 def get_repos(self, all_repos=None):
98 """
98 """
99 Get all repos from db and for each repo create it's backend instance.
99 Get all repos from db and for each repo create it's backend instance.
100 and fill that backed with information from database
100 and fill that backed with information from database
101
101
102 :param all_repos: give specific repositories list, good for filtering
102 :param all_repos: give specific repositories list, good for filtering
103 """
103 """
104 if not all_repos:
104 if not all_repos:
105 all_repos = self.sa.query(Repository).all()
105 all_repos = self.sa.query(Repository)\
106 .order_by(Repository.repo_name).all()
106
107
107 for r in all_repos:
108 for r in all_repos:
108
109
109 repo = self.get(r.repo_name)
110 repo = self.get(r.repo_name)
110
111
111 if repo is not None:
112 if repo is not None:
112 last_change = repo.last_change
113 last_change = repo.last_change
113 tip = h.get_changeset_safe(repo, 'tip')
114 tip = h.get_changeset_safe(repo, 'tip')
114
115
115 tmp_d = {}
116 tmp_d = {}
116 tmp_d['name'] = repo.name
117 tmp_d['name'] = repo.name
117 tmp_d['name_sort'] = tmp_d['name'].lower()
118 tmp_d['name_sort'] = tmp_d['name'].lower()
118 tmp_d['description'] = repo.dbrepo.description
119 tmp_d['description'] = repo.dbrepo.description
119 tmp_d['description_sort'] = tmp_d['description']
120 tmp_d['description_sort'] = tmp_d['description']
120 tmp_d['last_change'] = last_change
121 tmp_d['last_change'] = last_change
121 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
122 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
122 tmp_d['tip'] = tip.raw_id
123 tmp_d['tip'] = tip.raw_id
123 tmp_d['tip_sort'] = tip.revision
124 tmp_d['tip_sort'] = tip.revision
124 tmp_d['rev'] = tip.revision
125 tmp_d['rev'] = tip.revision
125 tmp_d['contact'] = repo.dbrepo.user.full_contact
126 tmp_d['contact'] = repo.dbrepo.user.full_contact
126 tmp_d['contact_sort'] = tmp_d['contact']
127 tmp_d['contact_sort'] = tmp_d['contact']
127 tmp_d['repo_archives'] = list(repo._get_archives())
128 tmp_d['repo_archives'] = list(repo._get_archives())
128 tmp_d['last_msg'] = tip.message
129 tmp_d['last_msg'] = tip.message
129 tmp_d['repo'] = repo
130 tmp_d['repo'] = repo
130 yield tmp_d
131 yield tmp_d
131
132
132 def get_repo(self, repo_name):
133 def get_repo(self, repo_name):
133 return self.get(repo_name)
134 return self.get(repo_name)
134
135
135 def get(self, repo_name):
136 def get(self, repo_name):
136 """
137 """
137 Get's repository from given name, creates BackendInstance and
138 Get's repository from given name, creates BackendInstance and
138 propagates it's data from database with all additional information
139 propagates it's data from database with all additional information
139 :param repo_name:
140 :param repo_name:
140 """
141 """
141 if not HasRepoPermissionAny('repository.read', 'repository.write',
142 if not HasRepoPermissionAny('repository.read', 'repository.write',
142 'repository.admin')(repo_name, 'get repo check'):
143 'repository.admin')(repo_name, 'get repo check'):
143 return
144 return
144
145
145 @cache_region('long_term')
146 @cache_region('long_term')
146 def _get_repo(repo_name):
147 def _get_repo(repo_name):
147
148
148 repo_path = os.path.join(self.repos_path, repo_name)
149 repo_path = os.path.join(self.repos_path, repo_name)
149 alias = get_scm(repo_path)[0]
150 alias = get_scm(repo_path)[0]
150
151
151 log.debug('Creating instance of %s repository', alias)
152 log.debug('Creating instance of %s repository', alias)
152 backend = get_backend(alias)
153 backend = get_backend(alias)
153
154
154 if alias == 'hg':
155 if alias == 'hg':
155 repo = backend(repo_path, create=False, baseui=None)
156 repo = backend(repo_path, create=False, baseui=None)
156 #skip hidden web repository
157 #skip hidden web repository
157 if repo._get_hidden():
158 if repo._get_hidden():
158 return
159 return
159 else:
160 else:
160 repo = backend(repo_path, create=False)
161 repo = backend(repo_path, create=False)
161
162
162 dbrepo = self.sa.query(Repository)\
163 dbrepo = self.sa.query(Repository)\
163 .options(joinedload(Repository.fork))\
164 .options(joinedload(Repository.fork))\
164 .options(joinedload(Repository.user))\
165 .options(joinedload(Repository.user))\
165 .filter(Repository.repo_name == repo_name)\
166 .filter(Repository.repo_name == repo_name)\
166 .scalar()
167 .scalar()
167 make_transient(dbrepo)
168 make_transient(dbrepo)
168 repo.dbrepo = dbrepo
169 repo.dbrepo = dbrepo
169 return repo
170 return repo
170
171
171 invalidate = self._should_invalidate(repo_name)
172 invalidate = self._should_invalidate(repo_name)
172 if invalidate:
173 if invalidate:
173 log.info('invalidating cache for repository %s', repo_name)
174 log.info('invalidating cache for repository %s', repo_name)
174 region_invalidate(_get_repo, None, repo_name)
175 region_invalidate(_get_repo, None, repo_name)
175 self._mark_invalidated(invalidate)
176 self._mark_invalidated(invalidate)
176
177
177 return _get_repo(repo_name)
178 return _get_repo(repo_name)
178
179
179
180
180
181
181 def mark_for_invalidation(self, repo_name):
182 def mark_for_invalidation(self, repo_name):
182 """
183 """
183 Puts cache invalidation task into db for
184 Puts cache invalidation task into db for
184 further global cache invalidation
185 further global cache invalidation
185
186
186 :param repo_name: this repo that should invalidation take place
187 :param repo_name: this repo that should invalidation take place
187 """
188 """
188 log.debug('marking %s for invalidation', repo_name)
189 log.debug('marking %s for invalidation', repo_name)
189 cache = self.sa.query(CacheInvalidation)\
190 cache = self.sa.query(CacheInvalidation)\
190 .filter(CacheInvalidation.cache_key == repo_name).scalar()
191 .filter(CacheInvalidation.cache_key == repo_name).scalar()
191
192
192 if cache:
193 if cache:
193 #mark this cache as inactive
194 #mark this cache as inactive
194 cache.cache_active = False
195 cache.cache_active = False
195 else:
196 else:
196 log.debug('cache key not found in invalidation db -> creating one')
197 log.debug('cache key not found in invalidation db -> creating one')
197 cache = CacheInvalidation(repo_name)
198 cache = CacheInvalidation(repo_name)
198
199
199 try:
200 try:
200 self.sa.add(cache)
201 self.sa.add(cache)
201 self.sa.commit()
202 self.sa.commit()
202 except:
203 except:
203 log.error(traceback.format_exc())
204 log.error(traceback.format_exc())
204 self.sa.rollback()
205 self.sa.rollback()
205
206
206
207
207
208
208
209
209
210
210 def _should_invalidate(self, repo_name):
211 def _should_invalidate(self, repo_name):
211 """
212 """
212 Looks up database for invalidation signals for this repo_name
213 Looks up database for invalidation signals for this repo_name
213 :param repo_name:
214 :param repo_name:
214 """
215 """
215
216
216 ret = self.sa.query(CacheInvalidation)\
217 ret = self.sa.query(CacheInvalidation)\
217 .options(FromCache('sql_cache_short',
218 .options(FromCache('sql_cache_short',
218 'get_invalidation_%s' % repo_name))\
219 'get_invalidation_%s' % repo_name))\
219 .filter(CacheInvalidation.cache_key == repo_name)\
220 .filter(CacheInvalidation.cache_key == repo_name)\
220 .filter(CacheInvalidation.cache_active == False)\
221 .filter(CacheInvalidation.cache_active == False)\
221 .scalar()
222 .scalar()
222
223
223 return ret
224 return ret
224
225
225 def _mark_invalidated(self, cache_key):
226 def _mark_invalidated(self, cache_key):
226 """
227 """
227 Marks all occurences of cache to invaldation as already invalidated
228 Marks all occurences of cache to invaldation as already invalidated
228 @param repo_name:
229 @param repo_name:
229 """
230 """
230 if cache_key:
231 if cache_key:
231 log.debug('marking %s as already invalidated', cache_key)
232 log.debug('marking %s as already invalidated', cache_key)
232 try:
233 try:
233 cache_key.cache_active = True
234 cache_key.cache_active = True
234 self.sa.add(cache_key)
235 self.sa.add(cache_key)
235 self.sa.commit()
236 self.sa.commit()
236 except:
237 except:
237 log.error(traceback.format_exc())
238 log.error(traceback.format_exc())
238 self.sa.rollback()
239 self.sa.rollback()
239
240
@@ -1,593 +1,594 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 <br/>
58 <br/>
59 %if c.repo_info.dbrepo.fork:
59 %if c.repo_info.dbrepo.fork:
60 <span style="margin-top:5px">
60 <span style="margin-top:5px">
61 <a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
61 <a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
62 <img class="icon" alt="${_('public')}"
62 <img class="icon" alt="${_('public')}"
63 title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}"
63 title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}"
64 src="/images/icons/arrow_divide.png"/>
64 src="/images/icons/arrow_divide.png"/>
65 ${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
65 ${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
66 </a>
66 </a>
67 </span>
67 </span>
68 %endif
68 %endif
69 </div>
69 </div>
70 </div>
70 </div>
71
71
72
72
73 <div class="field">
73 <div class="field">
74 <div class="label">
74 <div class="label">
75 <label>${_('Description')}:</label>
75 <label>${_('Description')}:</label>
76 </div>
76 </div>
77 <div class="input-short">
77 <div class="input-short">
78 ${c.repo_info.dbrepo.description}
78 ${c.repo_info.dbrepo.description}
79 </div>
79 </div>
80 </div>
80 </div>
81
81
82
82
83 <div class="field">
83 <div class="field">
84 <div class="label">
84 <div class="label">
85 <label>${_('Contact')}:</label>
85 <label>${_('Contact')}:</label>
86 </div>
86 </div>
87 <div class="input-short">
87 <div class="input-short">
88 <div class="gravatar">
88 <div class="gravatar">
89 <img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
89 <img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
90 </div>
90 </div>
91 ${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
91 ${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
92 ${_('Name')}: ${c.repo_info.dbrepo.user.name} ${c.repo_info.dbrepo.user.lastname}<br/>
92 ${_('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>
93 ${_('Email')}: <a href="mailto:${c.repo_info.dbrepo.user.email}">${c.repo_info.dbrepo.user.email}</a>
94 </div>
94 </div>
95 </div>
95 </div>
96
96
97 <div class="field">
97 <div class="field">
98 <div class="label">
98 <div class="label">
99 <label>${_('Last change')}:</label>
99 <label>${_('Last change')}:</label>
100 </div>
100 </div>
101 <div class="input-short">
101 <div class="input-short">
102 ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change}
102 ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change}
103 ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author}
103 ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author}
104
104
105 </div>
105 </div>
106 </div>
106 </div>
107
107
108 <div class="field">
108 <div class="field">
109 <div class="label">
109 <div class="label">
110 <label>${_('Clone url')}:</label>
110 <label>${_('Clone url')}:</label>
111 </div>
111 </div>
112 <div class="input-short">
112 <div class="input-short">
113 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
113 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
114 </div>
114 </div>
115 </div>
115 </div>
116
116
117 <div class="field">
117 <div class="field">
118 <div class="label">
118 <div class="label">
119 <label>${_('Trending languages')}:</label>
119 <label>${_('Trending languages')}:</label>
120 </div>
120 </div>
121 <div class="input-short">
121 <div class="input-short">
122 <div id="lang_stats">
122 <div id="lang_stats">
123
123
124 </div>
124 </div>
125 <script type="text/javascript">
125 <script type="text/javascript">
126 var data = ${c.trending_languages|n};
126 var data = ${c.trending_languages|n};
127 var total = 0;
127 var total = 0;
128 var no_data = true;
128 var no_data = true;
129 for (k in data){
129 for (k in data){
130 total += data[k];
130 total += data[k];
131 no_data = false;
131 no_data = false;
132 }
132 }
133 var tbl = document.createElement('table');
133 var tbl = document.createElement('table');
134 tbl.setAttribute('class','trending_language_tbl');
134 tbl.setAttribute('class','trending_language_tbl');
135 for (k in data){
135 for (k in data){
136 var tr = document.createElement('tr');
136 var tr = document.createElement('tr');
137 var percentage = Math.round((data[k]/total*100),2);
137 var percentage = Math.round((data[k]/total*100),2);
138 var value = data[k];
138 var value = data[k];
139 var td1 = document.createElement('td');
139 var td1 = document.createElement('td');
140 td1.width=150;
140 td1.width=150;
141 var trending_language_label = document.createElement('div');
141 var trending_language_label = document.createElement('div');
142 trending_language_label.innerHTML = k;
142 trending_language_label.innerHTML = k;
143 td1.appendChild(trending_language_label);
143 td1.appendChild(trending_language_label);
144
144
145 var td2 = document.createElement('td');
145 var td2 = document.createElement('td');
146 td2.setAttribute('style','padding-right:14px !important');
146 var trending_language = document.createElement('div');
147 var trending_language = document.createElement('div');
147 trending_language.title = k;
148 trending_language.title = k;
148 trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";
149 trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";
149 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
150 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
150 trending_language.style.width=percentage+"%";
151 trending_language.style.width=percentage+"%";
151 td2.appendChild(trending_language);
152 td2.appendChild(trending_language);
152
153
153 tr.appendChild(td1);
154 tr.appendChild(td1);
154 tr.appendChild(td2);
155 tr.appendChild(td2);
155 tbl.appendChild(tr);
156 tbl.appendChild(tr);
156
157
157 }
158 }
158 if(no_data){
159 if(no_data){
159 var tr = document.createElement('tr');
160 var tr = document.createElement('tr');
160 var td1 = document.createElement('td');
161 var td1 = document.createElement('td');
161 td1.innerHTML = "${_('No data loaded yet')}";
162 td1.innerHTML = "${_('No data loaded yet')}";
162 tr.appendChild(td1);
163 tr.appendChild(td1);
163 tbl.appendChild(tr);
164 tbl.appendChild(tr);
164 }
165 }
165 YAHOO.util.Dom.get('lang_stats').appendChild(tbl);
166 YAHOO.util.Dom.get('lang_stats').appendChild(tbl);
166 </script>
167 </script>
167
168
168 </div>
169 </div>
169 </div>
170 </div>
170
171
171 <div class="field">
172 <div class="field">
172 <div class="label">
173 <div class="label">
173 <label>${_('Download')}:</label>
174 <label>${_('Download')}:</label>
174 </div>
175 </div>
175 <div class="input-short">
176 <div class="input-short">
176 %for cnt,archive in enumerate(c.repo_info._get_archives()):
177 %for cnt,archive in enumerate(c.repo_info._get_archives()):
177 %if cnt >=1:
178 %if cnt >=1:
178 |
179 |
179 %endif
180 %endif
180 ${h.link_to(c.repo_info.name+'.'+archive['type'],
181 ${h.link_to(c.repo_info.name+'.'+archive['type'],
181 h.url('files_archive_home',repo_name=c.repo_info.name,
182 h.url('files_archive_home',repo_name=c.repo_info.name,
182 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
183 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
183 %endfor
184 %endfor
184 </div>
185 </div>
185 </div>
186 </div>
186
187
187 <div class="field">
188 <div class="field">
188 <div class="label">
189 <div class="label">
189 <label>${_('Feeds')}:</label>
190 <label>${_('Feeds')}:</label>
190 </div>
191 </div>
191 <div class="input-short">
192 <div class="input-short">
192 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
193 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
193 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
194 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
194 </div>
195 </div>
195 </div>
196 </div>
196 </div>
197 </div>
197 </div>
198 </div>
198 </div>
199 </div>
199
200
200 <div class="box box-right" style="min-height:455px">
201 <div class="box box-right" style="min-height:455px">
201 <!-- box / title -->
202 <!-- box / title -->
202 <div class="title">
203 <div class="title">
203 <h5>${_('Commit activity by day / author')}</h5>
204 <h5>${_('Commit activity by day / author')}</h5>
204 </div>
205 </div>
205
206
206 <div class="table">
207 <div class="table">
207 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
208 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
208 <div style="clear: both;height: 10px"></div>
209 <div style="clear: both;height: 10px"></div>
209 <div id="overview" style="width:460px;height:100px;float:left"></div>
210 <div id="overview" style="width:460px;height:100px;float:left"></div>
210
211
211 <div id="legend_data" style="clear:both;margin-top:10px;">
212 <div id="legend_data" style="clear:both;margin-top:10px;">
212 <div id="legend_container"></div>
213 <div id="legend_container"></div>
213 <div id="legend_choices">
214 <div id="legend_choices">
214 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
215 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
215 </div>
216 </div>
216 </div>
217 </div>
217 <script type="text/javascript">
218 <script type="text/javascript">
218 /**
219 /**
219 * Plots summary graph
220 * Plots summary graph
220 *
221 *
221 * @class SummaryPlot
222 * @class SummaryPlot
222 * @param {from} initial from for detailed graph
223 * @param {from} initial from for detailed graph
223 * @param {to} initial to for detailed graph
224 * @param {to} initial to for detailed graph
224 * @param {dataset}
225 * @param {dataset}
225 * @param {overview_dataset}
226 * @param {overview_dataset}
226 */
227 */
227 function SummaryPlot(from,to,dataset,overview_dataset) {
228 function SummaryPlot(from,to,dataset,overview_dataset) {
228 var initial_ranges = {
229 var initial_ranges = {
229 "xaxis":{
230 "xaxis":{
230 "from":from,
231 "from":from,
231 "to":to,
232 "to":to,
232 },
233 },
233 };
234 };
234 var dataset = dataset;
235 var dataset = dataset;
235 var overview_dataset = [overview_dataset];
236 var overview_dataset = [overview_dataset];
236 var choiceContainer = YAHOO.util.Dom.get("legend_choices");
237 var choiceContainer = YAHOO.util.Dom.get("legend_choices");
237 var choiceContainerTable = YAHOO.util.Dom.get("legend_choices_tables");
238 var choiceContainerTable = YAHOO.util.Dom.get("legend_choices_tables");
238 var plotContainer = YAHOO.util.Dom.get('commit_history');
239 var plotContainer = YAHOO.util.Dom.get('commit_history');
239 var overviewContainer = YAHOO.util.Dom.get('overview');
240 var overviewContainer = YAHOO.util.Dom.get('overview');
240
241
241 var plot_options = {
242 var plot_options = {
242 bars: {show:true,align:'center',lineWidth:4},
243 bars: {show:true,align:'center',lineWidth:4},
243 legend: {show:true, container:"legend_container"},
244 legend: {show:true, container:"legend_container"},
244 points: {show:true,radius:0,fill:false},
245 points: {show:true,radius:0,fill:false},
245 yaxis: {tickDecimals:0,},
246 yaxis: {tickDecimals:0,},
246 xaxis: {
247 xaxis: {
247 mode: "time",
248 mode: "time",
248 timeformat: "%d/%m",
249 timeformat: "%d/%m",
249 min:from,
250 min:from,
250 max:to,
251 max:to,
251 },
252 },
252 grid: {
253 grid: {
253 hoverable: true,
254 hoverable: true,
254 clickable: true,
255 clickable: true,
255 autoHighlight:true,
256 autoHighlight:true,
256 color: "#999"
257 color: "#999"
257 },
258 },
258 //selection: {mode: "x"}
259 //selection: {mode: "x"}
259 };
260 };
260 var overview_options = {
261 var overview_options = {
261 legend:{show:false},
262 legend:{show:false},
262 bars: {show:true,barWidth: 2,},
263 bars: {show:true,barWidth: 2,},
263 shadowSize: 0,
264 shadowSize: 0,
264 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
265 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
265 yaxis: {ticks: 3, min: 0,},
266 yaxis: {ticks: 3, min: 0,},
266 grid: {color: "#999",},
267 grid: {color: "#999",},
267 selection: {mode: "x"}
268 selection: {mode: "x"}
268 };
269 };
269
270
270 /**
271 /**
271 *get dummy data needed in few places
272 *get dummy data needed in few places
272 */
273 */
273 function getDummyData(label){
274 function getDummyData(label){
274 return {"label":label,
275 return {"label":label,
275 "data":[{"time":0,
276 "data":[{"time":0,
276 "commits":0,
277 "commits":0,
277 "added":0,
278 "added":0,
278 "changed":0,
279 "changed":0,
279 "removed":0,
280 "removed":0,
280 }],
281 }],
281 "schema":["commits"],
282 "schema":["commits"],
282 "color":'#ffffff',
283 "color":'#ffffff',
283 }
284 }
284 }
285 }
285
286
286 /**
287 /**
287 * generate checkboxes accordindly to data
288 * generate checkboxes accordindly to data
288 * @param keys
289 * @param keys
289 * @returns
290 * @returns
290 */
291 */
291 function generateCheckboxes(data) {
292 function generateCheckboxes(data) {
292 //append checkboxes
293 //append checkboxes
293 var i = 0;
294 var i = 0;
294 choiceContainerTable.innerHTML = '';
295 choiceContainerTable.innerHTML = '';
295 for(var pos in data) {
296 for(var pos in data) {
296
297
297 data[pos].color = i;
298 data[pos].color = i;
298 i++;
299 i++;
299 if(data[pos].label != ''){
300 if(data[pos].label != ''){
300 choiceContainerTable.innerHTML += '<tr><td>'+
301 choiceContainerTable.innerHTML += '<tr><td>'+
301 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
302 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
302 +data[pos].label+
303 +data[pos].label+
303 '</td></tr>';
304 '</td></tr>';
304 }
305 }
305 }
306 }
306 }
307 }
307
308
308 /**
309 /**
309 * ToolTip show
310 * ToolTip show
310 */
311 */
311 function showTooltip(x, y, contents) {
312 function showTooltip(x, y, contents) {
312 var div=document.getElementById('tooltip');
313 var div=document.getElementById('tooltip');
313 if(!div) {
314 if(!div) {
314 div = document.createElement('div');
315 div = document.createElement('div');
315 div.id="tooltip";
316 div.id="tooltip";
316 div.style.position="absolute";
317 div.style.position="absolute";
317 div.style.border='1px solid #fdd';
318 div.style.border='1px solid #fdd';
318 div.style.padding='2px';
319 div.style.padding='2px';
319 div.style.backgroundColor='#fee';
320 div.style.backgroundColor='#fee';
320 document.body.appendChild(div);
321 document.body.appendChild(div);
321 }
322 }
322 YAHOO.util.Dom.setStyle(div, 'opacity', 0);
323 YAHOO.util.Dom.setStyle(div, 'opacity', 0);
323 div.innerHTML = contents;
324 div.innerHTML = contents;
324 div.style.top=(y + 5) + "px";
325 div.style.top=(y + 5) + "px";
325 div.style.left=(x + 5) + "px";
326 div.style.left=(x + 5) + "px";
326
327
327 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
328 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
328 anim.animate();
329 anim.animate();
329 }
330 }
330
331
331 /**
332 /**
332 * This function will detect if selected period has some changesets for this user
333 * This function will detect if selected period has some changesets for this user
333 if it does this data is then pushed for displaying
334 if it does this data is then pushed for displaying
334 Additionally it will only display users that are selected by the checkbox
335 Additionally it will only display users that are selected by the checkbox
335 */
336 */
336 function getDataAccordingToRanges(ranges) {
337 function getDataAccordingToRanges(ranges) {
337
338
338 var data = [];
339 var data = [];
339 var keys = [];
340 var keys = [];
340 for(var key in dataset){
341 for(var key in dataset){
341 var push = false;
342 var push = false;
342 //method1 slow !!
343 //method1 slow !!
343 ///*
344 ///*
344 for(var ds in dataset[key].data){
345 for(var ds in dataset[key].data){
345 commit_data = dataset[key].data[ds];
346 commit_data = dataset[key].data[ds];
346 //console.log(key);
347 //console.log(key);
347 //console.log(new Date(commit_data.time*1000));
348 //console.log(new Date(commit_data.time*1000));
348 //console.log(new Date(ranges.xaxis.from*1000));
349 //console.log(new Date(ranges.xaxis.from*1000));
349 //console.log(new Date(ranges.xaxis.to*1000));
350 //console.log(new Date(ranges.xaxis.to*1000));
350 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
351 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
351 push = true;
352 push = true;
352 break;
353 break;
353 }
354 }
354 }
355 }
355 //*/
356 //*/
356 /*//method2 sorted commit data !!!
357 /*//method2 sorted commit data !!!
357 var first_commit = dataset[key].data[0].time;
358 var first_commit = dataset[key].data[0].time;
358 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
359 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
359
360
360 console.log(first_commit);
361 console.log(first_commit);
361 console.log(last_commit);
362 console.log(last_commit);
362
363
363 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
364 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
364 push = true;
365 push = true;
365 }
366 }
366 */
367 */
367 if(push){
368 if(push){
368 data.push(dataset[key]);
369 data.push(dataset[key]);
369 }
370 }
370 }
371 }
371 if(data.length >= 1){
372 if(data.length >= 1){
372 return data;
373 return data;
373 }
374 }
374 else{
375 else{
375 //just return dummy data for graph to plot itself
376 //just return dummy data for graph to plot itself
376 return [getDummyData('')];
377 return [getDummyData('')];
377 }
378 }
378
379
379 }
380 }
380
381
381 /**
382 /**
382 * redraw using new checkbox data
383 * redraw using new checkbox data
383 */
384 */
384 function plotchoiced(e,args){
385 function plotchoiced(e,args){
385 var cur_data = args[0];
386 var cur_data = args[0];
386 var cur_ranges = args[1];
387 var cur_ranges = args[1];
387
388
388 var new_data = [];
389 var new_data = [];
389 var inputs = choiceContainer.getElementsByTagName("input");
390 var inputs = choiceContainer.getElementsByTagName("input");
390
391
391 //show only checked labels
392 //show only checked labels
392 for(var i=0; i<inputs.length; i++) {
393 for(var i=0; i<inputs.length; i++) {
393 var checkbox_key = inputs[i].name;
394 var checkbox_key = inputs[i].name;
394
395
395 if(inputs[i].checked){
396 if(inputs[i].checked){
396 for(var d in cur_data){
397 for(var d in cur_data){
397 if(cur_data[d].label == checkbox_key){
398 if(cur_data[d].label == checkbox_key){
398 new_data.push(cur_data[d]);
399 new_data.push(cur_data[d]);
399 }
400 }
400 }
401 }
401 }
402 }
402 else{
403 else{
403 //push dummy data to not hide the label
404 //push dummy data to not hide the label
404 new_data.push(getDummyData(checkbox_key));
405 new_data.push(getDummyData(checkbox_key));
405 }
406 }
406 }
407 }
407
408
408 var new_options = YAHOO.lang.merge(plot_options, {
409 var new_options = YAHOO.lang.merge(plot_options, {
409 xaxis: {
410 xaxis: {
410 min: cur_ranges.xaxis.from,
411 min: cur_ranges.xaxis.from,
411 max: cur_ranges.xaxis.to,
412 max: cur_ranges.xaxis.to,
412 mode:"time",
413 mode:"time",
413 timeformat: "%d/%m",
414 timeformat: "%d/%m",
414 }
415 }
415 });
416 });
416 if (!new_data){
417 if (!new_data){
417 new_data = [[0,1]];
418 new_data = [[0,1]];
418 }
419 }
419 // do the zooming
420 // do the zooming
420 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
421 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
421
422
422 plot.subscribe("plotselected", plotselected);
423 plot.subscribe("plotselected", plotselected);
423
424
424 //resubscribe plothover
425 //resubscribe plothover
425 plot.subscribe("plothover", plothover);
426 plot.subscribe("plothover", plothover);
426
427
427 // don't fire event on the overview to prevent eternal loop
428 // don't fire event on the overview to prevent eternal loop
428 overview.setSelection(cur_ranges, true);
429 overview.setSelection(cur_ranges, true);
429
430
430 }
431 }
431
432
432 /**
433 /**
433 * plot only selected items from overview
434 * plot only selected items from overview
434 * @param ranges
435 * @param ranges
435 * @returns
436 * @returns
436 */
437 */
437 function plotselected(ranges,cur_data) {
438 function plotselected(ranges,cur_data) {
438 //updates the data for new plot
439 //updates the data for new plot
439 data = getDataAccordingToRanges(ranges);
440 data = getDataAccordingToRanges(ranges);
440 generateCheckboxes(data);
441 generateCheckboxes(data);
441
442
442 var new_options = YAHOO.lang.merge(plot_options, {
443 var new_options = YAHOO.lang.merge(plot_options, {
443 xaxis: {
444 xaxis: {
444 min: ranges.xaxis.from,
445 min: ranges.xaxis.from,
445 max: ranges.xaxis.to,
446 max: ranges.xaxis.to,
446 mode:"time",
447 mode:"time",
447 timeformat: "%d/%m",
448 timeformat: "%d/%m",
448 }
449 }
449 });
450 });
450 // do the zooming
451 // do the zooming
451 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
452 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
452
453
453 plot.subscribe("plotselected", plotselected);
454 plot.subscribe("plotselected", plotselected);
454
455
455 //resubscribe plothover
456 //resubscribe plothover
456 plot.subscribe("plothover", plothover);
457 plot.subscribe("plothover", plothover);
457
458
458 // don't fire event on the overview to prevent eternal loop
459 // don't fire event on the overview to prevent eternal loop
459 overview.setSelection(ranges, true);
460 overview.setSelection(ranges, true);
460
461
461 //resubscribe choiced
462 //resubscribe choiced
462 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
463 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
463 }
464 }
464
465
465 var previousPoint = null;
466 var previousPoint = null;
466
467
467 function plothover(o) {
468 function plothover(o) {
468 var pos = o.pos;
469 var pos = o.pos;
469 var item = o.item;
470 var item = o.item;
470
471
471 //YAHOO.util.Dom.get("x").innerHTML = pos.x.toFixed(2);
472 //YAHOO.util.Dom.get("x").innerHTML = pos.x.toFixed(2);
472 //YAHOO.util.Dom.get("y").innerHTML = pos.y.toFixed(2);
473 //YAHOO.util.Dom.get("y").innerHTML = pos.y.toFixed(2);
473 if (item) {
474 if (item) {
474 if (previousPoint != item.datapoint) {
475 if (previousPoint != item.datapoint) {
475 previousPoint = item.datapoint;
476 previousPoint = item.datapoint;
476
477
477 var tooltip = YAHOO.util.Dom.get("tooltip");
478 var tooltip = YAHOO.util.Dom.get("tooltip");
478 if(tooltip) {
479 if(tooltip) {
479 tooltip.parentNode.removeChild(tooltip);
480 tooltip.parentNode.removeChild(tooltip);
480 }
481 }
481 var x = item.datapoint.x.toFixed(2);
482 var x = item.datapoint.x.toFixed(2);
482 var y = item.datapoint.y.toFixed(2);
483 var y = item.datapoint.y.toFixed(2);
483
484
484 if (!item.series.label){
485 if (!item.series.label){
485 item.series.label = 'commits';
486 item.series.label = 'commits';
486 }
487 }
487 var d = new Date(x*1000);
488 var d = new Date(x*1000);
488 var fd = d.toDateString()
489 var fd = d.toDateString()
489 var nr_commits = parseInt(y);
490 var nr_commits = parseInt(y);
490
491
491 var cur_data = dataset[item.series.label].data[item.dataIndex];
492 var cur_data = dataset[item.series.label].data[item.dataIndex];
492 var added = cur_data.added;
493 var added = cur_data.added;
493 var changed = cur_data.changed;
494 var changed = cur_data.changed;
494 var removed = cur_data.removed;
495 var removed = cur_data.removed;
495
496
496 var nr_commits_suffix = " ${_('commits')} ";
497 var nr_commits_suffix = " ${_('commits')} ";
497 var added_suffix = " ${_('files added')} ";
498 var added_suffix = " ${_('files added')} ";
498 var changed_suffix = " ${_('files changed')} ";
499 var changed_suffix = " ${_('files changed')} ";
499 var removed_suffix = " ${_('files removed')} ";
500 var removed_suffix = " ${_('files removed')} ";
500
501
501
502
502 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
503 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
503 if(added==1){added_suffix=" ${_('file added')} ";}
504 if(added==1){added_suffix=" ${_('file added')} ";}
504 if(changed==1){changed_suffix=" ${_('file changed')} ";}
505 if(changed==1){changed_suffix=" ${_('file changed')} ";}
505 if(removed==1){removed_suffix=" ${_('file removed')} ";}
506 if(removed==1){removed_suffix=" ${_('file removed')} ";}
506
507
507 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
508 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
508 +'<br/>'+
509 +'<br/>'+
509 nr_commits + nr_commits_suffix+'<br/>'+
510 nr_commits + nr_commits_suffix+'<br/>'+
510 added + added_suffix +'<br/>'+
511 added + added_suffix +'<br/>'+
511 changed + changed_suffix + '<br/>'+
512 changed + changed_suffix + '<br/>'+
512 removed + removed_suffix + '<br/>');
513 removed + removed_suffix + '<br/>');
513 }
514 }
514 }
515 }
515 else {
516 else {
516 var tooltip = YAHOO.util.Dom.get("tooltip");
517 var tooltip = YAHOO.util.Dom.get("tooltip");
517
518
518 if(tooltip) {
519 if(tooltip) {
519 tooltip.parentNode.removeChild(tooltip);
520 tooltip.parentNode.removeChild(tooltip);
520 }
521 }
521 previousPoint = null;
522 previousPoint = null;
522 }
523 }
523 }
524 }
524
525
525 /**
526 /**
526 * MAIN EXECUTION
527 * MAIN EXECUTION
527 */
528 */
528
529
529 var data = getDataAccordingToRanges(initial_ranges);
530 var data = getDataAccordingToRanges(initial_ranges);
530 generateCheckboxes(data);
531 generateCheckboxes(data);
531
532
532 //main plot
533 //main plot
533 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
534 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
534
535
535 //overview
536 //overview
536 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
537 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
537
538
538 //show initial selection on overview
539 //show initial selection on overview
539 overview.setSelection(initial_ranges);
540 overview.setSelection(initial_ranges);
540
541
541 plot.subscribe("plotselected", plotselected);
542 plot.subscribe("plotselected", plotselected);
542
543
543 overview.subscribe("plotselected", function (ranges) {
544 overview.subscribe("plotselected", function (ranges) {
544 plot.setSelection(ranges);
545 plot.setSelection(ranges);
545 });
546 });
546
547
547 plot.subscribe("plothover", plothover);
548 plot.subscribe("plothover", plothover);
548
549
549 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
550 YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
550 }
551 }
551 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
552 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
552 </script>
553 </script>
553
554
554 </div>
555 </div>
555 </div>
556 </div>
556
557
557 <div class="box">
558 <div class="box">
558 <div class="title">
559 <div class="title">
559 <div class="breadcrumbs">${h.link_to(_('Last ten changes'),h.url('changelog_home',repo_name=c.repo_name))}</div>
560 <div class="breadcrumbs">${h.link_to(_('Last ten changes'),h.url('changelog_home',repo_name=c.repo_name))}</div>
560 </div>
561 </div>
561 <div class="table">
562 <div class="table">
562 <div id="shortlog_data">
563 <div id="shortlog_data">
563 <%include file='../shortlog/shortlog_data.html'/>
564 <%include file='../shortlog/shortlog_data.html'/>
564 </div>
565 </div>
565 ##%if c.repo_changesets:
566 ##%if c.repo_changesets:
566 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
567 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
567 ##%endif
568 ##%endif
568 </div>
569 </div>
569 </div>
570 </div>
570 <div class="box">
571 <div class="box">
571 <div class="title">
572 <div class="title">
572 <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
573 <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
573 </div>
574 </div>
574 <div class="table">
575 <div class="table">
575 <%include file='../tags/tags_data.html'/>
576 <%include file='../tags/tags_data.html'/>
576 %if c.repo_changesets:
577 %if c.repo_changesets:
577 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
578 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
578 %endif
579 %endif
579 </div>
580 </div>
580 </div>
581 </div>
581 <div class="box">
582 <div class="box">
582 <div class="title">
583 <div class="title">
583 <div class="breadcrumbs">${h.link_to(_('Last ten branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
584 <div class="breadcrumbs">${h.link_to(_('Last ten branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
584 </div>
585 </div>
585 <div class="table">
586 <div class="table">
586 <%include file='../branches/branches_data.html'/>
587 <%include file='../branches/branches_data.html'/>
587 %if c.repo_changesets:
588 %if c.repo_changesets:
588 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
589 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
589 %endif
590 %endif
590 </div>
591 </div>
591 </div>
592 </div>
592
593
593 </%def> No newline at end of file
594 </%def>
General Comments 0
You need to be logged in to leave comments. Login now