← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 17016: ER sorting option implemented.

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 17016 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-10-09 09:59:54 +0200
message:
  ER sorting option implemented.
modified:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-10-08 22:37:32 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-10-09 07:58:13 +0000
@@ -516,7 +516,9 @@
 
         // eventreport col/row subtotals
         executeSql( "update eventreport set colsubtotals = subtotals where colsubtotals is null" );
-        executeSql( "update eventreport set rowsubtotals = subtotals where rowsubtotals is null" );
+        executeSql( "update eventreport set rowsubtotals = subtotals where rowsubtotals is null" );        
+
+        executeSql( "update eventchart set sortorder = 0 where sortorder is null" );
 
         // Move chart filters to chart_filters table
 

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml	2014-07-09 15:43:12 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml	2014-10-09 07:58:13 +0000
@@ -148,6 +148,8 @@
 
     <property name="baseLineLabel" />
 
+    <property name="sortOrder" />
+
     <!-- Access properties -->
     <property name="externalAccess" />
 

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js	2014-10-07 10:55:39 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js	2014-10-09 07:58:13 +0000
@@ -1363,9 +1363,10 @@
 			targetLineTitle,
 			baseLineValue,
 			baseLineTitle,
+            sortOrder,
 
+            rangeAxisMinValue,
             rangeAxisMaxValue,
-            rangeAxisMinValue,
             rangeAxisSteps,
             rangeAxisDecimals,
 			rangeAxisTitle,
@@ -1380,13 +1381,28 @@
 			general,
 			window,
 
+            comboBottomMargin = 1,
+            checkboxBottomMargin = 2,
+            separatorTopMargin = 6,
 			cmpWidth = 340,
 			labelWidth = 125,
 			numberWidth = 80;
 
+        // data
+		showValues = Ext.create('Ext.form.field.Checkbox', {
+			boxLabel: NS.i18n.show_values,
+			style: 'margin-bottom:' + checkboxBottomMargin + 'px',
+			checked: true
+		});
+
+		hideEmptyRows = Ext.create('Ext.form.field.Checkbox', {
+			boxLabel: NS.i18n.hide_empty_category_items,
+			style: 'margin-bottom:' + checkboxBottomMargin + 'px'
+		});
+
 		showTrendLine = Ext.create('Ext.form.field.Checkbox', {
 			boxLabel: NS.i18n.trend_line,
-			style: 'margin-bottom:6px'
+			style: 'margin-bottom:' + checkboxBottomMargin + 'px'
 		});
 
 		targetLineValue = Ext.create('Ext.form.field.Number', {
@@ -1424,7 +1440,6 @@
 		});
 
 		baseLineTitle = Ext.create('Ext.form.field.Text', {
-			//cls: 'ns-textfield-alt1',
 			style: 'margin-left:1px; margin-bottom:1px',
 			fieldStyle: 'padding-left:3px',
 			emptyText: NS.i18n.base,
@@ -1437,9 +1452,32 @@
 			}
 		});
 
-		hideEmptyRows = Ext.create('Ext.form.field.Checkbox', {
-			boxLabel: NS.i18n.hide_empty_category_items,
-			style: 'margin-bottom:4px'
+		sortOrder = Ext.create('Ext.form.field.ComboBox', {
+			cls: 'ns-combo',
+			style: 'margin-bottom:' + comboBottomMargin + 'px',
+			width: cmpWidth,
+			labelWidth: 125,
+			fieldLabel: NS.i18n.sort_order,
+			labelStyle: 'color:#333',
+			queryMode: 'local',
+			valueField: 'id',
+			editable: false,
+			value: 0,
+			store: Ext.create('Ext.data.Store', {
+				fields: ['id', 'text'],
+				data: [
+					{id: 0, text: NS.i18n.none},
+					{id: -1, text: NS.i18n.low_to_high},
+					{id: 1, text: NS.i18n.high_to_low}
+				]
+			})
+		});
+
+        // axes
+		rangeAxisMinValue = Ext.create('Ext.form.field.Number', {
+			width: numberWidth,
+			height: 18,
+			labelWidth: 125
 		});
 
 		rangeAxisMaxValue = Ext.create('Ext.form.field.Number', {
@@ -1449,16 +1487,11 @@
             style: 'margin-left:1px'
 		});
 
-		rangeAxisMinValue = Ext.create('Ext.form.field.Number', {
-			width: numberWidth,
-			height: 18,
-			labelWidth: 125
-		});
-
 		rangeAxisSteps = Ext.create('Ext.form.field.Number', {
 			width: labelWidth + 5 + numberWidth,
 			height: 18,
 			fieldLabel: 'Range axis tick steps',
+			labelStyle: 'color:#333',
 			labelWidth: 125,
 			minValue: 1
 		});
@@ -1467,19 +1500,15 @@
 			width: labelWidth + 5 + numberWidth,
 			height: 18,
 			fieldLabel: 'Range axis decimals',
+			labelStyle: 'color:#333',
 			labelWidth: 125,
 			minValue: 0
 		});
 
