Changeset - 6a506a7acd1a
[Not reviewed]
default
0 2 0
Marcin Kuzminski - 15 years ago 2010-08-06 00:15:06
marcin@python-works.com
some small changes to commit activity graph
2 files changed with 2 insertions and 2 deletions:
0 comments (0 inline, 0 general)
pylons_app/controllers/summary.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# summary controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
# 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 18, 2010
 
summary controller for pylons
 
@author: marcink
 
"""
 
from datetime import datetime, timedelta
 
from pylons import tmpl_context as c, request
 
from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.helpers import person
 
from pylons_app.lib.utils import OrderedDict
 
from pylons_app.model.hg_model import HgModel
 
from time import mktime
 
from webhelpers.paginate import Page
 
import calendar
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class SummaryController(BaseController):
 
    
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')           
 
    def __before__(self):
 
        super(SummaryController, self).__before__()
 
                
 
    def index(self):
 
        hg_model = HgModel()
 
        c.repo_info = hg_model.get_repo(c.repo_name)
 
        c.repo_changesets = Page(list(c.repo_info[:10]), page=1, items_per_page=20)
 
        e = request.environ
 
        uri = u'%(protocol)s://%(user)s@%(host)s/%(repo_name)s' % {
 
                                        'protocol': e.get('wsgi.url_scheme'),
 
                                        'user':str(c.hg_app_user.username),
 
                                        'host':e.get('HTTP_HOST'),
 
                                        'repo_name':c.repo_name, }
 
        c.clone_repo_url = uri
 
        c.repo_tags = OrderedDict()
 
        for name, hash in c.repo_info.tags.items()[:10]:
 
            c.repo_tags[name] = c.repo_info.get_changeset(hash)
 
        
 
        c.repo_branches = OrderedDict()
 
        for name, hash in c.repo_info.branches.items()[:10]:
 
            c.repo_branches[name] = c.repo_info.get_changeset(hash)
 

	
 
        c.commit_data = self.__get_commit_stats(c.repo_info)
 
        
 
        return render('summary/summary.html')
 

	
 

	
 

	
 
    def __get_commit_stats(self, repo):
 
        aggregate = OrderedDict()
 
        
 
        #graph range
 
        td = datetime.today() 
 
        td = datetime.today() + timedelta(days=1) 
 
        y = td.year
 
        m = td.month
 
        d = td.day
 
        c.ts_min = mktime((y, (td - timedelta(days=calendar.mdays[m] - 1)).month, d, 0, 0, 0, 0, 0, 0,))
 
        c.ts_max = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
 

	
 
        
 
        def author_key_cleaner(k):
 
            k = person(k)
 
            return k
 
                
 
        for cs in repo:
 
            k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
 
                              cs.date.timetuple()[2])
 
            timetupple = [int(x) for x in k.split('-')]
 
            timetupple.extend([0 for _ in xrange(6)])
 
            k = mktime(timetupple)
 
            if aggregate.has_key(author_key_cleaner(cs.author)):
 
                if aggregate[author_key_cleaner(cs.author)].has_key(k):
 
                    aggregate[author_key_cleaner(cs.author)][k] += 1
 
                else:
 
                    #aggregate[author_key_cleaner(cs.author)].update(dates_range)
 
                    if k >= c.ts_min and k <= c.ts_max:
 
                        aggregate[author_key_cleaner(cs.author)][k] = 1
 
            else:
 
                if k >= c.ts_min and k <= c.ts_max:
 
                    aggregate[author_key_cleaner(cs.author)] = OrderedDict()
 
                    #aggregate[author_key_cleaner(cs.author)].update(dates_range)
 
                    aggregate[author_key_cleaner(cs.author)][k] = 1
 
        
 
        d = ''
 
        tmpl0 = u""""%s":%s"""
 
        tmpl1 = u"""{label:"%s",data:%s},"""
 
        for author in aggregate:
 
            d += tmpl0 % (author.decode('utf8'),
 
                          tmpl1 \
 
                          % (author.decode('utf8'),
 
                        [[x, aggregate[author][x]] for x in aggregate[author]]))
 
        if d == '':
 
            d = '"%s":{label:"%s",data:[[0,0],]}' \
 
                % (author_key_cleaner(repo.contact),
 
                   author_key_cleaner(repo.contact))
 
        return d
 

	
 

	
pylons_app/templates/summary/summary.html
Show inline comments
 
@@ -69,193 +69,193 @@ E.onDOMReady(function(e){
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Last change')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      ${h.age(c.repo_info.last_change)} - ${h.rfc822date(c.repo_info.last_change)}
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Clone url')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      <input type="text" id="clone_url"  readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Download')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
		        %for cnt,archive in enumerate(c.repo_info._get_archives()):
 
		             %if cnt >=1:
 
		             |
 
		             %endif
 
		             ${h.link_to(c.repo_info.name+'.'+archive['type'],
 
		                h.url('files_archive_home',repo_name=c.repo_info.name,
 
		                revision='tip',fileformat=archive['extension']),class_="archive_icon")}
 
		        %endfor
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Feeds')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
	            ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
 
	            ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
 
			  </div>
 
			 </div>				 			 			 
 
	  </div>		 
 
	</div>				
 
</div>
 
        
 
<div class="box box-right">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Last month commit activity')}</h5>
 
    </div>
 
    
 
    <div class="table">
 
        <div id="commit_history" style="width:460px;height:370px;float:left"></div>
 
    	<div id="legend_data">
 
	    	<div id="legend_container"></div>
 
	    	<div id="legend_choices">
 
				<table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
 
	    	</div>
 
    	</div>
 
		<script type="text/javascript">
 
		
 
		(function () {
 
			var datasets = {${c.commit_data|n}};
 
			var i = 0;
 
		    var choiceContainer = YAHOO.util.Dom.get("legend_choices");
 
		    var choiceContainerTable = YAHOO.util.Dom.get("legend_choices_tables");
 
		    for(var key in datasets) {
 
		        datasets[key].color = i;
 
		        i++;
 
		        choiceContainerTable.innerHTML += '<tr>'+
 
		        									'<td>'+
 
		        									'<input type="checkbox" name="' + key +'" checked="checked" />'+datasets[key].label+
 
		        									'</td>'+
 
		        								  '</tr>';
 
		    };
 
		    
 

	
 
		    function plotAccordingToChoices() {
 
		        var data = [];
 

	
 
		        var inputs = choiceContainer.getElementsByTagName("input");
 
		        for(var i=0; i<inputs.length; i++) {
 
		            if(!inputs[i].checked)
 
		                continue;
 

	
 
		            var key = inputs[i].name;
 
		            if (key && datasets[key])
 
		                data.push(datasets[key]);
 
		        };
 

	
 
		        if (data.length > 0){
 
				    var plot = YAHOO.widget.Flot("commit_history", data,
 
					        { bars: { show: true, align:'center' },
 
					        { bars: { show: true, align:'center',lineWidth:4 },
 
			    			  points: { show: true, radius:0,fill:true },
 
			    			  legend:{show:true, container:"legend_container"},
 
			    	          selection: { mode: "xy" },
 
			    	          yaxis:{tickSize:[1]},
 
				              xaxis: { mode: "time", timeformat: "%d",tickSize:[1, "day"],min:${c.ts_min},max:${c.ts_max} }, 
 
				              grid: { hoverable: true, clickable: true,autoHighlight:true },
 
					        });
 
		        
 
				    function showTooltip(x, y, contents) {
 
				        var div=document.getElementById('tooltip');
 
				        if(!div) {
 
				            div = document.createElement('div');
 
				            div.id="tooltip";
 
				            div.style.position="absolute";
 
				            div.style.border='1px solid #fdd';
 
				            div.style.padding='2px';
 
				            div.style.backgroundColor='#fee';
 
				            document.body.appendChild(div);
 
				        }
 
				        YAHOO.util.Dom.setStyle(div, 'opacity', 0);
 
				        div.innerHTML = contents;
 
				        div.style.top=(y + 5) + "px";
 
				        div.style.left=(x + 5) + "px";
 
		
 
				        var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
 
				        anim.animate();
 
				    }
 

	
 
			        var previousPoint = null;
 
			        plot.subscribe("plothover", function (o) {
 
				        var pos = o.pos;
 
				        var item = o.item;
 
				        
 
				        //YAHOO.util.Dom.get("x").innerHTML = pos.x.toFixed(2);
 
				        //YAHOO.util.Dom.get("y").innerHTML = pos.y.toFixed(2);
 
		                if (item) {
 
		                    if (previousPoint != item.datapoint) {
 
		                        previousPoint = item.datapoint;
 
		                        
 
		                        var tooltip = YAHOO.util.Dom.get("tooltip");
 
		                        if(tooltip) {
 
		                        	  tooltip.parentNode.removeChild(tooltip);
 
		                        }
 
		                        var x = item.datapoint.x.toFixed(2);
 
		                        var y = item.datapoint.y.toFixed(2);
 

	
 
		                        if (!item.series.label){
 
		                            item.series.label = 'commits';
 
			                    }
 
		                        var d = new Date(x*1000);
 
		                        var fd = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
 
		                        var nr_commits = parseInt(y);
 
		                        var suffix = '';
 
		                        if(nr_commits > 1){
 
									var suffix = 's';		
 
				                }
 
		                        showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd + ": " + nr_commits+" commit" + suffix);
 
		                    }
 
		                }
 
		                else {
 
		                	  var tooltip = YAHOO.util.Dom.get("tooltip");
 
		                	  
 
					          if(tooltip) {
 
					                tooltip.parentNode.removeChild(tooltip);
 
					          }
 
		                    previousPoint = null;
 
		                }
 
			        });
 

	
 
			    }
 
		    }
 

	
 
		    YAHOO.util.Event.on(choiceContainer.getElementsByTagName("input"), "click", plotAccordingToChoices);
 

	
 
		    plotAccordingToChoices();
 
		    })();
 
         </script>
 

	
 
    </div>
 
</div>    
 

	
 
<div class="box">    
 
    <div class="title">
 
        <div class="breadcrumbs">${h.link_to(_('Last ten changes'),h.url('changelog_home',repo_name=c.repo_name))}</div>
 
    </div>    
 
    <div class="table">
 
        <%include file='../shortlog/shortlog_data.html'/>
 
    </div>
 
</div>
 
<div class="box">    
 
    <div class="title">
 
        <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
 
    </div>    
 
    <div class="table">
 
        <%include file='../tags/tags_data.html'/>
 
    </div>
0 comments (0 inline, 0 general)