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