-		showValues = Ext.create('Ext.form.field.Checkbox', {
-			boxLabel: NS.i18n.show_values,
-			style: 'margin-bottom:4px',
-			checked: true
-		});
-
+        // general
 		hideLegend = Ext.create('Ext.form.field.Checkbox', {
 			boxLabel: NS.i18n.hide_legend,
-			style: 'margin-bottom:4px'
+			style: 'margin-bottom:' + checkboxBottomMargin + 'px'
 		});
 
 		hideTitle = Ext.create('Ext.form.field.Checkbox', {
@@ -1493,7 +1522,7 @@
 		});
 
 		title = Ext.create('Ext.form.field.Text', {
-			style: 'margin-bottom:2px',
+			style: 'margin-bottom:0',
 			width: cmpWidth,
 			fieldLabel: NS.i18n.chart_title,
 			labelStyle: 'color:#333',
@@ -1537,6 +1566,7 @@
 					xtype: 'container',
 					layout: 'column',
 					bodyStyle: 'border:0 none',
+                    style: 'margin-top:' + (separatorTopMargin + 1) + 'px',
 					items: [
 						{
 							bodyStyle: 'border:0 none; padding-top:3px; margin-right:5px; color:#333',
@@ -1560,7 +1590,8 @@
 						baseLineValue,
 						baseLineTitle
 					]
-				}
+				},
+                sortOrder
 			]
 		};
 
