← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 10089: (PT) Favorites (wip) + dhis-web-api-mobile compilation error commented out.

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 10089 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2013-03-08 17:41:49 +0100
message:
  (PT) Favorites (wip) + dhis-web-api-mobile compilation error commented out.
added:
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-dashboard_16.png
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-delete_16.png
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-edit_16.png
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-save_16.png
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/adapter/JacksonMapListIdentifiableObjectSerializer.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java
  dhis-2/dhis-web/dhis-web-api-mobile/src/main/java/org/hisp/dhis/api/mobile/controller/MobileClientController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/ReportTableController.java
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css


--
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-api/src/main/java/org/hisp/dhis/common/adapter/JacksonMapListIdentifiableObjectSerializer.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/adapter/JacksonMapListIdentifiableObjectSerializer.java	2013-02-27 11:10:13 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/adapter/JacksonMapListIdentifiableObjectSerializer.java	2013-03-08 16:16:46 +0000
@@ -47,7 +47,7 @@
     public void serialize( Map<String, List<IdentifiableObject>> value, JsonGenerator jgen, SerializerProvider provider )
         throws IOException
     {
-        if ( value != null )
+        if ( value != null && !value.isEmpty() )
         {
             jgen.writeStartObject();
             
@@ -59,6 +59,8 @@
                 {
                     jgen.writeStartObject();
                     jgen.writeStringField( "id", object.getUid() );
+                    jgen.writeStringField( "name", object.getName() );
+                    jgen.writeStringField( "code", object.getCode() );
                     jgen.writeEndObject();
                 }
                 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java	2013-03-07 20:07:23 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java	2013-03-08 15:40:04 +0000
@@ -418,6 +418,11 @@
      */
     private List<DataElementCategoryOptionCombo> categoryOptionCombos = new ArrayList<DataElementCategoryOptionCombo>();
 
+    /**
+     * Map linking organisation unit uids and parent graphs.
+     */
+    private Map<String, String> parentGraphMap = new HashMap<String, String>();
+
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
@@ -1634,4 +1639,16 @@
             filterDimensions.addAll( reportTable.getFilterDimensions() );
         }
     }
+
+    @JsonProperty
+    @JsonView({ DetailedView.class, ExportView.class })
+    public Map<String, String> getParentGraphMap()
+    {
+        return parentGraphMap;
+    }
+
+    public void setParentGraphMap( Map<String, String> parentGraphMap )
+    {
+        this.parentGraphMap = parentGraphMap;
+    }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-api-mobile/src/main/java/org/hisp/dhis/api/mobile/controller/MobileClientController.java'
--- dhis-2/dhis-web/dhis-web-api-mobile/src/main/java/org/hisp/dhis/api/mobile/controller/MobileClientController.java	2013-03-08 09:38:34 +0000
+++ dhis-2/dhis-web/dhis-web-api-mobile/src/main/java/org/hisp/dhis/api/mobile/controller/MobileClientController.java	2013-03-08 16:34:59 +0000
@@ -115,7 +115,7 @@
         orgUnit.setSearchUrl( getUrl( request, unit.getId(), "search" ) );
         orgUnit.setUpdateContactUrl( getUrl( request, unit.getId(), "updateContactForMobile" ) );
         orgUnit.setFindPatientUrl( getUrl( request, unit.getId(), "findPatient" ) );
-        orgUnit.setRegisterPerson(getUrl(request, unit.getId(), "registerPerson"));
+        //orgUnit.setRegisterPerson(getUrl(request, unit.getId(), "registerPerson")); TODO
         orgUnit.setUploadProgramStageUrl( getUrl( request, unit.getId(), "uploadProgramStage" ) );
         orgUnit.setEnrollProgramUrl( getUrl( request, unit.getId(), "enrollProgram" ) );
 

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/ReportTableController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/ReportTableController.java	2013-02-27 16:14:56 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/ReportTableController.java	2013-03-08 15:40:04 +0000
@@ -47,13 +47,16 @@
 import org.hisp.dhis.dataset.DataSet;
 import org.hisp.dhis.dataset.DataSetService;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.i18n.I18nManager;
+import org.hisp.dhis.i18n.I18nManagerException;
 import org.hisp.dhis.indicator.Indicator;
 import org.hisp.dhis.indicator.IndicatorService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroupService;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.Cal;
+import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
 import org.hisp.dhis.period.RelativePeriods;
 import org.hisp.dhis.reporttable.ReportTable;
@@ -176,9 +179,24 @@
     }
     
     @Override
-    protected void postProcessEntity( ReportTable reportTable )
+    protected void postProcessEntity( ReportTable reportTable ) throws Exception
     {
+        I18nFormat format = i18nManager.getI18nFormat();
+        
         reportTable.populatePresentationProps();
+        
+        for ( OrganisationUnit organisationUnit : reportTable.getOrganisationUnits() )
+        {
+            reportTable.getParentGraphMap().put( organisationUnit.getUid(), organisationUnit.getParentGraph() );
+        }
+        
+        if ( reportTable.getPeriods() != null && !reportTable.getPeriods().isEmpty() )
+        {
+            for ( Period period : reportTable.getPeriods() )
+            {
+                period.setName( format.formatPeriod( period ) );
+            }
+        }
     }
     
     //--------------------------------------------------------------------------

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css	2013-02-05 20:19:14 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css	2013-03-08 11:00:41 +0000
@@ -491,6 +491,9 @@
 .gis-grid .x-grid-row { /* middle align text in row with image */
 	vertical-align: middle;
 }
+.gis-grid .x-grid-row .x-grid-cell { /* remove blurry borders */
+	border-top: 0 none;
+}
 
 .gis-grid .link,
 .gis-grid .link * {

=== added file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-dashboard_16.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-dashboard_16.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-dashboard_16.png	2013-03-08 15:40:04 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-delete_16.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-delete_16.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-delete_16.png	2013-03-08 15:40:04 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-edit_16.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-edit_16.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-edit_16.png	2013-03-08 15:40:04 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-save_16.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-save_16.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/grid-save_16.png	2013-03-08 15:40:04 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-03-07 21:00:55 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-03-08 16:25:52 +0000
@@ -94,7 +94,8 @@
 			config = {
 				col: [],
 				row: [],
-				filter: []
+				filter: [],
+				objects: []
 			};
 
 			getData = function() {
@@ -105,42 +106,44 @@
 					dim = panels[i].getData();
 
 					if (dim) {
-						if (dim.name === pt.conf.finals.dimension.data.paramName) {
+						config.objects.push(dim);
+
+						if (dim.dimensionName === pt.conf.finals.dimension.data.dimensionName) {
 							dxItems = dxItems.concat(dim.items);
 						}
 						else {
-							data[dim.name] = dim.items;
+							data[dim.dimensionName] = dim.items;
 						}
 					}
 				}
 
 				if (dxItems.length) {
-					data[pt.conf.finals.dimension.data.paramName] = dxItems;
+					data[pt.conf.finals.dimension.data.dimensionName] = dxItems;
 				}
 			}();
 
 			extendSettings = function() {
-				for (var i = 0, name; i < setup.col.length; i++) {
-					name = setup.col[i];
+				for (var i = 0, dimensionName; i < setup.col.length; i++) {
+					dimensionName = setup.col[i];
 					config.col.push({
-						name: name,
-						items: data[name]
+						dimensionName: dimensionName,
+						items: data[dimensionName]
 					});
 				}
 
-				for (var i = 0, name; i < setup.row.length; i++) {
-					name = setup.row[i];
+				for (var i = 0, dimensionName; i < setup.row.length; i++) {
+					dimensionName = setup.row[i];
 					config.row.push({
-						name: name,
-						items: data[name]
+						dimensionName: dimensionName,
+						items: data[dimensionName]
 					});
 				}
 
-				for (var i = 0, name; i < setup.filter.length; i++) {
-					name = setup.filter[i];
+				for (var i = 0, dimensionName; i < setup.filter.length; i++) {
+					dimensionName = setup.filter[i];
 					config.filter.push({
-						name: name,
-						items: data[name]
+						dimensionName: dimensionName,
+						items: data[dimensionName]
 					});
 				}
 			}();
@@ -267,6 +270,48 @@
 			data: []
 		});
 
+		store.tables = Ext.create('Ext.data.Store', {
+			fields: ['id', 'name', 'lastUpdated'],
+			proxy: {
+				type: 'ajax',
+				reader: {
+					type: 'json',
+					root: 'reportTables'
+				}
+			},
+			isLoaded: false,
+			pageSize: 10,
+			page: 1,
+			defaultUrl: pt.baseUrl + '/api/reportTables.json?links=false',
+			loadStore: function(url) {
+				this.proxy.url = url || this.defaultUrl;
+
+				this.load({
+					params: {
+						pageSize: this.pageSize,
+						page: this.page
+					}
+				});
+			},
+			loadFn: function(fn) {
+				if (this.isLoaded) {
+					fn.call();
+				}
+				else {
+					this.load(fn);
+				}
+			},
+			listeners: {
+				load: function() {
+					if (!this.isLoaded) {
+						this.isLoaded = true;
+					}
+
+					this.sort('name', 'ASC');
+				}
+			}
+		});
+
 		return store;
 	};
 
@@ -321,7 +366,7 @@
 			dimConf = pt.conf.finals.dimension;
 
 		dimensionOrder = function() {
-			var order = [dimConf.data.paramName, dimConf.category.paramName, dimConf.period.paramName, dimConf.organisationUnit.paramName],
+			var order = [dimConf.data.dimensionName, dimConf.category.dimensionName, dimConf.period.dimensionName, dimConf.organisationUnit.dimensionName],
 				ougsOrder = [];
 
 			for (var i = 0; i < pt.init.ougs.length; i++) {
@@ -331,8 +376,19 @@
 			return order.concat(ougsOrder);
 		}();
 
-		getData = function() {
-			var data = [{id: dimConf.category.paramName, name: dimConf.category.rawValue}];
+		getData = function(all) {
+			var data = [];
+
+			if (all) {
+				data.push({id: dimConf.data.dimensionName, name: dimConf.data.rawValue});
+			}
+
+			data.push({id: dimConf.category.dimensionName, name: dimConf.category.rawValue});
+
+			if (all) {
+				data.push({id: dimConf.period.dimensionName, name: dimConf.period.rawValue});
+				data.push({id: dimConf.organisationUnit.dimensionName, name: dimConf.organisationUnit.rawValue});
+			}
 
 			return data.concat(pt.init.ougs, pt.init.degs);
 		};
@@ -363,15 +419,23 @@
 		};
 
 		dimensionStore = getStore(getData());
+		dimensionStore.reset = function(all) {
+			dimensionStore.removeAll();
+			dimensionStore.add(getData(all));
+		};
+		pt.viewport.dimensionStore = dimensionStore;
 
 		rowStore = getStore();
-		rowStore.add({id: dimConf.period.paramName, name: dimConf.period.rawValue}); //i18n
+		pt.viewport.rowStore = rowStore;
+		rowStore.add({id: dimConf.period.dimensionName, name: dimConf.period.rawValue}); //i18n
 
 		colStore = getStore();
-		colStore.add({id: dimConf.data.paramName, name: dimConf.data.rawValue}); //i18n
+		pt.viewport.colStore = colStore;
+		colStore.add({id: dimConf.data.dimensionName, name: dimConf.data.rawValue}); //i18n
 
 		filterStore = getStore();
-		filterStore.add({id: dimConf.organisationUnit.paramName, name: dimConf.organisationUnit.rawValue}); //i18n
+		pt.viewport.filterStore = filterStore;
+		filterStore.add({id: dimConf.organisationUnit.dimensionName, name: dimConf.organisationUnit.rawValue}); //i18n
 
 		getCmpHeight = function() {
 			var size = dimensionStore.totalCount,
@@ -610,7 +674,7 @@
 	PT.app.OptionsWindow = function() {
 		var showSubTotals,
 			hideEmptyRows,
-			cellPadding,
+			displayDensity,
 			fontSize,
 
 			data,
@@ -618,15 +682,17 @@
 			window;
 
 		showSubTotals = Ext.create('Ext.form.field.Checkbox', {
-			boxLabel: 'Show sub totals', //i18n
+			boxLabel: 'Show sub-totals', //i18n
 			checked: true
 		});
+		pt.viewport.showSubTotals = showSubTotals;
 
 		hideEmptyRows = Ext.create('Ext.form.field.Checkbox', {
 			boxLabel: 'Hide empty rows' //i18n
 		});
+		pt.viewport.hideEmptyRows = hideEmptyRows;
 
-		cellPadding = Ext.create('Ext.form.field.ComboBox', {
+		displayDensity = Ext.create('Ext.form.field.ComboBox', {
 			fieldLabel: 'Display density',
 			labelStyle: 'color:#333',
 			cls: 'pt-combo',
@@ -644,6 +710,7 @@
 				]
 			})
 		});
+		pt.viewport.displayDensity = displayDensity;
 
 		fontSize = Ext.create('Ext.form.field.ComboBox', {
 			xtype: 'combobox',
@@ -664,6 +731,7 @@
 				]
 			})
 		});
