##// END OF EJS Templates
fixed message about disabled stats, template fixes for summary page
marcink -
r820:de5d9de4 beta
parent child Browse files
Show More
@@ -1,143 +1,144
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 package.rhodecode.controllers.summary
3 package.rhodecode.controllers.summary
4 ~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~
5
5
6 Summary controller for Rhodecode
6 Summary controller for Rhodecode
7
7 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
8 :author: marcink
9 :author: marcink
9 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
11 """
12 """
12 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
15 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
16 #
17 #
17 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 # GNU General Public License for more details.
21 #
22 #
22 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
26
27
27 import calendar
28 import calendar
28 import logging
29 import logging
29 from time import mktime
30 from time import mktime
30 from datetime import datetime, timedelta
31 from datetime import datetime, timedelta
31
32
32 from vcs.exceptions import ChangesetError
33 from vcs.exceptions import ChangesetError
33
34
34 from pylons import tmpl_context as c, request, url
35 from pylons import tmpl_context as c, request, url
35 from pylons.i18n.translation import _
36 from pylons.i18n.translation import _
36
37
37 from rhodecode.model.scm import ScmModel
38 from rhodecode.model.scm import ScmModel
38 from rhodecode.model.db import Statistics
39 from rhodecode.model.db import Statistics
39
40
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
41 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
43 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
43
44
44 from rhodecode.lib.celerylib import run_task
45 from rhodecode.lib.celerylib import run_task
45 from rhodecode.lib.celerylib.tasks import get_commits_stats
46 from rhodecode.lib.celerylib.tasks import get_commits_stats
46
47
47 from webhelpers.paginate import Page
48 from webhelpers.paginate import Page
48
49
49 try:
50 try:
50 import json
51 import json
51 except ImportError:
52 except ImportError:
52 #python 2.5 compatibility
53 #python 2.5 compatibility
53 import simplejson as json
54 import simplejson as json
54 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
55
56
56 class SummaryController(BaseController):
57 class SummaryController(BaseController):
57
58
58 @LoginRequired()
59 @LoginRequired()
59 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
60 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
60 'repository.admin')
61 'repository.admin')
61 def __before__(self):
62 def __before__(self):
62 super(SummaryController, self).__before__()
63 super(SummaryController, self).__before__()
63
64
64 def index(self):
65 def index(self):
65 scm_model = ScmModel()
66 scm_model = ScmModel()
66 c.repo_info = scm_model.get_repo(c.repo_name)
67 c.repo_info = scm_model.get_repo(c.repo_name)
67 c.following = scm_model.is_following_repo(c.repo_name,
68 c.following = scm_model.is_following_repo(c.repo_name,
68 c.rhodecode_user.user_id)
69 c.rhodecode_user.user_id)
69 def url_generator(**kw):
70 def url_generator(**kw):
70 return url('shortlog_home', repo_name=c.repo_name, **kw)
71 return url('shortlog_home', repo_name=c.repo_name, **kw)
71
72
72 c.repo_changesets = Page(c.repo_info, page=1, items_per_page=10,
73 c.repo_changesets = Page(c.repo_info, page=1, items_per_page=10,
73 url=url_generator)
74 url=url_generator)
74
75
75 e = request.environ
76 e = request.environ
76
77
77 if self.rhodecode_user.username == 'default':
78 if self.rhodecode_user.username == 'default':
78 password = ':default'
79 password = ':default'
79 else:
80 else:
80 password = ''
81 password = ''
81
82
82 uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
83 uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
83 'protocol': e.get('wsgi.url_scheme'),
84 'protocol': e.get('wsgi.url_scheme'),
84 'user':str(c.rhodecode_user.username),
85 'user':str(c.rhodecode_user.username),
85 'password':password,
86 'password':password,
86 'host':e.get('HTTP_HOST'),
87 'host':e.get('HTTP_HOST'),
87 'prefix':e.get('SCRIPT_NAME'),
88 'prefix':e.get('SCRIPT_NAME'),
88 'repo_name':c.repo_name, }
89 'repo_name':c.repo_name, }
89 c.clone_repo_url = uri
90 c.clone_repo_url = uri
90 c.repo_tags = OrderedDict()
91 c.repo_tags = OrderedDict()
91 for name, hash in c.repo_info.tags.items()[:10]:
92 for name, hash in c.repo_info.tags.items()[:10]:
92 try:
93 try:
93 c.repo_tags[name] = c.repo_info.get_changeset(hash)
94 c.repo_tags[name] = c.repo_info.get_changeset(hash)
94 except ChangesetError:
95 except ChangesetError:
95 c.repo_tags[name] = EmptyChangeset(hash)
96 c.repo_tags[name] = EmptyChangeset(hash)
96
97
97 c.repo_branches = OrderedDict()
98 c.repo_branches = OrderedDict()
98 for name, hash in c.repo_info.branches.items()[:10]:
99 for name, hash in c.repo_info.branches.items()[:10]:
99 try:
100 try:
100 c.repo_branches[name] = c.repo_info.get_changeset(hash)
101 c.repo_branches[name] = c.repo_info.get_changeset(hash)
101 except ChangesetError:
102 except ChangesetError:
102 c.repo_branches[name] = EmptyChangeset(hash)
103 c.repo_branches[name] = EmptyChangeset(hash)
103
104
104 td = datetime.today() + timedelta(days=1)
105 td = datetime.today() + timedelta(days=1)
105 y, m, d = td.year, td.month, td.day
106 y, m, d = td.year, td.month, td.day
106
107
107 ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
108 ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
108 d, 0, 0, 0, 0, 0, 0,))
109 d, 0, 0, 0, 0, 0, 0,))
109 ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
110 ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
110 d, 0, 0, 0, 0, 0, 0,))
111 d, 0, 0, 0, 0, 0, 0,))
111
112
112 ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
113 ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
113 if c.repo_info.dbrepo.enable_statistics:
114 if c.repo_info.dbrepo.enable_statistics:
114 c.no_data_msg = _('No data loaded yet')
115 c.no_data_msg = _('No data loaded yet')
115 run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
116 run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
116 else:
117 else:
117 c.no_data_msg = _('Statistics are disabled for this repository')
118 c.no_data_msg = _('Statistics update are disabled for this repository')
118 c.ts_min = ts_min_m
119 c.ts_min = ts_min_m
119 c.ts_max = ts_max_y
120 c.ts_max = ts_max_y
120
121
121 stats = self.sa.query(Statistics)\
122 stats = self.sa.query(Statistics)\
122 .filter(Statistics.repository == c.repo_info.dbrepo)\
123 .filter(Statistics.repository == c.repo_info.dbrepo)\
123 .scalar()
124 .scalar()
124
125
125
126
126 if stats and stats.languages:
127 if stats and stats.languages:
127 c.no_data = False
128 c.no_data = False is c.repo_info.dbrepo.enable_statistics
128 lang_stats = json.loads(stats.languages)
129 lang_stats = json.loads(stats.languages)
129 c.commit_data = stats.commit_activity
130 c.commit_data = stats.commit_activity
130 c.overview_data = stats.commit_activity_combined
131 c.overview_data = stats.commit_activity_combined
131 c.trending_languages = json.dumps(OrderedDict(
132 c.trending_languages = json.dumps(OrderedDict(
132 sorted(lang_stats.items(), reverse=True,
133 sorted(lang_stats.items(), reverse=True,
133 key=lambda k: k[1])[:10]
134 key=lambda k: k[1])[:10]
134 )
135 )
135 )
136 )
136 else:
137 else:
137 c.commit_data = json.dumps({})
138 c.commit_data = json.dumps({})
138 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10] ])
139 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10] ])
139 c.trending_languages = json.dumps({})
140 c.trending_languages = json.dumps({})
140 c.no_data = True
141 c.no_data = True
141
142
142 return render('summary/summary.html')
143 return render('summary/summary.html')
143
144
@@ -1,643 +1,643
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 <div class="box box-left">
20 <div class="box box-left">
21 <!-- box / title -->
21 <!-- box / title -->
22 <div class="title">
22 <div class="title">
23 ${self.breadcrumbs()}
23 ${self.breadcrumbs()}
24 </div>
24 </div>
25 <!-- end box / title -->
25 <!-- end box / title -->
26 <div class="form">
26 <div class="form">
27 <div class="fields">
27 <div class="fields">
28
28
29 <div class="field">
29 <div class="field">
30 <div class="label">
30 <div class="label">
31 <label>${_('Name')}:</label>
31 <label>${_('Name')}:</label>
32 </div>
32 </div>
33 <div class="input-short">
33 <div class="input-short">
34 %if c.repo_info.dbrepo.repo_type =='hg':
34 %if c.repo_info.dbrepo.repo_type =='hg':
35 <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
35 <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
36 %endif
36 %endif
37 %if c.repo_info.dbrepo.repo_type =='git':
37 %if c.repo_info.dbrepo.repo_type =='git':
38 <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
38 <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
39 %endif
39 %endif
40
40
41 %if c.repo_info.dbrepo.private:
41 %if c.repo_info.dbrepo.private:
42 <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
42 <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
43 %else:
43 %else:
44 <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
44 <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
45 %endif
45 %endif
46 <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
46 <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
47 %if c.rhodecode_user.username != 'default':
47 %if c.rhodecode_user.username != 'default':
48 %if c.following:
48 %if c.following:
49 <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
49 <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
50 onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
50 onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
51 </span>
51 </span>
52 %else:
52 %else:
53 <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
53 <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
54 onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
54 onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
55 </span>
55 </span>
56 %endif
56 %endif
57 %endif:
57 %endif:
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 source files')}:</label>
119 <label>${_('Trending source files')}:</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 YUE.onDOMReady(function(e){
126 YUE.onDOMReady(function(e){
127 id = 'clone_url';
127 id = 'clone_url';
128 YUE.on(id,'click',function(e){
128 YUE.on(id,'click',function(e){
129 YUD.get('clone_url').select();
129 YUD.get('clone_url').select();
130 })
130 })
131 })
131 })
132 var data = ${c.trending_languages|n};
132 var data = ${c.trending_languages|n};
133 var total = 0;
133 var total = 0;
134 var no_data = true;
134 var no_data = true;
135 for (k in data){
135 for (k in data){
136 total += data[k];
136 total += data[k];
137 no_data = false;
137 no_data = false;
138 }
138 }
139 var tbl = document.createElement('table');
139 var tbl = document.createElement('table');
140 tbl.setAttribute('class','trending_language_tbl');
140 tbl.setAttribute('class','trending_language_tbl');
141 var cnt =0;
141 var cnt =0;
142 for (k in data){
142 for (k in data){
143 cnt+=1;
143 cnt+=1;
144 var hide = cnt>2;
144 var hide = cnt>2;
145 var tr = document.createElement('tr');
145 var tr = document.createElement('tr');
146 if (hide){
146 if (hide){
147 tr.setAttribute('style','display:none');
147 tr.setAttribute('style','display:none');
148 tr.setAttribute('class','stats_hidden');
148 tr.setAttribute('class','stats_hidden');
149 }
149 }
150 var percentage = Math.round((data[k]/total*100),2);
150 var percentage = Math.round((data[k]/total*100),2);
151 var value = data[k];
151 var value = data[k];
152 var td1 = document.createElement('td');
152 var td1 = document.createElement('td');
153 td1.width=150;
153 td1.width=150;
154 var trending_language_label = document.createElement('div');
154 var trending_language_label = document.createElement('div');
155 trending_language_label.innerHTML = k;
155 trending_language_label.innerHTML = k;
156 td1.appendChild(trending_language_label);
156 td1.appendChild(trending_language_label);
157
157
158 var td2 = document.createElement('td');
158 var td2 = document.createElement('td');
159 td2.setAttribute('style','padding-right:14px !important');
159 td2.setAttribute('style','padding-right:14px !important');
160 var trending_language = document.createElement('div');
160 var trending_language = document.createElement('div');
161 var nr_files = value+" ${_('files')}";
161 var nr_files = value+" ${_('files')}";
162
162
163 trending_language.title = k+" "+nr_files;
163 trending_language.title = k+" "+nr_files;
164
164
165 if (percentage>20){
165 if (percentage>20){
166 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
166 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
167 }
167 }
168 else{
168 else{
169 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
169 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
170 }
170 }
171
171
172 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
172 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
173 trending_language.style.width=percentage+"%";
173 trending_language.style.width=percentage+"%";
174 td2.appendChild(trending_language);
174 td2.appendChild(trending_language);
175
175
176 tr.appendChild(td1);
176 tr.appendChild(td1);
177 tr.appendChild(td2);
177 tr.appendChild(td2);
178 tbl.appendChild(tr);
178 tbl.appendChild(tr);
179 if(cnt == 2){
179 if(cnt == 2){
180 var show_more = document.createElement('tr');
180 var show_more = document.createElement('tr');
181 var td=document.createElement('td');
181 var td=document.createElement('td');
182 lnk = document.createElement('a');
182 lnk = document.createElement('a');
183 lnk.href='#';
183 lnk.href='#';
184 lnk.innerHTML = "${_("show more")}";
184 lnk.innerHTML = "${_("show more")}";
185 lnk.id='code_stats_show_more';
185 lnk.id='code_stats_show_more';
186 td.appendChild(lnk);
186 td.appendChild(lnk);
187 show_more.appendChild(td);
187 show_more.appendChild(td);
188 show_more.appendChild(document.createElement('td'));
188 show_more.appendChild(document.createElement('td'));
189 tbl.appendChild(show_more);
189 tbl.appendChild(show_more);
190 }
190 }
191
191
192 }
192 }
193 if(no_data){
193 if(no_data){
194 var tr = document.createElement('tr');
194 var tr = document.createElement('tr');
195 var td1 = document.createElement('td');
195 var td1 = document.createElement('td');
196 td1.innerHTML = "${c.no_data_msg}";
196 td1.innerHTML = "${c.no_data_msg}";
197 tr.appendChild(td1);
197 tr.appendChild(td1);
198 tbl.appendChild(tr);
198 tbl.appendChild(tr);
199 }
199 }
200 YUD.get('lang_stats').appendChild(tbl);
200 YUD.get('lang_stats').appendChild(tbl);
201 YUE.on('code_stats_show_more','click',function(){
201 YUE.on('code_stats_show_more','click',function(){
202 l = YUD.getElementsByClassName('stats_hidden')
202 l = YUD.getElementsByClassName('stats_hidden')
203 for (e in l){
203 for (e in l){
204 YUD.setStyle(l[e],'display','');
204 YUD.setStyle(l[e],'display','');
205 };
205 };
206 YUD.setStyle(YUD.get('code_stats_show_more'),
206 YUD.setStyle(YUD.get('code_stats_show_more'),
207 'display','none');
207 'display','none');
208 })
208 })
209
209
210 </script>
210 </script>
211
211
212 </div>
212 </div>
213 </div>
213 </div>
214
214
215 <div class="field">
215 <div class="field">
216 <div class="label">
216 <div class="label">
217 <label>${_('Download')}:</label>
217 <label>${_('Download')}:</label>
218 </div>
218 </div>
219 <div class="input-short">
219 <div class="input-short">
220 %for cnt,archive in enumerate(c.repo_info._get_archives()):
220 %for cnt,archive in enumerate(c.repo_info._get_archives()):
221 %if cnt >=1:
221 %if cnt >=1:
222 |
222 |
223 %endif
223 %endif
224 ${h.link_to(c.repo_info.name+'.'+archive['type'],
224 ${h.link_to(c.repo_info.name+'.'+archive['type'],
225 h.url('files_archive_home',repo_name=c.repo_info.name,
225 h.url('files_archive_home',repo_name=c.repo_info.name,
226 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
226 revision='tip',fileformat=archive['extension']),class_="archive_icon")}
227 %endfor
227 %endfor
228 </div>
228 </div>
229 </div>
229 </div>
230
230
231 <div class="field">
231 <div class="field">
232 <div class="label">
232 <div class="label">
233 <label>${_('Feeds')}:</label>
233 <label>${_('Feeds')}:</label>
234 </div>
234 </div>
235 <div class="input-short">
235 <div class="input-short">
236 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
236 ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
237 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
237 ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
238 </div>
238 </div>
239 </div>
239 </div>
240 </div>
240 </div>
241 </div>
241 </div>
242 </div>
242 </div>
243
243
244 <div class="box box-right" style="min-height:455px">
244 <div class="box box-right" style="min-height:455px">
245 <!-- box / title -->
245 <!-- box / title -->
246 <div class="title">
246 <div class="title">
247 <h5>${_('Commit activity by day / author')}</h5>
247 <h5>${_('Commit activity by day / author')}</h5>
248 </div>
248 </div>
249
249
250 <div class="table">
250 <div class="table">
251
251
252 %if c.no_data:
252 %if c.no_data:
253 <div style="padding:0 10px 10px 15px;font-size: 1.2em;">${c.no_data_msg}</div>
253 <div style="padding:0 10px 10px 15px;font-size: 1.2em;">${c.no_data_msg}</div>
254 %endif:
254 %endif:
255 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
255 <div id="commit_history" style="width:460px;height:300px;float:left"></div>
256 <div style="clear: both;height: 10px"></div>
256 <div style="clear: both;height: 10px"></div>
257 <div id="overview" style="width:460px;height:100px;float:left"></div>
257 <div id="overview" style="width:460px;height:100px;float:left"></div>
258
258
259 <div id="legend_data" style="clear:both;margin-top:10px;">
259 <div id="legend_data" style="clear:both;margin-top:10px;">
260 <div id="legend_container"></div>
260 <div id="legend_container"></div>
261 <div id="legend_choices">
261 <div id="legend_choices">
262 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
262 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
263 </div>
263 </div>
264 </div>
264 </div>
265 <script type="text/javascript">
265 <script type="text/javascript">
266 /**
266 /**
267 * Plots summary graph
267 * Plots summary graph
268 *
268 *
269 * @class SummaryPlot
269 * @class SummaryPlot
270 * @param {from} initial from for detailed graph
270 * @param {from} initial from for detailed graph
271 * @param {to} initial to for detailed graph
271 * @param {to} initial to for detailed graph
272 * @param {dataset}
272 * @param {dataset}
273 * @param {overview_dataset}
273 * @param {overview_dataset}
274 */
274 */
275 function SummaryPlot(from,to,dataset,overview_dataset) {
275 function SummaryPlot(from,to,dataset,overview_dataset) {
276 var initial_ranges = {
276 var initial_ranges = {
277 "xaxis":{
277 "xaxis":{
278 "from":from,
278 "from":from,
279 "to":to,
279 "to":to,
280 },
280 },
281 };
281 };
282 var dataset = dataset;
282 var dataset = dataset;
283 var overview_dataset = [overview_dataset];
283 var overview_dataset = [overview_dataset];
284 var choiceContainer = YUD.get("legend_choices");
284 var choiceContainer = YUD.get("legend_choices");
285 var choiceContainerTable = YUD.get("legend_choices_tables");
285 var choiceContainerTable = YUD.get("legend_choices_tables");
286 var plotContainer = YUD.get('commit_history');
286 var plotContainer = YUD.get('commit_history');
287 var overviewContainer = YUD.get('overview');
287 var overviewContainer = YUD.get('overview');
288
288
289 var plot_options = {
289 var plot_options = {
290 bars: {show:true,align:'center',lineWidth:4},
290 bars: {show:true,align:'center',lineWidth:4},
291 legend: {show:true, container:"legend_container"},
291 legend: {show:true, container:"legend_container"},
292 points: {show:true,radius:0,fill:false},
292 points: {show:true,radius:0,fill:false},
293 yaxis: {tickDecimals:0,},
293 yaxis: {tickDecimals:0,},
294 xaxis: {
294 xaxis: {
295 mode: "time",
295 mode: "time",
296 timeformat: "%d/%m",
296 timeformat: "%d/%m",
297 min:from,
297 min:from,
298 max:to,
298 max:to,
299 },
299 },
300 grid: {
300 grid: {
301 hoverable: true,
301 hoverable: true,
302 clickable: true,
302 clickable: true,
303 autoHighlight:true,
303 autoHighlight:true,
304 color: "#999"
304 color: "#999"
305 },
305 },
306 //selection: {mode: "x"}
306 //selection: {mode: "x"}
307 };
307 };
308 var overview_options = {
308 var overview_options = {
309 legend:{show:false},
309 legend:{show:false},
310 bars: {show:true,barWidth: 2,},
310 bars: {show:true,barWidth: 2,},
311 shadowSize: 0,
311 shadowSize: 0,
312 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
312 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
313 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
313 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
314 grid: {color: "#999",},
314 grid: {color: "#999",},
315 selection: {mode: "x"}
315 selection: {mode: "x"}
316 };
316 };
317
317
318 /**
318 /**
319 *get dummy data needed in few places
319 *get dummy data needed in few places
320 */
320 */
321 function getDummyData(label){
321 function getDummyData(label){
322 return {"label":label,
322 return {"label":label,
323 "data":[{"time":0,
323 "data":[{"time":0,
324 "commits":0,
324 "commits":0,
325 "added":0,
325 "added":0,
326 "changed":0,
326 "changed":0,
327 "removed":0,
327 "removed":0,
328 }],
328 }],
329 "schema":["commits"],
329 "schema":["commits"],
330 "color":'#ffffff',
330 "color":'#ffffff',
331 }
331 }
332 }
332 }
333
333
334 /**
334 /**
335 * generate checkboxes accordindly to data
335 * generate checkboxes accordindly to data
336 * @param keys
336 * @param keys
337 * @returns
337 * @returns
338 */
338 */
339 function generateCheckboxes(data) {
339 function generateCheckboxes(data) {
340 //append checkboxes
340 //append checkboxes
341 var i = 0;
341 var i = 0;
342 choiceContainerTable.innerHTML = '';
342 choiceContainerTable.innerHTML = '';
343 for(var pos in data) {
343 for(var pos in data) {
344
344
345 data[pos].color = i;
345 data[pos].color = i;
346 i++;
346 i++;
347 if(data[pos].label != ''){
347 if(data[pos].label != ''){
348 choiceContainerTable.innerHTML += '<tr><td>'+
348 choiceContainerTable.innerHTML += '<tr><td>'+
349 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
349 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
350 +data[pos].label+
350 +data[pos].label+
351 '</td></tr>';
351 '</td></tr>';
352 }
352 }
353 }
353 }
354 }
354 }
355
355
356 /**
356 /**
357 * ToolTip show
357 * ToolTip show
358 */
358 */
359 function showTooltip(x, y, contents) {
359 function showTooltip(x, y, contents) {
360 var div=document.getElementById('tooltip');
360 var div=document.getElementById('tooltip');
361 if(!div) {
361 if(!div) {
362 div = document.createElement('div');
362 div = document.createElement('div');
363 div.id="tooltip";
363 div.id="tooltip";
364 div.style.position="absolute";
364 div.style.position="absolute";
365 div.style.border='1px solid #fdd';
365 div.style.border='1px solid #fdd';
366 div.style.padding='2px';
366 div.style.padding='2px';
367 div.style.backgroundColor='#fee';
367 div.style.backgroundColor='#fee';
368 document.body.appendChild(div);
368 document.body.appendChild(div);
369 }
369 }
370 YUD.setStyle(div, 'opacity', 0);
370 YUD.setStyle(div, 'opacity', 0);
371 div.innerHTML = contents;
371 div.innerHTML = contents;
372 div.style.top=(y + 5) + "px";
372 div.style.top=(y + 5) + "px";
373 div.style.left=(x + 5) + "px";
373 div.style.left=(x + 5) + "px";
374
374
375 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
375 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
376 anim.animate();
376 anim.animate();
377 }
377 }
378
378
379 /**
379 /**
380 * This function will detect if selected period has some changesets
380 * This function will detect if selected period has some changesets
381 for this user if it does this data is then pushed for displaying
381 for this user if it does this data is then pushed for displaying
382 Additionally it will only display users that are selected by the checkbox
382 Additionally it will only display users that are selected by the checkbox
383 */
383 */
384 function getDataAccordingToRanges(ranges) {
384 function getDataAccordingToRanges(ranges) {
385
385
386 var data = [];
386 var data = [];
387 var keys = [];
387 var keys = [];
388 for(var key in dataset){
388 for(var key in dataset){
389 var push = false;
389 var push = false;
390
390
391 //method1 slow !!
391 //method1 slow !!
392 //*
392 //*
393 for(var ds in dataset[key].data){
393 for(var ds in dataset[key].data){
394 commit_data = dataset[key].data[ds];
394 commit_data = dataset[key].data[ds];
395 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
395 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
396 push = true;
396 push = true;
397 break;
397 break;
398 }
398 }
399 }
399 }
400 //*/
400 //*/
401
401
402 /*//method2 sorted commit data !!!
402 /*//method2 sorted commit data !!!
403
403
404 var first_commit = dataset[key].data[0].time;
404 var first_commit = dataset[key].data[0].time;
405 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
405 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
406
406
407 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
407 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
408 push = true;
408 push = true;
409 }
409 }
410 //*/
410 //*/
411
411
412 if(push){
412 if(push){
413 data.push(dataset[key]);
413 data.push(dataset[key]);
414 }
414 }
415 }
415 }
416 if(data.length >= 1){
416 if(data.length >= 1){
417 return data;
417 return data;
418 }
418 }
419 else{
419 else{
420 //just return dummy data for graph to plot itself
420 //just return dummy data for graph to plot itself
421 return [getDummyData('')];
421 return [getDummyData('')];
422 }
422 }
423
423
424 }
424 }
425
425
426 /**
426 /**
427 * redraw using new checkbox data
427 * redraw using new checkbox data
428 */
428 */
429 function plotchoiced(e,args){
429 function plotchoiced(e,args){
430 var cur_data = args[0];
430 var cur_data = args[0];
431 var cur_ranges = args[1];
431 var cur_ranges = args[1];
432
432
433 var new_data = [];
433 var new_data = [];
434 var inputs = choiceContainer.getElementsByTagName("input");
434 var inputs = choiceContainer.getElementsByTagName("input");
435
435
436 //show only checked labels
436 //show only checked labels
437 for(var i=0; i<inputs.length; i++) {
437 for(var i=0; i<inputs.length; i++) {
438 var checkbox_key = inputs[i].name;
438 var checkbox_key = inputs[i].name;
439
439
440 if(inputs[i].checked){
440 if(inputs[i].checked){
441 for(var d in cur_data){
441 for(var d in cur_data){
442 if(cur_data[d].label == checkbox_key){
442 if(cur_data[d].label == checkbox_key){
443 new_data.push(cur_data[d]);
443 new_data.push(cur_data[d]);
444 }
444 }
445 }
445 }
446 }
446 }
447 else{
447 else{
448 //push dummy data to not hide the label
448 //push dummy data to not hide the label
449 new_data.push(getDummyData(checkbox_key));
449 new_data.push(getDummyData(checkbox_key));
450 }
450 }
451 }
451 }
452
452
453 var new_options = YAHOO.lang.merge(plot_options, {
453 var new_options = YAHOO.lang.merge(plot_options, {
454 xaxis: {
454 xaxis: {
455 min: cur_ranges.xaxis.from,
455 min: cur_ranges.xaxis.from,
456 max: cur_ranges.xaxis.to,
456 max: cur_ranges.xaxis.to,
457 mode:"time",
457 mode:"time",
458 timeformat: "%d/%m",
458 timeformat: "%d/%m",
459 },
459 },
460 });
460 });
461 if (!new_data){
461 if (!new_data){
462 new_data = [[0,1]];
462 new_data = [[0,1]];
463 }
463 }
464 // do the zooming
464 // do the zooming
465 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
465 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
466
466
467 plot.subscribe("plotselected", plotselected);
467 plot.subscribe("plotselected", plotselected);
468
468
469 //resubscribe plothover
469 //resubscribe plothover
470 plot.subscribe("plothover", plothover);
470 plot.subscribe("plothover", plothover);
471
471
472 // don't fire event on the overview to prevent eternal loop
472 // don't fire event on the overview to prevent eternal loop
473 overview.setSelection(cur_ranges, true);
473 overview.setSelection(cur_ranges, true);
474
474
475 }
475 }
476
476
477 /**
477 /**
478 * plot only selected items from overview
478 * plot only selected items from overview
479 * @param ranges
479 * @param ranges
480 * @returns
480 * @returns
481 */
481 */
482 function plotselected(ranges,cur_data) {
482 function plotselected(ranges,cur_data) {
483 //updates the data for new plot
483 //updates the data for new plot
484 data = getDataAccordingToRanges(ranges);
484 data = getDataAccordingToRanges(ranges);
485 generateCheckboxes(data);
485 generateCheckboxes(data);
486
486
487 var new_options = YAHOO.lang.merge(plot_options, {
487 var new_options = YAHOO.lang.merge(plot_options, {
488 xaxis: {
488 xaxis: {
489 min: ranges.xaxis.from,
489 min: ranges.xaxis.from,
490 max: ranges.xaxis.to,
490 max: ranges.xaxis.to,
491 mode:"time",
491 mode:"time",
492 timeformat: "%d/%m",
492 timeformat: "%d/%m",
493 },
493 },
494 yaxis: {
494 yaxis: {
495 min: ranges.yaxis.from,
495 min: ranges.yaxis.from,
496 max: ranges.yaxis.to,
496 max: ranges.yaxis.to,
497 },
497 },
498
498
499 });
499 });
500 // do the zooming
500 // do the zooming
501 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
501 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
502
502
503 plot.subscribe("plotselected", plotselected);
503 plot.subscribe("plotselected", plotselected);
504
504
505 //resubscribe plothover
505 //resubscribe plothover
506 plot.subscribe("plothover", plothover);
506 plot.subscribe("plothover", plothover);
507
507
508 // don't fire event on the overview to prevent eternal loop
508 // don't fire event on the overview to prevent eternal loop
509 overview.setSelection(ranges, true);
509 overview.setSelection(ranges, true);
510
510
511 //resubscribe choiced
511 //resubscribe choiced
512 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
512 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
513 }
513 }
514
514
515 var previousPoint = null;
515 var previousPoint = null;
516
516
517 function plothover(o) {
517 function plothover(o) {
518 var pos = o.pos;
518 var pos = o.pos;
519 var item = o.item;
519 var item = o.item;
520
520
521 //YUD.get("x").innerHTML = pos.x.toFixed(2);
521 //YUD.get("x").innerHTML = pos.x.toFixed(2);
522 //YUD.get("y").innerHTML = pos.y.toFixed(2);
522 //YUD.get("y").innerHTML = pos.y.toFixed(2);
523 if (item) {
523 if (item) {
524 if (previousPoint != item.datapoint) {
524 if (previousPoint != item.datapoint) {
525 previousPoint = item.datapoint;
525 previousPoint = item.datapoint;
526
526
527 var tooltip = YUD.get("tooltip");
527 var tooltip = YUD.get("tooltip");
528 if(tooltip) {
528 if(tooltip) {
529 tooltip.parentNode.removeChild(tooltip);
529 tooltip.parentNode.removeChild(tooltip);
530 }
530 }
531 var x = item.datapoint.x.toFixed(2);
531 var x = item.datapoint.x.toFixed(2);
532 var y = item.datapoint.y.toFixed(2);
532 var y = item.datapoint.y.toFixed(2);
533
533
534 if (!item.series.label){
534 if (!item.series.label){
535 item.series.label = 'commits';
535 item.series.label = 'commits';
536 }
536 }
537 var d = new Date(x*1000);
537 var d = new Date(x*1000);
538 var fd = d.toDateString()
538 var fd = d.toDateString()
539 var nr_commits = parseInt(y);
539 var nr_commits = parseInt(y);
540
540
541 var cur_data = dataset[item.series.label].data[item.dataIndex];
541 var cur_data = dataset[item.series.label].data[item.dataIndex];
542 var added = cur_data.added;
542 var added = cur_data.added;
543 var changed = cur_data.changed;
543 var changed = cur_data.changed;
544 var removed = cur_data.removed;
544 var removed = cur_data.removed;
545
545
546 var nr_commits_suffix = " ${_('commits')} ";
546 var nr_commits_suffix = " ${_('commits')} ";
547 var added_suffix = " ${_('files added')} ";
547 var added_suffix = " ${_('files added')} ";
548 var changed_suffix = " ${_('files changed')} ";
548 var changed_suffix = " ${_('files changed')} ";
549 var removed_suffix = " ${_('files removed')} ";
549 var removed_suffix = " ${_('files removed')} ";
550
550
551
551
552 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
552 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
553 if(added==1){added_suffix=" ${_('file added')} ";}
553 if(added==1){added_suffix=" ${_('file added')} ";}
554 if(changed==1){changed_suffix=" ${_('file changed')} ";}
554 if(changed==1){changed_suffix=" ${_('file changed')} ";}
555 if(removed==1){removed_suffix=" ${_('file removed')} ";}
555 if(removed==1){removed_suffix=" ${_('file removed')} ";}
556
556
557 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
557 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
558 +'<br/>'+
558 +'<br/>'+
559 nr_commits + nr_commits_suffix+'<br/>'+
559 nr_commits + nr_commits_suffix+'<br/>'+
560 added + added_suffix +'<br/>'+
560 added + added_suffix +'<br/>'+
561 changed + changed_suffix + '<br/>'+
561 changed + changed_suffix + '<br/>'+
562 removed + removed_suffix + '<br/>');
562 removed + removed_suffix + '<br/>');
563 }
563 }
564 }
564 }
565 else {
565 else {
566 var tooltip = YUD.get("tooltip");
566 var tooltip = YUD.get("tooltip");
567
567
568 if(tooltip) {
568 if(tooltip) {
569 tooltip.parentNode.removeChild(tooltip);
569 tooltip.parentNode.removeChild(tooltip);
570 }
570 }
571 previousPoint = null;
571 previousPoint = null;
572 }
572 }
573 }
573 }
574
574
575 /**
575 /**
576 * MAIN EXECUTION
576 * MAIN EXECUTION
577 */
577 */
578
578
579 var data = getDataAccordingToRanges(initial_ranges);
579 var data = getDataAccordingToRanges(initial_ranges);
580 generateCheckboxes(data);
580 generateCheckboxes(data);
581
581
582 //main plot
582 //main plot
583 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
583 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
584
584
585 //overview
585 //overview
586 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
586 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
587
587
588 //show initial selection on overview
588 //show initial selection on overview
589 overview.setSelection(initial_ranges);
589 overview.setSelection(initial_ranges);
590
590
591 plot.subscribe("plotselected", plotselected);
591 plot.subscribe("plotselected", plotselected);
592
592
593 overview.subscribe("plotselected", function (ranges) {
593 overview.subscribe("plotselected", function (ranges) {
594 plot.setSelection(ranges);
594 plot.setSelection(ranges);
595 });
595 });
596
596
597 plot.subscribe("plothover", plothover);
597 plot.subscribe("plothover", plothover);
598
598
599 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
599 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
600 }
600 }
601 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
601 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
602 </script>
602 </script>
603
603
604 </div>
604 </div>
605 </div>
605 </div>
606
606
607 <div class="box">
607 <div class="box">
608 <div class="title">
608 <div class="title">
609 <div class="breadcrumbs">${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
609 <div class="breadcrumbs">${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
610 </div>
610 </div>
611 <div class="table">
611 <div class="table">
612 <div id="shortlog_data">
612 <div id="shortlog_data">
613 <%include file='../shortlog/shortlog_data.html'/>
613 <%include file='../shortlog/shortlog_data.html'/>
614 </div>
614 </div>
615 ##%if c.repo_changesets:
615 ##%if c.repo_changesets:
616 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
616 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
617 ##%endif
617 ##%endif
618 </div>
618 </div>
619 </div>
619 </div>
620 <div class="box">
620 <div class="box">
621 <div class="title">
621 <div class="title">
622 <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
622 <div class="breadcrumbs">${h.link_to(_('Tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
623 </div>
623 </div>
624 <div class="table">
624 <div class="table">
625 <%include file='../tags/tags_data.html'/>
625 <%include file='../tags/tags_data.html'/>
626 %if c.repo_changesets:
626 %if c.repo_changesets:
627 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
627 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
628 %endif
628 %endif
629 </div>
629 </div>
630 </div>
630 </div>
631 <div class="box">
631 <div class="box">
632 <div class="title">
632 <div class="title">
633 <div class="breadcrumbs">${h.link_to(_('Last ten branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
633 <div class="breadcrumbs">${h.link_to(_('Branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
634 </div>
634 </div>
635 <div class="table">
635 <div class="table">
636 <%include file='../branches/branches_data.html'/>
636 <%include file='../branches/branches_data.html'/>
637 %if c.repo_changesets:
637 %if c.repo_changesets:
638 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
638 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
639 %endif
639 %endif
640 </div>
640 </div>
641 </div>
641 </div>
642
642
643 </%def> No newline at end of file
643 </%def>
General Comments 0
You need to be logged in to leave comments. Login now