@@ -1600,7 +1631,7 @@
 
 		window = Ext.create('Ext.window.Window', {
 			title: NS.i18n.chart_options,
-			bodyStyle: 'background-color:#fff; padding:5px 5px 3px',
+			bodyStyle: 'background-color:#fff; padding:3px',
 			closeAction: 'hide',
 			autoShow: true,
 			modal: true,
@@ -1615,6 +1646,7 @@
 					targetLineTitle: targetLineTitle.getValue(),
 					baseLineValue: baseLineValue.getValue(),
 					baseLineTitle: baseLineTitle.getValue(),
+                    sortOrder: sortOrder.getValue(),
 					rangeAxisMaxValue: rangeAxisMaxValue.getValue(),
 					rangeAxisMinValue: rangeAxisMinValue.getValue(),
 					rangeAxisSteps: rangeAxisSteps.getValue(),
@@ -1661,6 +1693,8 @@
 					baseLineTitle.reset();
 				}
 
+                sortOrder.setValue(Ext.isNumber(layout.sortOrder) ? layout.sortOrder : 0);
+
 				// rangeAxisMaxValue
 				if (Ext.isNumber(layout.rangeAxisMaxValue)) {
 					rangeAxisMaxValue.setValue(layout.rangeAxisMaxValue);
@@ -1757,7 +1791,7 @@
 				{
 					text: '<b>' + NS.i18n.update + '</b>',
 					handler: function() {
-                        ns.app.viewport.update();                        
+                        ns.app.viewport.update();
 
 						window.hide();
 					}
@@ -1781,6 +1815,7 @@
 					w.targetLineTitle = targetLineTitle;
 					w.baseLineValue = baseLineValue;
 					w.baseLineTitle = baseLineTitle;
+                    w.sortOrder = sortOrder;
 
 					w.rangeAxisMaxValue = rangeAxisMaxValue;
 					w.rangeAxisMinValue = rangeAxisMinValue;

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js	2014-10-03 11:45:22 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js	2014-10-09 07:58:13 +0000
@@ -3,6 +3,13 @@
 	// ext config
 	Ext.Ajax.method = 'GET';
 
+    // override
+    Ext.override(Ext.chart.series.Line, {
+        drawSeries: function() {
+            var ak=this,au=ak.chart,S=au.axes,ao=au.getChartStore(),V=ao.getCount(),u=ak.chart.surface,am={},R=ak.group,K=ak.showMarkers,aA=ak.markerGroup,D=au.shadow,C=ak.shadowGroups,X=ak.shadowAttributes,O=ak.smooth,q=C.length,ar=["M"],T=["M"],d=["M"],b=["M"],J=au.markerIndex,ai=[].concat(ak.axis),ah,av=[],ag={},aa=[],v={},I=false,Q=[],az=ak.markerStyle,Z=ak.style,t=ak.colorArrayStyle,P=t&&t.length||0,L=Ext.isNumber,aw=ak.seriesIdx,g=ak.getAxesForXAndYFields(),l=g.xAxis,ay=g.yAxis,ac,h,ab,ad,A,c,ae,H,G,f,e,s,r,W,N,M,at,m,F,E,aB,n,p,B,a,Y,af,z,aq,w,ap,o,ax,an,al,U,k,aj;if(ak.fireEvent("beforedraw",ak)===false){return}if(!V||ak.seriesIsHidden){aj=this.items;if(aj){for(N=0,at=aj.length;N<at;++N){if(aj[N].sprite){aj[N].sprite.hide(true)}}}return}an=Ext.apply(az||{},ak.markerConfig);U=an.type;delete an.type;al=Z;if(!al["stroke-width"]){al["stroke-width"]=0.5}if(J&&aA&&aA.getCount()){for(N=0;N<J;N++){E=aA.getAt(N);aA.remove(E);aA.add(E);aB=aA.getAt(aA.getCount()-2);E.setAttributes({x:0,y:0,translate:{x:aB.attr.translation.x,y:aB.attr.translation.y}},true)}}ak.unHighlightItem();ak.cleanHighlights();ak.setBBox();am=ak.bbox;ak.clipRect=[am.x,am.y,am.width,am.height];for(N=0,at=ai.length;N<at;N++){m=S.get(ai[N]);if(m){F=m.calcEnds();if(m.position=="top"||m.position=="bottom"){z=F.from;aq=F.to}else{w=F.from;ap=F.to}}}if(ak.xField&&!L(z)&&(l=="bottom"||l=="top")&&!S.get(l)){m=Ext.create("Ext.chart.axis.Axis",{chart:au,fields:[].concat(ak.xField)}).calcEnds();z=m.from;aq=m.to}if(ak.yField&&!L(w)&&(ay=="right"||ay=="left")&&!S.get(ay)){m=Ext.create("Ext.chart.axis.Axis",{chart:au,fields:[].concat(ak.yField)}).calcEnds();w=m.from;ap=m.to}if(isNaN(z)){z=0;Y=am.width/((V-1)||1)}else{Y=am.width/((aq-z)||(V-1)||1)}if(isNaN(w)){w=0;af=am.height/((V-1)||1)}else{af=am.height/((ap-w)||(V-1)||1)}ak.eachRecord(function(j,x){p=j.get(ak.xField);if(typeof p=="string"||typeof p=="object"&&!Ext.isDate(p)||l&&S.get(l)&&S.get(l).type=="Category"){if(p in ag){p=ag[p]}else{p=ag[p]=x}}B=j.get(ak.yField);if(typeof B=="undefined"||(typeof B=="string"&&!B)){if(Ext.isDefined(Ext.global.console)){Ext.global.console.warn("[Ext.chart.series.Line]  Skipping a store element with an undefined value at ",j,p,B)}return}if(typeof B=="object"&&!Ext.isDate(B)||ay&&S.get(ay)&&S.get(ay).type=="Category"){B=x}Q.push(x);av.push(p);aa.push(B)});at=av.length;if(at>am.width){a=ak.shrink(av,aa,am.width);av=a.x;aa=a.y}ak.items=[];k=0;at=av.length;for(N=0;N<at;N++){p=av[N];B=aa[N];if(B===false){if(T.length==1){T=[]}I=true;ak.items.push(false);continue}else{H=(am.x+(p-z)*Y).toFixed(2);G=((am.y+am.height)-(B-w)*af).toFixed(2);if(I){I=false;T.push("M")}T=T.concat([H,G])}if((typeof r=="undefined")&&(typeof G!="undefined")){r=G;s=H}if(!ak.line||au.resizing){ar=ar.concat([H,am.y+am.height/2])}if(au.animate&&au.resizing&&ak.line){ak.line.setAttributes({path:ar},true);if(ak.fillPath){ak.fillPath.setAttributes({path:ar,opacity:0.2},true)}if(ak.line.shadows){ac=ak.line.shadows;for(M=0,q=ac.length;M<q;M++){h=ac[M];h.setAttributes({path:ar},true)}}}if(K){E=aA.getAt(k++);if(!E){E=Ext.chart.Shape[U](u,Ext.apply({group:[R,aA],x:0,y:0,translate:{x:+(f||H),y:e||(am.y+am.height/2)},value:'"'+p+", "+B+'"',zIndex:4000},an));E._to={translate:{x:+H,y:+G}}}else{E.setAttributes({value:'"'+p+", "+B+'"',x:0,y:0,hidden:false},true);E._to={translate:{x:+H,y:+G}}}}ak.items.push({series:ak,value:[p,B],point:[H,G],sprite:E,storeItem:ao.getAt(Q[N])});f=H;e=G}if(T.length<=1){return}if(ak.smooth){b=Ext.draw.Draw.smooth(T,L(O)?O:ak.defaultSmoothness)}d=O?b:T;if(au.markerIndex&&ak.previousPath){ad=ak.previousPath;if(!O){Ext.Array.erase(ad,1,2)}}else{ad=T}if(!ak.line){ak.line=u.add(Ext.apply({type:"path",group:R,path:ar,stroke:al.stroke||al.fill},al||{}));if(D){ak.line.setAttributes(Ext.apply({},ak.shadowOptions),true)}ak.line.setAttributes({fill:"none",zIndex:3000});if(!al.stroke&&P){ak.line.setAttributes({stroke:t[aw%P]},true)}if(D){ac=ak.line.shadows=[];for(ab=0;ab<q;ab++){ah=X[ab];ah=Ext.apply({},ah,{path:ar});h=u.add(Ext.apply({},{type:"path",group:C[ab]},ah));ac.push(h)}}}if(ak.fill){c=d.concat([["L",H,am.y+am.height],["L",s,am.y+am.height],["L",s,r]]);if(!ak.fillPath){ak.fillPath=u.add({group:R,type:"path",opacity:al.opacity||0.3,fill:al.fill||t[aw%P],path:ar})}}W=K&&aA.getCount();if(au.animate){A=ak.fill;o=ak.line;ae=ak.renderer(o,false,{path:d},N,ao);Ext.apply(ae,al||{},{stroke:al.stroke||al.fill});delete ae.fill;o.show(true);if(au.markerIndex&&ak.previousPath){ak.animation=ax=ak.onAnimate(o,{to:ae,from:{path:ad}})}else{ak.animation=ax=ak.onAnimate(o,{to:ae})}if(D){ac=o.shadows;for(M=0;M<q;M++){ac[M].show(true);if(au.markerIndex&&ak.previousPath){ak.onAnimate(ac[M],{to:{path:d},from:{path:ad}})}else{ak.onAnimate(ac[M],{to:{path:d}})}}}if(A){ak.fillPath.show(true);ak.onAnimate(ak.fillPath,{to:Ext.apply({},{path:c,fill:al.fill||t[aw%P],"stroke-width":0},al||{})})}if(K){k=0;for(N=0;N<at;N++){if(ak.items[N]){n=aA.getAt(k++);if(n){ae=ak.renderer(n,ao.getAt(N),n._to,N,ao);ak.onAnimate(n,{to:Ext.apply(ae,an||{})});n.show(true)}}}for(;k<W;k++){n=aA.getAt(k);n.hide(true)}}}else{ae=ak.renderer(ak.line,false,{path:d,hidden:false},N,ao);Ext.apply(ae,al||{},{stroke:al.stroke||al.fill});delete ae.fill;ak.line.setAttributes(ae,true);if(D){ac=ak.line.shadows;for(M=0;M<q;M++){ac[M].setAttributes({path:d,hidden:false},true)}}if(ak.fill){ak.fillPath.setAttributes({path:c,hidden:false},true)}if(K){k=0;for(N=0;N<at;N++){if(ak.items[N]){n=aA.getAt(k++);if(n){ae=ak.renderer(n,ao.getAt(N),n._to,N,ao);n.setAttributes(Ext.apply(an||{},ae||{}),true);n.show(true)}}}for(;k<W;k++){n=aA.getAt(k);n.hide(true)}}}if(au.markerIndex){if(ak.smooth){Ext.Array.erase(T,1,2)}else{Ext.Array.splice(T,1,0,T[1],T[2])}ak.previousPath=T}ak.renderLabels();ak.renderCallouts();ak.fireEvent("draw",ak);
+        }
+    });
+
 	// namespace
 	EV = {};
 	var NS = EV;
@@ -333,6 +340,8 @@
 
                 // baseLineTitle: string
 
+                // sortOrder: number
+
                 // rangeAxisMaxValue: number
 
                 // rangeAxisMinValue: number
@@ -559,6 +568,7 @@
                     layout.baseLineValue = Ext.isNumber(config.baseLineValue) ? config.baseLineValue : null;
                     layout.baseLineTitle = Ext.isString(config.baseLineLabel) && !Ext.isEmpty(config.baseLineLabel) ? config.baseLineLabel :
                         (Ext.isString(config.baseLineTitle) && !Ext.isEmpty(config.baseLineTitle) ? config.baseLineTitle : null);
+                    layout.sortOrder = Ext.isNumber(config.sortOrder) ? config.sortOrder : 0;
 
 					layout.rangeAxisMaxValue = Ext.isNumber(config.rangeAxisMaxValue) ? config.rangeAxisMaxValue : null;
 					layout.rangeAxisMinValue = Ext.isNumber(config.rangeAxisMinValue) ? config.rangeAxisMinValue : null;
@@ -2082,6 +2092,30 @@
                         return map;
                     }(),                          
 
+                    sortStoreBySum = function(store, ids, sortOrder) {
+                        var key = Ext.data.IdGenerator.get('uuid').generate(),
+                            total;
+
+                        // add totals
+                        store.each( function(record) {
+                            total = 0;
+
+                            for (var i = 0; i < ids.length; i++) {
+                                total += parseFloat(record.data[ids[i]]);
+
+                                record.set(key, total);
+                            }
+                        });
+
+                        // sort
+                        store.sort(key, sortOrder === -1 ? 'ASC' : 'DESC');
+
+                        // remove totals
+                        store.each( function(record) {
+                            delete record.data[key];
+                        });
+                    },
+
 					getSyncronizedXLayout,
                     getExtendedResponse,
                     validateUrl,
@@ -2189,6 +2223,11 @@
                         data: data
                     });
 