+		pt.viewport.fontSize = fontSize;
 
 		data = {
 			bodyStyle: 'border:0 none',
@@ -678,7 +746,7 @@
 			bodyStyle: 'border:0 none',
 			style: 'margin-left:14px',
 			items: [
-				cellPadding,
+				displayDensity,
 				fontSize
 			]
 		};
@@ -694,7 +762,7 @@
 				return {
 					showSubTotals: showSubTotals.getValue(),
 					hideEmptyRows: hideEmptyRows.getValue(),
-					cellPadding: cellPadding.getValue(),
+					displayDensity: displayDensity.getValue(),
 					fontSize: fontSize.getValue()
 				};
 			},
@@ -760,6 +828,9 @@
 		// Instances
 			nameWindow,
 
+		// Functions
+			getBody,
+
 		// Components
 			addButton,
 			searchTextfield,
@@ -778,13 +849,121 @@
 
 			mapWindow;
 
-		pt.store.maps.on('load', function(store, records) {
+		pt.store.tables.on('load', function(store, records) {
 			info.setText(records.length + ' favorite' + (records.length !== 1 ? 's' : '') + ' available');
 		});
 
+		getBody = function() {
+			var name = nameTextfield.getValue(),
+				system = systemCheckbox.getValue(),
+				favorite;
+
+			if (pt.xSettings) {
+				favorite = Ext.clone(pt.xSettings.options);
+
+				favorite.name = name;
+				favorite.user = system ? null : {id: 'currentUser'};
+
+				// Dimensions
+				for (var i = 0, obj, key, items; i < pt.xSettings.objects.length; i++) {
+					obj = pt.xSettings.objects[i];
+
+					if (obj.objectName === pt.conf.finals.dimension.period.objectName) {
+						for (var j = 0, item; j < obj.items.length; j++) {
+							item = obj.items[j];
+
+							if (pt.conf.period.relativePeriodValueKeys[item]) {
+								key = pt.conf.finals.dimension.relativePeriod.value;
+
+								if (!favorite[key]) {
+									favorite[key] = {};
+								}
+
+								favorite[key][pt.conf.period.relativePeriodValueKeys[item]] = true;
+							}
+							else {
+								key = pt.conf.finals.dimension.fixedPeriod.value;
+
+								if (!favorite[key]) {
+									favorite[key] = [];
+								}
+
+								favorite[key].push({
+									id: item
+								});
+							}
+						}
+					}
+					else if (obj.objectName === pt.conf.finals.dimension.organisationUnitGroupSet.objectName ||
+							 obj.objectName === pt.conf.finals.dimension.dataElementGroupSet.objectName) {
+						key = pt.conf.finals.dimension.objectNameMap[obj.objectName].value;
+
+						if (!favorite[key]) {
+							favorite[key] = {};
+						}
+
+						favorite[key][obj.dimensionName] = [];
+
+						for (var j = 0, item; j < obj.items.length; j++) {
+							item = obj.items[j];
+
+							favorite[key][obj.dimensionName].push({
+								id: item
+							});
+						}
+					}
+					else {
+						key = pt.conf.finals.dimension.objectNameMap[obj.objectName].value;
+						favorite[key] = [];
+
+						for (var j = 0, item; j < obj.items.length; j++) {
+							item = obj.items[j];
+
+							favorite[key].push({
+								id: item
+							});
+						}
+					}
+				}
+
+				// Setup
+				if (pt.xSettings.col) {
+					var a = [];
+
+					for (var i = 0; i < pt.xSettings.col.length; i++) {
+						a.push(pt.xSettings.col[i].dimensionName);
+					}
+
+					favorite['columnDimensions'] = a;
+				}
+
+				if (pt.xSettings.row) {
+					var a = [];
+
+					for (var i = 0; i < pt.xSettings.row.length; i++) {
+						a.push(pt.xSettings.row[i].dimensionName);
+					}
+
+					favorite['rowDimensions'] = a;
+				}
+
+				if (pt.xSettings.filter) {
+					var a = [];
+
+					for (var i = 0; i < pt.xSettings.filter.length; i++) {
+						a.push(pt.xSettings.filter[i].dimensionName);
+					}
+
+					favorite['filterDimensions'] = a;
+				}
+			}
+
+			return favorite;
+		};
+
 		NameWindow = function(id) {
 			var window,
-				record = gis.store.maps.getById(id);
+				record = pt.store.tables.getById(id);
 
 			nameTextfield = Ext.create('Ext.form.field.Text', {
 				height: 26,
@@ -804,72 +983,36 @@
 				labelWidth: 70,
 				fieldLabel: 'System', //i18n
 				style: 'margin-bottom: 0',
-				disabled: !gis.init.security.isAdmin,
+				disabled: !pt.init.user.isAdmin,
 				checked: !id ? false : (record.data.user ? false : true)
 			});
 
 			createButton = Ext.create('Ext.button.Button', {
 				text: 'Create', //i18n
 				handler: function() {
-					var name = nameTextfield.getValue(),
-						system = systemCheckbox.getValue(),
-						layers = gis.util.map.getVisibleVectorLayers(),
-						layer,
-						lonlat = gis.olmap.getCenter(),
-						views = [],
-						view,
-						map;
-
-					if (layers.length) {
-						if (name) {
-							for (var i = 0; i < layers.length; i++) {
-								layer = layers[i];
-								view = layer.widget.getView();
-
-								// add
-								view.layer = layer.id;
-
-								// remove
-								delete view.periodType;
-								views.push(view);
-							}
-
-							map = {
-								name: name,
-								longitude: lonlat.lon,
-								latitude: lonlat.lat,
-								zoom: gis.olmap.getZoom(),
-								mapViews: views
-							};
-
-							if (!system) {
-								map.user = {
-									id: 'currentUser'
-								};
-							}
-
-							Ext.Ajax.request({
-								url: gis.baseUrl + gis.conf.url.path_api + 'maps/',
-								method: 'POST',
-								headers: {'Content-Type': 'application/json'},
-								params: Ext.encode(map),
-								success: function(r) {
-									var id = r.getAllResponseHeaders().location.split('/').pop();
-
-									gis.store.maps.loadStore();
-
-									gis.viewport.interpretationButton.enable();
-
-									window.destroy();
-								}
-							});
-						}
-						else {
-							alert('Please enter a name');
-						}
+					var favorite = getBody();
+
+					if (favorite) {
+						Ext.Ajax.request({
+							url: pt.baseUrl + '/api/reportTables/',
+							method: 'POST',
+							headers: {'Content-Type': 'application/json'},
+							params: Ext.encode(favorite),
+							success: function(r) {
+								var id = r.getAllResponseHeaders().location.split('/').pop();
+
+								pt.favorite = favorite;
+
+								pt.store.tables.loadStore();
+
+								//pt.viewport.interpretationButton.enable();
+
+								window.destroy();
+							}
+						});
 					}
 					else {
-						alert('Please create a map first');
+						alert('Please create a table first');
 					}
 				}
 			});
@@ -881,9 +1024,9 @@
 						system = systemCheckbox.getValue();
 
 					Ext.Ajax.request({
-						url: gis.baseUrl + gis.conf.url.path_gis + 'renameMap.action?id=' + id + '&name=' + name + '&user=' + !system,
+						url: pt.baseUrl + pt.conf.finals.ajax.path_pivot + 'renameMap.action?id=' + id + '&name=' + name + '&user=' + !system,
 						success: function() {
-							gis.store.maps.loadStore();
+							pt.store.tables.loadStore();
 
 							window.destroy();
 						}
@@ -900,8 +1043,8 @@
 
 			window = Ext.create('Ext.window.Window', {
 				title: id ? 'Rename favorite' : 'Create new favorite',
-				iconCls: 'gis-window-title-icon-favorite',
-				cls: 'gis-container-default',
+				//iconCls: 'pt-window-title-icon-favorite',
+				bodyStyle: 'padding:8px; background:#fff',
 				resizable: false,
 				modal: true,
 				items: [
@@ -914,8 +1057,8 @@
 					id ? updateButton : createButton
 				],
 				listeners: {
-					show: function() {
-						this.setPosition(mapWindow.x + 14, mapWindow.y + 67);
+					show: function(w) {
+						pt.util.window.setAnchorPosition(w, pt.viewport.favoriteButton);
 					}
 				}
 			});
@@ -938,7 +1081,7 @@
 		searchTextfield = Ext.create('Ext.form.field.Text', {
 			width: 340,
 			height: 26,
-			fieldStyle: 'padding-right: 0; padding-left: 6px; border-radius: 1px; border-color: #bbb',
+			fieldStyle: 'padding-right: 0; padding-left: 6px; border-radius: 1px; border-color: #bbb; font-size:11px',
 			emptyText: 'Search for favorites', //i18n
 			enableKeyEvents: true,
 			currentValue: '',
@@ -948,8 +1091,8 @@
 						this.currentValue = this.getValue();
 
 						var value = this.getValue(),
-							url = value ? gis.baseUrl + gis.conf.url.path_api +  'maps/query/' + value + '.json?links=false' : null,
-							store = gis.store.maps;
+							url = value ? pt.baseUrl + '/api/reportTables/query/' + value + '.json?links=false' : null,
+							store = pt.store.tables;
 
 						store.page = 1;
 						store.loadStore(url);
@@ -962,8 +1105,8 @@
 			text: 'Prev', //i18n
 			handler: function() {
 				var value = searchTextfield.getValue(),
-					url = value ? gis.baseUrl + gis.conf.url.path_api +  'maps/query/' + value + '.json?links=false' : null,
-					store = gis.store.maps;
+					url = value ? pt.baseUrl + '/api/reportTables/query/' + value + '.json?links=false' : null,
+					store = pt.store.tables;
 
 				store.page = store.page <= 1 ? 1 : store.page - 1;
 				store.loadStore(url);
@@ -974,8 +1117,8 @@
 			text: 'Next', //i18n
 			handler: function() {
 				var value = searchTextfield.getValue(),
-					url = value ? gis.baseUrl + gis.conf.url.path_api +  'maps/query/' + value + '.json?links=false' : null,
-					store = gis.store.maps;
+					url = value ? pt.baseUrl + '/api/reportTables/query/' + value + '.json?links=false' : null,
+					store = pt.store.tables;
 
 				store.page = store.page + 1;
 				store.loadStore(url);
@@ -983,15 +1126,17 @@
 		});
 
 		info = Ext.create('Ext.form.Label', {
-			cls: 'gis-label-info',
+			cls: 'pt-label-info',
 			width: 300,
 			height: 22
 		});
 
 		grid = Ext.create('Ext.grid.Panel', {
-			cls: 'gis-grid',
+			cls: 'pt-grid',
 			scroll: false,
 			hideHeaders: true,
+			bodyStyle: 'padding-bottom:1px solid red !important',
+			style: 'padding-bottom:1px solid red !important',
 			columns: [
 				{
 					dataIndex: 'name',
@@ -1003,9 +1148,9 @@
 							if (el) {
 								el = el.parent('td');
 								el.addClsOnOver('link');
-								el.gis = gis;
-								el.map = {id: record.data.id};
-								el.dom.setAttribute('onclick', 'Ext.get(this).gis.map = Ext.get(this).map; GIS.core.MapLoader(Ext.get(this).gis).load();');
+								el.pt = pt;
+								el.favoriteId = record.data.id;
+								el.dom.setAttribute('onclick', 'Ext.get(this).pt.util.pivot.loadTable(Ext.get(this).favoriteId);');
 							}
 						};
 
@@ -1020,20 +1165,20 @@
 					width: 80,
 					items: [
 						{
-							iconCls: 'gis-grid-row-icon-edit',
+							iconCls: 'pt-grid-row-icon-edit',
 							getClass: function(value, metaData, record) {
 								var system = !record.data.user,
-									isAdmin = gis.init.security.isAdmin;
+									isAdmin = pt.init.user.isAdmin;
 
 								if (isAdmin || (!isAdmin && !system)) {
-									return 'tooltip-map-edit';
+									return 'tooltip-favorite-edit';
 								}
 							},
 							handler: function(grid, rowIndex, colIndex, col, event) {
 								var record = this.up('grid').store.getAt(rowIndex),
 									id = record.data.id,
 									system = !record.data.user,
-									isAdmin = gis.init.security.isAdmin;
+									isAdmin = pt.init.user.isAdmin;
 
 								if (isAdmin || (!isAdmin && !system)) {
 									var id = this.up('grid').store.getAt(rowIndex).data.id;
@@ -1043,72 +1188,48 @@
 							}
 						},
 						{
-							iconCls: 'gis-grid-row-icon-overwrite',
+							iconCls: 'pt-grid-row-icon-overwrite',
 							getClass: function(value, metaData, record) {
 								var system = !record.data.user,
-									isAdmin = gis.init.security.isAdmin;
+									isAdmin = pt.init.user.isAdmin;
 
 								if (isAdmin || (!isAdmin && !system)) {
-									return 'tooltip-map-overwrite';
+									return 'tooltip-favorite-overwrite';
 								}
 							},
 							handler: function(grid, rowIndex, colIndex, col, event) {
 								var record = this.up('grid').store.getAt(rowIndex),
 									id = record.data.id,
 									name = record.data.name,
-									layers = gis.util.map.getVisibleVectorLayers(),
-									layer,
-									lonlat = gis.olmap.getCenter(),
-									views = [],
-									view,
-									map,
-									message = 'Overwrite favorite?\n\n' + name;
+									message = 'Overwrite favorite?\n\n' + name,
+									favorite = getBody();
 
-								if (layers.length) {
+								if (favorite) {
 									if (confirm(message)) {
-										for (var i = 0; i < layers.length; i++) {
-											layer = layers[i];
-											view = layer.core.view;
-
-											// add
-											view.layer = layer.id;
-
-											// remove
-											delete view.periodType;
-
-											views.push(view);
-										}
-
-										map = {
-											longitude: lonlat.lon,
-											latitude: lonlat.lat,
-											zoom: gis.olmap.getZoom(),
-											mapViews: views
-										};
-
 										Ext.Ajax.request({
-											url: gis.baseUrl + gis.conf.url.path_api + 'maps/' + id,
+											url: pt.baseUrl + '/api/reportTables/' + id,
 											method: 'PUT',
 											headers: {'Content-Type': 'application/json'},
-											params: Ext.encode(map),
+											params: Ext.encode(favorite),
 											success: function() {
-												gis.map = map;
-												gis.viewport.interpretationButton.enable();
-
-												gis.store.maps.loadStore();
+												pt.favorite = favorite;
+
+												//pt.viewport.interpretationButton.enable();
+
+												pt.store.tables.loadStore();
 											}
 										});
 									}
 								}
 								else {
-									alert('No layers to save'); //i18n
+									alert('Please create a table first'); //i18n
 								}
 							}
 						},
 						{
-							iconCls: 'gis-grid-row-icon-dashboard',
+							iconCls: 'pt-grid-row-icon-dashboard',
 							getClass: function() {
-								return 'tooltip-map-dashboard';
+								return 'tooltip-favorite-dashboard';
 							},
 							handler: function(grid, rowIndex) {
 								var record = this.up('grid').store.getAt(rowIndex),
@@ -1118,7 +1239,7 @@
 
 								if (confirm(message)) {
 									Ext.Ajax.request({
-										url: gis.baseUrl + gis.conf.url.path_gis + 'addMapViewToDashboard.action',
+										url: pt.baseUrl + pt.conf.finals.ajax.path_pivot + 'addMapViewToDashboard.action',
 										params: {
 											id: id
 										}
@@ -1127,13 +1248,13 @@
 							}
 						},
 						{
-							iconCls: 'gis-grid-row-icon-delete',
+							iconCls: 'pt-grid-row-icon-delete',
 							getClass: function(value, metaData, record) {
 								var system = !record.data.user,
-									isAdmin = gis.init.security.isAdmin;
+									isAdmin = pt.init.user.isAdmin;
 
 								if (isAdmin || (!isAdmin && !system)) {
-									return 'tooltip-map-delete';
+									return 'tooltip-favorite-delete';
 								}
 							},
 							handler: function(grid, rowIndex, colIndex, col, event) {
@@ -1144,10 +1265,10 @@
 
 								if (confirm(message)) {
 									Ext.Ajax.request({
-										url: gis.baseUrl + gis.conf.url.path_api + 'maps/' + id,
+										url: pt.baseUrl + '/api/reportTables/' + id,
 										method: 'DELETE',
 										success: function() {
-											gis.store.maps.loadStore();
+											pt.store.tables.loadStore();
 										}
 									});
 								}
@@ -1155,8 +1276,8 @@
 						}
 					],
 					renderer: function(value, metaData, record) {
-						if (!gis.init.security.isAdmin && !record.data.user) {
-							metaData.tdCls = 'gis-grid-row-icon-disabled';
+						if (!pt.init.user.isAdmin && !record.data.user) {
+							metaData.tdCls = 'pt-grid-row-icon-disabled';
 						}
 					}
 				},
@@ -1165,7 +1286,7 @@
 					width: 6
 				}
 			],
-			store: gis.store.maps,
+			store: pt.store.tables,
 			bbar: [
 				info,
 				'->',
@@ -1174,15 +1295,15 @@
 			],
 			listeners: {
 				added: function() {
-					gis.viewport.mapGrid = this;
+					pt.viewport.favoriteGrid = this;
 				},
 				render: function() {
-					var size = Math.floor((gis.viewport.centerRegion.getHeight() - 155) / gis.conf.layout.grid.row_height);
+					var size = Math.floor((pt.viewport.centerRegion.getHeight() - 155) / pt.conf.layout.grid_row_height);
 					this.store.pageSize = size;
 					this.store.page = 1;
 					this.store.loadStore();
 
-					gis.store.maps.on('load', function() {
+					pt.store.tables.on('load', function() {
 						if (this.isVisible()) {
 							this.fireEvent('afterrender');
 						}
@@ -1190,10 +1311,10 @@
 				},
 				afterrender: function() {
 					var fn = function() {
-						var editArray = document.getElementsByClassName('tooltip-map-edit'),
-							overwriteArray = document.getElementsByClassName('tooltip-map-overwrite'),
-							dashboardArray = document.getElementsByClassName('tooltip-map-dashboard'),
-							deleteArray = document.getElementsByClassName('tooltip-map-delete'),
+						var editArray = document.getElementsByClassName('tooltip-favorite-edit'),
+							overwriteArray = document.getElementsByClassName('tooltip-favorite-overwrite'),
+							dashboardArray = document.getElementsByClassName('tooltip-favorite-dashboard'),
+							deleteArray = document.getElementsByClassName('tooltip-favorite-delete'),
 							el;
 
 						for (var i = 0; i < deleteArray.length; i++) {
@@ -1252,10 +1373,10 @@
 			}
 		});
 
-		mapWindow = Ext.create('Ext.window.Window', {
+		favoriteWindow = Ext.create('Ext.window.Window', {
 			title: 'Manage favorites',
-			iconCls: 'gis-window-title-icon-favorite',
-			cls: 'gis-container-default',
+			//iconCls: 'pt-window-title-icon-favorite',
+			bodyStyle: 'padding: 8px; background-color:#fff',
 			resizable: false,
 			modal: true,
 			width: 450,
@@ -1264,7 +1385,7 @@
 					xtype: 'panel',
 					layout: 'hbox',
 					width: 422,
-					cls: 'gis-container-inner',
+					bodyStyle: 'border:0 none',
 					items: [
 						addButton,
 						{
@@ -1279,13 +1400,13 @@
 				grid
 			],
 			listeners: {
-				show: function() {
-					this.setPosition(115, 37);
+				show: function(w) {
+					pt.util.window.setAnchorPosition(w, pt.viewport.favoriteButton);
 				}
 			}
 		});
 
-		return mapWindow;
+		return favoriteWindow;
 	};
 
 	PT.app.init.onInitialize = function(r) {
@@ -1307,6 +1428,7 @@
 				fixedPeriodSelected,
 				period,
 				organisationUnit,
+				groupSetIdStoreMap,
 				getGroupSetPanels,
 				validateSpecialCases,
 				update,
@@ -1318,8 +1440,10 @@
 				accordion,
 				westRegion,
 				centerRegion,
+
+				setFavorite,
+
 				viewport,
-
 				addListeners;
 
 			indicatorAvailable = Ext.create('Ext.ux.form.MultiSelect', {
@@ -1408,7 +1532,8 @@
 				hideCollapseTool: true,
 				getData: function() {
 					var data = {
-						name: pt.conf.finals.dimension.indicator.paramName,
+						dimensionName: pt.conf.finals.dimension.indicator.dimensionName,
+						objectName: pt.conf.finals.dimension.indicator.objectName,
 						items: []
 					};
 
@@ -1599,7 +1724,8 @@
 				hideCollapseTool: true,
 				getData: function() {
 					var data = {
-						name: pt.conf.finals.dimension.indicator.paramName,
+						dimensionName: pt.conf.finals.dimension.dataElement.dimensionName,
+						objectName: pt.conf.finals.dimension.dataElement.objectName,
 						items: []
 					};
 
@@ -1786,7 +1912,8 @@
 				hideCollapseTool: true,
 				getData: function() {
 					var data = {
-						name: pt.conf.finals.dimension.indicator.paramName,
+						dimensionName: pt.conf.finals.dimension.dataSet.dimensionName,
+						objectName: pt.conf.finals.dimension.dataSet.objectName,
 						items: []
 					};
 
@@ -1830,7 +1957,7 @@
 			};
 
 			rewind = Ext.create('Ext.form.field.Checkbox', {
-				paramName: 'rewind',
+				relativePeriodId: 'rewind',
 				boxLabel: 'Rewind one period',
 				xable: function() {
 					this.setDisabled(pt.util.checkbox.isAllFalse());
@@ -1842,6 +1969,7 @@
 				hideCollapseTool: true,
 				autoScroll: true,
 				bodyStyle: 'border:0 none',
+				valueComponentMap: {},
 				items: [
 					{
 						xtype: 'panel',
@@ -1859,6 +1987,7 @@
 										added: function(chb) {
 											if (chb.xtype === 'checkbox') {
 												pt.cmp.dimension.relativePeriod.checkbox.push(chb);
+												relativePeriod.valueComponentMap[chb.relativePeriodId] = chb;
 											}
 										},
 										change: function() {
@@ -1874,17 +2003,17 @@
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_MONTH',
+										relativePeriodId: 'LAST_MONTH',
 										boxLabel: 'Last month', //i18n pt.i18n.last_month
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_3_MONTHS',
+										relativePeriodId: 'LAST_3_MONTHS',
 										boxLabel: 'Last 3 months', //i18n pt.i18n.last_3_months
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_12_MONTHS',
+										relativePeriodId: 'LAST_12_MONTHS',
 										boxLabel: 'Last 12 months', //i18n pt.i18n.last_12_months,
 										checked: true
 									}
@@ -1901,6 +2030,7 @@
 										added: function(chb) {
 											if (chb.xtype === 'checkbox') {
 												pt.cmp.dimension.relativePeriod.checkbox.push(chb);
+												relativePeriod.valueComponentMap[chb.relativePeriodId] = chb;
 											}
 										},
 										change: function() {
@@ -1916,12 +2046,12 @@
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_QUARTER',
+										relativePeriodId: 'LAST_QUARTER',
 										boxLabel: 'Last quarter', //i18n pt.i18n.last_quarter
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_4_QUARTERS',
+										relativePeriodId: 'LAST_4_QUARTERS',
 										boxLabel: 'Last 4 quarters', //i18n pt.i18n.last_4_quarters
 									}
 								]
@@ -1937,6 +2067,7 @@
 										added: function(chb) {
 											if (chb.xtype === 'checkbox') {
 												pt.cmp.dimension.relativePeriod.checkbox.push(chb);
+												relativePeriod.valueComponentMap[chb.relativePeriodId] = chb;
 											}
 										},
 										change: function() {
@@ -1952,12 +2083,12 @@
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_SIX_MONTH',
+										relativePeriodId: 'LAST_SIX_MONTH',
 										boxLabel: 'Last six-month', //i18n pt.i18n.last_six_month
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_2_SIXMONTHS',
+										relativePeriodId: 'LAST_2_SIXMONTHS',
 										boxLabel: 'Last two six-months', //i18n pt.i18n.last_two_six_month
 									}
 								]
@@ -1980,6 +2111,7 @@
 										added: function(chb) {
 											if (chb.xtype === 'checkbox') {
 												pt.cmp.dimension.relativePeriod.checkbox.push(chb);
+												relativePeriod.valueComponentMap[chb.relativePeriodId] = chb;
 											}
 										},
 										change: function() {
@@ -1995,17 +2127,17 @@
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'THIS_YEAR',
+										relativePeriodId: 'THIS_YEAR',
 										boxLabel: 'This year', //i18n pt.i18n.this_year
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_YEAR',
+										relativePeriodId: 'LAST_YEAR',
 										boxLabel: 'Last year', //i18n pt.i18n.last_year
 									},
 									{
 										xtype: 'checkbox',
-										paramName: 'LAST_5_YEARS',
+										relativePeriodId: 'LAST_5_YEARS',
 										boxLabel: 'Last 5 years', //i18n pt.i18n.last_5_years
 									}
 								]
@@ -2121,7 +2253,8 @@
 				hideCollapseTool: true,
 				getData: function() {
 					var data = {
-						name: pt.conf.finals.dimension.period.paramName,
+							dimensionName: pt.conf.finals.dimension.period.dimensionName,
+							objectName: pt.conf.finals.dimension.period.objectName,
 							items: []
 						},
 						chb = pt.cmp.dimension.relativePeriod.checkbox;
@@ -2132,7 +2265,7 @@
 
 					for (var i = 0; i < chb.length; i++) {
 						if (chb[i].getValue()) {
-							data.items.push(chb[i].paramName);
+							data.items.push(chb[i].relativePeriodId);
 						}
 					}
 
@@ -2160,8 +2293,9 @@
 								width: pt.conf.layout.west_fieldset_width - pt.conf.layout.west_width_padding - 62 - 62 - 7,
 								valueField: 'id',
 								displayField: 'name',
-								fieldLabel: 'Select type', //i18n pt.i18n.select_type,
+								fieldLabel: 'Select period type', //i18n pt.i18n.select_type,
 								labelStyle: 'padding-left:8px',
+								labelWidth: 110,
 								editable: false,
 								queryMode: 'remote',
 								store: pt.store.periodType,
@@ -2241,7 +2375,8 @@
 				getData: function() {
 					var records = pt.cmp.dimension.organisationUnit.treepanel.getSelectionModel().getSelection(),
 						data = {
-							name: 'ou',
+							dimensionName: pt.conf.finals.dimension.organisationUnit.dimensionName,
+							objectName: pt.conf.finals.dimension.organisationUnit.objectName,
 							items: []
 						};
 
@@ -2486,6 +2621,7 @@
 						listeners: {
 							added: function() {
 								pt.cmp.dimension.organisationUnit.treepanel = this;
+								organisationUnit.treePanel = this;
 							},
 							render: function() {
 								this.rendered = true;
@@ -2536,7 +2672,9 @@
 				}
 			};
 
-			getGroupSetPanels = function(groupSets, iconCls) {
+			groupSetIdStoreMap = {};
+
+			getGroupSetPanels = function(groupSets, objectName, iconCls) {
 				var	getAvailableStore,
 					getSelectedStore,
 
@@ -2668,6 +2806,8 @@
 					availableStore = getAvailableStore(groupSet);
 					selectedStore = getSelectedStore();
 
+					groupSetIdStoreMap[groupSet.id] = selectedStore;
+
 					available = getAvailable(availableStore);
 					selected = getSelected(selectedStore);
 
@@ -2681,7 +2821,8 @@
 						hideCollapseTool: true,
 						getData: function() {
 							var data = {
-								name: groupSet.id,
+								dimensionName: groupSet.id,
+								objectName: objectName,
 								items: []
 							};
 
@@ -2749,18 +2890,18 @@
 
 			validateSpecialCases = function(settings) {
 				var dimConf = pt.conf.finals.dimension,
-					settingsNames = [],
+					dimensionNames = [],
 					settingsObjects = [].concat(Ext.clone(settings.col || []), Ext.clone(settings.row || []), Ext.clone(settings.filter || []));
 
 				// Settings names
 				for (var i = 0; i < settingsObjects.length; i++) {
-					settingsNames.push(settingsObjects[i].name);
+					dimensionNames.push(settingsObjects[i].dimensionName);
 				}
 
 				// Indicator as filter
 				if (settings.filter && pt.store.indicatorSelected.data.length) {
 					for (var i = 0; i < settings.filter.length; i++) {
-						if (settings.filter[i].name === dimConf.data.paramName) {
+						if (settings.filter[i].dimensionName === dimConf.data.dimensionName) {
 							alert('Indicators cannot be specified as filter'); //i18n
 							return;
 						}
@@ -2768,15 +2909,15 @@
 				}
 
 				// Categories as filter
-				if (settings.filter && pt.viewport.settingsWindow.filterStore.getById(dimConf.category.paramName)) {
+				if (settings.filter && pt.viewport.settingsWindow.filterStore.getById(dimConf.category.dimensionName)) {
 					alert('Categories cannot be specified as filter');
 					return;
 				}
 
 				// Degs and datasets in the same query
-				if (Ext.Array.contains(settingsNames, dimConf.data.paramName) && pt.store.dataSetSelected.data.length) {
+				if (Ext.Array.contains(dimensionNames, dimConf.data.dimensionName) && pt.store.dataSetSelected.data.length) {
 					for (var i = 0; i < pt.init.degs.length; i++) {
-						if (Ext.Array.contains(settingsNames, pt.init.degs[i].id)) {
+						if (Ext.Array.contains(dimensionNames, pt.init.degs[i].id)) {
 							alert('Data element group sets cannot be specified together with data sets');
 							return;
 						}
@@ -2828,8 +2969,8 @@
 							pt.util.array.sortObjectsByString(ougs);
 							pt.util.array.sortObjectsByString(degs);
 
-							panels = panels.concat(getGroupSetPanels(ougs, 'pt-panel-title-organisationunitgroupset'));
-							panels = panels.concat(getGroupSetPanels(degs, 'pt-panel-title-dataelementgroupset'));
+							panels = panels.concat(getGroupSetPanels(ougs, pt.conf.finals.dimension.organisationUnitGroupSet.objectName, 'pt-panel-title-organisationunitgroupset'));
+							panels = panels.concat(getGroupSetPanels(degs, pt.conf.finals.dimension.dataElementGroupSet.objectName, 'pt-panel-title-dataelementgroupset'));
 
 							last = panels[panels.length - 1];
 							last.cls = 'pt-accordion-last';
@@ -2883,6 +3024,19 @@
 				}
 			});
 
+			favoriteButton = Ext.create('Ext.button.Button', {
+				text: 'Favorites',
+				menu: {},
+				handler: function() {
+					if (pt.viewport.favoriteWindow) {
+						pt.viewport.favoriteWindow.destroy();
+					}
+
+					pt.viewport.favoriteWindow = PT.app.FavoriteWindow();
+					pt.viewport.favoriteWindow.show();
+				}
+			});
+
 			downloadButton = Ext.create('Ext.button.Button', {
 				text: 'Download',
 				disabled: true,
@@ -2951,11 +3105,7 @@
 							height: 18,
 							style: 'border-color: transparent #d1d1d1 transparent transparent; margin-right: 4px',
 						},
-						{
-							text: 'Favorites',
-							handler: function() {
-							}
-						},
+						favoriteButton,
 						downloadButton,
                         '->',
                         {
@@ -2988,6 +3138,121 @@
 				}
 			});
 
+			setFavorite = function(r) {
+
+				// Indicators
+				if (Ext.isArray(r.indicators)) {
+					pt.store.indicatorSelected.removeAll();
+					pt.store.indicatorSelected.add(r.indicators);
+				}
+
+				// Data elements
+				if (Ext.isArray(r.dataElements)) {
+					pt.store.dataElementSelected.removeAll();
+					pt.store.dataElementSelected.add(r.dataElements);
+				}
+
+				// Data sets
+				if (Ext.isArray(r.dataSets)) {
+					pt.store.dataSetsSelected.removeAll();
+					pt.store.dataSetsSelected.add(r.dataSets);
+				}
+
+				// Fixed periods
+				if (Ext.isArray(r.periods)) {
+					pt.store.fixedPeriodSelected.removeAll();
+					pt.store.fixedPeriodSelected.add(r.periods);
+				}
+
+				// Relative periods
+				if (Ext.isObject(r.relativePeriods)) {
+
+					//todo
+					r.relativePeriods.reportingMonth = r.relativePeriods.lastMonth;
+					r.relativePeriods.reportingQuarter = r.relativePeriods.lastQuarter;
+
+					for (var key in r.relativePeriods) {
+						if (r.relativePeriods.hasOwnProperty(key) && pt.conf.period.relativePeriodParamKeys.hasOwnProperty(key)) {
+							var value = pt.conf.period.relativePeriodParamKeys[key];
+							relativePeriod.valueComponentMap[value].setValue(!!r.relativePeriods[key]);
+						}
+					}
+				}
+
+				// Organisation units
+				if (Ext.isArray(r.organisationUnits) && Ext.isObject(r.parentGraphMap)) {
+					for (var key in r.parentGraphMap) {
+						if (r.parentGraphMap.hasOwnProperty(key)) {
+							organisationUnit.treePanel.selectPath('/root' + r.parentGraphMap[key] + '/' + key);
+						}
+					}
+				}
+
+				// Organisation unit group sets
+				if (Ext.isObject(r.organisationUnitGroupSets)) {
+					for (var key in r.organisationUnitGroupSets) {
+						if (r.organisationUnitGroupSets.hasOwnProperty(key)) {
+							groupSetIdStoreMap[key].removeAll();
+							groupSetIdStoreMap[key].add(r.organisationUnitGroupSets[key]);
+						}
+					}
+				}
+
+				// Data element group sets
+				if (Ext.isObject(r.dataElementGroupSets)) {
+					for (var key in r.dataElementGroupSets) {
+						if (r.dataElementGroupSets.hasOwnProperty(key)) {
+							groupSetIdStoreMap[key].removeAll();
+							groupSetIdStoreMap[key].add(r.dataElementGroupSets[key]);
+						}
+					}
+				}
+
+				// Layout
+				pt.viewport.dimensionStore.reset(true);
+				pt.viewport.colStore.removeAll();
+				pt.viewport.rowStore.removeAll();
+				pt.viewport.filterStore.removeAll();
+
+				if (Ext.isArray(r.columnDimensions)) {
+					for (var i = 0, dim; i < r.columnDimensions.length; i++) {
+						dim = pt.conf.finals.dimension.objectNameMap[r.columnDimensions[i]];
+						pt.viewport.colStore.add({
+							id: dim.dimensionName,
+							name: dim.rawValue
+						});
+					}
+				}
+
+				if (Ext.isArray(r.rowDimensions)) {
+					for (var i = 0, dim; i < r.rowDimensions.length; i++) {
+						dim = pt.conf.finals.dimension.objectNameMap[r.rowDimensions[i]];
+						pt.viewport.rowStore.add({
+							id: dim.dimensionName,
+							name: dim.rawValue
+						});
+					}
+				}
+
+				if (Ext.isArray(r.filterDimensions)) {
+					for (var i = 0, dim; i < r.filterDimensions.length; i++) {
+						dim = pt.conf.finals.dimension.objectNameMap[r.filterDimensions[i]];
+						pt.viewport.filterStore.add({
+							id: dim.dimensionName,
+							name: dim.rawValue
+						});
+					}
+				}
+
+				// Options
+				pt.viewport.showSubTotals.setValue(!!r.subtotals);
+				pt.viewport.hideEmptyRows.setValue(!!r.hideEmptyRows);
+				pt.viewport.displayDensity.setValue(!!r.displayDensity);
+				pt.viewport.fontSize.setValue(!!r.fontSize);
+
+				update();
+			};
+
 			viewport = Ext.create('Ext.container.Viewport', {
 				layout: 'border',
 				westRegion: westRegion,
@@ -2995,7 +3260,10 @@
 				updateViewport: update,
 				layoutButton: layoutButton,
 				optionsButton: optionsButton,
+				favoriteButton: favoriteButton,
 				downloadButton: downloadButton,
+				setFavorite: setFavorite,
+				groupSetIdStoreMap: groupSetIdStoreMap,
 				items: [
 					westRegion,
 					centerRegion
@@ -3025,8 +3293,6 @@
 				});
 			}();
 
-			pt.container = centerRegion;
-
 			return viewport;
 		};
 

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js	2013-03-07 14:46:14 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js	2013-03-08 16:25:52 +0000
@@ -5,7 +5,8 @@
 Ext.onReady( function() {
 
 PT.core.getConfigs = function() {
-	var conf = {};
+	var conf = {},
+		dim;
 
 	conf.finals = {
         ajax: {
@@ -43,48 +44,66 @@
             data: {
                 value: 'data',
                 rawValue: 'Data', //i18n PT.i18n.data,
-                paramName: 'dx',
+                dimensionName: 'dx',
+                objectName: 'dx',
                 warning: {
 					filter: '...'//PT.i18n.wm_multiple_filter_ind_de
 				}
             },
             category: {
-				paramName: 'co',
-				rawValue: 'Categories'
+				rawValue: 'Categories',
+				dimensionName: 'co',
+                objectName: 'co',
 			},
             indicator: {
-                value: 'indicator',
+                value: 'indicators',
                 rawValue: 'Indicators', //i18n PT.i18n.indicator,
-                paramName: 'dx'
+                dimensionName: 'dx',
+                objectName: 'in'
             },
             dataElement: {
-                value: 'dataelement',
+                value: 'dataElements',
                 rawValue: 'Data elements', //i18n PT.i18n.data_element,
-                paramName: 'dx'
+                dimensionName: 'dx',
+                objectName: 'de'
             },
             dataSet: {
-				value: 'dataset',
+				value: 'dataSets',
                 rawValue: 'Data sets', //i18n PT.i18n.dataset,
-                paramName: 'dx'
+                dimensionName: 'dx',
+                objectName: 'ds'
 			},
             period: {
                 value: 'period',
                 rawValue: 'Periods', //i18n PT.i18n.period,
-                paramName: 'pe',
+                dimensionName: 'pe',
+                objectName: 'pe',
                 warning: {
 					filter: '...'//PT.i18n.wm_multiple_filter_period
 				}
             },
+            fixedPeriod: {
+				value: 'periods'
+			},
+			relativePeriod: {
+				value: 'relativePeriods'
+			},
             organisationUnit: {
-                value: 'organisationunit',
+                value: 'organisationUnits',
                 rawValue: 'Organisation units', //i18n PT.i18n.organisation_unit,
-                paramName: 'ou',
+                dimensionName: 'ou',
+                objectName: 'ou',
                 warning: {
 					filter: '...'//PT.i18n.wm_multiple_filter_orgunit
 				}
             },
-            organisationUnitGroup: {
-				value: 'organisationunitgroup'
+            organisationUnitGroupSet: {
+				value: 'organisationUnitGroupSets',
+				objectName: 'ougs'
+			},
+            dataElementGroupSet: {
+				value: 'dataElementGroupSets',
+				objectName: 'degs'
 			},
 			value: {
 				value: 'value'
@@ -95,6 +114,18 @@
 		}
 	};
 
+	dim = conf.finals.dimension;
+
+	dim.objectNameMap = {};
+	dim.objectNameMap[dim.data.objectName] = dim.data;
+	dim.objectNameMap[dim.indicator.objectName] = dim.indicator;
+	dim.objectNameMap[dim.dataElement.objectName] = dim.dataElement;
+	dim.objectNameMap[dim.dataSet.objectName] = dim.dataSet;
+	dim.objectNameMap[dim.period.objectName] = dim.period;
+	dim.objectNameMap[dim.organisationUnit.objectName] = dim.organisationUnit;
+	dim.objectNameMap[dim.organisationUnitGroupSet.objectName] = dim.organisationUnitGroupSet;
+	dim.objectNameMap[dim.dataElementGroupSet.objectName] = dim.dataElementGroupSet;
+
 	conf.period = {
 		relativePeriods: {
 			LAST_MONTH: 1,
@@ -108,6 +139,30 @@
 			LAST_YEAR: 1,
 			LAST_5_YEARS: 5
 		},
+		relativePeriodValueKeys: {
+			'LAST_MONTH': 'reportingMonth',
+			'LAST_3_MONTHS': 'last3Months',
+			'LAST_12_MONTHS': 'last12Months',
+			'LAST_QUARTER': 'reportingQuarter',
+			'LAST_4_QUARTERS': 'last4Quarters',
+			'LAST_SIX_MONTH': 'lastSixMonth',
+			'LAST_2_SIXMONTHS': 'last2SixMonths',
+			'THIS_YEAR': 'thisYear',
+			'LAST_YEAR': 'lastYear',
+			'LAST_5_YEARS': 'last5Years'
+		},
+		relativePeriodParamKeys: {
+			'reportingMonth': 'LAST_MONTH',
+			'last3Months': 'LAST_3_MONTHS',
+			'last12Months': 'LAST_12_MONTHS',
+			'reportingQuarter': 'LAST_QUARTER',
+			'last4Quarters': 'LAST_4_QUARTERS',
+			'lastSixMonth': 'LAST_SIX_MONTH',
+			'last2SixMonths': 'LAST_2_SIXMONTHS',
+			'thisYear': 'THIS_YEAR',
+			'lastYear': 'LAST_YEAR',
+			'last5Years': 'LAST_5_YEARS'
+		},
 		periodTypes: [
 			{id: 'Daily', name: 'Daily'},
 			{id: 'Weekly', name: 'Weekly'},
@@ -146,6 +201,7 @@
         window_confirm_width: 250,
         window_share_width: 500,
         grid_favorite_width: 420,
+        grid_row_height: 27,
         treepanel_minheight: 135,
         treepanel_maxheight: 400,
         treepanel_fill_default: 310,
@@ -158,7 +214,7 @@
     };
 
 	conf.pivot = {
-		cellPadding: {
+		displayDensity: {
 			'compact': '3px',
 			'normal': '5px',
 			'comfortable': '10px'
@@ -355,7 +411,7 @@
 		setRelativePeriods: function(rp) {
 			if (rp) {
 				for (var r in rp) {
-					var cmp = pt.util.getCmp('checkbox[paramName="' + r + '"]');
+					var cmp = pt.util.getCmp('checkbox[relativePeriodId="' + r + '"]');
 					if (cmp) {
 						cmp.setValue(rp[r]);
 					}
@@ -383,14 +439,15 @@
 	};
 
 	util.array = {
-		sortDimensions: function(dimensions) {
+		sortDimensions: function(dimensions, key) {
+			key = key || 'dimensionName';
 
 			// Sort object order
 			Ext.Array.sort(dimensions, function(a,b) {
-				if (a.name < b.name) {
+				if (a[key] < b[key]) {
 					return -1;
 				}
-				if (a.name > b.name) {
+				if (a[key] > b[key]) {
 					return 1;
 				}
 				return 0;
@@ -443,40 +500,16 @@
 	};
 
 	util.pivot = {
-		getTdHtml: function(options, config) {
-			var cls,
-				colSpan,
-				rowSpan,
-				htmlValue,
-				cellPadding,
-				fontSize;
-
-			if (!(config && Ext.isObject(config))) {
-				return '';
-			}
-
-			cls = config.cls ? config.cls : '';
-			cls += config.hidden ? ' td-hidden' : '';
-			cls += config.collapsed ? ' td-collapsed' : '';
-			colSpan = config.colSpan ? 'colspan="' + config.colSpan + '"' : '';
-			rowSpan = config.rowSpan ? 'rowspan="' + config.rowSpan + '"' : '';
-			htmlValue = config.collapsed ? '&nbsp;' : config.htmlValue || config.value || '&nbsp;';
-			htmlValue = config.type !== 'dimension' ? pt.util.number.pp(htmlValue) : htmlValue;
-			cellPadding = pt.conf.pivot.cellPadding[config.cellPadding] || pt.conf.pivot.cellPadding[options.cellPadding];
-			fontSize = pt.conf.pivot.fontSize[config.fontSize] || pt.conf.pivot.fontSize[options.fontSize];
-
-			return '<td class="' + cls + '" ' + colSpan + ' ' + rowSpan + ' style="padding:' + cellPadding + '; font-size:' + fontSize + ';">' + htmlValue + '</td>';
-		},
-
 		getTable: function(settings, pt) {
 			var options = settings.options,
-				getParamStringFromDimensions,
 				extendSettings,
+				getSyncronizedXSettings,
+				getParamString,
 				validateResponse,
 				extendResponse,
 				extendAxis,
-				extendRowAxis,
-				getTableHtmlArrays,
+				validateUrl,
+				getTableHtml,
 				initialize,
 
 				dimConf = pt.conf.finals.dimension;
@@ -497,7 +530,7 @@
 						dimensions = Ext.clone(xSettings.dimensions) || [];
 
 					for (var i = 0; i < dimensions.length; i++) {
-						a.push(dimensions[i].name);
+						a.push(dimensions[i].dimensionName);
 					}
 
 					xSettings.dimensionNames = a;
@@ -518,7 +551,7 @@
 					for (var i = 0, dim; i < dimensions.length; i++) {
 						dim = dimensions[i];
 
-						map[dim.name] = dim.items || [];
+						map[dim.dimensionName] = dim.items || [];
 					}
 
 					xSettings.nameItemsMap = map;
@@ -551,7 +584,7 @@
 							dimension;
 
 						for (var i = 0; i < axis.length; i++) {
-							if (axis[i].name === dimensionName) {
+							if (axis[i].dimensionName === dimensionName) {
 								dimension = axis[i];
 							}
 						}
@@ -577,8 +610,8 @@
 				headerNames = getHeaderNames();
 
 				// remove co from settings if it does not exist in response
-				if (Ext.Array.contains(xSettings.dimensionNames, dimConf.category.paramName) && !(Ext.Array.contains(headerNames, dimConf.category.paramName))) {
-					removeDimensionFromSettings(dimConf.category.paramName);
+				if (Ext.Array.contains(xSettings.dimensionNames, dimConf.category.dimensionName) && !(Ext.Array.contains(headerNames, dimConf.category.dimensionName))) {
+					removeDimensionFromSettings(dimConf.category.dimensionName);
 
 					newSettings = pt.api.Settings(settings);
 
@@ -601,9 +634,9 @@
 				for (var i = 0, sortedDim; i < sortedDimensions.length; i++) {
 					sortedDim = sortedDimensions[i];
 
-					paramString += 'dimension=' + sortedDim.name;
+					paramString += 'dimension=' + sortedDim.dimensionName;
 
-					if (sortedDim.name !== pt.conf.finals.dimension.category.paramName) {
+					if (sortedDim.dimensionName !== pt.conf.finals.dimension.category.dimensionName) {
 						paramString += ':' + sortedDim.items.join(';');
 					}
 
@@ -616,7 +649,7 @@
 					for (var i = 0, sortedFilterDim; i < sortedFilterDimensions.length; i++) {
 						sortedFilterDim = sortedFilterDimensions[i];
 
-						paramString += '&filter=' + sortedFilterDim.name + ':' + sortedFilterDim.items.join(';');
+						paramString += '&filter=' + sortedFilterDim.dimensionName + ':' + sortedFilterDim.items.join(';');
 					}
 				}
 
@@ -682,7 +715,7 @@
 								for (var j = 0, item; j < settingsItems.length; j++) {
 									item = settingsItems[j];
 
-									if (header.name === dimConf.period.paramName && pt.conf.period.relativePeriods[item]) {
+									if (header.name === dimConf.period.dimensionName && pt.conf.period.relativePeriods[item]) {
 										orderedResponseItems = responseItems;
 										orderedResponseItems.sort();
 									}
@@ -761,7 +794,7 @@
 					for (var i = 0, dim; i < axis.length; i++) {
 						dim = axis[i];
 
-						a.push(xResponse.nameHeaderMap[dim.name].items);
+						a.push(xResponse.nameHeaderMap[dim.dimensionName].items);
 					}
 
 					return a;
@@ -919,8 +952,19 @@
 				};
 			};
 
+			validateUrl = function(url) {
+				if (!Ext.isString(url) || url.length > 2000) {
+					var percent = ((url.length - 2000) / url.length) * 100;
+					alert('Too many parameters selected. Please reduce the number of parameters by minimum ' + percent.toFixed(0) + '%');
+					return;
+				}
+
+				return true;
+			};
+
 			getTableHtml = function(xColAxis, xRowAxis, xResponse) {
-				var doSubTotals,
+				var getTdHtml,
+					doSubTotals,
 					getColAxisHtmlArray,
 					getRowHtmlArray,
 					rowAxisHtmlArray,
@@ -955,6 +999,31 @@
 					totalColItems = [],
 					htmlArray;
 
+				getTdHtml = function(options, config) {
+					var cls,
+						colSpan,
+						rowSpan,
+						htmlValue,
+						displayDensity,
+						fontSize;
+
+					if (!(config && Ext.isObject(config))) {
+						return '';
+					}
+
+					cls = config.cls ? config.cls : '';
+					cls += config.hidden ? ' td-hidden' : '';
+					cls += config.collapsed ? ' td-collapsed' : '';
+					colSpan = config.colSpan ? 'colspan="' + config.colSpan + '"' : '';
+					rowSpan = config.rowSpan ? 'rowspan="' + config.rowSpan + '"' : '';
+					htmlValue = config.collapsed ? '&nbsp;' : config.htmlValue || config.value || '&nbsp;';
+					htmlValue = config.type !== 'dimension' ? pt.util.number.pp(htmlValue) : htmlValue;
+					displayDensity = pt.conf.pivot.cellPadding[config.displayDensity] || pt.conf.pivot.displayDensity[options.displayDensity];
+					fontSize = pt.conf.pivot.fontSize[config.fontSize] || pt.conf.pivot.fontSize[options.fontSize];
+
+					return '<td class="' + cls + '" ' + colSpan + ' ' + rowSpan + ' style="padding:' + displayDensity + '; font-size:' + fontSize + ';">' + htmlValue + '</td>';
+				};
+
 				doSubTotals = function(xAxis) {
 					return !!options.showSubTotals && xAxis && xAxis.dims > 1;
 
@@ -981,8 +1050,7 @@
 						getEmptyHtmlArray;
 
 					getEmptyHtmlArray = function() {
-						return (xColAxis && xRowAxis) ?
-							pt.util.pivot.getTdHtml(options, {cls: 'pivot-dim-empty', colSpan: xRowAxis.dims, rowSpan: xColAxis.dims}) : '';
+						return (xColAxis && xRowAxis) ? getTdHtml(options, {cls: 'pivot-dim-empty', colSpan: xRowAxis.dims, rowSpan: xColAxis.dims}) : '';
 					};
 
 					if (!(xColAxis && Ext.isObject(xColAxis))) {
@@ -1000,7 +1068,7 @@
 
 						for (var j = 0, id; j < dimItems.length; j++) {
 							id = dimItems[j];
-							dimHtml.push(pt.util.pivot.getTdHtml(options, {
+							dimHtml.push(getTdHtml(options, {
 								type: 'dimension',
 								cls: 'pivot-dim',
 								colSpan: colSpan,
@@ -1008,7 +1076,7 @@
 							}));
 
 							if (doSubTotals(xColAxis) && i === 0) {
-								dimHtml.push(pt.util.pivot.getTdHtml(options, {
+								dimHtml.push(getTdHtml(options, {
 									type: 'dimensionSubtotal',
 									cls: 'pivot-dim-subtotal',
 									rowSpan: xColAxis.dims
@@ -1016,7 +1084,7 @@
 							}
 
 							if (i === 0 && j === (dimItems.length - 1)) {
-								dimHtml.push(pt.util.pivot.getTdHtml(options, {
+								dimHtml.push(getTdHtml(options, {
 									type: 'dimensionTotal',
 									cls: 'pivot-dim-total',
 									rowSpan: xColAxis.dims,
@@ -1325,7 +1393,7 @@
 						row = [];
 
 						for (var j = 0; j < mergedObjects[i].length; j++) {
-							row.push(pt.util.pivot.getTdHtml(options, mergedObjects[i][j]));
+							row.push(getTdHtml(options, mergedObjects[i][j]));
 						}
 
 						a.push(row);
@@ -1385,7 +1453,7 @@
 							item = totalColItems[i];
 							item.htmlValue = pt.util.number.roundIf(item.htmlValue, 1).toString();
 
-							a.push(pt.util.pivot.getTdHtml(options, {
+							a.push(getTdHtml(options, {
 								cls: item.cls,
 								htmlValue: item.htmlValue
 							}));
@@ -1407,7 +1475,7 @@
 					if (xColAxis && xRowAxis) {
 						grandTotalSum = Ext.Array.sum(values);
 
-						a.push(pt.util.pivot.getTdHtml(options, {
+						a.push(getTdHtml(options, {
 							cls: 'pivot-value-grandtotal',
 							htmlValue: pt.util.number.roundIf(grandTotalSum, 1).toString()
 						}));
@@ -1424,7 +1492,7 @@
 						a = [];
 
 					if (xRowAxis) {
-						dimTotalArray = [pt.util.pivot.getTdHtml(options, {
+						dimTotalArray = [getTdHtml(options, {
 							cls: 'pivot-dim-total',
 							colSpan: xRowAxis.dims,
 							htmlValue: 'Total'
@@ -1466,10 +1534,7 @@
 				pt.paramString = getParamString(xSettings);
 				url = pt.init.contextPath + '/api/analytics.jsonp' + pt.paramString;
 
-				if (url.length > 2000) {
-					var percent = ((url.length - 2000) / url.length) * 100;
-
-					alert('Too many parameters selected. Please reduce the number of parameters by minimum ' + percent.toFixed(0) + '%');
+				if (!validateUrl(url)) {
 					return;
 				}
 
@@ -1512,8 +1577,8 @@
 
 						html = getTableHtml(xColAxis, xRowAxis, xResponse);
 
-						pt.container.removeAll(true);
-						pt.container.update(html);
+						pt.viewport.centerRegion.removeAll(true);
+						pt.viewport.centerRegion.update(html);
 
 						// After table success
 						pt.util.mask.hideMask();
@@ -1521,10 +1586,28 @@
 						if (pt.viewport.downloadButton) {
 							pt.viewport.downloadButton.enable();
 						}
+
+						pt.xSettings = xSettings;
+						pt.xResponse = xResponse;
 					}
 				});
 
 			}();
+		},
+
+		loadTable: function(id) {
+			if (!Ext.isString(id)) {
+				alert('Invalid id');
+				return;
+			}
+
+			Ext.data.JsonP.request({
+				url: pt.baseUrl + '/api/reportTables/' + id + '.jsonp?links=false',
+				method: 'GET',
+				success: function(r) {
+					pt.viewport.setFavorite(r);
+				}
+			});
 		}
 	};
 
@@ -1545,7 +1628,7 @@
 
 			defaultOptions = {
 				showSubTotals: true,
-				cellPadding: 'normal',
+				displayDensity: 'normal',
 				fontSize: 'normal'
 			};
 
@@ -1558,7 +1641,7 @@
 				remove = false;
 				dimension = axis[i];
 
-				if (dimension.name !== pt.conf.finals.dimension.category.paramName) {
+				if (dimension.dimensionName !== pt.conf.finals.dimension.category.dimensionName) {
 					if (!(Ext.isArray(dimension.items) && dimension.items.length)) {
 						remove = true;
 					}
@@ -1581,6 +1664,7 @@
 		};
 
 		getValidatedAxis = function(axis) {
+
 			if (!(axis && Ext.isArray(axis) && axis.length)) {
 				return;
 			}
@@ -1588,7 +1672,7 @@
 			for (var i = 0, dimension; i < axis.length; i++) {
 				dimension = axis[i];
 
-				if (!(Ext.isObject(dimension) && Ext.isString(dimension.name))) {
+				if (!(Ext.isObject(dimension) && Ext.isString(dimension.dimensionName))) {
 					return;
 				}
 			}
@@ -1604,7 +1688,7 @@
 			}
 
 			options.showSubTotals = Ext.isDefined(options.showSubTotals) ? options.showSubTotals : defaultOptions.showSubTotals;
-			options.cellPadding = options.cellPadding || defaultOptions.cellPadding;
+			options.displayDensity = options.displayDensity || defaultOptions.displayDensity;
 			options.fontSize = options.fontSize || defaultOptions.fontSize;
 
 			return options;
@@ -1612,7 +1696,7 @@
 
 		validateSettings = function() {
 			var a = [].concat(Ext.clone(col), Ext.clone(row), Ext.clone(filter)),
-				names = [],
+				dimensionNames = [],
 				dimConf = pt.conf.finals.dimension;
 
 			if (!(col || row)) {
@@ -1620,19 +1704,14 @@
 				return;
 			}
 
-			// Selected dimensions
+			// Selected dimension names
 			for (var i = 0; i < a.length; i++) {
 				if (a[i]) {
-					names.push(a[i].name);
+					dimensionNames.push(a[i].dimensionName);
 				}
 			}
 
-			//if (!Ext.Array.contains(names, dimConf.data.paramName)) {
-				//alert('At least one indicator, data element or dataset must be specified as column, row or filter');
-				//return;
-			//}
-
-			if (!Ext.Array.contains(names, dimConf.period.paramName)) {
+			if (!Ext.Array.contains(dimensionNames, dimConf.period.dimensionName)) {
 				alert('At least one period must be specified as column, row or filter');
 				return;
 			}
@@ -1666,6 +1745,8 @@
 				obj.filter = filter;
 			}
 
+			obj.objects = config.objects;
+
 			obj.options = getValidatedOptions(config.options);
 
 			return obj;

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js	2013-03-05 11:05:59 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/plugin.js	2013-03-08 16:25:52 +0000
@@ -14,7 +14,7 @@
 	],
 	options: {
 		showSubTotals: false,
-		cellPadding: 'normal',
+		displayDensity: 'normal',
 		fontSize: 'normal'
 	}
 };
@@ -58,7 +58,7 @@
 	},
 	options: {
 		showSubTotals: false,
-		cellPadding: 'normal',
+		displayDensity: 'normal',
 		fontSize: 'normal'
 	}
 };

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css	2013-03-07 14:46:14 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/styles/style.css	2013-03-08 11:00:41 +0000
@@ -20,15 +20,14 @@
  * Menu
  * PT Menu
  *
- * Grid
  * Button
  * Tooltip
  * LoadMask
  *
+ * PT Grid
  * PT Window
  * PT Label
  * PT Textfield
- * PT Menugrid
  * PT Treepanel
  * PT Radiogroup
  * PT Messagebox
@@ -452,33 +451,6 @@
 
 
 /*----------------------------------------------------------------------------
- * Grid
- *--------------------------------------------------------------------------*/
-
-.x-grid-row .x-grid-cell {
-    color: #222;
-    background-color: transparent;
-    border: 1px solid transparent;
-}
-
-.x-grid-row-selected .x-grid-cell {
-    border: 1px solid transparent;
-}
-
-.x-grid-row-over {
-    background-color: #f1f1f1;
-}
-
-.x-grid-row-over .x-grid-cell-first, .x-grid-row-selected .x-grid-cell-first {
-    border-radius: 2px 0 0 2px;
-}
-
-.x-grid-row-over .x-grid-cell-last, .x-grid-row-selected .x-grid-cell-last {
-    border-radius: 0 2px 2px 0;
-}
-
-
-/*----------------------------------------------------------------------------
  * Button
  *--------------------------------------------------------------------------*/
 
@@ -561,6 +533,86 @@
 
 
 /*----------------------------------------------------------------------------
+ * PT Grid
+ *--------------------------------------------------------------------------*/
+
+.pt-grid-row-icon-edit,
+.pt-grid-row-icon-overwrite,
+.pt-grid-row-icon-dashboard,
+.pt-grid-row-icon-delete {
+	width: 16px;
+	height: 16px;
+	cursor: pointer;
+}
+.pt-grid-row-icon-edit {
+	background: url('../images/grid-edit_16.png') no-repeat;
+}
+.pt-grid-row-icon-overwrite {
+	background: url('../images/grid-save_16.png') no-repeat;
+	margin-left: 4px;
+}
+.pt-grid-row-icon-dashboard {
+	background: url('../images/grid-dashboard_16.png') no-repeat;
+	margin-left: 4px;
+}
+.pt-grid-row-icon-delete {
+	background: url('../images/grid-delete_16.png') no-repeat;
+	margin-left: 4px;
+}
+.pt-grid-row-icon-disabled img.pt-grid-row-icon-edit,
+.pt-grid-row-icon-disabled img.pt-grid-row-icon-overwrite,
+.pt-grid-row-icon-disabled img.pt-grid-row-icon-delete {
+	opacity: 0;
+	filter:Alpha(opacity=0);
+}
+.pt-grid-row-icon-disabled * {
+	cursor: default !important;
+}
+.pt-grid-row-icon-disabled img.pt-grid-row-icon-dashboard {
+	cursor: pointer !important;
+}
+
+.pt-grid .x-grid-cell-inner,
+.pt-grid .x-grid-cell-inner * {
+	font-size: 10px !important;
+}
+.pt-grid .x-grid-cell-inner {
+	padding-top: 3px;
+	padding-bottom: 3px;
+}
+
+.pt-grid .x-column-header-text {
+	color: #333;
+}
+.pt-grid .x-grid-header-ct {
+	border-bottom-width: 1px !important;
+	border-bottom-color: #d0d0d0;
+}
+.pt-grid .x-grid-body {
+	border: 1px solid #d0d0d0;
+	border-top: 0 none !important;
+}
+
+.pt-grid .x-grid-dirty-cell { /* hide red "dirty" icon */
+	background-image: none;
+}
+.pt-grid .x-grid-row { /* middle align text in row with image */
+	vertical-align: middle;
+}
+.pt-grid .x-grid-row .x-grid-cell { /* remove blurry borders */
+	border-top: 0 none;
+}
+
+.pt-grid .link,
+.pt-grid .link * {
+	cursor: pointer;
+	cursor: hand;
+	color: blue;
+	text-decoration: underline;
+}
+
+
+/*----------------------------------------------------------------------------
  * PT Window
  *--------------------------------------------------------------------------*/
 
@@ -608,6 +660,14 @@
     border-radius: 2px
 }
 
+	/* Window bbar info */
+.pt-label-info {
+	font-size: 10px !important;
+	color: #666;
+	padding-left: 4px;
+	height: 22px;
+	line-height: 21px;
+}
 
 /*----------------------------------------------------------------------------
  * PT Textfield
@@ -631,53 +691,6 @@
 
 
 /*----------------------------------------------------------------------------
- * PT Menugrid
- *--------------------------------------------------------------------------*/
-
-.pt-menugrid .x-grid-row .x-grid-cell, .pt-menugrid .x-grid-row-selected .x-grid-cell {
-    border: 0 none;
-    background: #f5f5f5;
-}
-.pt-menugrid .x-grid-row .x-grid-cell-first,
-.pt-menugrid .x-grid-row-selected .x-grid-cell-first,
-.pt-menugrid .x-grid-row .x-grid-cell-last,
-.pt-menugrid .x-grid-row-selected .x-grid-cell-last {
-	border: 0 none;
-}
-
-.pt-menugrid .x-grid-row-over .x-grid-cell {
-    border: 0 none;
-    background-color: #e4e4e4;
-    background-image: none;
-}
-.pt-menugrid .x-grid-row-over .x-grid-cell-first,
-.pt-menugrid .x-grid-row-over .x-grid-cell-last {
-	border: 0 none;
-}
-
-.pt-menugrid .x-grid-row-focused .x-grid-cell-inner {
-	background-color: #f1f1f1;
-}
-.pt-menugrid .x-grid-row-focused .x-grid-cell {
-	border-color: #f1f1f1;
-}
-
-	/* DV menu grid icon/text position aligned with menuitem */
-.pt-menugrid .x-grid-cell-inner {
-    padding: 4px 3px 4px 6px;
-    font-size: 10px;
-    color: #444;
-    line-height: 16px;
-    height: 23px;
-}
-
-	/* DV menu grid background now looks like a menu */
-.pt-menugrid .x-grid-view {
-    background-color: #f1f1f1;
-}
-
-
-/*----------------------------------------------------------------------------
  * PT Treepanel
  *--------------------------------------------------------------------------*/