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