Mercurial > kallithea
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> |