comparison rhodecode/templates/summary/summary.html @ 1605:df59c0503636 beta

implements #215 Repository view uses a README (text/markdown + rst)
author Marcin Kuzminski <marcin@python-works.com>
date Thu, 27 Oct 2011 03:26:02 +0200
parents 6ff50754d22d
children 4a28aff31a15
comparison
equal deleted inserted replaced
1604:bb3c2111bf92 1605:df59c0503636
62 <span class="repo_name">${h.repo_link(c.dbrepo.groups_and_repo)}</span> 62 <span class="repo_name">${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)}"><img class="icon" alt="${_('public')}" title="${_('Fork of')} ${c.dbrepo.fork.repo_name}" src="${h.url('/images/icons/arrow_divide.png')}"/>
68 <img class="icon" alt="${_('public')}" 68 ${_('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')}"/>
71 ${_('Fork of')} ${c.dbrepo.fork.repo_name}
72 </a> 69 </a>
73 </div> 70 </div>
74 %endif 71 %endif
75 ##REMOTE 72 ##REMOTE
76 %if c.dbrepo.clone_uri: 73 %if c.dbrepo.clone_uri:
77 <div style="margin-top:5px;clear:both"> 74 <div style="margin-top:5px;clear:both">
78 <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}"> 75 <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}"><img class="icon" alt="${_('remote clone')}" title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}" src="${h.url('/images/icons/connect.png')}"/>
79 <img class="icon" alt="${_('remote clone')}" 76 ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
80 title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}"
81 src="${h.url('/images/icons/connect.png')}"/>
82 ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
83 </a> 77 </a>
84 </div> 78 </div>
85 %endif 79 %endif
86 </div> 80 </div>
87 </div> 81 </div>
88 82
89
90 <div class="field"> 83 <div class="field">
91 <div class="label"> 84 <div class="label">
92 <label>${_('Description')}:</label> 85 <label>${_('Description')}:</label>
93 </div> 86 </div>
94 <div class="input-short desc">${h.urlify_text(c.dbrepo.description)}</div> 87 <div class="input-short desc">${h.urlify_text(c.dbrepo.description)}</div>
95 </div> 88 </div>
96
97 89
98 <div class="field"> 90 <div class="field">
99 <div class="label"> 91 <div class="label">
100 <label>${_('Contact')}:</label> 92 <label>${_('Contact')}:</label>
101 </div> 93 </div>
117 <b>${'r%s:%s' % (h.get_changeset_safe(c.rhodecode_repo,'tip').revision, 109 <b>${'r%s:%s' % (h.get_changeset_safe(c.rhodecode_repo,'tip').revision,
118 h.get_changeset_safe(c.rhodecode_repo,'tip').short_id)}</b> - 110 h.get_changeset_safe(c.rhodecode_repo,'tip').short_id)}</b> -
119 <span class="tooltip" title="${c.rhodecode_repo.last_change}"> 111 <span class="tooltip" title="${c.rhodecode_repo.last_change}">
120 ${h.age(c.rhodecode_repo.last_change)}</span><br/> 112 ${h.age(c.rhodecode_repo.last_change)}</span><br/>
121 ${_('by')} ${h.get_changeset_safe(c.rhodecode_repo,'tip').author} 113 ${_('by')} ${h.get_changeset_safe(c.rhodecode_repo,'tip').author}
122
123 </div> 114 </div>
124 </div> 115 </div>
125 116
126 <div class="field"> 117 <div class="field">
127 <div class="label"> 118 <div class="label">
185 %endif 176 %endif
186 </div> 177 </div>
187 </div> 178 </div>
188 </div> 179 </div>
189 </div> 180 </div>
190 <script type="text/javascript">
191 YUE.onDOMReady(function(e){
192 id = 'clone_url';
193 YUE.on(id,'click',function(e){
194 if(YUD.hasClass(id,'selected')){
195 return
196 }
197 else{
198 YUD.addClass(id,'selected');
199 YUD.get(id).select();
200 }
201
202 })
203 })
204 var data = ${c.trending_languages|n};
205 var total = 0;
206 var no_data = true;
207 for (k in data){
208 total += data[k].count;
209 no_data = false;
210 }
211 var tbl = document.createElement('table');
212 tbl.setAttribute('class','trending_language_tbl');
213 var cnt = 0;
214 for (k in data){
215 cnt += 1;
216 var hide = cnt>2;
217 var tr = document.createElement('tr');
218 if (hide){
219 tr.setAttribute('style','display:none');
220 tr.setAttribute('class','stats_hidden');
221 }
222 var percentage = Math.round((data[k].count/total*100),2);
223 var value = data[k].count;
224 var td1 = document.createElement('td');
225 td1.width = 150;
226 var trending_language_label = document.createElement('div');
227 trending_language_label.innerHTML = data[k].desc+" ("+k+")";
228 td1.appendChild(trending_language_label);
229
230 var td2 = document.createElement('td');
231 td2.setAttribute('style','padding-right:14px !important');
232 var trending_language = document.createElement('div');
233 var nr_files = value+" ${_('files')}";
234
235 trending_language.title = k+" "+nr_files;
236
237 if (percentage>22){
238 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
239 }
240 else{
241 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
242 }
243
244 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
245 trending_language.style.width=percentage+"%";
246 td2.appendChild(trending_language);
247
248 tr.appendChild(td1);
249 tr.appendChild(td2);
250 tbl.appendChild(tr);
251 if(cnt == 3){
252 var show_more = document.createElement('tr');
253 var td = document.createElement('td');
254 lnk = document.createElement('a');
255
256 lnk.href='#';
257 lnk.innerHTML = "${_('show more')}";
258 lnk.id='code_stats_show_more';
259 td.appendChild(lnk);
260
261 show_more.appendChild(td);
262 show_more.appendChild(document.createElement('td'));
263 tbl.appendChild(show_more);
264 }
265
266 }
267 if(no_data){
268 var tr = document.createElement('tr');
269 var td1 = document.createElement('td');
270 td1.innerHTML = "${c.no_data_msg}";
271 tr.appendChild(td1);
272 tbl.appendChild(tr);
273 }
274 YUD.get('lang_stats').appendChild(tbl);
275 YUE.on('code_stats_show_more','click',function(){
276 l = YUD.getElementsByClassName('stats_hidden')
277 for (e in l){
278 YUD.setStyle(l[e],'display','');
279 };
280 YUD.setStyle(YUD.get('code_stats_show_more'),
281 'display','none');
282 })
283
284 var tmpl_links = {}
285 %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
286 tmpl_links['${archive['type']}'] = '${h.link_to(archive['type'],
287 h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
288 fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_="archive_icon")}';
289 %endfor
290
291 YUE.on(['download_options','archive_subrepos'],'change',function(e){
292 var sm = YUD.get('download_options');
293 var new_cs = sm.options[sm.selectedIndex];
294
295 for(k in tmpl_links){
296 var s = YUD.get(k+'_link');
297 title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
298 s.title = title_tmpl.replace('__CS_NAME__',new_cs.text);
299 s.title = s.title.replace('__CS_EXT__',k);
300 var url = tmpl_links[k].replace('__CS__',new_cs.value);
301 var subrepos = YUD.get('archive_subrepos').checked
302 url = url.replace('__SUB__',subrepos);
303 s.innerHTML = url
304 }
305 });
306 </script>
307 </div> 181 </div>
308 182
309 <div class="box box-right" style="min-height:455px"> 183 <div class="box box-right" style="min-height:455px">
310 <!-- box / title --> 184 <!-- box / title -->
311 <div class="title"> 185 <div class="title">
317 %if c.no_data: 191 %if c.no_data:
318 ${c.no_data_msg} 192 ${c.no_data_msg}
319 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'): 193 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
320 ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-button-small")} 194 ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-button-small")}
321 %endif 195 %endif
322
323 %else: 196 %else:
324 ${_('Loaded in')} ${c.stats_percentage} % 197 ${_('Loaded in')} ${c.stats_percentage} %
325 %endif 198 %endif
326 </div> 199 </div>
327 <div id="commit_history" style="width:450px;height:300px;float:left"></div> 200 <div id="commit_history" style="width:450px;height:300px;float:left"></div>
329 <div id="overview" style="width:450px;height:100px;float:left"></div> 202 <div id="overview" style="width:450px;height:100px;float:left"></div>
330 203
331 <div id="legend_data" style="clear:both;margin-top:10px;"> 204 <div id="legend_data" style="clear:both;margin-top:10px;">
332 <div id="legend_container"></div> 205 <div id="legend_container"></div>
333 <div id="legend_choices"> 206 <div id="legend_choices">
334 <table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table> 207 <table id="legend_choices_tables" class="noborder" style="font-size:smaller;color:#545454"></table>
335 </div> 208 </div>
336 </div> 209 </div>
337 <script type="text/javascript">
338 /**
339 * Plots summary graph
340 *
341 * @class SummaryPlot
342 * @param {from} initial from for detailed graph
343 * @param {to} initial to for detailed graph
344 * @param {dataset}
345 * @param {overview_dataset}
346 */
347 function SummaryPlot(from,to,dataset,overview_dataset) {
348 var initial_ranges = {
349 "xaxis":{
350 "from":from,
351 "to":to,
352 },
353 };
354 var dataset = dataset;
355 var overview_dataset = [overview_dataset];
356 var choiceContainer = YUD.get("legend_choices");
357 var choiceContainerTable = YUD.get("legend_choices_tables");
358 var plotContainer = YUD.get('commit_history');
359 var overviewContainer = YUD.get('overview');
360
361 var plot_options = {
362 bars: {show:true,align:'center',lineWidth:4},
363 legend: {show:true, container:"legend_container"},
364 points: {show:true,radius:0,fill:false},
365 yaxis: {tickDecimals:0,},
366 xaxis: {
367 mode: "time",
368 timeformat: "%d/%m",
369 min:from,
370 max:to,
371 },
372 grid: {
373 hoverable: true,
374 clickable: true,
375 autoHighlight:true,
376 color: "#999"
377 },
378 //selection: {mode: "x"}
379 };
380 var overview_options = {
381 legend:{show:false},
382 bars: {show:true,barWidth: 2,},
383 shadowSize: 0,
384 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
385 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
386 grid: {color: "#999",},
387 selection: {mode: "x"}
388 };
389
390 /**
391 *get dummy data needed in few places
392 */
393 function getDummyData(label){
394 return {"label":label,
395 "data":[{"time":0,
396 "commits":0,
397 "added":0,
398 "changed":0,
399 "removed":0,
400 }],
401 "schema":["commits"],
402 "color":'#ffffff',
403 }
404 }
405
406 /**
407 * generate checkboxes accordindly to data
408 * @param keys
409 * @returns
410 */
411 function generateCheckboxes(data) {
412 //append checkboxes
413 var i = 0;
414 choiceContainerTable.innerHTML = '';
415 for(var pos in data) {
416
417 data[pos].color = i;
418 i++;
419 if(data[pos].label != ''){
420 choiceContainerTable.innerHTML += '<tr><td>'+
421 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
422 +data[pos].label+
423 '</td></tr>';
424 }
425 }
426 }
427
428 /**
429 * ToolTip show
430 */
431 function showTooltip(x, y, contents) {
432 var div=document.getElementById('tooltip');
433 if(!div) {
434 div = document.createElement('div');
435 div.id="tooltip";
436 div.style.position="absolute";
437 div.style.border='1px solid #fdd';
438 div.style.padding='2px';
439 div.style.backgroundColor='#fee';
440 document.body.appendChild(div);
441 }
442 YUD.setStyle(div, 'opacity', 0);
443 div.innerHTML = contents;
444 div.style.top=(y + 5) + "px";
445 div.style.left=(x + 5) + "px";
446
447 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
448 anim.animate();
449 }
450
451 /**
452 * This function will detect if selected period has some changesets
453 for this user if it does this data is then pushed for displaying
454 Additionally it will only display users that are selected by the checkbox
455 */
456 function getDataAccordingToRanges(ranges) {
457
458 var data = [];
459 var new_dataset = {};
460 var keys = [];
461 var max_commits = 0;
462 for(var key in dataset){
463
464 for(var ds in dataset[key].data){
465 commit_data = dataset[key].data[ds];
466 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
467
468 if(new_dataset[key] === undefined){
469 new_dataset[key] = {data:[],schema:["commits"],label:key};
470 }
471 new_dataset[key].data.push(commit_data);
472 }
473 }
474 if (new_dataset[key] !== undefined){
475 data.push(new_dataset[key]);
476 }
477 }
478
479 if (data.length > 0){
480 return data;
481 }
482 else{
483 //just return dummy data for graph to plot itself
484 return [getDummyData('')];
485 }
486 }
487
488 /**
489 * redraw using new checkbox data
490 */
491 function plotchoiced(e,args){
492 var cur_data = args[0];
493 var cur_ranges = args[1];
494
495 var new_data = [];
496 var inputs = choiceContainer.getElementsByTagName("input");
497
498 //show only checked labels
499 for(var i=0; i<inputs.length; i++) {
500 var checkbox_key = inputs[i].name;
501
502 if(inputs[i].checked){
503 for(var d in cur_data){
504 if(cur_data[d].label == checkbox_key){
505 new_data.push(cur_data[d]);
506 }
507 }
508 }
509 else{
510 //push dummy data to not hide the label
511 new_data.push(getDummyData(checkbox_key));
512 }
513 }
514
515 var new_options = YAHOO.lang.merge(plot_options, {
516 xaxis: {
517 min: cur_ranges.xaxis.from,
518 max: cur_ranges.xaxis.to,
519 mode:"time",
520 timeformat: "%d/%m",
521 },
522 });
523 if (!new_data){
524 new_data = [[0,1]];
525 }
526 // do the zooming
527 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
528
529 plot.subscribe("plotselected", plotselected);
530
531 //resubscribe plothover
532 plot.subscribe("plothover", plothover);
533
534 // don't fire event on the overview to prevent eternal loop
535 overview.setSelection(cur_ranges, true);
536
537 }
538
539 /**
540 * plot only selected items from overview
541 * @param ranges
542 * @returns
543 */
544 function plotselected(ranges,cur_data) {
545 //updates the data for new plot
546 var data = getDataAccordingToRanges(ranges);
547 generateCheckboxes(data);
548
549 var new_options = YAHOO.lang.merge(plot_options, {
550 xaxis: {
551 min: ranges.xaxis.from,
552 max: ranges.xaxis.to,
553 mode:"time",
554 timeformat: "%d/%m",
555 },
556 });
557 // do the zooming
558 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
559
560 plot.subscribe("plotselected", plotselected);
561
562 //resubscribe plothover
563 plot.subscribe("plothover", plothover);
564
565 // don't fire event on the overview to prevent eternal loop
566 overview.setSelection(ranges, true);
567
568 //resubscribe choiced
569 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
570 }
571
572 var previousPoint = null;
573
574 function plothover(o) {
575 var pos = o.pos;
576 var item = o.item;
577
578 //YUD.get("x").innerHTML = pos.x.toFixed(2);
579 //YUD.get("y").innerHTML = pos.y.toFixed(2);
580 if (item) {
581 if (previousPoint != item.datapoint) {
582 previousPoint = item.datapoint;
583
584 var tooltip = YUD.get("tooltip");
585 if(tooltip) {
586 tooltip.parentNode.removeChild(tooltip);
587 }
588 var x = item.datapoint.x.toFixed(2);
589 var y = item.datapoint.y.toFixed(2);
590
591 if (!item.series.label){
592 item.series.label = 'commits';
593 }
594 var d = new Date(x*1000);
595 var fd = d.toDateString()
596 var nr_commits = parseInt(y);
597
598 var cur_data = dataset[item.series.label].data[item.dataIndex];
599 var added = cur_data.added;
600 var changed = cur_data.changed;
601 var removed = cur_data.removed;
602
603 var nr_commits_suffix = " ${_('commits')} ";
604 var added_suffix = " ${_('files added')} ";
605 var changed_suffix = " ${_('files changed')} ";
606 var removed_suffix = " ${_('files removed')} ";
607
608
609 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
610 if(added==1){added_suffix=" ${_('file added')} ";}
611 if(changed==1){changed_suffix=" ${_('file changed')} ";}
612 if(removed==1){removed_suffix=" ${_('file removed')} ";}
613
614 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
615 +'<br/>'+
616 nr_commits + nr_commits_suffix+'<br/>'+
617 added + added_suffix +'<br/>'+
618 changed + changed_suffix + '<br/>'+
619 removed + removed_suffix + '<br/>');
620 }
621 }
622 else {
623 var tooltip = YUD.get("tooltip");
624
625 if(tooltip) {
626 tooltip.parentNode.removeChild(tooltip);
627 }
628 previousPoint = null;
629 }
630 }
631
632 /**
633 * MAIN EXECUTION
634 */
635
636 var data = getDataAccordingToRanges(initial_ranges);
637 generateCheckboxes(data);
638
639 //main plot
640 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
641
642 //overview
643 var overview = YAHOO.widget.Flot(overviewContainer,
644 overview_dataset, overview_options);
645
646 //show initial selection on overview
647 overview.setSelection(initial_ranges);
648
649 plot.subscribe("plotselected", plotselected);
650 plot.subscribe("plothover", plothover)
651
652 overview.subscribe("plotselected", function (ranges) {
653 plot.setSelection(ranges);
654 });
655
656 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
657 }
658 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
659 </script>
660
661 </div> 210 </div>
662 </div> 211 </div>
663 212
664 <div class="box"> 213 <div class="box">
665 <div class="title"> 214 <div class="title">
667 </div> 216 </div>
668 <div class="table"> 217 <div class="table">
669 <div id="shortlog_data"> 218 <div id="shortlog_data">
670 <%include file='../shortlog/shortlog_data.html'/> 219 <%include file='../shortlog/shortlog_data.html'/>
671 </div> 220 </div>
672 ##%if c.repo_changesets:
673 ## ${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
674 ##%endif
675 </div> 221 </div>
676 </div> 222 </div>
677 <div class="box"> 223
224 %if c.readme_data:
225 <div class="box" style="background-color: #FAFAFA">
678 <div class="title"> 226 <div class="title">
679 <div class="breadcrumbs">${h.link_to(_('Tags'),h.url('tags_home',repo_name=c.repo_name))}</div> 227 <div class="breadcrumbs"><a href="${h.url('files_home',repo_name=c.repo_name,revision='tip',f_path=c.readme_file)}">${c.readme_file}</a></div>
680 </div> 228 </div>
681 <div class="table"> 229 <div class="readme">
682 <%include file='../tags/tags_data.html'/> 230 <div class="readme_box">
683 %if c.repo_changesets: 231 ${c.readme_data|n}
684 ${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))} 232 </div>
685 %endif
686 </div> 233 </div>
687 </div> 234 </div>
688 <div class="box"> 235 %endif
689 <div class="title"> 236
690 <div class="breadcrumbs">${h.link_to(_('Branches'),h.url('branches_home',repo_name=c.repo_name))}</div> 237 <script type="text/javascript">
691 </div> 238 YUE.onDOMReady(function(e){
692 <div class="table"> 239 id = 'clone_url';
693 <%include file='../branches/branches_data.html'/> 240 YUE.on(id,'click',function(e){
694 %if c.repo_changesets: 241 if(YUD.hasClass(id,'selected')){
695 ${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))} 242 return
696 %endif 243 }
697 </div> 244 else{
698 </div> 245 YUD.addClass(id,'selected');
246 YUD.get(id).select();
247 }
248
249 })
250 })
251 var data = ${c.trending_languages|n};
252 var total = 0;
253 var no_data = true;
254 for (k in data){
255 total += data[k].count;
256 no_data = false;
257 }
258 var tbl = document.createElement('table');
259 tbl.setAttribute('class','trending_language_tbl');
260 var cnt = 0;
261 for (k in data){
262 cnt += 1;
263 var hide = cnt>2;
264 var tr = document.createElement('tr');
265 if (hide){
266 tr.setAttribute('style','display:none');
267 tr.setAttribute('class','stats_hidden');
268 }
269 var percentage = Math.round((data[k].count/total*100),2);
270 var value = data[k].count;
271 var td1 = document.createElement('td');
272 td1.width = 150;
273 var trending_language_label = document.createElement('div');
274 trending_language_label.innerHTML = data[k].desc+" ("+k+")";
275 td1.appendChild(trending_language_label);
276
277 var td2 = document.createElement('td');
278 td2.setAttribute('style','padding-right:14px !important');
279 var trending_language = document.createElement('div');
280 var nr_files = value+" ${_('files')}";
281
282 trending_language.title = k+" "+nr_files;
283
284 if (percentage>22){
285 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
286 }
287 else{
288 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
289 }
290
291 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
292 trending_language.style.width=percentage+"%";
293 td2.appendChild(trending_language);
294
295 tr.appendChild(td1);
296 tr.appendChild(td2);
297 tbl.appendChild(tr);
298 if(cnt == 3){
299 var show_more = document.createElement('tr');
300 var td = document.createElement('td');
301 lnk = document.createElement('a');
302
303 lnk.href='#';
304 lnk.innerHTML = "${_('show more')}";
305 lnk.id='code_stats_show_more';
306 td.appendChild(lnk);
307
308 show_more.appendChild(td);
309 show_more.appendChild(document.createElement('td'));
310 tbl.appendChild(show_more);
311 }
312
313 }
314 if(no_data){
315 var tr = document.createElement('tr');
316 var td1 = document.createElement('td');
317 td1.innerHTML = "${c.no_data_msg}";
318 tr.appendChild(td1);
319 tbl.appendChild(tr);
320 }
321 YUD.get('lang_stats').appendChild(tbl);
322 YUE.on('code_stats_show_more','click',function(){
323 l = YUD.getElementsByClassName('stats_hidden')
324 for (e in l){
325 YUD.setStyle(l[e],'display','');
326 };
327 YUD.setStyle(YUD.get('code_stats_show_more'),
328 'display','none');
329 })
330
331 var tmpl_links = {}
332 %for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
333 tmpl_links['${archive['type']}'] = '${h.link_to(archive['type'],
334 h.url('files_archive_home',repo_name=c.dbrepo.repo_name,
335 fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_="archive_icon")}';
336 %endfor
337
338 YUE.on(['download_options','archive_subrepos'],'change',function(e){
339 var sm = YUD.get('download_options');
340 var new_cs = sm.options[sm.selectedIndex];
341
342 for(k in tmpl_links){
343 var s = YUD.get(k+'_link');
344 title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
345 s.title = title_tmpl.replace('__CS_NAME__',new_cs.text);
346 s.title = s.title.replace('__CS_EXT__',k);
347 var url = tmpl_links[k].replace('__CS__',new_cs.value);
348 var subrepos = YUD.get('archive_subrepos').checked
349 url = url.replace('__SUB__',subrepos);
350 s.innerHTML = url
351 }
352 });
353 </script>
354 <script type="text/javascript">
355 /**
356 * Plots summary graph
357 *
358 * @class SummaryPlot
359 * @param {from} initial from for detailed graph
360 * @param {to} initial to for detailed graph
361 * @param {dataset}
362 * @param {overview_dataset}
363 */
364 function SummaryPlot(from,to,dataset,overview_dataset) {
365 var initial_ranges = {
366 "xaxis":{
367 "from":from,
368 "to":to,
369 },
370 };
371 var dataset = dataset;
372 var overview_dataset = [overview_dataset];
373 var choiceContainer = YUD.get("legend_choices");
374 var choiceContainerTable = YUD.get("legend_choices_tables");
375 var plotContainer = YUD.get('commit_history');
376 var overviewContainer = YUD.get('overview');
377
378 var plot_options = {
379 bars: {show:true,align:'center',lineWidth:4},
380 legend: {show:true, container:"legend_container"},
381 points: {show:true,radius:0,fill:false},
382 yaxis: {tickDecimals:0,},
383 xaxis: {
384 mode: "time",
385 timeformat: "%d/%m",
386 min:from,
387 max:to,
388 },
389 grid: {
390 hoverable: true,
391 clickable: true,
392 autoHighlight:true,
393 color: "#999"
394 },
395 //selection: {mode: "x"}
396 };
397 var overview_options = {
398 legend:{show:false},
399 bars: {show:true,barWidth: 2,},
400 shadowSize: 0,
401 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
402 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
403 grid: {color: "#999",},
404 selection: {mode: "x"}
405 };
406
407 /**
408 *get dummy data needed in few places
409 */
410 function getDummyData(label){
411 return {"label":label,
412 "data":[{"time":0,
413 "commits":0,
414 "added":0,
415 "changed":0,
416 "removed":0,
417 }],
418 "schema":["commits"],
419 "color":'#ffffff',
420 }
421 }
422
423 /**
424 * generate checkboxes accordindly to data
425 * @param keys
426 * @returns
427 */
428 function generateCheckboxes(data) {
429 //append checkboxes
430 var i = 0;
431 choiceContainerTable.innerHTML = '';
432 for(var pos in data) {
433
434 data[pos].color = i;
435 i++;
436 if(data[pos].label != ''){
437 choiceContainerTable.innerHTML += '<tr><td>'+
438 '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
439 +data[pos].label+
440 '</td></tr>';
441 }
442 }
443 }
444
445 /**
446 * ToolTip show
447 */
448 function showTooltip(x, y, contents) {
449 var div=document.getElementById('tooltip');
450 if(!div) {
451 div = document.createElement('div');
452 div.id="tooltip";
453 div.style.position="absolute";
454 div.style.border='1px solid #fdd';
455 div.style.padding='2px';
456 div.style.backgroundColor='#fee';
457 document.body.appendChild(div);
458 }
459 YUD.setStyle(div, 'opacity', 0);
460 div.innerHTML = contents;
461 div.style.top=(y + 5) + "px";
462 div.style.left=(x + 5) + "px";
463
464 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
465 anim.animate();
466 }
467
468 /**
469 * This function will detect if selected period has some changesets
470 for this user if it does this data is then pushed for displaying
471 Additionally it will only display users that are selected by the checkbox
472 */
473 function getDataAccordingToRanges(ranges) {
474
475 var data = [];
476 var new_dataset = {};
477 var keys = [];
478 var max_commits = 0;
479 for(var key in dataset){
480
481 for(var ds in dataset[key].data){
482 commit_data = dataset[key].data[ds];
483 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
484
485 if(new_dataset[key] === undefined){
486 new_dataset[key] = {data:[],schema:["commits"],label:key};
487 }
488 new_dataset[key].data.push(commit_data);
489 }
490 }
491 if (new_dataset[key] !== undefined){
492 data.push(new_dataset[key]);
493 }
494 }
495
496 if (data.length > 0){
497 return data;
498 }
499 else{
500 //just return dummy data for graph to plot itself
501 return [getDummyData('')];
502 }
503 }
504
505 /**
506 * redraw using new checkbox data
507 */
508 function plotchoiced(e,args){
509 var cur_data = args[0];
510 var cur_ranges = args[1];
511
512 var new_data = [];
513 var inputs = choiceContainer.getElementsByTagName("input");
514
515 //show only checked labels
516 for(var i=0; i<inputs.length; i++) {
517 var checkbox_key = inputs[i].name;
518
519 if(inputs[i].checked){
520 for(var d in cur_data){
521 if(cur_data[d].label == checkbox_key){
522 new_data.push(cur_data[d]);
523 }
524 }
525 }
526 else{
527 //push dummy data to not hide the label
528 new_data.push(getDummyData(checkbox_key));
529 }
530 }
531
532 var new_options = YAHOO.lang.merge(plot_options, {
533 xaxis: {
534 min: cur_ranges.xaxis.from,
535 max: cur_ranges.xaxis.to,
536 mode:"time",
537 timeformat: "%d/%m",
538 },
539 });
540 if (!new_data){
541 new_data = [[0,1]];
542 }
543 // do the zooming
544 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
545
546 plot.subscribe("plotselected", plotselected);
547
548 //resubscribe plothover
549 plot.subscribe("plothover", plothover);
550
551 // don't fire event on the overview to prevent eternal loop
552 overview.setSelection(cur_ranges, true);
553
554 }
555
556 /**
557 * plot only selected items from overview
558 * @param ranges
559 * @returns
560 */
561 function plotselected(ranges,cur_data) {
562 //updates the data for new plot
563 var data = getDataAccordingToRanges(ranges);
564 generateCheckboxes(data);
565
566 var new_options = YAHOO.lang.merge(plot_options, {
567 xaxis: {
568 min: ranges.xaxis.from,
569 max: ranges.xaxis.to,
570 mode:"time",
571 timeformat: "%d/%m",
572 },
573 });
574 // do the zooming
575 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
576
577 plot.subscribe("plotselected", plotselected);
578
579 //resubscribe plothover
580 plot.subscribe("plothover", plothover);
581
582 // don't fire event on the overview to prevent eternal loop
583 overview.setSelection(ranges, true);
584
585 //resubscribe choiced
586 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
587 }
588
589 var previousPoint = null;
590
591 function plothover(o) {
592 var pos = o.pos;
593 var item = o.item;
594
595 //YUD.get("x").innerHTML = pos.x.toFixed(2);
596 //YUD.get("y").innerHTML = pos.y.toFixed(2);
597 if (item) {
598 if (previousPoint != item.datapoint) {
599 previousPoint = item.datapoint;
600
601 var tooltip = YUD.get("tooltip");
602 if(tooltip) {
603 tooltip.parentNode.removeChild(tooltip);
604 }
605 var x = item.datapoint.x.toFixed(2);
606 var y = item.datapoint.y.toFixed(2);
607
608 if (!item.series.label){
609 item.series.label = 'commits';
610 }
611 var d = new Date(x*1000);
612 var fd = d.toDateString()
613 var nr_commits = parseInt(y);
614
615 var cur_data = dataset[item.series.label].data[item.dataIndex];
616 var added = cur_data.added;
617 var changed = cur_data.changed;
618 var removed = cur_data.removed;
619
620 var nr_commits_suffix = " ${_('commits')} ";
621 var added_suffix = " ${_('files added')} ";
622 var changed_suffix = " ${_('files changed')} ";
623 var removed_suffix = " ${_('files removed')} ";
624
625
626 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
627 if(added==1){added_suffix=" ${_('file added')} ";}
628 if(changed==1){changed_suffix=" ${_('file changed')} ";}
629 if(removed==1){removed_suffix=" ${_('file removed')} ";}
630
631 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
632 +'<br/>'+
633 nr_commits + nr_commits_suffix+'<br/>'+
634 added + added_suffix +'<br/>'+
635 changed + changed_suffix + '<br/>'+
636 removed + removed_suffix + '<br/>');
637 }
638 }
639 else {
640 var tooltip = YUD.get("tooltip");
641
642 if(tooltip) {
643 tooltip.parentNode.removeChild(tooltip);
644 }
645 previousPoint = null;
646 }
647 }
648
649 /**
650 * MAIN EXECUTION
651 */
652
653 var data = getDataAccordingToRanges(initial_ranges);
654 generateCheckboxes(data);
655
656 //main plot
657 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
658
659 //overview
660 var overview = YAHOO.widget.Flot(overviewContainer,
661 overview_dataset, overview_options);
662
663 //show initial selection on overview
664 overview.setSelection(initial_ranges);
665
666 plot.subscribe("plotselected", plotselected);
667 plot.subscribe("plothover", plothover)
668
669 overview.subscribe("plotselected", function (ranges) {
670 plot.setSelection(ranges);
671 });
672
673 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
674 }
675 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
676 </script>
699 677
700 </%def> 678 </%def>