changeset 486:5c376ac2d4c9 celery

rewrote graph plotting, added zooming and json dump insted of stupid string formating.
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 18 Sep 2010 17:03:29 +0200
parents 9836541b0509
children b12ea84fb906
files pylons_app/controllers/summary.py pylons_app/lib/celerylib/tasks.py pylons_app/templates/summary/summary.html setup.py
diffstat 4 files changed, 119 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/pylons_app/controllers/summary.py	Sat Sep 18 00:50:54 2010 +0200
+++ b/pylons_app/controllers/summary.py	Sat Sep 18 17:03:29 2010 +0200
@@ -22,7 +22,7 @@
 summary controller for pylons
 @author: marcink
 """
-from pylons import tmpl_context as c, request,url
+from pylons import tmpl_context as c, request, url
 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 from pylons_app.lib.base import BaseController, render
 from pylons_app.lib.utils import OrderedDict
@@ -61,10 +61,11 @@
         for name, hash in c.repo_info.branches.items()[:10]:
             c.repo_branches[name] = c.repo_info.get_changeset(hash)
         
-        task = run_task(get_commits_stats,c.repo_info.name)
+        task = run_task(get_commits_stats, c.repo_info.name)
         c.ts_min = task.result[0]
         c.ts_max = task.result[1]
         c.commit_data = task.result[2]
+        c.overview_data = task.result[3]
         
         return render('summary/summary.html')
 
--- a/pylons_app/lib/celerylib/tasks.py	Sat Sep 18 00:50:54 2010 +0200
+++ b/pylons_app/lib/celerylib/tasks.py	Sat Sep 18 17:03:29 2010 +0200
@@ -11,6 +11,7 @@
 from vcs.backends.hg import MercurialRepository
 import calendar
 import traceback
+import json
 
 __all__ = ['whoosh_index', 'get_commits_stats',
            'reset_user_password', 'send_email']
@@ -84,21 +85,26 @@
 def get_commits_stats(repo):
     log = get_commits_stats.get_logger()
     aggregate = OrderedDict()
+    overview_aggregate = OrderedDict()
     repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
     repo = MercurialRepository(repos_path + repo)
     #graph range
     td = datetime.today() + timedelta(days=1) 
     y, m, d = td.year, td.month, td.day
-    ts_min = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
+    
+    ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
                         d, 0, 0, 0, 0, 0, 0,))
-    ts_max = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
+    ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
+                        d, 0, 0, 0, 0, 0, 0,))
     
+    ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
+
     def author_key_cleaner(k):
         k = person(k)
-        k = k.replace('"', "'") #for js data compatibilty
+        k = k.replace('"', "") #for js data compatibilty
         return k
             
-    for cs in repo[:200]:#added limit 200 until fix #29 is made
+    for cs in repo[:1000]:#added limit 200 until fix #29 is made
         k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
                           cs.date.timetuple()[2])
         timetupple = [int(x) for x in k.split('-')]
@@ -113,7 +119,7 @@
                 
             else:
                 #aggregate[author_key_cleaner(cs.author)].update(dates_range)
-                if k >= ts_min and k <= ts_max:
+                if k >= ts_min_y and k <= ts_max_y:
                     aggregate[author_key_cleaner(cs.author)][k] = {}
                     aggregate[author_key_cleaner(cs.author)][k]["commits"] = 1
                     aggregate[author_key_cleaner(cs.author)][k]["added"] = len(cs.added)
@@ -121,7 +127,7 @@
                     aggregate[author_key_cleaner(cs.author)][k]["removed"] = len(cs.removed) 
                                         
         else:
-            if k >= ts_min and k <= ts_max:
+            if k >= ts_min_y and k <= ts_max_y:
                 aggregate[author_key_cleaner(cs.author)] = OrderedDict()
                 #aggregate[author_key_cleaner(cs.author)].update(dates_range)
                 aggregate[author_key_cleaner(cs.author)][k] = {}
@@ -130,25 +136,35 @@
                 aggregate[author_key_cleaner(cs.author)][k]["changed"] = len(cs.changed)
                 aggregate[author_key_cleaner(cs.author)][k]["removed"] = len(cs.removed)                 
     
-    d = ''
-    tmpl0 = u""""%s":%s"""
-    tmpl1 = u"""{label:"%s",data:%s,schema:["commits"]},"""
-    for author in aggregate:
         
-        d += tmpl0 % (author,
-                      tmpl1 \
-                      % (author,
-                    [{"time":x,
-                      "commits":aggregate[author][x]['commits'],
-                      "added":aggregate[author][x]['added'],
-                      "changed":aggregate[author][x]['changed'],
-                      "removed":aggregate[author][x]['removed'],
-                      } for x in aggregate[author]]))
-    if d == '':
-        d = '"%s":{label:"%s",data:[[0,1],]}' \
-            % (author_key_cleaner(repo.contact),
-               author_key_cleaner(repo.contact))
-    return (ts_min, ts_max, d)    
+        if overview_aggregate.has_key(k):
+            overview_aggregate[k] += 1
+        else:
+            overview_aggregate[k] = 1
+    
+    overview_data = []
+    for k, v in overview_aggregate.items():
+        overview_data.append([k, v])
+    data = {}
+    for author in aggregate:
+        data[author] = {"label":author,
+                      "data":[{"time":x,
+                               "commits":aggregate[author][x]['commits'],
+                               "added":aggregate[author][x]['added'],
+                               "changed":aggregate[author][x]['changed'],
+                               "removed":aggregate[author][x]['removed'],
+                              } for x in aggregate[author]],
+                      "schema":["commits"]
+                      }
+        
+    if not data:
+        data[author_key_cleaner(repo.contact)] = {
+            "label":author_key_cleaner(repo.contact),
+            "data":[0, 1],
+            "schema":["commits"],
+        }
+                
+    return (ts_min_m, ts_max_y, json.dumps(data), json.dumps(overview_data))    
 
 @task
 def reset_user_password(user_email):
@@ -157,7 +173,6 @@
     from pylons_app.model.db import User
     
     try:
-        
         try:
             sa = get_session()
             user = sa.query(User).filter(User.email == user_email).scalar()
--- a/pylons_app/templates/summary/summary.html	Sat Sep 18 00:50:54 2010 +0200
+++ b/pylons_app/templates/summary/summary.html	Sat Sep 18 17:03:29 2010 +0200
@@ -126,7 +126,10 @@
     
     <div class="table">
         <div id="commit_history" style="width:560px;height:300px;float:left"></div>
-    	<div id="legend_data" style="clear:both;margin-top:10px">
+        <div style="clear: both;height: 10px"></div>
+        <div id="overview" style="width:560px;height:100px;float:left"></div>
+        
+    	<div id="legend_data" style="clear:both;margin-top:10px;">
 	    	<div id="legend_container"></div>
 	    	<div id="legend_choices">
 				<table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
@@ -135,7 +138,9 @@
 		<script type="text/javascript">
 		
 		(function () {
-			var datasets = {${c.commit_data|n}};
+			var datasets = ${c.commit_data|n};
+			var overview_data = ${c.overview_data|n};
+						
 			var i = 0;
 		    var choiceContainer = YAHOO.util.Dom.get("legend_choices");
 		    var choiceContainerTable = YAHOO.util.Dom.get("legend_choices_tables");
@@ -147,8 +152,7 @@
 		        +datasets[key].label+
 		        '</td></tr>';
 		    };
-		    
-
+			
 		    function plotAccordingToChoices() {
 		        var data = [];
 
@@ -162,23 +166,50 @@
 			            else{
 			            	data.push(datasets[key]);
 			            }
-		                
 		            }
-		            
 		        };
 
 		        if (data.length > 0){
+		            var options = { 
+				            bars: {show:true,align:'center',lineWidth:4},
+				            legend: {show:true, container:"legend_container"},
+			    			points: {show:true,radius:0,fill:false},
+			    	        yaxis: {tickDecimals:0,},
+				            xaxis: {mode: "time", 
+					            	timeformat: "%d/%m",
+					            	min:${c.ts_min},
+					            	max:${c.ts_max},
+					            	
+					        }, 
+				            grid: {hoverable: true, 
+					               clickable: true,
+					               autoHighlight:true,
+					               color: "#999"},
+				            selection: {mode: "x"}
+					};
 
-				    var plot = YAHOO.widget.Flot("commit_history", data,
-					        { bars: { show: true, align:'center',lineWidth:4 },
-			    			  points: { show: true, radius:0,fill:true },
-			    			  legend:{show:true, container:"legend_container"},
-			    	          selection: { mode: "xy" },
-			    	          yaxis: {tickDecimals:0},
-				              xaxis: { mode: "time", timeformat: "%d",tickSize:[1, "day"],min:${c.ts_min},max:${c.ts_max} }, 
-				              grid: { hoverable: true, clickable: true,autoHighlight:true },
-					        });
-			        
+					//main plot
+				    var plot = YAHOO.widget.Flot("commit_history",data,options);
+
+					//overview
+				    var overview = YAHOO.widget.Flot("overview", [overview_data], {
+				    	legend:{show:false},
+				        bars: {show:true,
+					           barWidth: 2,
+					    },
+				        shadowSize: 0,
+			            xaxis: {mode: "time", 
+			            		timeformat: "%d/%m/%y",
+			            },
+				        yaxis: {ticks: 3, min: 0,},
+				        grid: {color: "#999",},
+				        selection: {mode: "x"}
+				    });
+
+					var ranges = {"xaxis":{"from":${c.ts_min},
+										   "to":${c.ts_max},},}
+					overview.setSelection(ranges);
+					
 				    function showTooltip(x, y, contents) {
 				        var div=document.getElementById('tooltip');
 				        if(!div) {
@@ -198,9 +229,10 @@
 				        var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
 				        anim.animate();
 				    }
-
+				    
 			        var previousPoint = null;
-			        plot.subscribe("plothover", function (o) {
+
+					function plothover(o) {
 				        var pos = o.pos;
 				        var item = o.item;
 				        
@@ -221,7 +253,7 @@
 		                            item.series.label = 'commits';
 			                    }
 		                        var d = new Date(x*1000);
-		                        var fd = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
+		                        var fd = d.toDateString()
 		                        var nr_commits = parseInt(y);
 		                        
 		                        var cur_data = datasets[item.series.label].data[item.dataIndex];
@@ -256,8 +288,31 @@
 					          }
 		                    previousPoint = null;
 		                }
-			        });
+			        }
+			        
+			        plot.subscribe("plothover", plothover);
+			        
+				    function plotselected(ranges) {
+				        // do the zooming
+				        plot = YAHOO.widget.Flot("commit_history", data,
+				                      YAHOO.lang.merge(options, {
+				                          xaxis: { min: ranges.xaxis.from, 
+				                          		   max: ranges.xaxis.to,
+				                          		   mode:"time",
+				                          		   timeformat: "%d/%m",
+				                          		 }
+				                      }));
+				        plot.subscribe("plotselected", plotselected);
+				        plot.subscribe("plothover", plothover);
 
+				        // don't fire event on the overview to prevent eternal loop
+				        overview.setSelection(ranges, true);
+				    }
+				    plot.subscribe("plotselected", plotselected);
+				    
+				    overview.subscribe("plotselected", function (ranges) {
+				        plot.setSelection(ranges);
+				    });
 			    }
 		    }
 
--- a/setup.py	Sat Sep 18 00:50:54 2010 +0200
+++ b/setup.py	Sat Sep 18 17:03:29 2010 +0200
@@ -24,7 +24,7 @@
         "pygments>=1.3.0",
         "mercurial>=1.6",
         "pysqlite",
-        "whoosh==1.0.0b16",
+        "whoosh==1.0.0b17",
         "py-bcrypt",
         "celery",
     ],