##// END OF EJS Templates
small fixes for git support
marcink -
r1281:0d3706cc beta
parent child Browse files
Show More
@@ -1,104 +1,111
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.changelog
3 rhodecode.controllers.changelog
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 changelog controller for rhodecode
6 changelog controller for rhodecode
7
7
8 :created_on: Apr 21, 2010
8 :created_on: Apr 21, 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 modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27
27
28 try:
28 try:
29 import json
29 import json
30 except ImportError:
30 except ImportError:
31 #python 2.5 compatibility
31 #python 2.5 compatibility
32 import simplejson as json
32 import simplejson as json
33
33
34 from mercurial.graphmod import colored, CHANGESET, revisions as graph_rev
34 from mercurial.graphmod import colored, CHANGESET, revisions as graph_rev
35 from pylons import request, session, tmpl_context as c
35 from pylons import request, session, tmpl_context as c
36
36
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 from rhodecode.lib.base import BaseRepoController, render
38 from rhodecode.lib.base import BaseRepoController, render
39 from rhodecode.lib.helpers import RepoPage
39 from rhodecode.lib.helpers import RepoPage
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43
43
44 class ChangelogController(BaseRepoController):
44 class ChangelogController(BaseRepoController):
45
45
46 @LoginRequired()
46 @LoginRequired()
47 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
47 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
48 'repository.admin')
48 'repository.admin')
49 def __before__(self):
49 def __before__(self):
50 super(ChangelogController, self).__before__()
50 super(ChangelogController, self).__before__()
51 c.affected_files_cut_off = 60
51 c.affected_files_cut_off = 60
52
52
53 def index(self):
53 def index(self):
54 limit = 100
54 limit = 100
55 default = 20
55 default = 20
56 if request.params.get('size'):
56 if request.params.get('size'):
57 try:
57 try:
58 int_size = int(request.params.get('size'))
58 int_size = int(request.params.get('size'))
59 except ValueError:
59 except ValueError:
60 int_size = default
60 int_size = default
61 int_size = int_size if int_size <= limit else limit
61 int_size = int_size if int_size <= limit else limit
62 c.size = int_size
62 c.size = int_size
63 session['changelog_size'] = c.size
63 session['changelog_size'] = c.size
64 session.save()
64 session.save()
65 else:
65 else:
66 c.size = int(session.get('changelog_size', default))
66 c.size = int(session.get('changelog_size', default))
67
67
68 p = int(request.params.get('page', 1))
68 p = int(request.params.get('page', 1))
69 branch_name = request.params.get('branch', None)
69 branch_name = request.params.get('branch', None)
70 c.total_cs = len(c.rhodecode_repo)
70 c.total_cs = len(c.rhodecode_repo)
71 c.pagination = RepoPage(c.rhodecode_repo, page=p,
71 c.pagination = RepoPage(c.rhodecode_repo, page=p,
72 item_count=c.total_cs, items_per_page=c.size,
72 item_count=c.total_cs, items_per_page=c.size,
73 branch_name=branch_name)
73 branch_name=branch_name)
74
74
75 self._graph(c.rhodecode_repo, c.total_cs, c.size, p)
75 self._graph(c.rhodecode_repo, c.total_cs, c.size, p)
76
76
77 return render('changelog/changelog.html')
77 return render('changelog/changelog.html')
78
78
79 def _graph(self, repo, repo_size, size, p):
79 def _graph(self, repo, repo_size, size, p):
80 """
80 """
81 Generates a DAG graph for mercurial
81 Generates a DAG graph for mercurial
82
82
83 :param repo: repo instance
83 :param repo: repo instance
84 :param size: number of commits to show
84 :param size: number of commits to show
85 :param p: page number
85 :param p: page number
86 """
86 """
87 if not repo.revisions or repo.alias == 'git':
87 if not repo.revisions:
88 c.jsdata = json.dumps([])
88 c.jsdata = json.dumps([])
89 return
89 return
90
90
91 revcount = min(repo_size, size)
91 revcount = min(repo_size, size)
92 offset = 1 if p == 1 else ((p - 1) * revcount + 1)
92 offset = 1 if p == 1 else ((p - 1) * revcount + 1)
93 rev_start = repo.revisions.index(repo.revisions[(-1 * offset)])
93 rev_start = repo.revisions.index(repo.revisions[(-1 * offset)])
94 rev_end = max(0, rev_start - revcount)
94 rev_end = max(0, rev_start - revcount)
95
95
96 data = []
97 if repo.alias == 'git':
98 for _ in xrange(rev_end, rev_start):
99 vtx = [0, 1]
100 edges = [[0, 0, 1]]
101 data.append(['', vtx, edges])
102
103 elif repo.alias == 'hg':
96 dag = graph_rev(repo._repo, rev_start, rev_end)
104 dag = graph_rev(repo._repo, rev_start, rev_end)
97 c.dag = tree = list(colored(dag))
105 c.dag = tree = list(colored(dag))
98 data = []
99 for (id, type, ctx, vtx, edges) in tree:
106 for (id, type, ctx, vtx, edges) in tree:
100 if type != CHANGESET:
107 if type != CHANGESET:
101 continue
108 continue
102 data.append(('', vtx, edges))
109 data.append(['', vtx, edges])
103
110
104 c.jsdata = json.dumps(data)
111 c.jsdata = json.dumps(data)
@@ -1,187 +1,187
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 modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import calendar
26 import calendar
27 import logging
27 import logging
28 from time import mktime
28 from time import mktime
29 from datetime import datetime, timedelta, date
29 from datetime import datetime, timedelta, date
30
30
31 from vcs.exceptions import ChangesetError
31 from vcs.exceptions import ChangesetError
32
32
33 from pylons import tmpl_context as c, request, url
33 from pylons import tmpl_context as c, request, url
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35
35
36 from rhodecode.model.db import Statistics, Repository
36 from rhodecode.model.db import Statistics, Repository
37 from rhodecode.model.repo import RepoModel
37 from rhodecode.model.repo import RepoModel
38
38
39 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
39 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
40 from rhodecode.lib.base import BaseRepoController, render
40 from rhodecode.lib.base import BaseRepoController, render
41 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
41 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
42
42
43 from rhodecode.lib.celerylib import run_task
43 from rhodecode.lib.celerylib import run_task
44 from rhodecode.lib.celerylib.tasks import get_commits_stats, \
44 from rhodecode.lib.celerylib.tasks import get_commits_stats, \
45 LANGUAGES_EXTENSIONS_MAP
45 LANGUAGES_EXTENSIONS_MAP
46 from rhodecode.lib.helpers import RepoPage
46 from rhodecode.lib.helpers import RepoPage
47
47
48 try:
48 try:
49 import json
49 import json
50 except ImportError:
50 except ImportError:
51 #python 2.5 compatibility
51 #python 2.5 compatibility
52 import simplejson as json
52 import simplejson as json
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
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
71
72 def url_generator(**kw):
72 def url_generator(**kw):
73 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
73 return url('shortlog_home', repo_name=repo_name, size=10, **kw)
74
74
75 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
75 c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
76 items_per_page=10, url=url_generator)
76 items_per_page=10, url=url_generator)
77
77
78 if self.rhodecode_user.username == 'default':
78 if self.rhodecode_user.username == 'default':
79 #for default(anonymous) user we don't need to pass credentials
79 #for default(anonymous) user we don't need to pass credentials
80 username = ''
80 username = ''
81 password = ''
81 password = ''
82 else:
82 else:
83 username = str(self.rhodecode_user.username)
83 username = str(self.rhodecode_user.username)
84 password = '@'
84 password = '@'
85
85
86 if e.get('wsgi.url_scheme') == 'https':
86 if e.get('wsgi.url_scheme') == 'https':
87 split_s = 'https://'
87 split_s = 'https://'
88 else:
88 else:
89 split_s = 'http://'
89 split_s = 'http://'
90
90
91 qualified_uri = [split_s] + [url.current(qualified=True)\
91 qualified_uri = [split_s] + [url.current(qualified=True)\
92 .split(split_s)[-1]]
92 .split(split_s)[-1]]
93 uri = u'%(proto)s%(user)s%(pass)s%(rest)s' \
93 uri = u'%(proto)s%(user)s%(pass)s%(rest)s' \
94 % {'user': username,
94 % {'user': username,
95 'pass': password,
95 'pass': password,
96 'proto': qualified_uri[0],
96 'proto': qualified_uri[0],
97 'rest': qualified_uri[1]}
97 'rest': qualified_uri[1]}
98 c.clone_repo_url = uri
98 c.clone_repo_url = uri
99 c.repo_tags = OrderedDict()
99 c.repo_tags = OrderedDict()
100 for name, hash in c.rhodecode_repo.tags.items()[:10]:
100 for name, hash in c.rhodecode_repo.tags.items()[:10]:
101 try:
101 try:
102 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash)
102 c.repo_tags[name] = c.rhodecode_repo.get_changeset(hash)
103 except ChangesetError:
103 except ChangesetError:
104 c.repo_tags[name] = EmptyChangeset(hash)
104 c.repo_tags[name] = EmptyChangeset(hash)
105
105
106 c.repo_branches = OrderedDict()
106 c.repo_branches = OrderedDict()
107 for name, hash in c.rhodecode_repo.branches.items()[:10]:
107 for name, hash in c.rhodecode_repo.branches.items()[:10]:
108 try:
108 try:
109 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash)
109 c.repo_branches[name] = c.rhodecode_repo.get_changeset(hash)
110 except ChangesetError:
110 except ChangesetError:
111 c.repo_branches[name] = EmptyChangeset(hash)
111 c.repo_branches[name] = EmptyChangeset(hash)
112
112
113 td = date.today() + timedelta(days=1)
113 td = date.today() + timedelta(days=1)
114 td_1m = td - timedelta(days=calendar.mdays[td.month])
114 td_1m = td - timedelta(days=calendar.mdays[td.month])
115 td_1y = td - timedelta(days=365)
115 td_1y = td - timedelta(days=365)
116
116
117 ts_min_m = mktime(td_1m.timetuple())
117 ts_min_m = mktime(td_1m.timetuple())
118 ts_min_y = mktime(td_1y.timetuple())
118 ts_min_y = mktime(td_1y.timetuple())
119 ts_max_y = mktime(td.timetuple())
119 ts_max_y = mktime(td.timetuple())
120
120
121 if dbrepo.enable_statistics:
121 if dbrepo.enable_statistics:
122 c.no_data_msg = _('No data loaded yet')
122 c.no_data_msg = _('No data loaded yet')
123 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
123 run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
124 else:
124 else:
125 c.no_data_msg = _('Statistics are disabled for this repository')
125 c.no_data_msg = _('Statistics are disabled for this repository')
126 c.ts_min = ts_min_m
126 c.ts_min = ts_min_m
127 c.ts_max = ts_max_y
127 c.ts_max = ts_max_y
128
128
129 stats = self.sa.query(Statistics)\
129 stats = self.sa.query(Statistics)\
130 .filter(Statistics.repository == dbrepo)\
130 .filter(Statistics.repository == dbrepo)\
131 .scalar()
131 .scalar()
132
132
133 c.stats_percentage = 0
133 c.stats_percentage = 0
134
134
135 if stats and stats.languages:
135 if stats and stats.languages:
136 c.no_data = False is dbrepo.enable_statistics
136 c.no_data = False is dbrepo.enable_statistics
137 lang_stats = json.loads(stats.languages)
137 lang_stats_d = json.loads(stats.languages)
138 c.commit_data = stats.commit_activity
138 c.commit_data = stats.commit_activity
139 c.overview_data = stats.commit_activity_combined
139 c.overview_data = stats.commit_activity_combined
140
140
141 lang_stats = [(x, {"count": y,
141 lang_stats = [(x, {"count": y,
142 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
142 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
143 for x, y in lang_stats.items()]
143 for x, y in lang_stats_d.items()]
144
144
145 c.trending_languages = json.dumps(OrderedDict(
145 c.trending_languages = json.dumps(OrderedDict(
146 sorted(lang_stats, reverse=True,
146 sorted(lang_stats, reverse=True,
147 key=lambda k: k[1])[:10]
147 key=lambda k: k[1])[:10]
148 )
148 )
149 )
149 )
150 last_rev = stats.stat_on_revision
150 last_rev = stats.stat_on_revision
151 c.repo_last_rev = c.rhodecode_repo.count() - 1 \
151 c.repo_last_rev = c.rhodecode_repo.count() - 1 \
152 if c.rhodecode_repo.revisions else 0
152 if c.rhodecode_repo.revisions else 0
153 if last_rev == 0 or c.repo_last_rev == 0:
153 if last_rev == 0 or c.repo_last_rev == 0:
154 pass
154 pass
155 else:
155 else:
156 c.stats_percentage = '%.2f' % ((float((last_rev)) /
156 c.stats_percentage = '%.2f' % ((float((last_rev)) /
157 c.repo_last_rev) * 100)
157 c.repo_last_rev) * 100)
158 else:
158 else:
159 c.commit_data = json.dumps({})
159 c.commit_data = json.dumps({})
160 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
160 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
161 c.trending_languages = json.dumps({})
161 c.trending_languages = json.dumps({})
162 c.no_data = True
162 c.no_data = True
163
163
164 c.enable_downloads = dbrepo.enable_downloads
164 c.enable_downloads = dbrepo.enable_downloads
165 if c.enable_downloads:
165 if c.enable_downloads:
166 c.download_options = self._get_download_links(c.rhodecode_repo)
166 c.download_options = self._get_download_links(c.rhodecode_repo)
167
167
168 return render('summary/summary.html')
168 return render('summary/summary.html')
169
169
170 def _get_download_links(self, repo):
170 def _get_download_links(self, repo):
171
171
172 download_l = []
172 download_l = []
173
173
174 branches_group = ([], _("Branches"))
174 branches_group = ([], _("Branches"))
175 tags_group = ([], _("Tags"))
175 tags_group = ([], _("Tags"))
176
176
177 for name, chs in c.rhodecode_repo.branches.items():
177 for name, chs in c.rhodecode_repo.branches.items():
178 #chs = chs.split(':')[-1]
178 #chs = chs.split(':')[-1]
179 branches_group[0].append((chs, name),)
179 branches_group[0].append((chs, name),)
180 download_l.append(branches_group)
180 download_l.append(branches_group)
181
181
182 for name, chs in c.rhodecode_repo.tags.items():
182 for name, chs in c.rhodecode_repo.tags.items():
183 #chs = chs.split(':')[-1]
183 #chs = chs.split(':')[-1]
184 tags_group[0].append((chs, name),)
184 tags_group[0].append((chs, name),)
185 download_l.append(tags_group)
185 download_l.append(tags_group)
186
186
187 return download_l
187 return download_l
@@ -1,704 +1,704
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="${c.rhodecode_repo.alias} 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].count;
200 total += data[k].count;
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].count/total*100),2);
214 var percentage = Math.round((data[k].count/total*100),2);
215 var value = data[k].count;
215 var value = data[k].count;
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 = data[k].desc+" ("+k+")";
219 trending_language_label.innerHTML = data[k].desc+" ("+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>22){
229 if (percentage>22){
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__','__CS_EXT__')}";
287 title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
288 s.title = title_tmpl.replace('__CS_NAME__',new_cs.text);
288 s.title = title_tmpl.replace('__CS_NAME__',new_cs.text);
289 s.title = s.title.replace('__CS_EXT__',k);
289 s.title = s.title.replace('__CS_EXT__',k);
290 s.innerHTML = tmpl_links[k].replace('__CS__',new_cs.value);
290 s.innerHTML = tmpl_links[k].replace('__CS__',new_cs.value);
291 }
291 }
292
292
293 })
293 })
294
294
295 </script>
295 </script>
296 </div>
296 </div>
297
297
298 <div class="box box-right" style="min-height:455px">
298 <div class="box box-right" style="min-height:455px">
299 <!-- box / title -->
299 <!-- box / title -->
300 <div class="title">
300 <div class="title">
301 <h5>${_('Commit activity by day / author')}</h5>
301 <h5>${_('Commit activity by day / author')}</h5>
302 </div>
302 </div>
303
303
304 <div class="graph">
304 <div class="graph">
305 <div style="padding:0 10px 10px 15px;font-size: 1.2em;">
305 <div style="padding:0 10px 10px 15px;font-size: 1.2em;">
306 %if c.no_data:
306 %if c.no_data:
307 ${c.no_data_msg}
307 ${c.no_data_msg}
308 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
308 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
309 [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
309 [${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name))}]
310 %endif
310 %endif
311
311
312 %else:
312 %else:
313 ${_('Loaded in')} ${c.stats_percentage} %
313 ${_('Loaded in')} ${c.stats_percentage} %
314 %endif
314 %endif
315 </div>
315 </div>
316 <div id="commit_history" style="width:450px;height:300px;float:left"></div>
316 <div id="commit_history" style="width:450px;height:300px;float:left"></div>
317 <div style="clear: both;height: 10px"></div>
317 <div style="clear: both;height: 10px"></div>
318 <div id="overview" style="width:450px;height:100px;float:left"></div>
318 <div id="overview" style="width:450px;height:100px;float:left"></div>
319
319
320 <div id="legend_data" style="clear:both;margin-top:10px;">
320 <div id="legend_data" style="clear:both;margin-top:10px;">
321 <div id="legend_container"></div>
321 <div id="legend_container"></div>
322 <div id="legend_choices">
322 <div id="legend_choices">
323 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
323 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
324 </div>
324 </div>
325 </div>
325 </div>
326 <script type="text/javascript">
326 <script type="text/javascript">
327 /**
327 /**
328 * Plots summary graph
328 * Plots summary graph
329 *
329 *
330 * @class SummaryPlot
330 * @class SummaryPlot
331 * @param {from} initial from for detailed graph
331 * @param {from} initial from for detailed graph
332 * @param {to} initial to for detailed graph
332 * @param {to} initial to for detailed graph
333 * @param {dataset}
333 * @param {dataset}
334 * @param {overview_dataset}
334 * @param {overview_dataset}
335 */
335 */
336 function SummaryPlot(from,to,dataset,overview_dataset) {
336 function SummaryPlot(from,to,dataset,overview_dataset) {
337 var initial_ranges = {
337 var initial_ranges = {
338 "xaxis":{
338 "xaxis":{
339 "from":from,
339 "from":from,
340 "to":to,
340 "to":to,
341 },
341 },
342 };
342 };
343 var dataset = dataset;
343 var dataset = dataset;
344 var overview_dataset = [overview_dataset];
344 var overview_dataset = [overview_dataset];
345 var choiceContainer = YUD.get("legend_choices");
345 var choiceContainer = YUD.get("legend_choices");
346 var choiceContainerTable = YUD.get("legend_choices_tables");
346 var choiceContainerTable = YUD.get("legend_choices_tables");
347 var plotContainer = YUD.get('commit_history');
347 var plotContainer = YUD.get('commit_history');
348 var overviewContainer = YUD.get('overview');
348 var overviewContainer = YUD.get('overview');
349
349
350 var plot_options = {
350 var plot_options = {
351 bars: {show:true,align:'center',lineWidth:4},
351 bars: {show:true,align:'center',lineWidth:4},
352 legend: {show:true, container:"legend_container"},
352 legend: {show:true, container:"legend_container"},
353 points: {show:true,radius:0,fill:false},
353 points: {show:true,radius:0,fill:false},
354 yaxis: {tickDecimals:0,},
354 yaxis: {tickDecimals:0,},
355 xaxis: {
355 xaxis: {
356 mode: "time",
356 mode: "time",
357 timeformat: "%d/%m",
357 timeformat: "%d/%m",
358 min:from,
358 min:from,
359 max:to,
359 max:to,
360 },
360 },
361 grid: {
361 grid: {
362 hoverable: true,
362 hoverable: true,
363 clickable: true,
363 clickable: true,
364 autoHighlight:true,
364 autoHighlight:true,
365 color: "#999"
365 color: "#999"
366 },
366 },
367 //selection: {mode: "x"}
367 //selection: {mode: "x"}
368 };
368 };
369 var overview_options = {
369 var overview_options = {
370 legend:{show:false},
370 legend:{show:false},
371 bars: {show:true,barWidth: 2,},
371 bars: {show:true,barWidth: 2,},
372 shadowSize: 0,
372 shadowSize: 0,
373 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
373 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
374 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
374 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
375 grid: {color: "#999",},
375 grid: {color: "#999",},
376 selection: {mode: "x"}
376 selection: {mode: "x"}
377 };
377 };
378
378
379 /**
379 /**
380 *get dummy data needed in few places
380 *get dummy data needed in few places
381 */
381 */
382 function getDummyData(label){
382 function getDummyData(label){
383 return {"label":label,
383 return {"label":label,
384 "data":[{"time":0,
384 "data":[{"time":0,
385 "commits":0,
385 "commits":0,
386 "added":0,
386 "added":0,
387 "changed":0,
387 "changed":0,
388 "removed":0,
388 "removed":0,
389 }],
389 }],
390 "schema":["commits"],
390 "schema":["commits"],
391 "color":'#ffffff',
391 "color":'#ffffff',
392 }
392 }
393 }
393 }
394
394
395 /**
395 /**
396 * generate checkboxes accordindly to data
396 * generate checkboxes accordindly to data
397 * @param keys
397 * @param keys
398 * @returns
398 * @returns
399 */
399 */
400 function generateCheckboxes(data) {
400 function generateCheckboxes(data) {
401 //append checkboxes
401 //append checkboxes
402 var i = 0;
402 var i = 0;
403 choiceContainerTable.innerHTML = '';
403 choiceContainerTable.innerHTML = '';
404 for(var pos in data) {
404 for(var pos in data) {
405
405
406 data[pos].color = i;
406 data[pos].color = i;
407 i++;
407 i++;
408 if(data[pos].label != ''){
408 if(data[pos].label != ''){
409 choiceContainerTable.innerHTML += '<tr><td>'+
409 choiceContainerTable.innerHTML += '<tr><td>'+
410 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
410 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
411 +data[pos].label+
411 +data[pos].label+
412 '</td></tr>';
412 '</td></tr>';
413 }
413 }
414 }
414 }
415 }
415 }
416
416
417 /**
417 /**
418 * ToolTip show
418 * ToolTip show
419 */
419 */
420 function showTooltip(x, y, contents) {
420 function showTooltip(x, y, contents) {
421 var div=document.getElementById('tooltip');
421 var div=document.getElementById('tooltip');
422 if(!div) {
422 if(!div) {
423 div = document.createElement('div');
423 div = document.createElement('div');
424 div.id="tooltip";
424 div.id="tooltip";
425 div.style.position="absolute";
425 div.style.position="absolute";
426 div.style.border='1px solid #fdd';
426 div.style.border='1px solid #fdd';
427 div.style.padding='2px';
427 div.style.padding='2px';
428 div.style.backgroundColor='#fee';
428 div.style.backgroundColor='#fee';
429 document.body.appendChild(div);
429 document.body.appendChild(div);
430 }
430 }
431 YUD.setStyle(div, 'opacity', 0);
431 YUD.setStyle(div, 'opacity', 0);
432 div.innerHTML = contents;
432 div.innerHTML = contents;
433 div.style.top=(y + 5) + "px";
433 div.style.top=(y + 5) + "px";
434 div.style.left=(x + 5) + "px";
434 div.style.left=(x + 5) + "px";
435
435
436 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
436 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
437 anim.animate();
437 anim.animate();
438 }
438 }
439
439
440 /**
440 /**
441 * This function will detect if selected period has some changesets
441 * This function will detect if selected period has some changesets
442 for this user if it does this data is then pushed for displaying
442 for this user if it does this data is then pushed for displaying
443 Additionally it will only display users that are selected by the checkbox
443 Additionally it will only display users that are selected by the checkbox
444 */
444 */
445 function getDataAccordingToRanges(ranges) {
445 function getDataAccordingToRanges(ranges) {
446
446
447 var data = [];
447 var data = [];
448 var keys = [];
448 var keys = [];
449 for(var key in dataset){
449 for(var key in dataset){
450 var push = false;
450 var push = false;
451
451
452 //method1 slow !!
452 //method1 slow !!
453 //*
453 //*
454 for(var ds in dataset[key].data){
454 for(var ds in dataset[key].data){
455 commit_data = dataset[key].data[ds];
455 commit_data = dataset[key].data[ds];
456 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
456 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
457 push = true;
457 push = true;
458 break;
458 break;
459 }
459 }
460 }
460 }
461 //*/
461 //*/
462
462
463 /*//method2 sorted commit data !!!
463 /*//method2 sorted commit data !!!
464
464
465 var first_commit = dataset[key].data[0].time;
465 var first_commit = dataset[key].data[0].time;
466 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
466 var last_commit = dataset[key].data[dataset[key].data.length-1].time;
467
467
468 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
468 if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
469 push = true;
469 push = true;
470 }
470 }
471 //*/
471 //*/
472
472
473 if(push){
473 if(push){
474 data.push(dataset[key]);
474 data.push(dataset[key]);
475 }
475 }
476 }
476 }
477 if(data.length >= 1){
477 if(data.length >= 1){
478 return data;
478 return data;
479 }
479 }
480 else{
480 else{
481 //just return dummy data for graph to plot itself
481 //just return dummy data for graph to plot itself
482 return [getDummyData('')];
482 return [getDummyData('')];
483 }
483 }
484
484
485 }
485 }
486
486
487 /**
487 /**
488 * redraw using new checkbox data
488 * redraw using new checkbox data
489 */
489 */
490 function plotchoiced(e,args){
490 function plotchoiced(e,args){
491 var cur_data = args[0];
491 var cur_data = args[0];
492 var cur_ranges = args[1];
492 var cur_ranges = args[1];
493
493
494 var new_data = [];
494 var new_data = [];
495 var inputs = choiceContainer.getElementsByTagName("input");
495 var inputs = choiceContainer.getElementsByTagName("input");
496
496
497 //show only checked labels
497 //show only checked labels
498 for(var i=0; i<inputs.length; i++) {
498 for(var i=0; i<inputs.length; i++) {
499 var checkbox_key = inputs[i].name;
499 var checkbox_key = inputs[i].name;
500
500
501 if(inputs[i].checked){
501 if(inputs[i].checked){
502 for(var d in cur_data){
502 for(var d in cur_data){
503 if(cur_data[d].label == checkbox_key){
503 if(cur_data[d].label == checkbox_key){
504 new_data.push(cur_data[d]);
504 new_data.push(cur_data[d]);
505 }
505 }
506 }
506 }
507 }
507 }
508 else{
508 else{
509 //push dummy data to not hide the label
509 //push dummy data to not hide the label
510 new_data.push(getDummyData(checkbox_key));
510 new_data.push(getDummyData(checkbox_key));
511 }
511 }
512 }
512 }
513
513
514 var new_options = YAHOO.lang.merge(plot_options, {
514 var new_options = YAHOO.lang.merge(plot_options, {
515 xaxis: {
515 xaxis: {
516 min: cur_ranges.xaxis.from,
516 min: cur_ranges.xaxis.from,
517 max: cur_ranges.xaxis.to,
517 max: cur_ranges.xaxis.to,
518 mode:"time",
518 mode:"time",
519 timeformat: "%d/%m",
519 timeformat: "%d/%m",
520 },
520 },
521 });
521 });
522 if (!new_data){
522 if (!new_data){
523 new_data = [[0,1]];
523 new_data = [[0,1]];
524 }
524 }
525 // do the zooming
525 // do the zooming
526 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
526 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
527
527
528 plot.subscribe("plotselected", plotselected);
528 plot.subscribe("plotselected", plotselected);
529
529
530 //resubscribe plothover
530 //resubscribe plothover
531 plot.subscribe("plothover", plothover);
531 plot.subscribe("plothover", plothover);
532
532
533 // don't fire event on the overview to prevent eternal loop
533 // don't fire event on the overview to prevent eternal loop
534 overview.setSelection(cur_ranges, true);
534 overview.setSelection(cur_ranges, true);
535
535
536 }
536 }
537
537
538 /**
538 /**
539 * plot only selected items from overview
539 * plot only selected items from overview
540 * @param ranges
540 * @param ranges
541 * @returns
541 * @returns
542 */
542 */
543 function plotselected(ranges,cur_data) {
543 function plotselected(ranges,cur_data) {
544 //updates the data for new plot
544 //updates the data for new plot
545 data = getDataAccordingToRanges(ranges);
545 data = getDataAccordingToRanges(ranges);
546 generateCheckboxes(data);
546 generateCheckboxes(data);
547
547
548 var new_options = YAHOO.lang.merge(plot_options, {
548 var new_options = YAHOO.lang.merge(plot_options, {
549 xaxis: {
549 xaxis: {
550 min: ranges.xaxis.from,
550 min: ranges.xaxis.from,
551 max: ranges.xaxis.to,
551 max: ranges.xaxis.to,
552 mode:"time",
552 mode:"time",
553 timeformat: "%d/%m",
553 timeformat: "%d/%m",
554 },
554 },
555 yaxis: {
555 yaxis: {
556 min: ranges.yaxis.from,
556 min: ranges.yaxis.from,
557 max: ranges.yaxis.to,
557 max: ranges.yaxis.to,
558 },
558 },
559
559
560 });
560 });
561 // do the zooming
561 // do the zooming
562 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
562 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
563
563
564 plot.subscribe("plotselected", plotselected);
564 plot.subscribe("plotselected", plotselected);
565
565
566 //resubscribe plothover
566 //resubscribe plothover
567 plot.subscribe("plothover", plothover);
567 plot.subscribe("plothover", plothover);
568
568
569 // don't fire event on the overview to prevent eternal loop
569 // don't fire event on the overview to prevent eternal loop
570 overview.setSelection(ranges, true);
570 overview.setSelection(ranges, true);
571
571
572 //resubscribe choiced
572 //resubscribe choiced
573 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
573 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
574 }
574 }
575
575
576 var previousPoint = null;
576 var previousPoint = null;
577
577
578 function plothover(o) {
578 function plothover(o) {
579 var pos = o.pos;
579 var pos = o.pos;
580 var item = o.item;
580 var item = o.item;
581
581
582 //YUD.get("x").innerHTML = pos.x.toFixed(2);
582 //YUD.get("x").innerHTML = pos.x.toFixed(2);
583 //YUD.get("y").innerHTML = pos.y.toFixed(2);
583 //YUD.get("y").innerHTML = pos.y.toFixed(2);
584 if (item) {
584 if (item) {
585 if (previousPoint != item.datapoint) {
585 if (previousPoint != item.datapoint) {
586 previousPoint = item.datapoint;
586 previousPoint = item.datapoint;
587
587
588 var tooltip = YUD.get("tooltip");
588 var tooltip = YUD.get("tooltip");
589 if(tooltip) {
589 if(tooltip) {
590 tooltip.parentNode.removeChild(tooltip);
590 tooltip.parentNode.removeChild(tooltip);
591 }
591 }
592 var x = item.datapoint.x.toFixed(2);
592 var x = item.datapoint.x.toFixed(2);
593 var y = item.datapoint.y.toFixed(2);
593 var y = item.datapoint.y.toFixed(2);
594
594
595 if (!item.series.label){
595 if (!item.series.label){
596 item.series.label = 'commits';
596 item.series.label = 'commits';
597 }
597 }
598 var d = new Date(x*1000);
598 var d = new Date(x*1000);
599 var fd = d.toDateString()
599 var fd = d.toDateString()
600 var nr_commits = parseInt(y);
600 var nr_commits = parseInt(y);
601
601
602 var cur_data = dataset[item.series.label].data[item.dataIndex];
602 var cur_data = dataset[item.series.label].data[item.dataIndex];
603 var added = cur_data.added;
603 var added = cur_data.added;
604 var changed = cur_data.changed;
604 var changed = cur_data.changed;
605 var removed = cur_data.removed;
605 var removed = cur_data.removed;
606
606
607 var nr_commits_suffix = " ${_('commits')} ";
607 var nr_commits_suffix = " ${_('commits')} ";
608 var added_suffix = " ${_('files added')} ";
608 var added_suffix = " ${_('files added')} ";
609 var changed_suffix = " ${_('files changed')} ";
609 var changed_suffix = " ${_('files changed')} ";
610 var removed_suffix = " ${_('files removed')} ";
610 var removed_suffix = " ${_('files removed')} ";
611
611
612
612
613 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
613 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
614 if(added==1){added_suffix=" ${_('file added')} ";}
614 if(added==1){added_suffix=" ${_('file added')} ";}
615 if(changed==1){changed_suffix=" ${_('file changed')} ";}
615 if(changed==1){changed_suffix=" ${_('file changed')} ";}
616 if(removed==1){removed_suffix=" ${_('file removed')} ";}
616 if(removed==1){removed_suffix=" ${_('file removed')} ";}
617
617
618 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
618 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
619 +'<br/>'+
619 +'<br/>'+
620 nr_commits + nr_commits_suffix+'<br/>'+
620 nr_commits + nr_commits_suffix+'<br/>'+
621 added + added_suffix +'<br/>'+
621 added + added_suffix +'<br/>'+
622 changed + changed_suffix + '<br/>'+
622 changed + changed_suffix + '<br/>'+
623 removed + removed_suffix + '<br/>');
623 removed + removed_suffix + '<br/>');
624 }
624 }
625 }
625 }
626 else {
626 else {
627 var tooltip = YUD.get("tooltip");
627 var tooltip = YUD.get("tooltip");
628
628
629 if(tooltip) {
629 if(tooltip) {
630 tooltip.parentNode.removeChild(tooltip);
630 tooltip.parentNode.removeChild(tooltip);
631 }
631 }
632 previousPoint = null;
632 previousPoint = null;
633 }
633 }
634 }
634 }
635
635
636 /**
636 /**
637 * MAIN EXECUTION
637 * MAIN EXECUTION
638 */
638 */
639
639
640 var data = getDataAccordingToRanges(initial_ranges);
640 var data = getDataAccordingToRanges(initial_ranges);
641 generateCheckboxes(data);
641 generateCheckboxes(data);
642
642
643 //main plot
643 //main plot
644 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
644 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
645
645
646 //overview
646 //overview
647 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
647 var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
648
648
649 //show initial selection on overview
649 //show initial selection on overview
650 overview.setSelection(initial_ranges);
650 overview.setSelection(initial_ranges);
651
651
652 plot.subscribe("plotselected", plotselected);
652 plot.subscribe("plotselected", plotselected);
653
653
654 overview.subscribe("plotselected", function (ranges) {
654 overview.subscribe("plotselected", function (ranges) {
655 plot.setSelection(ranges);
655 plot.setSelection(ranges);
656 });
656 });
657
657
658 plot.subscribe("plothover", plothover);
658 plot.subscribe("plothover", plothover);
659
659
660 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
660 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
661 }
661 }
662 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
662 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
663 </script>
663 </script>
664
664
665 </div>
665 </div>
666 </div>
666 </div>
667
667
668 <div class="box">
668 <div class="box">
669 <div class="title">
669 <div class="title">
670 <div class="breadcrumbs">${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
670 <div class="breadcrumbs">${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
671 </div>
671 </div>
672 <div class="table">
672 <div class="table">
673 <div id="shortlog_data">
673 <div id="shortlog_data">
674 <%include file='../shortlog/shortlog_data.html'/>
674 <%include file='../shortlog/shortlog_data.html'/>
675 </div>
675 </div>
676 ##%if c.repo_changesets:
676 ##%if c.repo_changesets:
677 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
677 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
678 ##%endif
678 ##%endif
679 </div>
679 </div>
680 </div>
680 </div>
681 <div class="box">
681 <div class="box">
682 <div class="title">
682 <div class="title">
683 <div class="breadcrumbs">${h.link_to(_('Tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
683 <div class="breadcrumbs">${h.link_to(_('Tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
684 </div>
684 </div>
685 <div class="table">
685 <div class="table">
686 <%include file='../tags/tags_data.html'/>
686 <%include file='../tags/tags_data.html'/>
687 %if c.repo_changesets:
687 %if c.repo_changesets:
688 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
688 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
689 %endif
689 %endif
690 </div>
690 </div>
691 </div>
691 </div>
692 <div class="box">
692 <div class="box">
693 <div class="title">
693 <div class="title">
694 <div class="breadcrumbs">${h.link_to(_('Branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
694 <div class="breadcrumbs">${h.link_to(_('Branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
695 </div>
695 </div>
696 <div class="table">
696 <div class="table">
697 <%include file='../branches/branches_data.html'/>
697 <%include file='../branches/branches_data.html'/>
698 %if c.repo_changesets:
698 %if c.repo_changesets:
699 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
699 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
700 %endif
700 %endif
701 </div>
701 </div>
702 </div>
702 </div>
703
703
704 </%def>
704 </%def>
General Comments 0
You need to be logged in to leave comments. Login now