+                    // sort order
+                    if (xLayout.sortOrder) {
+                        store.sort(replacedColumnIds[0], xLayout.sortOrder === -1 ? 'ASC' : 'DESC');
+                    }
+
                     store.rangeFields = replacedColumnIds;
                     store.domainFields = [conf.finals.data.domain];
                     store.trendLineFields = trendLineFields;
@@ -2826,6 +2865,11 @@
                 generator.stackedcolumn = function() {
                     var chart = this.column();
 
+                    // sort order
+                    if (xLayout.sortOrder) {
+                        sortStoreBySum(chart.store, replacedColumnIds, xLayout.sortOrder);
+                    }
+
                     for (var i = 0, item; i < chart.series.items.length; i++) {
                         item = chart.series.items[i];
 
@@ -2908,6 +2952,11 @@
                 generator.stackedbar = function() {
                     var chart = this.bar();
 
+                    // sort order
+                    if (xLayout.sortOrder) {
+                        sortStoreBySum(chart.store, replacedColumnIds, xLayout.sortOrder);
+                    }
+
                     for (var i = 0, item; i < chart.series.items.length; i++) {
                         item = chart.series.items[i];
 
@@ -2996,6 +3045,11 @@
                         axes = [numericAxis, categoryAxis],
                         series = getDefaultSeries(store);
 
+                    // sort order
+                    if (xLayout.sortOrder) {
+                        sortStoreBySum(store, replacedColumnIds, xLayout.sortOrder);
+                    }
+
                     series.type = 'area';
                     series.style.opacity = 0.7;
                     series.style.lineWidth = 0;

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js	2014-10-08 21:49:29 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js	2014-10-09 07:58:13 +0000
@@ -506,6 +506,7 @@
 			targetLineTitle,
 			baseLineValue,
 			baseLineTitle,
+            sortOrder,
 
             rangeAxisMinValue,
             rangeAxisMaxValue,