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