← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 13347: (GIS) Event layer implementation. Work in progress.

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 13347 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2013-12-20 14:40:41 +0100
message:
  (GIS) Event layer implementation. Work in progress.
added:
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdown.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdowndouble.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/data.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_14.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_20.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/organisationunit.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/period.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/trigger.gif
modified:
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/openlayers/OpenLayers.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/chart_14.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/map_14.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/table_14.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/all.js
  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/jsonInitialize.vm
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/chart_14.png
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/map_14.png
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/table_14.png
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/chart_14.png
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/map_14.png
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/table_14.png
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/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-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/openlayers/OpenLayers.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/openlayers/OpenLayers.js	2013-10-10 11:15:21 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/openlayers/OpenLayers.js	2013-12-18 17:22:52 +0000
@@ -27,22 +27,22 @@
  * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
  * Copyright (c) 2006, Yahoo! Inc.
  * All rights reserved.
- * 
+ *
  * Redistribution and use of this software in source and binary forms, with or
  * without modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright notice,
  *   this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright notice,
  *   this list of conditions and the following disclaimer in the documentation
  *   and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
  *   used to endorse or promote products derived from this software without
  *   specific prior written permission of Yahoo! Inc.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -52,7 +52,7 @@
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
 var OpenLayers={VERSION_NUMBER:"Release 2.12",singleFile:!0,_getScriptLocation:function(){for(var a=/(^|(.*?\/))(OpenLayers[^\/]*?\.js)(\?|$)/,b=document.getElementsByTagName("script"),c,d="",e=0,f=b.length;e<f;e++)if(c=b[e].getAttribute("src"))if(c=c.match(a)){d=c[1];break}return function(){return d}}(),ImgPath:""};OpenLayers.Class=function(){var a=arguments.length,b=arguments[0],c=arguments[a-1],d="function"==typeof c.initialize?c.initialize:function(){b.prototype.initialize.apply(this,arguments)};1<a?(a=[d,b].concat(Array.prototype.slice.call(arguments).slice(1,a-1),c),OpenLayers.inherit.apply(null,a)):d.prototype=c;return d};
@@ -798,23 +798,23 @@
 OpenLayers.Popup.OPACITY=1;OpenLayers.Popup.BORDER="0px";OpenLayers.Popup.Anchored=OpenLayers.Class(OpenLayers.Popup,{relativePosition:null,keepInMap:!0,anchor:null,initialize:function(a,b,c,d,e,f,g){OpenLayers.Popup.prototype.initialize.apply(this,[a,b,c,d,f,g]);this.anchor=null!=e?e:{size:new OpenLayers.Size(0,0),offset:new OpenLayers.Pixel(0,0)}},destroy:function(){this.relativePosition=this.anchor=null;OpenLayers.Popup.prototype.destroy.apply(this,arguments)},show:function(){this.updatePosition();OpenLayers.Popup.prototype.show.apply(this,arguments)},
 moveTo:function(a){var b=this.relativePosition;this.relativePosition=this.calculateRelativePosition(a);a=this.calculateNewPx(a);OpenLayers.Popup.prototype.moveTo.apply(this,Array(a));this.relativePosition!=b&&this.updateRelativePosition()},setSize:function(a){OpenLayers.Popup.prototype.setSize.apply(this,arguments);this.lonlat&&this.map&&this.moveTo(this.map.getLayerPxFromLonLat(this.lonlat))},calculateRelativePosition:function(a){a=this.map.getLonLatFromLayerPx(a);a=this.map.getExtent().determineQuadrant(a);
 return OpenLayers.Bounds.oppositeQuadrant(a)},updateRelativePosition:function(){},calculateNewPx:function(a){var a=a.offset(this.anchor.offset),b=this.size||this.contentSize,c="t"==this.relativePosition.charAt(0);a.y+=c?-b.h:this.anchor.size.h;c="l"==this.relativePosition.charAt(1);a.x+=c?-b.w:this.anchor.size.w;return a},CLASS_NAME:"OpenLayers.Popup.Anchored"});/*
- Apache 2 
+ Apache 2
 
  Contains portions of Rico <http://openrico.org/>
 
- Copyright 2005 Sabre Airline Solutions  
+ Copyright 2005 Sabre Airline Solutions
 
  Licensed under the Apache License, Version 2.0 (the "License"); you
  may not use this file except in compliance with the License. You
  may obtain a copy of the License at
 
-     http://www.apache.org/licenses/LICENSE-2.0  
+     http://www.apache.org/licenses/LICENSE-2.0
 
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  implied. See the License for the specific language governing
- permissions and limitations under the License. 
+ permissions and limitations under the License.
 */
 OpenLayers.Console.warn("OpenLayers.Rico is deprecated");OpenLayers.Rico=OpenLayers.Rico||{};
 OpenLayers.Rico.Color=OpenLayers.Class({initialize:function(a,b,c){this.rgb={r:a,g:b,b:c}},setRed:function(a){this.rgb.r=a},setGreen:function(a){this.rgb.g=a},setBlue:function(a){this.rgb.b=a},setHue:function(a){var b=this.asHSB();b.h=a;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,b.b)},setSaturation:function(a){var b=this.asHSB();b.s=a;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,b.b)},setBrightness:function(a){var b=this.asHSB();b.b=a;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(b.h,b.s,b.b)},

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties	2013-11-06 19:01:46 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties	2013-12-09 11:30:45 +0000
@@ -400,4 +400,5 @@
 financial_july=Financial July
 financial_april=Financial April
 relative=Relative
-reporting_rates=Reporting rates
\ No newline at end of file
+reporting_rates=Reporting rates
+event_layer=Event layer
\ No newline at end of file

=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdown.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdown.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdown.png	2013-12-13 09:48:48 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdowndouble.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdowndouble.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/arrowdowndouble.png	2013-12-13 09:48:48 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/chart_14.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/chart_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/chart_14.png	2013-12-09 14:13:05 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/data.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/data.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/data.png	2013-12-10 15:51:49 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_14.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_14.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_14.png	2013-12-09 11:30:45 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_20.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_20.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/event_20.png	2013-12-09 11:30:45 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/map_14.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/map_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/map_14.png	2013-12-09 14:13:05 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/organisationunit.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/organisationunit.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/organisationunit.png	2013-12-10 15:51:49 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/period.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/period.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/period.png	2013-12-18 22:13:59 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/table_14.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/table_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/table_14.png	2013-12-09 14:13:05 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/trigger.gif'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/trigger.gif	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/trigger.gif	2013-12-18 22:13:59 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js	2013-12-05 16:36:13 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js	2013-12-20 13:39:21 +0000
@@ -266,7 +266,7 @@
 					svgArray.push(layer.div.innerHTML);
 
 					// Legend
-					if (id !== gis.layer.boundary.id && id !== gis.layer.facility.id) {
+					if (id !== gis.layer.boundary.id && id !== gis.layer.facility.id && id !== gis.layer.event.id) {
 						what = '<g id="indicator" style="display: block; visibility: visible;">' +
 							   '<text id="indicator" x="' + x + '" y="' + y + '" font-size="12">' +
 							   '<tspan>' + Ext.htmlEncode(layer.core.view.columns[0].items[0].name) + '</tspan></text></g>';
@@ -657,8 +657,15 @@
 
 		// layer
 		(function() {
+			layer = gis.layer.event;
+			layer.menu = GIS.app.LayerMenu(layer, 'gis-toolbar-btn-menu-first');
+			layer.widget = GIS.app.LayerWidgetEvent(layer);
+			layer.window = GIS.app.WidgetWindow(layer, gis.conf.layout.widget.window_width + 150, 3);
+			layer.window.widget = layer.widget;
+			GIS.core.createSelectHandlers(gis, layer);
+
 			layer = gis.layer.facility;
-			layer.menu = GIS.app.LayerMenu(layer, 'gis-toolbar-btn-menu-first');
+			layer.menu = GIS.app.LayerMenu(layer);
 			layer.widget = GIS.app.LayerWidgetFacility(layer);
 			layer.window = GIS.app.WidgetWindow(layer);
 			layer.window.widget = layer.widget;
@@ -701,6 +708,7 @@
 	};
 
 	GIS.app.createExtensions = function() {
+
 		Ext.define('Ext.ux.panel.LayerItemPanel', {
 			extend: 'Ext.panel.Panel',
 			alias: 'widget.layeritempanel',
@@ -933,7 +941,490 @@
 				this.callParent();
 			}
 		});
-	};
+
+        Ext.define('Ext.ux.panel.DataElementIntegerContainer', {
+			extend: 'Ext.container.Container',
+			alias: 'widget.dataelementintegerpanel',
+			layout: 'column',
+            bodyStyle: 'border:0 none',
+            getRecord: function() {
+                return {
+                    id: this.dataElement.id,
+                    name: this.dataElement.name,
+                    operator: this.operatorCmp.getValue(),
+                    value: this.valueCmp.getValue()
+                };
+            },
+            initComponent: function() {
+                var container = this;
+
+                this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
+                    valueField: 'id',
+                    displayField: 'name',
+                    queryMode: 'local',
+                    editable: false,
+                    width: 70,
+                    value: 'EQ',
+                    store: {
+                        fields: ['id', 'name'],
+                        data: [
+                            {id: 'EQ', name: '='},
+                            {id: 'GT', name: '>'},
+                            {id: 'GE', name: '>='},
+                            {id: 'LT', name: '<'},
+                            {id: 'LE', name: '<='},
+                            {id: 'NE', name: '!='}
+                        ]
+                    }
+                });
+
+                this.valueCmp = Ext.create('Ext.form.field.Number', {
+                    width: 300,
+                    value: 0
+                });
+
+                this.addCmp = Ext.create('Ext.button.Button', {
+                    text: '+',
+                    width: 20,
+                    handler: function() {
+						container.duplicateDataElement();
+					}
+                });
+
+                this.removeCmp = Ext.create('Ext.button.Button', {
+                    text: 'x',
+                    width: 20,
+                    handler: function() {
+                        container.removeDataElement();
+                    }
+                });
+
+                this.nameCmp = Ext.create('Ext.form.Label', {
+                    text: this.dataElement.name,
+                    width: 360,
+                    style: 'padding:2px'
+                });
+
+                this.items = [
+                    this.nameCmp,
+                    this.operatorCmp,
+                    this.valueCmp,
+                    this.addCmp,
+                    this.removeCmp
+                ];
+
+                this.callParent();
+            }
+        });
+
+        Ext.define('Ext.ux.panel.DataElementStringContainer', {
+			extend: 'Ext.container.Container',
+			alias: 'widget.dataelementintegerpanel',
+			layout: 'column',
+            bodyStyle: 'border:0 none',
+            getRecord: function() {
+                return {
+                    id: this.dataElement.id,
+                    name: this.dataElement.name,
+                    operator: this.operatorCmp.getValue(),
+                    value: this.valueCmp.getValue()
+                };
+            },
+            initComponent: function() {
+                var container = this;
+
+                this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
+                    valueField: 'id',
+                    displayField: 'name',
+                    queryMode: 'local',
+                    editable: false,
+                    width: 70,
+                    value: 'LIKE',
+                    store: {
+                        fields: ['id', 'name'],
+                        data: [
+                            {id: 'LIKE', name: 'Contains'},
+                            {id: 'EQ', name: 'Is exact'}
+                        ]
+                    }
+                });
+
+                this.valueCmp = Ext.create('Ext.form.field.Text', {
+                    width: 300
+                });
+
+                this.addCmp = Ext.create('Ext.button.Button', {
+                    text: '+',
+                    width: 20
+                });
+
+                this.removeCmp = Ext.create('Ext.button.Button', {
+                    text: 'x',
+                    width: 20,
+                    handler: function() {
+                        container.removeDataElement();
+                    }
+                });
+
+                this.nameCmp = Ext.create('Ext.form.Label', {
+                    text: this.dataElement.name,
+                    width: 360,
+                    style: 'padding:2px'
+                });
+
+                this.items = [
+                    this.nameCmp,
+                    this.operatorCmp,
+                    this.valueCmp,
+                    this.addCmp,
+                    this.removeCmp
+                ];
+
+                this.callParent();
+            }
+        });
+
+        Ext.define('Ext.ux.panel.DataElementDateContainer', {
+			extend: 'Ext.container.Container',
+			alias: 'widget.dataelementdatepanel',
+			layout: 'column',
+            bodyStyle: 'border:0 none',
+            getRecord: function() {
+                return {
+                    id: this.dataElement.id,
+                    name: this.dataElement.name,
+                    operator: this.operatorCmp.getValue(),
+                    value: this.valueCmp.getSubmitValue()
+                };
+            },
+            initComponent: function() {
+                var container = this;
+
+                this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
+                    valueField: 'id',
+                    displayField: 'name',
+                    queryMode: 'local',
+                    editable: false,
+                    width: 70,
+                    value: 'EQ',
+                    store: {
+                        fields: ['id', 'name'],
+                        data: [
+                            {id: 'EQ', name: '='},
+                            {id: 'GT', name: '>'},
+                            {id: 'GE', name: '>='},
+                            {id: 'LT', name: '<'},
+                            {id: 'LE', name: '<='},
+                            {id: 'NE', name: '!='}
+                        ]
+                    }
+                });
+
+                this.valueCmp = Ext.create('Ext.form.field.Date', {
+					width: 300,
+					format: 'Y-m-d'
+				});
+
+                this.addCmp = Ext.create('Ext.button.Button', {
+                    text: '+',
+                    width: 20
+                });
+
+                this.removeCmp = Ext.create('Ext.button.Button', {
+                    text: 'x',
+                    width: 20,
+                    handler: function() {
+                        container.removeDataElement();
+                    }
+                });
+
+                this.nameCmp = Ext.create('Ext.form.Label', {
+                    text: this.dataElement.name,
+                    width: 360,
+                    style: 'padding:2px'
+                });
+
+                this.items = [
+                    this.nameCmp,
+                    this.operatorCmp,
+                    this.valueCmp,
+                    this.addCmp,
+                    this.removeCmp
+                ];
+
+                this.callParent();
+            }
+        });
+
+        Ext.define('Ext.ux.panel.DataElementBooleanContainer', {
+			extend: 'Ext.container.Container',
+			alias: 'widget.dataelementbooleanpanel',
+			layout: 'column',
+            bodyStyle: 'border:0 none',
+            getRecord: function() {
+                return {
+                    id: this.dataElement.id,
+                    name: this.dataElement.name,
+                    value: this.valueCmp.getValue()
+                };
+            },
+            initComponent: function() {
+                var container = this;
+
+                this.valueCmp = Ext.create('Ext.form.field.ComboBox', {
+                    valueField: 'id',
+                    displayField: 'name',
+                    queryMode: 'local',
+                    editable: false,
+                    width: 70,
+                    value: 'false',
+                    store: {
+                        fields: ['id', 'name'],
+                        data: [
+                            {id: 'true', name: 'Yes'},
+                            {id: 'false', name: 'No'}
+                        ]
+                    }
+                });
+
+                this.addCmp = Ext.create('Ext.button.Button', {
+                    text: '+',
+                    width: 20
+                });
+
+                this.removeCmp = Ext.create('Ext.button.Button', {
+                    text: 'x',
+                    width: 20,
+                    handler: function() {
+                        container.removeDataElement();
+                    }
+                });
+
+                this.nameCmp = Ext.create('Ext.form.Label', {
+                    text: this.dataElement.name,
+                    width: 360,
+                    style: 'padding:2px'
+                });
+
+                this.items = [
+                    this.nameCmp,
+                    this.valueCmp,
+                    this.addCmp,
+                    this.removeCmp
+                ];
+
+                this.callParent();
+            }
+        });
+
+		Ext.define('Ext.ux.panel.DataElementOptionContainer', {
+			extend: 'Ext.container.Container',
+			alias: 'widget.dataelementoptionpanel',
+			layout: 'column',
+            bodyStyle: 'border:0 none',
+            getRecord: function() {
+                return {
+                    id: this.dataElement.id,
+                    name: this.dataElement.name,
+                    operator: this.operatorCmp.getValue(),
+                    value: this.valueCmp.getValue()
+                };
+            },
+            initComponent: function() {
+                var container = this;
+
+                this.nameCmp = Ext.create('Ext.form.Label', {
+                    text: this.dataElement.name,
+                    width: 360,
+                    style: 'padding:2px 2px 2px 1px'
+                });
+
+                this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
+                    valueField: 'id',
+                    displayField: 'name',
+                    queryMode: 'local',
+                    editable: false,
+                    width: 70,
+                    value: 'IN',
+                    store: {
+                        fields: ['id', 'name'],
+                        data: [
+                            {id: 'IN', name: 'One of'}
+                        ]
+                    }							
+                });
+
+                this.valueStore = Ext.create('Ext.data.Store', {
+					fields: ['id', 'name'],
+					data: [],
+					loadOptionSet: function(optionSetId, key, pageSize) {
+						var store = this,
+							params = {};
+
+						params['max'] = pageSize || 15;
+
+						if (key) {
+							params['key'] = key;
+						}
+
+						Ext.Ajax.request({
+							url: gis.init.contextPath + '/api/optionSets/' + optionSetId + '/options.json',
+							params: params,
+							disableCaching: false,
+							success: function(r) {
+								var options = Ext.decode(r.responseText),
+									data = [];
+
+								Ext.each(options, function(option) {
+									data.push({
+										id: option,
+										name: option
+									});
+								});
+
+								store.removeAll();
+								store.add(data);
+							}
+						});
+					},
+                    listeners: {
+						datachanged: function(s) {
+							if (container.searchCmp && s.getRange().length) {
+								container.searchCmp.expand();
+							}
+						}
+					}
+				});
+
+                this.searchCmp = Ext.create('Ext.form.field.ComboBox', {
+                    width: 62,
+                    emptyText: 'Search..',
+                    valueField: 'id',
+                    displayField: 'name',
+                    hideTrigger: true,
+                    delimiter: '; ',
+                    enableKeyEvents: true,
+                    queryMode: 'local',
+                    listConfig: {
+                        minWidth: 300
+                    },
+                    store: this.valueStore,
+                    listeners: {
+						keyup: {
+							fn: function(cb) {
+								var value = cb.getValue(),
+									optionSetId = container.dataElement.optionSet.id;
+								
+								// search									
+								container.valueStore.loadOptionSet(optionSetId, value);
+
+                                // trigger
+                                if (!value || (Ext.isString(value) && value.length === 1)) {
+									container.triggerCmp.setDisabled(!!value);
+								}
+							}
+						},
+						select: function(cb) {
+
+                            // value
+							container.valueCmp.addOptionValue(cb.getValue());
+
+                            // search
+							cb.clearValue();
+
+                            // trigger
+                            container.triggerCmp.enable();
+						}
+					}
+                });
+
+                this.triggerCmp = Ext.create('Ext.button.Button', {
+                    cls: 'gis-button-combotrigger',
+                    disabledCls: 'gis-button-combotrigger-disabled',
+                    width: 18,
+                    height: 22,
+                    storage: [],
+                    handler: function(b) {
+                        if (b.storage.length) {
+							container.valueStore.removeAll();
+                            container.valueStore.add(Ext.clone(b.storage));
+                        }
+                        else {
+                            Ext.Ajax.request({
+                                url: gis.init.contextPath + '/api/optionSets/' + container.dataElement.optionSet.id + '/options.json',
+                                params: {
+                                    'max': 15
+                                },
+                                success: function(r) {
+                                    var options = Ext.decode(r.responseText),
+                                        data = [];
+
+                                    Ext.each(options, function(option) {
+                                        data.push({
+                                            id: option,
+                                            name: option
+                                        });
+                                    });
+
+                                    b.storage = Ext.clone(data);
+									container.valueStore.removeAll();
+                                    container.valueStore.add(data);
+                                }
+                            });
+                        }
+                    }
+                });
+
+                this.valueCmp = Ext.create('Ext.form.field.Text', {
+					width: 220,
+					addOptionValue: function(option) {
+						var value = this.getValue();
+
+						if (value) {
+							var a = value.split(';');
+
+							for (var i = 0; i < a.length; i++) {
+								a[i] = Ext.String.trim(a[i]);
+							};
+
+							a = Ext.Array.clean(a);
+
+							value = a.join('; ');
+							value += '; ';
+						}
+
+						this.setValue(value += option);
+					}
+				});
+
+                this.addCmp = Ext.create('Ext.button.Button', {
+                    text: '+',
+                    width: 20,
+                    style: 'font-weight:bold'
+                });
+
+                this.removeCmp = Ext.create('Ext.button.Button', {
+                    text: 'x',
+                    width: 20,
+                    handler: function() {
+                        container.removeDataElement();
+                    }
+                });
+
+                this.items = [
+                    this.nameCmp,
+                    this.operatorCmp,
+                    this.searchCmp,
+                    this.triggerCmp,
+                    this.valueCmp,
+                    this.addCmp,
+                    this.removeCmp
+                ];
+
+                this.callParent();
+            }
+        });
+    };
 
     // Objects
 
@@ -972,7 +1463,7 @@
 		};
 		items.push(item);
 
-		if (!(layer.id === gis.layer.boundary.id || layer.id === gis.layer.facility.id)) {
+		if (!(layer.id === gis.layer.boundary.id || layer.id === gis.layer.facility.id || layer.id === gis.layer.event.id)) {
 			item = {
 				text: GIS.i18n.filter + '..',
 				iconCls: 'gis-menu-item-icon-filter',
@@ -1108,16 +1599,19 @@
 		return panel;
 	};
 
-	GIS.app.WidgetWindow = function(layer) {
+	GIS.app.WidgetWindow = function(layer, width, padding) {
+		width = width || gis.conf.layout.widget.window_width;
+		padding = padding || 5;
+		
 		return Ext.create('Ext.window.Window', {
 			//autoShow: true,
 			title: layer.name,
 			layout: 'fit',
 			iconCls: 'gis-window-title-icon-' + layer.id,
-            bodyStyle: 'padding:5px',
+            bodyStyle: 'padding:' + padding + 'px',
 			cls: 'gis-container-default',
 			closeAction: 'hide',
-			width: gis.conf.layout.widget.window_width,
+			width: width,
 			resizable: false,
 			isRendered: false,
 			items: layer.widget,
@@ -2151,17 +2645,20 @@
 			enableKeyEvents: true,
 			currentValue: '',
 			listeners: {
-				keyup: function() {
-					if (this.getValue() !== this.currentValue) {
-						this.currentValue = this.getValue();
-
-						var value = this.getValue(),
-							url = value ? gis.init.contextPath + gis.conf.finals.url.path_api + 'maps/query/' + value + '.json?viewClass=sharing&links=false' : null,
-							store = gis.store.maps;
-
-						store.page = 1;
-						store.loadStore(url);
-					}
+				keyup: {
+					fn: function() {
+						if (this.getValue() !== this.currentValue) {
+							this.currentValue = this.getValue();
+
+							var value = this.getValue(),
+								url = value ? gis.init.contextPath + gis.conf.finals.url.path_api + 'maps/query/' + value + '.json?viewClass=sharing&links=false' : null,
+								store = gis.store.maps;
+
+							store.page = 1;
+							store.loadStore(url);
+						}
+					},
+					buffer: 100
 				}
 			}
 		});
@@ -3415,6 +3912,1827 @@
 		return layer;
 	};
 
+	GIS.app.LayerWidgetEvent = function(layer) {
+
+		// stores
+		var programStore,
+			stagesByProgramStore,
+            dataElementsByStageStore,
+
+		// components
+			program,
+            onProgramSelect,
+			stage,
+            onStageSelect,
+            loadDataElements,
+            dataElementAvailable,
+            dataElementSelected,
+            addUxFromDataElement,
+            selectDataElements,
+            dataElement,
+
+			startDate,
+			endDate,
+			period,
+
+			treePanel,
+			userOrganisationUnit,
+			userOrganisationUnitChildren,
+			userOrganisationUnitGrandChildren,
+			organisationUnitLevel,
+			organisationUnitGroup,
+			toolMenu,
+			tool,
+			toolPanel,
+            organisationUnit,
+
+			panel,
+
+		// functions
+			reset,
+			setGui,
+			getView,
+			validateView,
+
+        // constants
+            baseWidth = 442,
+            toolWidth = 36,
+
+            accBaseWidth = baseWidth - 6;
+
+
+		// stores
+
+		programStore = Ext.create('Ext.data.Store', {
+			fields: ['id', 'name'],
+			proxy: {
+				type: 'ajax',
+				url: gis.init.contextPath + '/api/programs.json?links=false',
+				reader: {
+					type: 'json',
+					root: 'programs'
+				}
+			},
+			sortInfo: {field: 'name', direction: 'ASC'},
+			isLoaded: false,
+			listeners: {
+				load: function() {
+					if (!this.isLoaded) {
+						this.isLoaded = true;
+					}
+				}
+			}
+		});
+
+		stagesByProgramStore = Ext.create('Ext.data.Store', {
+			fields: ['id', 'name'],
+			proxy: {
+				type: 'ajax',
+				url: '',
+				reader: {
+					type: 'json',
+					root: 'programStages'
+				}
+			},
+			isLoaded: false,
+			loadFn: function(fn) {
+				if (Ext.isFunction(fn)) {
+					if (this.isLoaded) {
+						fn.call();
+					}
+					else {
+						this.load({
+							callback: fn
+						});
+					}
+				}
+			},
+			listeners: {
+				load: function() {
+					if (!this.isLoaded) {
+						this.isLoaded = true;
+					}
+					this.sort('name', 'ASC');
+				}
+			}
+		});
+
+		dataElementsByStageStore = Ext.create('Ext.data.Store', {
+			fields: [''],
+			data: [],
+			sorters: [{
+				property: 'name',
+				direction: 'ASC'
+			}]
+		});
+
+		// components
+
+            // data element
+		program = Ext.create('Ext.form.field.ComboBox', {
+			fieldLabel: GIS.i18n.programs,
+			editable: false,
+			valueField: 'id',
+			displayField: 'name',
+			fieldLabel: 'Program',
+			labelAlign: 'top',
+			labelCls: 'gis-form-item-label-top',
+			labelSeparator: '',
+			emptyText: 'Select program',
+			forceSelection: true,
+			queryMode: 'remote',
+			//width: gis.conf.layout.widget.item_width,
+			columnWidth: 0.5,
+			style: 'margin:1px 1px 2px 0',
+			//labelWidth: gis.conf.layout.widget.itemlabel_width,
+			store: programStore,
+            getRecord: function() {
+                return {
+                    id: this.getValue(),
+                    name: this.getRawValue()
+                };
+            },
+			listeners: {
+				select: function(cb) {
+					onProgramSelect(cb.getValue());
+				}
+			}
+		});
+
+		onProgramSelect = function(programId) {
+			stage.clearValue();
+
+			stagesByProgramStore.proxy.url = gis.init.contextPath + '/api/programs/' + programId + '.json?viewClass=withoutOrganisationUnits&links=false&paging=false';
+			stagesByProgramStore.load({
+				callback: function(records) {
+					stage.enable();
+					stage.clearValue();
+					stage.queryMode = 'local';
+
+					if (records.length === 1) {
+						stage.setValue(records[0].data.id);
+
+						onStageSelect(records[0].data.id);
+					}
+				}
+			});
+
+		};
+
+		stage = Ext.create('Ext.form.field.ComboBox', {
+			fieldLabel: GIS.i18n.indicator,
+			editable: false,
+			valueField: 'id',
+			displayField: 'name',
+			fieldLabel: 'Stage',
+			labelAlign: 'top',
+			labelCls: 'gis-form-item-label-top',
+			labelSeparator: '',
+			emptyText: 'Select stage',
+			queryMode: 'remote',
+			forceSelection: true,
+			//width: gis.conf.layout.widget.item_width,
+			columnWidth: 0.5,
+			style: 'margin:1px 0 2px 1px',
+			disabled: true,
+			//labelWidth: gis.conf.layout.widget.itemlabel_width,
+			listConfig: {loadMask: false},
+			store: stagesByProgramStore,
+            getRecord: function() {
+                return {
+                    id: this.getValue(),
+                    name: this.getRawValue()
+                };
+            },
+			listeners: {
+				select: function(cb) {
+					onStageSelect(cb.getValue());
+				}
+			}
+		});
+
+		onStageSelect = function(stageId) {
+			dataElementSelected.removeAll();
+
+			loadDataElements(stageId);
+		};
+
+		loadDataElements = function(param) {
+			if (Ext.isString(param)) {
+				Ext.Ajax.request({
+					url: gis.init.contextPath + '/api/programStages/' + param + '.json?links=false&paging=false',
+					success: function(r) {
+						var dataElements = Ext.Array.pluck(Ext.decode(r.responseText).programStageDataElements, 'dataElement');
+
+						dataElementsByStageStore.loadData(dataElements);
+					}
+				});
+			}
+			else if (Ext.isArray(param)) {
+				dataElementsByStageStore.loadData(param);
+			}
+		};
+
+		dataElementAvailable = Ext.create('Ext.ux.form.MultiSelect', {
+			cls: 'ns-toolbar-multiselect-left',
+			width: accBaseWidth,
+            height: 112,
+			valueField: 'id',
+			displayField: 'name',
+            style: 'margin-bottom:2px',
+			store: dataElementsByStageStore,
+			tbar: [
+				{
+					xtype: 'label',
+					//text: GIS.i18n.available,
+                    text: 'Available data elements',
+					cls: 'ns-toolbar-multiselect-left-label'
+				},
+				'->',
+				{
+					xtype: 'button',
+					icon: 'images/arrowdown.png',
+					width: 22,
+					height: 22,
+					handler: function() {
+                        if (dataElementAvailable.getValue().length) {
+                            selectDataElements(dataElementAvailable.getValue());
+                        }
+					}
+				},
+				{
+					xtype: 'button',
+					icon: 'images/arrowdowndouble.png',
+					width: 22,
+					height: 22,
+					handler: function() {
+                        if (dataElementsByStageStore.getRange().length) {
+                            selectDataElements(dataElementsByStageStore.getRange());
+                        }
+					}
+				}
+			],
+			listeners: {
+				afterrender: function(ms) {
+					this.boundList.on('itemdblclick', function() {
+                        if (ms.getValue().length) {
+                            selectDataElements(ms.getValue());
+                        }
+					});
+				}
+			}
+		});
+
+        dataElementSelected = Ext.create('Ext.panel.Panel', {
+			width: accBaseWidth,
+            height: 204,
+            bodyStyle: 'padding:2px 5px 5px; overflow-y: scroll',
+            tbar: {
+                height: 27,
+                items: {
+					xtype: 'label',
+					//text: GIS.i18n.available,
+                    text: 'Selected data elements',
+                    style: 'padding-left:6px; color:#222',
+					cls: 'ns-toolbar-multiselect-left-label'
+				}
+            },
+            getChildIndex: function(child) {
+				this.items.each(function(item, index) {
+					if (item.id === child.id) {
+						return index;
+					}
+				});
+			},
+			hasDataElement: function(dataElementId) {
+				var hasDataElement = false;
+				
+				this.items.each(function(item) {				
+					if (item.dataElement.id === dataElementId) {
+						hasDataElement = true;
+					}
+				});
+
+				return hasDataElement;
+			}					
+        });
+
+        addUxFromDataElement = function(element, index) {
+			var getUxType,
+				ux;
+
+			index = index || dataElementSelected.items.items.length;
+
+			getUxType = function(element) {
+				if (Ext.isObject(element.optionSet) && Ext.isString(element.optionSet.id)) {
+					return 'Ext.ux.panel.DataElementOptionContainer';
+				}
+
+				if (element.type === 'int') {
+					return 'Ext.ux.panel.DataElementIntegerContainer';
+				}
+
+				if (element.type === 'string') {
+					return 'Ext.ux.panel.DataElementStringContainer';
+				}
+
+				if (element.type === 'date') {
+					return 'Ext.ux.panel.DataElementDateContainer';
+				}
+
+				return 'Ext.ux.panel.DataElementIntegerContainer';
+			};
+
+			// add
+			ux = dataElementSelected.insert(index, Ext.create(getUxType(element), {
+				dataElement: element
+			}));
+
+			ux.removeDataElement = function() {
+				dataElementSelected.remove(ux);
+
+				if (!dataElementSelected.hasDataElement(element.id)) {
+					dataElementsByStageStore.add(element);
+					dataElementsByStageStore.sort();
+				}
+			};
+
+			ux.duplicateDataElement = function() {
+				var index = dataElementSelected.getChildIndex(ux) + 1;
+
+				addUxFromDataElement(element, index);
+			};
+
+			dataElementsByStageStore.removeAt(dataElementsByStageStore.findExact('id', element.id));
+		};			
+
+        selectDataElements = function(items) {
+            var dataElements = [];
+
+			// data element objects
+            for (var i = 0, item; i < items.length; i++) {
+				item = items[i];
+				
+                if (Ext.isString(item)) {
+                    dataElements.push(dataElementsByStageStore.getAt(dataElementsByStageStore.findExact('id', item)).data);
+                }
+                else if (Ext.isObject(item)) {
+                    if (item.data) {
+                        dataElements.push(item.data);
+                    }
+                    else {
+                        dataElements.push(item);
+                    }
+                }
+            }
+
+			// panel, store
+            for (var i = 0, element, ux; i < dataElements.length; i++) {
+				element = dataElements[i];
+
+				addUxFromDataElement(element);
+			}
+        };
+
+        dataElement = Ext.create('Ext.panel.Panel', {
+            title: '<div class="gis-panel-title-data">Data elements</div>',
+            bodyStyle: 'padding:2px',
+            hideCollapseTool: true,
+            items: [
+                {
+					layout: 'column',
+                    bodyStyle: 'border:0 none',
+					style: 'margin-top:2px',
+					items: [
+						program,
+						stage
+					]
+				},
+                dataElementAvailable,
+                dataElementSelected
+            ]
+        });
+
+            // date
+		startDate = Ext.create('Ext.form.field.Date', {
+			fieldLabel: 'Start date',
+			labelAlign: 'top',
+			labelCls: 'gis-form-item-label-top',
+            //labelStyle: 'font-weight: bold',
+			labelSeparator: '',
+			columnWidth: 0.5,
+			style: 'margin-right: 1px',
+			format: 'Y-m-d',
+			//value: new Date( (new Date()).setMonth( (new Date()).getMonth() - 3))
+            value: new Date('2012-01-01') //todo
+		});
+
+		endDate = Ext.create('Ext.form.field.Date', {
+			fieldLabel: 'End date',
+			labelAlign: 'top',
+			labelCls: 'gis-form-item-label-top',
+            //labelStyle: 'font-weight: bold',
+			labelSeparator: '',
+			columnWidth: 0.5,
+			style: 'margin-left: 1px',
+			format: 'Y-m-d',
+			value: new Date()
+		});
+
+        period = Ext.create('Ext.panel.Panel', {
+            title: '<div class="gis-panel-title-period">Periods</div>',
+            bodyStyle: 'padding:4px 2px 2px',
+            hideCollapseTool: true,
+            layout: 'column',
+            width: accBaseWidth,
+            items: [
+                startDate,
+                endDate
+            ]
+        });
+
+            // organisation unit
+		treePanel = Ext.create('Ext.tree.Panel', {
+			cls: 'gis-tree',
+			height: 333,
+            bodyStyle: 'border:0 none',
+			style: 'border-top: 1px solid #ddd; padding-top: 1px',
+			displayField: 'name',
+			rootVisible: false,
+			autoScroll: true,
+			multiSelect: true,
+			rendered: false,
+			reset: function() {
+				var rootNode = this.getRootNode().findChild('id', gis.init.rootNodes[0].id);
+				this.collapseAll();
+				this.expandPath(rootNode.getPath());
+				this.getSelectionModel().select(rootNode);
+			},
+			selectRootIf: function() {
+				if (this.getSelectionModel().getSelection().length < 1) {
+					var node = this.getRootNode().findChild('id', gis.init.rootNodes[0].id);
+					if (this.rendered) {
+						this.getSelectionModel().select(node);
+					}
+					return node;
+				}
+			},
+			isPending: false,
+			recordsToSelect: [],
+			recordsToRestore: [],
+			multipleSelectIf: function(map, doUpdate) {
+				if (this.recordsToSelect.length === gis.util.object.getLength(map)) {
+					this.getSelectionModel().select(this.recordsToSelect);
+					this.recordsToSelect = [];
+					this.isPending = false;
+
+					if (doUpdate) {
+						update();
+					}
+				}
+			},
+			multipleExpand: function(id, map, doUpdate) {
+				var that = this,
+					rootId = gis.conf.finals.root.id,
+					path = map[id];
+
+				if (path.substr(0, rootId.length + 1) !== ('/' + rootId)) {
+					path = '/' + rootId + path;
+				}
+
+				that.expandPath(path, 'id', '/', function() {
+					record = Ext.clone(that.getRootNode().findChild('id', id, true));
+					that.recordsToSelect.push(record);
+					that.multipleSelectIf(map, doUpdate);
+				});
+			},
+            select: function(url, params) {
+                if (!params) {
+                    params = {};
+                }
+                Ext.Ajax.request({
+                    url: url,
+                    method: 'GET',
+                    params: params,
+                    scope: this,
+                    success: function(r) {
+                        var a = Ext.decode(r.responseText).organisationUnits;
+                        this.numberOfRecords = a.length;
+                        for (var i = 0; i < a.length; i++) {
+                            this.multipleExpand(a[i].id, a[i].path);
+                        }
+                    }
+                });
+            },
+			getParentGraphMap: function() {
+				var selection = this.getSelectionModel().getSelection(),
+					map = {};
+
+				if (Ext.isArray(selection) && selection.length) {
+					for (var i = 0, pathArray, key; i < selection.length; i++) {
+						pathArray = selection[i].getPath().split('/');
+						map[pathArray.pop()] = pathArray.join('/');
+					}
+				}
+
+				return map;
+			},
+			selectGraphMap: function(map, update) {
+				if (!gis.util.object.getLength(map)) {
+					return;
+				}
+
+				this.isPending = true;
+
+				for (var key in map) {
+					if (map.hasOwnProperty(key)) {
+						treePanel.multipleExpand(key, map, update);
+					}
+				}
+			},
+			store: Ext.create('Ext.data.TreeStore', {
+				fields: ['id', 'name'],
+				proxy: {
+					type: 'rest',
+					format: 'json',
+					noCache: false,
+					extraParams: {
+						links: 'false'
+					},
+					url: gis.init.contextPath + '/api/organisationUnits',
+					reader: {
+						type: 'json',
+						root: 'children'
+					}
+				},
+				sorters: [{
+					property: 'name',
+					direction: 'ASC'
+				}],
+				root: {
+					id: gis.conf.finals.root.id,
+					expanded: true,
+					children: gis.init.rootNodes
+				},
+				listeners: {
+					load: function(store, node, records) {
+						Ext.Array.each(records, function(record) {
+							record.set('leaf', !record.raw.hasChildren);
+						});
+					}
+				}
+			}),
+			xable: function(values) {
+				for (var i = 0; i < values.length; i++) {
+					if (!!values[i]) {
+						this.disable();
+						return;
+					}
+				}
+
+				this.enable();
+			},
+			getDimension: function() {
+				var r = treePanel.getSelectionModel().getSelection(),
+					config = {
+						dimension: gis.conf.finals.dimension.organisationUnit.objectName,
+						items: []
+					};
+
+				if (toolMenu.menuValue === 'orgunit') {
+					if (userOrganisationUnit.getValue() || userOrganisationUnitChildren.getValue() || userOrganisationUnitGrandChildren.getValue()) {
+						if (userOrganisationUnit.getValue()) {
+							config.items.push({
+								id: 'USER_ORGUNIT',
+								name: ''
+							});
+						}
+						if (userOrganisationUnitChildren.getValue()) {
+							config.items.push({
+								id: 'USER_ORGUNIT_CHILDREN',
+								name: ''
+							});
+						}
+						if (userOrganisationUnitGrandChildren.getValue()) {
+							config.items.push({
+								id: 'USER_ORGUNIT_GRANDCHILDREN',
+								name: ''
+							});
+						}
+					}
+					else {
+						for (var i = 0; i < r.length; i++) {
+							config.items.push({id: r[i].data.id});
+						}
+					}
+				}
+				else if (toolMenu.menuValue === 'level') {
+					var levels = organisationUnitLevel.getValue();
+
+					for (var i = 0; i < levels.length; i++) {
+						config.items.push({
+							id: 'LEVEL-' + levels[i],
+							name: ''
+						});
+					}
+
+					for (var i = 0; i < r.length; i++) {
+						config.items.push({
+							id: r[i].data.id,
+							name: ''
+						});
+					}
+				}
+				else if (toolMenu.menuValue === 'group') {
+					var groupIds = organisationUnitGroup.getValue();
+
+					for (var i = 0; i < groupIds.length; i++) {
+						config.items.push({
+							id: 'OU_GROUP-' + groupIds[i],
+							name: ''
+						});
+					}
+
+					for (var i = 0; i < r.length; i++) {
+						config.items.push({
+							id: r[i].data.id,
+							name: ''
+						});
+					}
+				}
+
+				return config.items.length ? config : null;
+			},
+			listeners: {
+				beforeitemexpand: function() {
+					var rts = treePanel.recordsToSelect;
+
+					if (!treePanel.isPending) {
+						treePanel.recordsToRestore = treePanel.getSelectionModel().getSelection();
+					}
+				},
+				itemexpand: function() {
+					if (!treePanel.isPending && treePanel.recordsToRestore.length) {
+						treePanel.getSelectionModel().select(treePanel.recordsToRestore);
+						treePanel.recordsToRestore = [];
+					}
+				},
+				render: function() {
+					this.rendered = true;
+				},
+				afterrender: function() {
+					this.getSelectionModel().select(0);
+				},
+				itemcontextmenu: function(v, r, h, i, e) {
+					v.getSelectionModel().select(r, false);
+
+					if (v.menu) {
+						v.menu.destroy();
+					}
+					v.menu = Ext.create('Ext.menu.Menu', {
+						id: 'treepanel-contextmenu',
+						showSeparator: false,
+						shadow: false
+					});
+					if (!r.data.leaf) {
+						v.menu.add({
+							id: 'treepanel-contextmenu-item',
+							text: gis.i18n.select_all_children,
+							icon: 'images/node-select-child.png',
+							handler: function() {
+								r.expand(false, function() {
+									v.getSelectionModel().select(r.childNodes, true);
+									v.getSelectionModel().deselect(r);
+								});
+							}
+						});
+					}
+					else {
+						return;
+					}
+
+					v.menu.showAt(e.xy);
+				}
+			}
+		});
+
+		userOrganisationUnit = Ext.create('Ext.form.field.Checkbox', {
+			columnWidth: 0.28,
+			style: 'padding-top:2px; padding-left:3px; margin-bottom:0',
+			boxLabelCls: 'x-form-cb-label-alt1',
+			boxLabel: 'User org unit',
+			labelWidth: gis.conf.layout.form_label_width,
+			handler: function(chb, checked) {
+				treePanel.xable([checked, userOrganisationUnitChildren.getValue(), userOrganisationUnitGrandChildren.getValue()]);
+			}
+		});
+
+		userOrganisationUnitChildren = Ext.create('Ext.form.field.Checkbox', {
+			columnWidth: 0.34,
+			style: 'padding-top:2px; margin-bottom:0',
+			boxLabelCls: 'x-form-cb-label-alt1',
+			boxLabel: 'User OU children',
+			labelWidth: gis.conf.layout.form_label_width,
+			handler: function(chb, checked) {
+				treePanel.xable([checked, userOrganisationUnit.getValue(), userOrganisationUnitGrandChildren.getValue()]);
+			}
+		});
+
+		userOrganisationUnitGrandChildren = Ext.create('Ext.form.field.Checkbox', {
+			columnWidth: 0.38,
+			style: 'padding-top:2px; margin-bottom:0',
+			boxLabelCls: 'x-form-cb-label-alt1',
+			boxLabel: 'User OU grand children',
+			labelWidth: gis.conf.layout.form_label_width,
+			handler: function(chb, checked) {
+				treePanel.xable([checked, userOrganisationUnit.getValue(), userOrganisationUnitChildren.getValue()]);
+			}
+		});
+
+		organisationUnitLevel = Ext.create('Ext.form.field.ComboBox', {
+			cls: 'gis-combo',
+			multiSelect: true,
+			style: 'margin-bottom:0',
+			width: accBaseWidth - toolWidth - 2,
+			valueField: 'level',
+			displayField: 'name',
+			emptyText: GIS.i18n.select_organisation_unit_levels,
+			editable: false,
+			hidden: true,
+			store: {
+				fields: ['id', 'name', 'level'],
+				data: gis.init.organisationUnitLevels
+			}
+		});
+
+		organisationUnitGroup = Ext.create('Ext.form.field.ComboBox', {
+			cls: 'gis-combo',
+			multiSelect: true,
+			style: 'margin-bottom:0',
+			width: accBaseWidth - toolWidth - 2,
+			valueField: 'id',
+			displayField: 'name',
+			emptyText: GIS.i18n.select_organisation_unit_groups,
+			editable: false,
+			hidden: true,
+			store: gis.store.organisationUnitGroup
+		});
+
+        organisationUnitPanel = Ext.create('Ext.panel.Panel', {
+			width: accBaseWidth - toolWidth - 2,
+            layout: 'column',
+            bodyStyle: 'border:0 none',
+            items: [
+                userOrganisationUnit,
+                userOrganisationUnitChildren,
+                userOrganisationUnitGrandChildren,
+                organisationUnitLevel,
+                organisationUnitGroup
+            ]
+        });
+
+		toolMenu = Ext.create('Ext.menu.Menu', {
+			shadow: false,
+			showSeparator: false,
+			menuValue: 'orgunit',
+			clickHandler: function(param) {
+				if (!param) {
+					return;
+				}
+
+				var items = this.items.items;
+				this.menuValue = param;
+
+				// Menu item icon cls
+				for (var i = 0; i < items.length; i++) {
+					if (items[i].setIconCls) {
+						if (items[i].param === param) {
+							items[i].setIconCls('gis-menu-item-selected');
+						}
+						else {
+							items[i].setIconCls('gis-menu-item-unselected');
+						}
+					}
+				}
+
+				// Gui
+				if (param === 'orgunit') {
+					userOrganisationUnit.show();
+					userOrganisationUnitChildren.show();
+					userOrganisationUnitGrandChildren.show();
+					organisationUnitLevel.hide();
+					organisationUnitGroup.hide();
+
+					if (userOrganisationUnit.getValue() || userOrganisationUnitChildren.getValue()) {
+						treePanel.disable();
+					}
+				}
+				else if (param === 'level') {
+					userOrganisationUnit.hide();
+					userOrganisationUnitChildren.hide();
+					userOrganisationUnitGrandChildren.hide();
+					organisationUnitLevel.show();
+					organisationUnitGroup.hide();
+					treePanel.enable();
+				}
+				else if (param === 'group') {
+					userOrganisationUnit.hide();
+					userOrganisationUnitChildren.hide();
+					userOrganisationUnitGrandChildren.hide();
+					organisationUnitLevel.hide();
+					organisationUnitGroup.show();
+					treePanel.enable();
+				}
+			},
+			items: [
+				{
+					xtype: 'label',
+					text: 'Selection mode',
+					style: 'padding:7px 5px 5px 7px; font-weight:bold; border:0 none'
+				},
+				{
+					text: GIS.i18n.select_organisation_units + '&nbsp;&nbsp;',
+					param: 'orgunit',
+					iconCls: 'gis-menu-item-selected'
+				},
+				{
+					text: 'Select levels' + '&nbsp;&nbsp;',
+					param: 'level',
+					iconCls: 'gis-menu-item-unselected'
+				},
+				{
+					text: 'Select groups' + '&nbsp;&nbsp;',
+					param: 'group',
+					iconCls: 'gis-menu-item-unselected'
+				}
+			],
+			listeners: {
+				afterrender: function() {
+					this.getEl().addCls('gis-btn-menu');
+				},
+				click: function(menu, item) {
+					this.clickHandler(item.param);
+				}
+			}
+		});
+
+		tool = Ext.create('Ext.button.Button', {
+			cls: 'gis-button-organisationunitselection',
+			iconCls: 'gis-button-icon-gear',
+			width: toolWidth,
+			height: 24,
+			menu: toolMenu
+		});
+
+		toolPanel = Ext.create('Ext.panel.Panel', {
+			width: toolWidth,
+			bodyStyle: 'border:0 none; text-align:right',
+			style: 'margin-right:2px',
+			items: tool
+		});
+
+        organisationUnit = Ext.create('Ext.panel.Panel', {
+            title: '<div class="gis-panel-title-organisationunit">' + GIS.i18n.organisation_units + '</div>',
+            cls: 'gis-accordion-last',
+            bodyStyle: 'padding:2px',
+            hideCollapseTool: true,
+            items: [
+                {
+                    layout: 'column',
+                    width: accBaseWidth,
+                    bodyStyle: 'border:0 none',
+                    style: 'padding-bottom:2px',
+                    items: [
+                        toolPanel,
+                        organisationUnitPanel
+                    ]
+                },
+                treePanel
+            ]
+        });
+
+            // accordion
+        accordionBody = Ext.create('Ext.panel.Panel', {
+			layout: 'accordion',
+			activeOnTop: true,
+			cls: 'gis-accordion',
+			bodyStyle: 'border:0 none',
+			height: 450,
+			items: [
+                dataElement,
+                period,
+                organisationUnit
+            ],
+            listeners: {
+                afterrender: function() { // nasty workaround
+                    organisationUnit.expand();
+                    period.expand();
+                    dataElement.expand();
+                }
+            }
+		});
+
+		// functions
+
+		reset = function(skipTree) {
+
+			// Item
+			layer.item.setValue(false);
+
+			if (!layer.window.isRendered) {
+				layer.core.view = null;
+				return;
+			}
+
+			// Components
+            program.clearValue();
+            stage.clearValue();
+
+            dataElementAvailable.removeAll();
+            dataElementSelected.removeAll();
+
+            startDate.reset();
+            endDate.reset();
+
+			toolMenu.clickHandler(toolMenu.menuValue);
+
+			if (!skipTree) {
+				treePanel.reset();
+			}
+
+			userOrganisationUnit.setValue(false);
+			userOrganisationUnitChildren.setValue(false);
+			userOrganisationUnitGrandChildren.setValue(false);
+
+			organisationUnitLevel.clearValue();
+			organisationUnitGroup.clearValue();
+
+			// Layer options
+			//if (layer.labelWindow) {
+				//layer.labelWindow.destroy();
+				//layer.labelWindow = null;
+			//}
+		};
+
+		setGui = function(view) { //todo
+			var ouDim = view.rows[0],
+				isOu = false,
+				isOuc = false,
+				isOugc = false,
+				levels = [],
+				groups = [],
+				setWidgetGui,
+				setLayerGui;
+
+			setWidgetGui = function() {
+
+				// Components
+				if (!layer.window.isRendered) {
+					return;
+				}
+
+				reset(true);
+
+				// Organisation units
+				for (var i = 0, item; i < ouDim.items.length; i++) {
+					item = ouDim.items[i];
+
+					if (item.id === 'USER_ORGUNIT') {
+						isOu = true;
+					}
+					else if (item.id === 'USER_ORGUNIT_CHILDREN') {
+						isOuc = true;
+					}
+					else if (item.id === 'USER_ORGUNIT_GRANDCHILDREN') {
+						isOugc = true;
+					}
+					else if (item.id.substr(0,5) === 'LEVEL') {
+						levels.push(parseInt(item.id.split('-')[1]));
+					}
+					else if (item.id.substr(0,8) === 'OU_GROUP') {
+						groups.push(parseInt(item.id.split('-')[1]));
+					}
+				}
+
+				if (levels.length) {
+					toolMenu.clickHandler('level');
+					organisationUnitLevel.setValue(levels);
+				}
+				else if (groups.length) {
+					toolMenu.clickHandler('group');
+					organisationUnitGroup.setValue(groups);
+				}
+				else {
+					toolMenu.clickHandler('orgunit');
+					userOrganisationUnit.setValue(isOu);
+					userOrganisationUnitChildren.setValue(isOuc);
+					userOrganisationUnitGrandChildren.setValue(isOugc);
+				}
+
+				treePanel.selectGraphMap(view.parentGraphMap);
+			}();
+
+			setLayerGui = function() {
+
+				// Layer item
+				layer.item.setValue(true, view.opacity);
+
+				// Layer menu
+				layer.menu.enableItems();
+			}();
+		};
+
+		getView = function(config) {
+			var view = {};
+
+            view.program = program.getRecord();
+            view.stage = stage.getRecord();
+
+            view.startDate = startDate.getSubmitValue();
+            view.endDate = endDate.getSubmitValue();
+
+            view.dataElements = [];
+
+            for (var i = 0, panel; i < dataElementSelected.items.items.length; i++) {
+                panel = dataElementSelected.items.items[i];
+
+                view.dataElements.push(panel.getRecord());
+            }
+
+            view.organisationUnits = treePanel.getDimension().items;
+
+			return view;
+		};
+
+		validateView = function(view) {
+			if (!(Ext.isArray(view.rows) && view.rows.length && Ext.isString(view.rows[0].dimension) && Ext.isArray(view.rows[0].items) && view.rows[0].items.length)) {
+				GIS.logg.push([view.rows, layer.id + '.rows: dimension array']);
+				alert('No organisation units selected');
+				return false;
+			}
+
+			return view;
+		};
+
+		panel = Ext.create('Ext.panel.Panel', {
+			map: layer.map,
+			layer: layer,
+			menu: layer.menu,
+
+			reset: reset,
+			setGui: setGui,
+			getView: getView,
+			getParentGraphMap: function() {
+				return treePanel.getParentGraphMap();
+			},
+
+			cls: 'gis-form-widget',
+			border: false,
+			items: [
+                accordionBody
+			]
+		});
+
+		return panel;
+	};
+
+	GIS.app.LayerWidgetFacility = function(layer) {
+
+		// Stores
+		var infrastructuralDataElementValuesStore,
+
+		// Components
+			groupSet,
+
+			treePanel,
+			userOrganisationUnit,
+			userOrganisationUnitChildren,
+			userOrganisationUnitGrandChildren,
+			organisationUnitLevel,
+			organisationUnitGroup,
+			toolMenu,
+			tool,
+			toolPanel,
+
+			areaRadius,
+
+		// Functions
+
+			//createSelectHandlers,
+			reset,
+			setGui,
+			getView,
+			validateView,
+
+			panel;
+
+		// Stores
+
+		infrastructuralDataElementValuesStore = Ext.create('Ext.data.Store', {
+			fields: ['dataElementName', 'value'],
+			proxy: {
+				type: 'ajax',
+				url: '../getInfrastructuralDataElementMapValues.action',
+				reader: {
+					type: 'json',
+					root: 'mapValues'
+				}
+			},
+			sortInfo: {field: 'dataElementName', direction: 'ASC'},
+			autoLoad: false,
+			isLoaded: false,
+			listeners: {
+				load: function() {
+					if (!this.isLoaded) {
+						this.isLoaded = true;
+					}
+				}
+			}
+		});
+
+		// Components
+
+		groupSet = Ext.create('Ext.form.field.ComboBox', {
+			cls: 'gis-combo',
+            editable: false,
+            valueField: 'id',
+            displayField: 'name',
+            emptyText: GIS.i18n.select_groupset,
+            mode: 'remote',
+            forceSelection: true,
+            width: gis.conf.layout.widget.item_width,
+            labelWidth: gis.conf.layout.widget.itemlabel_width,
+            currentValue: false,
+            store: gis.store.groupSets
+        });
+
+		treePanel = Ext.create('Ext.tree.Panel', {
+			cls: 'gis-tree',
+			height: 300,
+			style: 'border-top: 1px solid #ddd; padding-top: 1px',
+			displayField: 'name',
+			width: gis.conf.layout.widget.item_width,
+			rootVisible: false,
+			autoScroll: true,
+			multiSelect: true,
+			rendered: false,
+			reset: function() {
+				var rootNode = this.getRootNode().findChild('id', gis.init.rootNodes[0].id);
+				this.collapseAll();
+				this.expandPath(rootNode.getPath());
+				this.getSelectionModel().select(rootNode);
+			},
+			selectRootIf: function() {
+				if (this.getSelectionModel().getSelection().length < 1) {
+					var node = this.getRootNode().findChild('id', gis.init.rootNodes[0].id);
+					if (this.rendered) {
+						this.getSelectionModel().select(node);
+					}
+					return node;
+				}
+			},
+			isPending: false,
+			recordsToSelect: [],
+			recordsToRestore: [],
+			multipleSelectIf: function(map, doUpdate) {
+				if (this.recordsToSelect.length === gis.util.object.getLength(map)) {
+					this.getSelectionModel().select(this.recordsToSelect);
+					this.recordsToSelect = [];
+					this.isPending = false;
+
+					if (doUpdate) {
+						update();
+					}
+				}
+			},
+			multipleExpand: function(id, map, doUpdate) {
+				var that = this,
+					rootId = gis.conf.finals.root.id,
+					path = map[id];
+
+				if (path.substr(0, rootId.length + 1) !== ('/' + rootId)) {
+					path = '/' + rootId + path;
+				}
+
+				that.expandPath(path, 'id', '/', function() {
+					record = Ext.clone(that.getRootNode().findChild('id', id, true));
+					that.recordsToSelect.push(record);
+					that.multipleSelectIf(map, doUpdate);
+				});
+			},
+            select: function(url, params) {
+                if (!params) {
+                    params = {};
+                }
+                Ext.Ajax.request({
+                    url: url,
+                    method: 'GET',
+                    params: params,
+                    scope: this,
+                    success: function(r) {
+                        var a = Ext.decode(r.responseText).organisationUnits;
+                        this.numberOfRecords = a.length;
+                        for (var i = 0; i < a.length; i++) {
+                            this.multipleExpand(a[i].id, a[i].path);
+                        }
+                    }
+                });
+            },
+			getParentGraphMap: function() {
+				var selection = this.getSelectionModel().getSelection(),
+					map = {};
+
+				if (Ext.isArray(selection) && selection.length) {
+					for (var i = 0, pathArray, key; i < selection.length; i++) {
+						pathArray = selection[i].getPath().split('/');
+						map[pathArray.pop()] = pathArray.join('/');
+					}
+				}
+
+				return map;
+			},
+			selectGraphMap: function(map, update) {
+				if (!gis.util.object.getLength(map)) {
+					return;
+				}
+
+				this.isPending = true;
+
+				for (var key in map) {
+					if (map.hasOwnProperty(key)) {
+						treePanel.multipleExpand(key, map, update);
+					}
+				}
+			},
+			store: Ext.create('Ext.data.TreeStore', {
+				fields: ['id', 'name'],
+				proxy: {
+					type: 'rest',
+					format: 'json',
+					noCache: false,
+					extraParams: {
+						links: 'false'
+					},
+					url: gis.init.contextPath + '/api/organisationUnits',
+					reader: {
+						type: 'json',
+						root: 'children'
+					}
+				},
+				sorters: [{
+					property: 'name',
+					direction: 'ASC'
+				}],
+				root: {
+					id: gis.conf.finals.root.id,
+					expanded: true,
+					children: gis.init.rootNodes
+				},
+				listeners: {
+					load: function(store, node, records) {
+						Ext.Array.each(records, function(record) {
+							record.set('leaf', !record.raw.hasChildren);
+						});
+					}
+				}
+			}),
+			xable: function(values) {
+				for (var i = 0; i < values.length; i++) {
+					if (!!values[i]) {
+						this.disable();
+						return;
+					}
+				}
+
+				this.enable();
+			},
+			getDimension: function() {
+				var r = treePanel.getSelectionModel().getSelection(),
+					config = {
+						dimension: gis.conf.finals.dimension.organisationUnit.objectName,
+						items: []
+					};
+
+				if (toolMenu.menuValue === 'orgunit') {
+					if (userOrganisationUnit.getValue() || userOrganisationUnitChildren.getValue() || userOrganisationUnitGrandChildren.getValue()) {
+						if (userOrganisationUnit.getValue()) {
+							config.items.push({
+								id: 'USER_ORGUNIT',
+								name: ''
+							});
+						}
+						if (userOrganisationUnitChildren.getValue()) {
+							config.items.push({
+								id: 'USER_ORGUNIT_CHILDREN',
+								name: ''
+							});
+						}
+						if (userOrganisationUnitGrandChildren.getValue()) {
+							config.items.push({
+								id: 'USER_ORGUNIT_GRANDCHILDREN',
+								name: ''
+							});
+						}
+					}
+					else {
+						for (var i = 0; i < r.length; i++) {
+							config.items.push({id: r[i].data.id});
+						}
+					}
+				}
+				else if (toolMenu.menuValue === 'level') {
+					var levels = organisationUnitLevel.getValue();
+
+					for (var i = 0; i < levels.length; i++) {
+						config.items.push({
+							id: 'LEVEL-' + levels[i],
+							name: ''
+						});
+					}
+
+					for (var i = 0; i < r.length; i++) {
+						config.items.push({
+							id: r[i].data.id,
+							name: ''
+						});
+					}
+				}
+				else if (toolMenu.menuValue === 'group') {
+					var groupIds = organisationUnitGroup.getValue();
+
+					for (var i = 0; i < groupIds.length; i++) {
+						config.items.push({
+							id: 'OU_GROUP-' + groupIds[i],
+							name: ''
+						});
+					}
+
+					for (var i = 0; i < r.length; i++) {
+						config.items.push({
+							id: r[i].data.id,
+							name: ''
+						});
+					}
+				}
+
+				return config.items.length ? config : null;
+			},
+			listeners: {
+				beforeitemexpand: function() {
+					var rts = treePanel.recordsToSelect;
+
+					if (!treePanel.isPending) {
+						treePanel.recordsToRestore = treePanel.getSelectionModel().getSelection();
+					}
+				},
+				itemexpand: function() {
+					if (!treePanel.isPending && treePanel.recordsToRestore.length) {
+						treePanel.getSelectionModel().select(treePanel.recordsToRestore);
+						treePanel.recordsToRestore = [];
+					}
+				},
+				render: function() {
+					this.rendered = true;
+				},
+				afterrender: function() {
+					this.getSelectionModel().select(0);
+				},
+				itemcontextmenu: function(v, r, h, i, e) {
+					v.getSelectionModel().select(r, false);
+
+					if (v.menu) {
+						v.menu.destroy();
+					}
+					v.menu = Ext.create('Ext.menu.Menu', {
+						id: 'treepanel-contextmenu',
+						showSeparator: false,
+						shadow: false
+					});
+					if (!r.data.leaf) {
+						v.menu.add({
+							id: 'treepanel-contextmenu-item',
+							text: gis.i18n.select_all_children,
+							icon: 'images/node-select-child.png',
+							handler: function() {
+								r.expand(false, function() {
+									v.getSelectionModel().select(r.childNodes, true);
+									v.getSelectionModel().deselect(r);
+								});
+							}
+						});
+					}
+					else {
+						return;
+					}
+
+					v.menu.showAt(e.xy);
+				}
+			}
+		});
+
+		userOrganisationUnit = Ext.create('Ext.form.field.Checkbox', {
+			columnWidth: 0.30,
+			style: 'padding-top:2px; padding-left:3px; margin-bottom:0',
+			boxLabelCls: 'x-form-cb-label-alt1',
+			boxLabel: 'User OU',
+			labelWidth: gis.conf.layout.form_label_width,
+			handler: function(chb, checked) {
+				treePanel.xable([checked, userOrganisationUnitChildren.getValue(), userOrganisationUnitGrandChildren.getValue()]);
+			}
+		});
+
+		userOrganisationUnitChildren = Ext.create('Ext.form.field.Checkbox', {
+			columnWidth: 0.30,
+			style: 'padding-top:2px; margin-bottom:0',
+			boxLabelCls: 'x-form-cb-label-alt1',
+			boxLabel: 'Children',
+			labelWidth: gis.conf.layout.form_label_width,
+			handler: function(chb, checked) {
+				treePanel.xable([checked, userOrganisationUnit.getValue(), userOrganisationUnitGrandChildren.getValue()]);
+			}
+		});
+
+		userOrganisationUnitGrandChildren = Ext.create('Ext.form.field.Checkbox', {
+			columnWidth: 0.40,
+			style: 'padding-top:2px; margin-bottom:0',
+			boxLabelCls: 'x-form-cb-label-alt1',
+			boxLabel: 'Grand children',
+			labelWidth: gis.conf.layout.form_label_width,
+			handler: function(chb, checked) {
+				treePanel.xable([checked, userOrganisationUnit.getValue(), userOrganisationUnitChildren.getValue()]);
+			}
+		});
+
+		organisationUnitLevel = Ext.create('Ext.form.field.ComboBox', {
+			cls: 'gis-combo',
+			multiSelect: true,
+			style: 'margin-bottom:0',
+			width: gis.conf.layout.widget.item_width - 38,
+			valueField: 'level',
+			displayField: 'name',
+			emptyText: GIS.i18n.select_organisation_unit_levels,
+			editable: false,
+			hidden: true,
+			store: {
+				fields: ['id', 'name', 'level'],
+				data: gis.init.organisationUnitLevels
+			}
+		});
+
+		organisationUnitGroup = Ext.create('Ext.form.field.ComboBox', {
+			cls: 'gis-combo',
+			multiSelect: true,
+			style: 'margin-bottom:0',
+			width: gis.conf.layout.widget.item_width - 38,
+			valueField: 'id',
+			displayField: 'name',
+			emptyText: GIS.i18n.select_organisation_unit_groups,
+			editable: false,
+			hidden: true,
+			store: gis.store.organisationUnitGroup
+		});
+
+		toolMenu = Ext.create('Ext.menu.Menu', {
+			shadow: false,
+			showSeparator: false,
+			menuValue: 'level',
+			clickHandler: function(param) {
+				if (!param) {
+					return;
+				}
+
+				var items = this.items.items;
+				this.menuValue = param;
+
+				// Menu item icon cls
+				for (var i = 0; i < items.length; i++) {
+					if (items[i].setIconCls) {
+						if (items[i].param === param) {
+							items[i].setIconCls('gis-menu-item-selected');
+						}
+						else {
+							items[i].setIconCls('gis-menu-item-unselected');
+						}
+					}
+				}
+
+				// Gui
+				if (param === 'orgunit') {
+					userOrganisationUnit.show();
+					userOrganisationUnitChildren.show();
+					userOrganisationUnitGrandChildren.show();
+					organisationUnitLevel.hide();
+					organisationUnitGroup.hide();
+
+					if (userOrganisationUnit.getValue() || userOrganisationUnitChildren.getValue()) {
+						treePanel.disable();
+					}
+				}
+				else if (param === 'level') {
+					userOrganisationUnit.hide();
+					userOrganisationUnitChildren.hide();
+					userOrganisationUnitGrandChildren.hide();
+					organisationUnitLevel.show();
+					organisationUnitGroup.hide();
+					treePanel.enable();
+				}
+				else if (param === 'group') {
+					userOrganisationUnit.hide();
+					userOrganisationUnitChildren.hide();
+					userOrganisationUnitGrandChildren.hide();
+					organisationUnitLevel.hide();
+					organisationUnitGroup.show();
+					treePanel.enable();
+				}
+			},
+			items: [
+				{
+					xtype: 'label',
+					text: 'Selection mode',
+					style: 'padding:7px 5px 5px 7px; font-weight:bold; border:0 none'
+				},
+				{
+					text: GIS.i18n.select_organisation_units + '&nbsp;&nbsp;',
+					param: 'orgunit',
+					iconCls: 'gis-menu-item-selected'
+				},
+				{
+					text: 'Select levels' + '&nbsp;&nbsp;',
+					param: 'level',
+					iconCls: 'gis-menu-item-unselected'
+				},
+				{
+					text: 'Select groups' + '&nbsp;&nbsp;',
+					param: 'group',
+					iconCls: 'gis-menu-item-unselected'
+				}
+			],
+			listeners: {
+				afterrender: function() {
+					this.getEl().addCls('gis-btn-menu');
+				},
+				click: function(menu, item) {
+					this.clickHandler(item.param);
+				}
+			}
+		});
+
+		tool = Ext.create('Ext.button.Button', {
+			cls: 'gis-button-organisationunitselection',
+			iconCls: 'gis-button-icon-gear',
+			width: 36,
+			height: 24,
+			menu: toolMenu
+		});
+
+		toolPanel = Ext.create('Ext.panel.Panel', {
+			width: 36,
+			bodyStyle: 'border:0 none; text-align:right',
+			style: 'margin-right:2px',
+			items: tool
+		});
+
+		areaRadius = Ext.create('Ext.ux.panel.CheckTextNumber', {
+			width: gis.conf.layout.widget.item_width,
+			text: GIS.i18n.show_circular_area + ':'
+		});
+
+		// Functions
+
+		reset = function(skipTree) {
+
+			// Item
+			layer.item.setValue(false, layer.item.defaultOpacity);
+
+			// Layer
+			if (layer.searchWindow) {
+				layer.searchWindow.destroy();
+				layer.searchWindow = null;
+			}
+			if (layer.filterWindow) {
+				layer.filterWindow.destroy();
+				layer.filterWindow = null;
+			}
+			if (layer.labelWindow) {
+				layer.labelWindow.destroy();
+				layer.labelWindow = null;
+			}
+
+			if (layer.circleLayer & !skipTree) {
+				layer.circleLayer.deactivateControls();
+				layer.circleLayer = null;
+			}
+
+			// Components
+			if (!layer.window.isRendered) {
+				layer.core.view = null;
+				return;
+			}
+
+			groupSet.clearValue();
+
+			toolMenu.clickHandler(toolMenu.menuValue);
+
+			if (!skipTree) {
+				treePanel.reset();
+			}
+
+			userOrganisationUnit.setValue(false);
+			userOrganisationUnitChildren.setValue(false);
+			userOrganisationUnitGrandChildren.setValue(false);
+
+			organisationUnitLevel.clearValue();
+			organisationUnitGroup.clearValue();
+
+			areaRadius.reset();
+		};
+
+		setGui = function(view) {
+			var ouDim = view.rows[0],
+				isOu = false,
+				isOuc = false,
+				isOugc = false,
+				levels = [],
+				groups = [],
+				setWidgetGui,
+				setLayerGui;
+
+			setWidgetGui = function() {
+
+				// Components
+				if (!layer.window.isRendered) {
+					return;
+				}
+
+				reset(true);
+
+				// Group set
+				groupSet.store.removeAll();
+				groupSet.store.add(view.organisationUnitGroupSet);
+				groupSet.setValue(view.organisationUnitGroupSet.id);
+
+				// Organisation units
+				for (var i = 0, item; i < ouDim.items.length; i++) {
+					item = ouDim.items[i];
+
+					if (item.id === 'USER_ORGUNIT') {
+						isOu = true;
+					}
+					else if (item.id === 'USER_ORGUNIT_CHILDREN') {
+						isOuc = true;
+					}
+					else if (item.id === 'USER_ORGUNIT_GRANDCHILDREN') {
+						isOugc = true;
+					}
+					else if (item.id.substr(0,5) === 'LEVEL') {
+						levels.push(parseInt(item.id.split('-')[1]));
+					}
+					else if (item.id.substr(0,8) === 'OU_GROUP') {
+						groups.push(parseInt(item.id.split('-')[1]));
+					}
+				}
+
+				if (levels.length) {
+					toolMenu.clickHandler('level');
+					organisationUnitLevel.setValue(levels);
+				}
+				else if (groups.length) {
+					toolMenu.clickHandler('group');
+					organisationUnitGroup.setValue(groups);
+				}
+				else {
+					toolMenu.clickHandler('orgunit');
+					userOrganisationUnit.setValue(isOu);
+					userOrganisationUnitChildren.setValue(isOuc);
+					userOrganisationUnitGrandChildren.setValue(isOugc);
+				}
+
+				treePanel.selectGraphMap(view.parentGraphMap);
+
+				// Area radius
+				areaRadius.setValue(!!view.areaRadius, !!view.areaRadius ? view.areaRadius : null);
+			}();
+
+			setLayerGui = function() {
+
+				// Layer item
+				layer.item.setValue(true, view.opacity);
+
+				// Layer menu
+				layer.menu.enableItems();
+
+				// Update filter window
+				if (layer.filterWindow && layer.filterWindow.isVisible()) {
+					layer.filterWindow.filter();
+				}
+			}();
+		};
+
+		getView = function(config) {
+			var view = {};
+
+			view.layer = layer.id;
+
+			view.rows = [treePanel.getDimension()];
+
+			view.organisationUnitGroupSet = {
+				id: groupSet.getValue()
+			};
+
+			view.areaRadius = areaRadius.getValue() ? areaRadius.getNumber() : null;
+
+			view.opacity = layer.item.getOpacity();
+
+			return validateView(view);
+		};
+
+		validateView = function(view) {
+			if (!(Ext.isObject(view.organisationUnitGroupSet) && Ext.isString(view.organisationUnitGroupSet.id))) {
+				GIS.logg.push([view.organisationUnitGroupSet.id, layer.id + '.organisationUnitGroupSet.id: string']);
+				alert(GIS.i18n.no_groupset_selected);
+				return false;
+			}
+
+			if (!(Ext.isArray(view.rows) && view.rows.length && Ext.isString(view.rows[0].dimension) && Ext.isArray(view.rows[0].items) && view.rows[0].items.length)) {
+				GIS.logg.push([view.rows, layer.id + '.rows: dimension array']);
+				alert('No organisation units selected');
+				return false;
+			}
+
+			return view;
+		};
+
+		panel = Ext.create('Ext.panel.Panel', {
+			map: layer.map,
+			layer: layer,
+			menu: layer.menu,
+
+			reset: reset,
+			setGui: setGui,
+			getView: getView,
+			getParentGraphMap: function() {
+				return treePanel.getParentGraphMap();
+			},
+
+			infrastructuralDataElementValuesStore: infrastructuralDataElementValuesStore,
+
+			cls: 'gis-form-widget el-border-0',
+			border: false,
+			items: [
+				{
+					xtype: 'form',
+					cls: 'el-border-0',
+					items: [
+						{
+							html: GIS.i18n.organisationunit_groupset,
+							cls: 'gis-form-subtitle-first'
+						},
+						groupSet,
+						{
+							html: GIS.i18n.organisation_units,
+							cls: 'gis-form-subtitle'
+						},
+						{
+							layout: 'column',
+							bodyStyle: 'border:0 none',
+							style: 'padding-bottom:2px',
+							items: [
+								toolPanel,
+								{
+									width: gis.conf.layout.widget.item_width - 38,
+									layout: 'column',
+									bodyStyle: 'border:0 none',
+									items: [
+										userOrganisationUnit,
+										userOrganisationUnitChildren,
+										userOrganisationUnitGrandChildren,
+										organisationUnitLevel,
+										organisationUnitGroup
+									]
+								}
+							]
+						},
+						treePanel,
+						{
+							html: GIS.i18n.surrounding_areas,
+							cls: 'gis-form-subtitle'
+						},
+						areaRadius
+					]
+				}
+			],
+			listeners: {
+				render: function() {
+					toolMenu.clickHandler('level');
+				}
+			}
+		});
+
+		//createSelectHandlers();
+
+		return panel;
+	};
+
 	GIS.app.LayerWidgetBoundary = function(layer) {
 
 		// Stores
@@ -5602,743 +7920,6 @@
 		return panel;
 	};
 
-	GIS.app.LayerWidgetFacility = function(layer) {
-
-		// Stores
-		var infrastructuralDataElementValuesStore,
-
-		// Components
-			groupSet,
-
-			treePanel,
-			userOrganisationUnit,
-			userOrganisationUnitChildren,
-			userOrganisationUnitGrandChildren,
-			organisationUnitLevel,
-			organisationUnitGroup,
-			toolMenu,
-			tool,
-			toolPanel,
-
-			areaRadius,
-
-		// Functions
-
-			//createSelectHandlers,
-			reset,
-			setGui,
-			getView,
-			validateView,
-
-			panel;
-
-		// Stores
-
-		infrastructuralDataElementValuesStore = Ext.create('Ext.data.Store', {
-			fields: ['dataElementName', 'value'],
-			proxy: {
-				type: 'ajax',
-				url: '../getInfrastructuralDataElementMapValues.action',
-				reader: {
-					type: 'json',
-					root: 'mapValues'
-				}
-			},
-			sortInfo: {field: 'dataElementName', direction: 'ASC'},
-			autoLoad: false,
-			isLoaded: false,
-			listeners: {
-				load: function() {
-					if (!this.isLoaded) {
-						this.isLoaded = true;
-					}
-				}
-			}
-		});
-
-		// Components
-
-		groupSet = Ext.create('Ext.form.field.ComboBox', {
-			cls: 'gis-combo',
-            editable: false,
-            valueField: 'id',
-            displayField: 'name',
-            emptyText: GIS.i18n.select_groupset,
-            mode: 'remote',
-            forceSelection: true,
-            width: gis.conf.layout.widget.item_width,
-            labelWidth: gis.conf.layout.widget.itemlabel_width,
-            currentValue: false,
-            store: gis.store.groupSets
-        });
-
-		treePanel = Ext.create('Ext.tree.Panel', {
-			cls: 'gis-tree',
-			height: 300,
-			style: 'border-top: 1px solid #ddd; padding-top: 1px',
-			displayField: 'name',
-			width: gis.conf.layout.widget.item_width,
-			rootVisible: false,
-			autoScroll: true,
-			multiSelect: true,
-			rendered: false,
-			reset: function() {
-				var rootNode = this.getRootNode().findChild('id', gis.init.rootNodes[0].id);
-				this.collapseAll();
-				this.expandPath(rootNode.getPath());
-				this.getSelectionModel().select(rootNode);
-			},
-			selectRootIf: function() {
-				if (this.getSelectionModel().getSelection().length < 1) {
-					var node = this.getRootNode().findChild('id', gis.init.rootNodes[0].id);
-					if (this.rendered) {
-						this.getSelectionModel().select(node);
-					}
-					return node;
-				}
-			},
-			isPending: false,
-			recordsToSelect: [],
-			recordsToRestore: [],
-			multipleSelectIf: function(map, doUpdate) {
-				if (this.recordsToSelect.length === gis.util.object.getLength(map)) {
-					this.getSelectionModel().select(this.recordsToSelect);
-					this.recordsToSelect = [];
-					this.isPending = false;
-
-					if (doUpdate) {
-						update();
-					}
-				}
-			},
-			multipleExpand: function(id, map, doUpdate) {
-				var that = this,
-					rootId = gis.conf.finals.root.id,
-					path = map[id];
-
-				if (path.substr(0, rootId.length + 1) !== ('/' + rootId)) {
-					path = '/' + rootId + path;
-				}
-
-				that.expandPath(path, 'id', '/', function() {
-					record = Ext.clone(that.getRootNode().findChild('id', id, true));
-					that.recordsToSelect.push(record);
-					that.multipleSelectIf(map, doUpdate);
-				});
-			},
-            select: function(url, params) {
-                if (!params) {
-                    params = {};
-                }
-                Ext.Ajax.request({
-                    url: url,
-                    method: 'GET',
-                    params: params,
-                    scope: this,
-                    success: function(r) {
-                        var a = Ext.decode(r.responseText).organisationUnits;
-                        this.numberOfRecords = a.length;
-                        for (var i = 0; i < a.length; i++) {
-                            this.multipleExpand(a[i].id, a[i].path);
-                        }
-                    }
-                });
-            },
-			getParentGraphMap: function() {
-				var selection = this.getSelectionModel().getSelection(),
-					map = {};
-
-				if (Ext.isArray(selection) && selection.length) {
-					for (var i = 0, pathArray, key; i < selection.length; i++) {
-						pathArray = selection[i].getPath().split('/');
-						map[pathArray.pop()] = pathArray.join('/');
-					}
-				}
-
-				return map;
-			},
-			selectGraphMap: function(map, update) {
-				if (!gis.util.object.getLength(map)) {
-					return;
-				}
-
-				this.isPending = true;
-
-				for (var key in map) {
-					if (map.hasOwnProperty(key)) {
-						treePanel.multipleExpand(key, map, update);
-					}
-				}
-			},
-			store: Ext.create('Ext.data.TreeStore', {
-				fields: ['id', 'name'],
-				proxy: {
-					type: 'rest',
-					format: 'json',
-					noCache: false,
-					extraParams: {
-						links: 'false'
-					},
-					url: gis.init.contextPath + '/api/organisationUnits',
-					reader: {
-						type: 'json',
-						root: 'children'
-					}
-				},
-				sorters: [{
-					property: 'name',
-					direction: 'ASC'
-				}],
-				root: {
-					id: gis.conf.finals.root.id,
-					expanded: true,
-					children: gis.init.rootNodes
-				},
-				listeners: {
-					load: function(store, node, records) {
-						Ext.Array.each(records, function(record) {
-							record.set('leaf', !record.raw.hasChildren);
-						});
-					}
-				}
-			}),
-			xable: function(values) {
-				for (var i = 0; i < values.length; i++) {
-					if (!!values[i]) {
-						this.disable();
-						return;
-					}
-				}
-
-				this.enable();
-			},
-			getDimension: function() {
-				var r = treePanel.getSelectionModel().getSelection(),
-					config = {
-						dimension: gis.conf.finals.dimension.organisationUnit.objectName,
-						items: []
-					};
-
-				if (toolMenu.menuValue === 'orgunit') {
-					if (userOrganisationUnit.getValue() || userOrganisationUnitChildren.getValue() || userOrganisationUnitGrandChildren.getValue()) {
-						if (userOrganisationUnit.getValue()) {
-							config.items.push({
-								id: 'USER_ORGUNIT',
-								name: ''
-							});
-						}
-						if (userOrganisationUnitChildren.getValue()) {
-							config.items.push({
-								id: 'USER_ORGUNIT_CHILDREN',
-								name: ''
-							});
-						}
-						if (userOrganisationUnitGrandChildren.getValue()) {
-							config.items.push({
-								id: 'USER_ORGUNIT_GRANDCHILDREN',
-								name: ''
-							});
-						}
-					}
-					else {
-						for (var i = 0; i < r.length; i++) {
-							config.items.push({id: r[i].data.id});
-						}
-					}
-				}
-				else if (toolMenu.menuValue === 'level') {
-					var levels = organisationUnitLevel.getValue();
-
-					for (var i = 0; i < levels.length; i++) {
-						config.items.push({
-							id: 'LEVEL-' + levels[i],
-							name: ''
-						});
-					}
-
-					for (var i = 0; i < r.length; i++) {
-						config.items.push({
-							id: r[i].data.id,
-							name: ''
-						});
-					}
-				}
-				else if (toolMenu.menuValue === 'group') {
-					var groupIds = organisationUnitGroup.getValue();
-
-					for (var i = 0; i < groupIds.length; i++) {
-						config.items.push({
-							id: 'OU_GROUP-' + groupIds[i],
-							name: ''
-						});
-					}
-
-					for (var i = 0; i < r.length; i++) {
-						config.items.push({
-							id: r[i].data.id,
-							name: ''
-						});
-					}
-				}
-
-				return config.items.length ? config : null;
-			},
-			listeners: {
-				beforeitemexpand: function() {
-					var rts = treePanel.recordsToSelect;
-
-					if (!treePanel.isPending) {
-						treePanel.recordsToRestore = treePanel.getSelectionModel().getSelection();
-					}
-				},
-				itemexpand: function() {
-					if (!treePanel.isPending && treePanel.recordsToRestore.length) {
-						treePanel.getSelectionModel().select(treePanel.recordsToRestore);
-						treePanel.recordsToRestore = [];
-					}
-				},
-				render: function() {
-					this.rendered = true;
-				},
-				afterrender: function() {
-					this.getSelectionModel().select(0);
-				},
-				itemcontextmenu: function(v, r, h, i, e) {
-					v.getSelectionModel().select(r, false);
-
-					if (v.menu) {
-						v.menu.destroy();
-					}
-					v.menu = Ext.create('Ext.menu.Menu', {
-						id: 'treepanel-contextmenu',
-						showSeparator: false,
-						shadow: false
-					});
-					if (!r.data.leaf) {
-						v.menu.add({
-							id: 'treepanel-contextmenu-item',
-							text: gis.i18n.select_all_children,
-							icon: 'images/node-select-child.png',
-							handler: function() {
-								r.expand(false, function() {
-									v.getSelectionModel().select(r.childNodes, true);
-									v.getSelectionModel().deselect(r);
-								});
-							}
-						});
-					}
-					else {
-						return;
-					}
-
-					v.menu.showAt(e.xy);
-				}
-			}
-		});
-
-		userOrganisationUnit = Ext.create('Ext.form.field.Checkbox', {
-			columnWidth: 0.30,
-			style: 'padding-top:2px; padding-left:3px; margin-bottom:0',
-			boxLabelCls: 'x-form-cb-label-alt1',
-			boxLabel: 'User OU',
-			labelWidth: gis.conf.layout.form_label_width,
-			handler: function(chb, checked) {
-				treePanel.xable([checked, userOrganisationUnitChildren.getValue(), userOrganisationUnitGrandChildren.getValue()]);
-			}
-		});
-
-		userOrganisationUnitChildren = Ext.create('Ext.form.field.Checkbox', {
-			columnWidth: 0.30,
-			style: 'padding-top:2px; margin-bottom:0',
-			boxLabelCls: 'x-form-cb-label-alt1',
-			boxLabel: 'Children',
-			labelWidth: gis.conf.layout.form_label_width,
-			handler: function(chb, checked) {
-				treePanel.xable([checked, userOrganisationUnit.getValue(), userOrganisationUnitGrandChildren.getValue()]);
-			}
-		});
-
-		userOrganisationUnitGrandChildren = Ext.create('Ext.form.field.Checkbox', {
-			columnWidth: 0.40,
-			style: 'padding-top:2px; margin-bottom:0',
-			boxLabelCls: 'x-form-cb-label-alt1',
-			boxLabel: 'Grand children',
-			labelWidth: gis.conf.layout.form_label_width,
-			handler: function(chb, checked) {
-				treePanel.xable([checked, userOrganisationUnit.getValue(), userOrganisationUnitChildren.getValue()]);
-			}
-		});
-
-		organisationUnitLevel = Ext.create('Ext.form.field.ComboBox', {
-			cls: 'gis-combo',
-			multiSelect: true,
-			style: 'margin-bottom:0',
-			width: gis.conf.layout.widget.item_width - 38,
-			valueField: 'level',
-			displayField: 'name',
-			emptyText: GIS.i18n.select_organisation_unit_levels,
-			editable: false,
-			hidden: true,
-			store: {
-				fields: ['id', 'name', 'level'],
-				data: gis.init.organisationUnitLevels
-			}
-		});
-
-		organisationUnitGroup = Ext.create('Ext.form.field.ComboBox', {
-			cls: 'gis-combo',
-			multiSelect: true,
-			style: 'margin-bottom:0',
-			width: gis.conf.layout.widget.item_width - 38,
-			valueField: 'id',
-			displayField: 'name',
-			emptyText: GIS.i18n.select_organisation_unit_groups,
-			editable: false,
-			hidden: true,
-			store: gis.store.organisationUnitGroup
-		});
-
-		toolMenu = Ext.create('Ext.menu.Menu', {
-			shadow: false,
-			showSeparator: false,
-			menuValue: 'level',
-			clickHandler: function(param) {
-				if (!param) {
-					return;
-				}
-
-				var items = this.items.items;
-				this.menuValue = param;
-
-				// Menu item icon cls
-				for (var i = 0; i < items.length; i++) {
-					if (items[i].setIconCls) {
-						if (items[i].param === param) {
-							items[i].setIconCls('gis-menu-item-selected');
-						}
-						else {
-							items[i].setIconCls('gis-menu-item-unselected');
-						}
-					}
-				}
-
-				// Gui
-				if (param === 'orgunit') {
-					userOrganisationUnit.show();
-					userOrganisationUnitChildren.show();
-					userOrganisationUnitGrandChildren.show();
-					organisationUnitLevel.hide();
-					organisationUnitGroup.hide();
-
-					if (userOrganisationUnit.getValue() || userOrganisationUnitChildren.getValue()) {
-						treePanel.disable();
-					}
-				}
-				else if (param === 'level') {
-					userOrganisationUnit.hide();
-					userOrganisationUnitChildren.hide();
-					userOrganisationUnitGrandChildren.hide();
-					organisationUnitLevel.show();
-					organisationUnitGroup.hide();
-					treePanel.enable();
-				}
-				else if (param === 'group') {
-					userOrganisationUnit.hide();
-					userOrganisationUnitChildren.hide();
-					userOrganisationUnitGrandChildren.hide();
-					organisationUnitLevel.hide();
-					organisationUnitGroup.show();
-					treePanel.enable();
-				}
-			},
-			items: [
-				{
-					xtype: 'label',
-					text: 'Selection mode',
-					style: 'padding:7px 5px 5px 7px; font-weight:bold; border:0 none'
-				},
-				{
-					text: GIS.i18n.select_organisation_units + '&nbsp;&nbsp;',
-					param: 'orgunit',
-					iconCls: 'gis-menu-item-selected'
-				},
-				{
-					text: 'Select levels' + '&nbsp;&nbsp;',
-					param: 'level',
-					iconCls: 'gis-menu-item-unselected'
-				},
-				{
-					text: 'Select groups' + '&nbsp;&nbsp;',
-					param: 'group',
-					iconCls: 'gis-menu-item-unselected'
-				}
-			],
-			listeners: {
-				afterrender: function() {
-					this.getEl().addCls('gis-btn-menu');
-				},
-				click: function(menu, item) {
-					this.clickHandler(item.param);
-				}
-			}
-		});
-
-		tool = Ext.create('Ext.button.Button', {
-			cls: 'gis-button-organisationunitselection',
-			iconCls: 'gis-button-icon-gear',
-			width: 36,
-			height: 24,
-			menu: toolMenu
-		});
-
-		toolPanel = Ext.create('Ext.panel.Panel', {
-			width: 36,
-			bodyStyle: 'border:0 none; text-align:right',
-			style: 'margin-right:2px',
-			items: tool
-		});
-
-		areaRadius = Ext.create('Ext.ux.panel.CheckTextNumber', {
-			width: gis.conf.layout.widget.item_width,
-			text: GIS.i18n.show_circular_area + ':'
-		});
-
-		// Functions
-
-		reset = function(skipTree) {
-
-			// Item
-			layer.item.setValue(false, layer.item.defaultOpacity);
-
-			// Layer
-			if (layer.searchWindow) {
-				layer.searchWindow.destroy();
-				layer.searchWindow = null;
-			}
-			if (layer.filterWindow) {
-				layer.filterWindow.destroy();
-				layer.filterWindow = null;
-			}
-			if (layer.labelWindow) {
-				layer.labelWindow.destroy();
-				layer.labelWindow = null;
-			}
-
-			if (layer.circleLayer & !skipTree) {
-				layer.circleLayer.deactivateControls();
-				layer.circleLayer = null;
-			}
-
-			// Components
-			if (!layer.window.isRendered) {
-				layer.core.view = null;
-				return;
-			}
-
-			groupSet.clearValue();
-
-			toolMenu.clickHandler(toolMenu.menuValue);
-
-			if (!skipTree) {
-				treePanel.reset();
-			}
-
-			userOrganisationUnit.setValue(false);
-			userOrganisationUnitChildren.setValue(false);
-			userOrganisationUnitGrandChildren.setValue(false);
-
-			organisationUnitLevel.clearValue();
-			organisationUnitGroup.clearValue();
-
-			areaRadius.reset();
-		};
-
-		setGui = function(view) {
-			var ouDim = view.rows[0],
-				isOu = false,
-				isOuc = false,
-				isOugc = false,
-				levels = [],
-				groups = [],
-				setWidgetGui,
-				setLayerGui;
-
-			setWidgetGui = function() {
-
-				// Components
-				if (!layer.window.isRendered) {
-					return;
-				}
-
-				reset(true);
-
-				// Group set
-				groupSet.store.removeAll();
-				groupSet.store.add(view.organisationUnitGroupSet);
-				groupSet.setValue(view.organisationUnitGroupSet.id);
-
-				// Organisation units
-				for (var i = 0, item; i < ouDim.items.length; i++) {
-					item = ouDim.items[i];
-
-					if (item.id === 'USER_ORGUNIT') {
-						isOu = true;
-					}
-					else if (item.id === 'USER_ORGUNIT_CHILDREN') {
-						isOuc = true;
-					}
-					else if (item.id === 'USER_ORGUNIT_GRANDCHILDREN') {
-						isOugc = true;
-					}
-					else if (item.id.substr(0,5) === 'LEVEL') {
-						levels.push(parseInt(item.id.split('-')[1]));
-					}
-					else if (item.id.substr(0,8) === 'OU_GROUP') {
-						groups.push(parseInt(item.id.split('-')[1]));
-					}
-				}
-
-				if (levels.length) {
-					toolMenu.clickHandler('level');
-					organisationUnitLevel.setValue(levels);
-				}
-				else if (groups.length) {
-					toolMenu.clickHandler('group');
-					organisationUnitGroup.setValue(groups);
-				}
-				else {
-					toolMenu.clickHandler('orgunit');
-					userOrganisationUnit.setValue(isOu);
-					userOrganisationUnitChildren.setValue(isOuc);
-					userOrganisationUnitGrandChildren.setValue(isOugc);
-				}
-
-				treePanel.selectGraphMap(view.parentGraphMap);
-
-				// Area radius
-				areaRadius.setValue(!!view.areaRadius, !!view.areaRadius ? view.areaRadius : null);
-			}();
-
-			setLayerGui = function() {
-
-				// Layer item
-				layer.item.setValue(true, view.opacity);
-
-				// Layer menu
-				layer.menu.enableItems();
-
-				// Update filter window
-				if (layer.filterWindow && layer.filterWindow.isVisible()) {
-					layer.filterWindow.filter();
-				}
-			}();
-		};
-
-		getView = function(config) {
-			var view = {};
-
-			view.layer = layer.id;
-
-			view.rows = [treePanel.getDimension()];
-
-			view.organisationUnitGroupSet = {
-				id: groupSet.getValue()
-			};
-
-			view.areaRadius = areaRadius.getValue() ? areaRadius.getNumber() : null;
-
-			view.opacity = layer.item.getOpacity();
-
-			return validateView(view);
-		};
-
-		validateView = function(view) {
-			if (!(Ext.isObject(view.organisationUnitGroupSet) && Ext.isString(view.organisationUnitGroupSet.id))) {
-				GIS.logg.push([view.organisationUnitGroupSet.id, layer.id + '.organisationUnitGroupSet.id: string']);
-				alert(GIS.i18n.no_groupset_selected);
-				return false;
-			}
-
-			if (!(Ext.isArray(view.rows) && view.rows.length && Ext.isString(view.rows[0].dimension) && Ext.isArray(view.rows[0].items) && view.rows[0].items.length)) {
-				GIS.logg.push([view.rows, layer.id + '.rows: dimension array']);
-				alert('No organisation units selected');
-				return false;
-			}
-
-			return view;
-		};
-
-		panel = Ext.create('Ext.panel.Panel', {
-			map: layer.map,
-			layer: layer,
-			menu: layer.menu,
-
-			reset: reset,
-			setGui: setGui,
-			getView: getView,
-			getParentGraphMap: function() {
-				return treePanel.getParentGraphMap();
-			},
-
-			infrastructuralDataElementValuesStore: infrastructuralDataElementValuesStore,
-
-			cls: 'gis-form-widget el-border-0',
-			border: false,
-			items: [
-				{
-					xtype: 'form',
-					cls: 'el-border-0',
-					items: [
-						{
-							html: GIS.i18n.organisationunit_groupset,
-							cls: 'gis-form-subtitle-first'
-						},
-						groupSet,
-						{
-							html: GIS.i18n.organisation_units,
-							cls: 'gis-form-subtitle'
-						},
-						{
-							layout: 'column',
-							bodyStyle: 'border:0 none',
-							style: 'padding-bottom:2px',
-							items: [
-								toolPanel,
-								{
-									width: gis.conf.layout.widget.item_width - 38,
-									layout: 'column',
-									bodyStyle: 'border:0 none',
-									items: [
-										userOrganisationUnit,
-										userOrganisationUnitChildren,
-										userOrganisationUnitGrandChildren,
-										organisationUnitLevel,
-										organisationUnitGroup
-									]
-								}
-							]
-						},
-						treePanel,
-						{
-							html: GIS.i18n.surrounding_areas,
-							cls: 'gis-form-subtitle'
-						},
-						areaRadius
-					]
-				}
-			],
-			listeners: {
-				render: function() {
-					toolMenu.clickHandler('level');
-				}
-			}
-		});
-
-		//createSelectHandlers();
-
-		return panel;
-	};
-
 	createViewport = function() {
 		var centerRegion,
 			eastRegion,
@@ -6489,6 +8070,12 @@
 				items: function() {
 					var a = [];
 					a.push({
+						iconCls: 'gis-btn-icon-' + gis.layer.event.id,
+						menu: gis.layer.event.menu,
+						tooltip: GIS.i18n.event_layer,
+						width: 26
+					});
+					a.push({
 						iconCls: 'gis-btn-icon-' + gis.layer.facility.id,
 						menu: gis.layer.facility.menu,
 						tooltip: GIS.i18n.symbol_layer,

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js	2013-12-05 16:34:40 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js	2013-12-19 23:02:08 +0000
@@ -76,12 +76,13 @@
 		};
 
 		olmap.closeAllLayers = function() {
+			gis.layer.event.core.reset();
+			gis.layer.facility.core.reset();
 			gis.layer.boundary.core.reset();
 			gis.layer.thematic1.core.reset();
 			gis.layer.thematic2.core.reset();
 			gis.layer.thematic3.core.reset();
 			gis.layer.thematic4.core.reset();
-			gis.layer.facility.core.reset();
 		};
 
 		addControl('zoomIn', olmap.zoomIn);
@@ -142,6 +143,12 @@
 		});
 		layers.openStreetMap.id = 'openStreetMap';
 
+		layers.event = GIS.core.VectorLayer(gis, 'event', GIS.i18n.event_layer, {opacity: 0.8});
+		layers.event.core = new mapfish.GeoStat.Event(gis.olmap, {
+			layer: layers.event,
+			gis: gis
+		});
+
 		layers.facility = GIS.core.VectorLayer(gis, 'facility', GIS.i18n.facility_layer, {opacity: 1});
 		layers.facility.core = new mapfish.GeoStat.Facility(gis.olmap, {
 			layer: layers.facility,
@@ -418,7 +425,7 @@
 				// parent graph map
 				view.parentGraphMap = {};
 				view.parentGraphMap[parentId] = parentGraph;
-console.log(view.parentGraphMap);
+
 				// dimension
 				view.rows = [{
 					dimension: dimConf.organisationUnit.objectName,
@@ -837,6 +844,406 @@
 		return loader;
 	};
 
+	GIS.core.LayerLoaderEvent = function(gis, layer) {
+		var olmap = layer.map,
+			compareView,
+			loadOrganisationUnits,
+			loadData,
+			loadLegend,
+			afterLoad,
+			loader,
+			dimConf = gis.conf.finals.dimension;
+
+		loadOrganisationUnits = function(view) {
+            loadData(view);
+		};
+
+		loadData = function(view) {
+			view = view || layer.core.view;
+
+            var paramString = '?',
+                features = [];
+
+            // stage
+            paramString += 'stage=' + view.stage.id;
+
+            // dates
+            paramString += '&startDate=' + view.startDate;
+            paramString += '&endDate=' + view.endDate;
+
+            // ou //todo
+            paramString += '&dimension=ou:' + view.organisationUnits[0].id;
+
+            // de
+            for (var i = 0, element; i < view.dataElements.length; i++) {
+                element = view.dataElements[i];
+
+                paramString += '&dimension=' + element.id;
+
+                if (element.value) {
+					if (element.operator) {
+						paramString += ':' + element.operator;
+					}
+
+					paramString += ':' + element.value;
+                }
+            }
+
+			Ext.data.JsonP.request({
+				url: gis.init.contextPath + '/api/analytics/events/query/' + view.program.id + '.jsonp' + paramString,
+				disableCaching: false,
+				scope: this,
+				success: function(r) {
+                    var events = [],
+                        features = [];
+
+                    if (!r.rows) {
+                        alert('No coordinates found');
+                        return;
+                    }
+
+                    // events
+                    for (var i = 0, row, obj; i < r.rows.length; i++) {
+                        row = r.rows[i];
+                        obj = {};
+
+                        for (var j = 0; j < row.length; j++) {
+                            obj[r.headers[j].name] = row[j];
+                        }
+
+                        obj[gis.conf.finals.widget.value] = 0;
+
+                        events.push(obj);
+                    }
+
+                    // features
+                    for (var i = 0, event, point; i < events.length; i++) {
+                        event = events[i];
+
+                        point = gis.util.map.getTransformedPointByXY(event.longitude, event.latitude);
+
+                        features.push(new OpenLayers.Feature.Vector(point, event));
+                    }
+
+                    layer.removeFeatures(layer.features);
+                    layer.addFeatures(features);
+
+                    loadLegend(view);
+                }
+            });
+		};
+
+		loadLegend = function(view) {
+			view = view || layer.core.view;
+
+            // classification optionsvar options = {
+            var options = {
+            	indicator: gis.conf.finals.widget.value,
+				method: 2,
+				numClasses: 5,
+				colors: layer.core.getColors('ffffff', 'ff0000'),
+				minSize: 4,
+				maxSize: 4
+			};
+
+            layer.core.view = view;
+
+            layer.core.applyClassification(options);
+
+            afterLoad(view);
+		};
+
+		afterLoad = function(view) {
+
+			// Layer
+			if (layer.item) {
+				layer.item.setValue(true, view.opacity);
+			}
+			else {
+				layer.setLayerOpacity(view.opacity);
+			}
+
+			// Gui
+			if (loader.updateGui && Ext.isObject(layer.widget)) {
+				layer.widget.setGui(view);
+			}
+
+			// Zoom
+			if (loader.zoomToVisibleExtent) {
+				olmap.zoomToVisibleExtent();
+			}
+
+			// Mask
+			if (loader.hideMask) {
+				olmap.mask.hide();
+			}
+
+			// Map callback
+			if (loader.callBack) {
+				loader.callBack(layer);
+			}
+			else {
+				gis.map = null;
+			}
+
+			// session storage
+			//if (GIS.isSessionStorage) {
+				//gis.util.layout.setSessionStorage('map', gis.util.layout.getAnalytical());
+			//}
+		};
+
+		loader = {
+			compare: false,
+			updateGui: false,
+			zoomToVisibleExtent: false,
+			hideMask: false,
+			callBack: null,
+			load: function(view) {
+				gis.olmap.mask.show();
+
+                loadOrganisationUnits(view);
+			},
+			loadData: loadData,
+			loadLegend: loadLegend
+		};
+
+		return loader;
+	};
+
+	GIS.core.LayerLoaderFacility = function(gis, layer) {
+		var olmap = layer.map,
+			compareView,
+			loadOrganisationUnits,
+			loadData,
+			loadLegend,
+			addCircles,
+			afterLoad,
+			loader;
+
+		compareView = function(view, doExecute) {
+			var src = layer.core.view,
+				viewIds,
+				viewDim,
+				srcIds,
+				srcDim;
+
+			loader.zoomToVisibleExtent = true;
+
+			if (!src) {
+				if (doExecute) {
+					loadOrganisationUnits(view);
+				}
+				return gis.conf.finals.widget.loadtype_organisationunit;
+			}
+
+			// organisation units
+			viewIds = [];
+			viewDim = view.rows[0];
+			srcIds = [];
+			srcDim = src.rows[0];
+
+			if (viewDim.items.length === srcDim.items.length) {
+				for (var i = 0; i < viewDim.items.length; i++) {
+					viewIds.push(viewDim.items[i].id);
+				}
+
+				for (var i = 0; i < srcDim.items.length; i++) {
+					srcIds.push(srcDim.items[i].id);
+				}
+
+				if (Ext.Array.difference(viewIds, srcIds).length !== 0) {
+					if (doExecute) {
+						loadOrganisationUnits(view);
+					}
+					return gis.conf.finals.widget.loadtype_organisationunit;
+				}
+			}
+			else {
+				if (doExecute) {
+					loadOrganisationUnits(view);
+				}
+				return gis.conf.finals.widget.loadtype_organisationunit;
+			}
+
+			// Group set
+			loader.zoomToVisibleExtent = false;
+
+			if (view.organisationUnitGroupSet.id !== src.organisationUnitGroupSet.id) {
+				if (doExecute) {
+					loadOrganisationUnits(view);
+				}
+				return gis.conf.finals.widget.loadtype_organisationunit;
+			}
+
+			//if (view.areaRadius !== src.areaRadius) {
+				//if (doExecute) {
+					//loadLegend(view);
+				//}
+				//return gis.conf.finals.widget.loadtype_legend;
+			//}
+
+			// always reload legend
+			if (doExecute) {
+				loadLegend(view);
+				return gis.conf.finals.widget.loadtype_legend;
+			}
+
+			//gis.olmap.mask.hide();
+		};
+
+		loadOrganisationUnits = function(view) {
+			var items = view.rows[0].items,
+				idParamString = '';
+
+			for (var i = 0; i < items.length; i++) {
+				idParamString += 'ids=' + items[i].id;
+				idParamString += i !== items.length - 1 ? '&' : '';
+			}
+
+			Ext.data.JsonP.request({
+				url: gis.init.contextPath + gis.conf.finals.url.path_module + 'getGeoJsonFacilities.action?' + idParamString,
+				scope: this,
+				disableCaching: false,
+				success: function(r) {
+					var geojson = layer.core.decode(r),
+						format = new OpenLayers.Format.GeoJSON(),
+						features = gis.util.map.getTransformedFeatureArray(format.read(geojson));
+
+					if (!Ext.isArray(features)) {
+						olmap.mask.hide();
+						alert(GIS.i18n.invalid_coordinates);
+						return;
+					}
+
+					if (!features.length) {
+						olmap.mask.hide();
+						alert(GIS.i18n.no_valid_coordinates_found);
+						return;
+					}
+
+					layer.core.featureStore.loadFeatures(features.slice(0));
+
+					loadData(view, features);
+				},
+				failure: function(r) {
+					olmap.mask.hide();
+					alert(GIS.i18n.coordinates_could_not_be_loaded);
+				}
+			});
+		};
+
+		loadData = function(view, features) {
+			view = view || layer.core.view;
+			features = features || layer.core.featureStore.features;
+
+			for (var i = 0; i < features.length; i++) {
+				features[i].attributes.label = features[i].attributes.name;
+			}
+
+			layer.removeFeatures(layer.features);
+			layer.addFeatures(features);
+
+			loadLegend(view);
+		};
+
+		loadLegend = function(view) {
+			view = view || layer.core.view;
+
+			var store = gis.store.groupsByGroupSet;
+
+			store.proxy.url = gis.init.contextPath + gis.conf.finals.url.path_module + 'getOrganisationUnitGroupsByGroupSet.action?id=' + view.organisationUnitGroupSet.id;
+			store.load({
+				scope: this,
+				callback: function() {
+					var options = {
+						indicator: view.organisationUnitGroupSet.id
+					};
+
+					layer.core.view = view;
+
+					layer.core.applyClassification(options);
+
+					addCircles(view);
+
+					afterLoad(view);
+				}
+			});
+		};
+
+		addCircles = function(view) {
+			var radius = view.areaRadius;
+
+			if (layer.circleLayer) {
+				layer.circleLayer.deactivateControls();
+				layer.circleLayer = null;
+			}
+			if (Ext.isDefined(radius) && radius) {
+				layer.circleLayer = GIS.app.CircleLayer(layer.features, radius);
+				nissa = layer.circleLayer;
+			}
+		};
+
+		afterLoad = function(view) {
+
+			// Legend
+			gis.viewport.eastRegion.doLayout();
+			layer.legendPanel.expand();
+
+			// Layer
+			if (layer.item) {
+				layer.item.setValue(true, view.opacity);
+			}
+			else {
+				layer.setLayerOpacity(view.opacity);
+			}
+
+			// Gui
+			if (loader.updateGui && Ext.isObject(layer.widget)) {
+				layer.widget.setGui(view);
+			}
+
+			// Zoom
+			if (loader.zoomToVisibleExtent) {
+				olmap.zoomToVisibleExtent();
+			}
+
+			// Mask
+			if (loader.hideMask) {
+				olmap.mask.hide();
+			}
+
+			// Map callback
+			if (loader.callBack) {
+				loader.callBack(layer);
+			}
+			else {
+				gis.map = null;
+			}
+		};
+
+		loader = {
+			compare: false,
+			updateGui: false,
+			zoomToVisibleExtent: false,
+			hideMask: false,
+			callBack: null,
+			load: function(view) {
+				gis.olmap.mask.show();
+
+				if (this.compare) {
+					compareView(view, true);
+				}
+				else {
+					loadOrganisationUnits(view);
+				}
+			},
+			loadData: loadData,
+			loadLegend: loadLegend
+		};
+
+		return loader;
+	};
+
 	GIS.core.LayerLoaderBoundary = function(gis, layer) {
 		var olmap = layer.map,
 			compareView,
@@ -1482,240 +1889,6 @@
 		return loader;
 	};
 
-	GIS.core.LayerLoaderFacility = function(gis, layer) {
-		var olmap = layer.map,
-			compareView,
-			loadOrganisationUnits,
-			loadData,
-			loadLegend,
-			addCircles,
-			afterLoad,
-			loader;
-
-		compareView = function(view, doExecute) {
-			var src = layer.core.view,
-				viewIds,
-				viewDim,
-				srcIds,
-				srcDim;
-
-			loader.zoomToVisibleExtent = true;
-
-			if (!src) {
-				if (doExecute) {
-					loadOrganisationUnits(view);
-				}
-				return gis.conf.finals.widget.loadtype_organisationunit;
-			}
-
-			// organisation units
-			viewIds = [];
-			viewDim = view.rows[0];
-			srcIds = [];
-			srcDim = src.rows[0];
-
-			if (viewDim.items.length === srcDim.items.length) {
-				for (var i = 0; i < viewDim.items.length; i++) {
-					viewIds.push(viewDim.items[i].id);
-				}
-
-				for (var i = 0; i < srcDim.items.length; i++) {
-					srcIds.push(srcDim.items[i].id);
-				}
-
-				if (Ext.Array.difference(viewIds, srcIds).length !== 0) {
-					if (doExecute) {
-						loadOrganisationUnits(view);
-					}
-					return gis.conf.finals.widget.loadtype_organisationunit;
-				}
-			}
-			else {
-				if (doExecute) {
-					loadOrganisationUnits(view);
-				}
-				return gis.conf.finals.widget.loadtype_organisationunit;
-			}
-
-			// Group set
-			loader.zoomToVisibleExtent = false;
-
-			if (view.organisationUnitGroupSet.id !== src.organisationUnitGroupSet.id) {
-				if (doExecute) {
-					loadOrganisationUnits(view);
-				}
-				return gis.conf.finals.widget.loadtype_organisationunit;
-			}
-
-			//if (view.areaRadius !== src.areaRadius) {
-				//if (doExecute) {
-					//loadLegend(view);
-				//}
-				//return gis.conf.finals.widget.loadtype_legend;
-			//}
-
-			// always reload legend
-			if (doExecute) {
-				loadLegend(view);
-				return gis.conf.finals.widget.loadtype_legend;
-			}
-
-			//gis.olmap.mask.hide();
-		};
-
-		loadOrganisationUnits = function(view) {
-			var items = view.rows[0].items,
-				idParamString = '';
-
-			for (var i = 0; i < items.length; i++) {
-				idParamString += 'ids=' + items[i].id;
-				idParamString += i !== items.length - 1 ? '&' : '';
-			}
-
-			Ext.data.JsonP.request({
-				url: gis.init.contextPath + gis.conf.finals.url.path_module + 'getGeoJsonFacilities.action?' + idParamString,
-				scope: this,
-				disableCaching: false,
-				success: function(r) {
-					var geojson = layer.core.decode(r),
-						format = new OpenLayers.Format.GeoJSON(),
-						features = gis.util.map.getTransformedFeatureArray(format.read(geojson));
-
-					if (!Ext.isArray(features)) {
-						olmap.mask.hide();
-						alert(GIS.i18n.invalid_coordinates);
-						return;
-					}
-
-					if (!features.length) {
-						olmap.mask.hide();
-						alert(GIS.i18n.no_valid_coordinates_found);
-						return;
-					}
-
-					layer.core.featureStore.loadFeatures(features.slice(0));
-
-					loadData(view, features);
-				},
-				failure: function(r) {
-					olmap.mask.hide();
-					alert(GIS.i18n.coordinates_could_not_be_loaded);
-				}
-			});
-		};
-
-		loadData = function(view, features) {
-			view = view || layer.core.view;
-			features = features || layer.core.featureStore.features;
-
-			for (var i = 0; i < features.length; i++) {
-				features[i].attributes.label = features[i].attributes.name;
-			}
-
-			layer.removeFeatures(layer.features);
-			layer.addFeatures(features);
-
-			loadLegend(view);
-		};
-
-		loadLegend = function(view) {
-			view = view || layer.core.view;
-
-			var store = gis.store.groupsByGroupSet;
-
-			store.proxy.url = gis.init.contextPath + gis.conf.finals.url.path_module + 'getOrganisationUnitGroupsByGroupSet.action?id=' + view.organisationUnitGroupSet.id;
-			store.load({
-				scope: this,
-				callback: function() {
-					var options = {
-						indicator: view.organisationUnitGroupSet.id
-					};
-
-					layer.core.view = view;
-
-					layer.core.applyClassification(options);
-
-					addCircles(view);
-
-					afterLoad(view);
-				}
-			});
-		};
-
-		addCircles = function(view) {
-			var radius = view.areaRadius;
-
-			if (layer.circleLayer) {
-				layer.circleLayer.deactivateControls();
-				layer.circleLayer = null;
-			}
-			if (Ext.isDefined(radius) && radius) {
-				layer.circleLayer = GIS.app.CircleLayer(layer.features, radius);
-				nissa = layer.circleLayer;
-			}
-		};
-
-		afterLoad = function(view) {
-
-			// Legend
-			gis.viewport.eastRegion.doLayout();
-			layer.legendPanel.expand();
-
-			// Layer
-			if (layer.item) {
-				layer.item.setValue(true, view.opacity);
-			}
-			else {
-				layer.setLayerOpacity(view.opacity);
-			}
-
-			// Gui
-			if (loader.updateGui && Ext.isObject(layer.widget)) {
-				layer.widget.setGui(view);
-			}
-
-			// Zoom
-			if (loader.zoomToVisibleExtent) {
-				olmap.zoomToVisibleExtent();
-			}
-
-			// Mask
-			if (loader.hideMask) {
-				olmap.mask.hide();
-			}
-
-			// Map callback
-			if (loader.callBack) {
-				loader.callBack(layer);
-			}
-			else {
-				gis.map = null;
-			}
-		};
-
-		loader = {
-			compare: false,
-			updateGui: false,
-			zoomToVisibleExtent: false,
-			hideMask: false,
-			callBack: null,
-			load: function(view) {
-				gis.olmap.mask.show();
-
-				if (this.compare) {
-					compareView(view, true);
-				}
-				else {
-					loadOrganisationUnits(view);
-				}
-			},
-			loadData: loadData,
-			loadLegend: loadLegend
-		};
-
-		return loader;
-	};
-
 	GIS.core.getInstance = function(init) {
 		var conf = {},
 			util = {},
@@ -2389,12 +2562,14 @@
 			gis.layer.thematic2,
 			gis.layer.thematic1,
 			gis.layer.boundary,
-			gis.layer.facility
+			gis.layer.facility,
+			gis.layer.event
 		);
 
 		gis.olmap.addLayers(layers);
 
 		GIS.core.instances.push(gis);
+e = gis.layer.event;
 
 		return gis;
 	};

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/all.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/all.js	2013-10-15 19:57:13 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/all.js	2013-12-09 11:30:45 +0000
@@ -21,156 +21,6 @@
  * @requires core/GeoStat.js
  */
 
-mapfish.GeoStat.Boundary = OpenLayers.Class(mapfish.GeoStat, {
-
-    colors: [new mapfish.ColorRgb(120, 120, 0), new mapfish.ColorRgb(255, 0, 0)],
-    method: mapfish.GeoStat.Distribution.CLASSIFY_BY_QUANTILS,
-    numClasses: 5,
-	minSize: 3,
-	maxSize: 20,
-	minVal: null,
-	maxVal: null,
-    defaultSymbolizer: {'fillOpacity': 1},
-    classification: null,
-    colorInterpolation: null,
-
-    gis: null,
-    view: null,
-    featureStore: Ext.create('Ext.data.Store', {
-		fields: ['id', 'name'],
-		features: [],
-		loadFeatures: function(features) {
-			if (features && features.length) {
-				var data = [];
-				for (var i = 0; i < features.length; i++) {
-					data.push([features[i].attributes.id, features[i].attributes.name]);
-				}
-				this.loadData(data);
-				this.sortStore();
-
-				this.features = features;
-			}
-			else {
-				this.removeAll();
-			}
-		},
-		sortStore: function() {
-			this.sort('name', 'ASC');
-		}
-	}),
-
-    initialize: function(map, options) {
-        mapfish.GeoStat.prototype.initialize.apply(this, arguments);
-    },
-
-    getLoader: function() {
-		return GIS.core.LayerLoaderBoundary(this.gis, this.layer);
-	},
-
-	reset: function() {
-		this.layer.destroyFeatures();
-
-		if (this.layer.widget) {
-			this.layer.widget.reset();
-		}
-	},
-
-	extendView: function(view, config) {
-		view = view || this.view;
-
-		view.organisationUnitLevel = config.organisationUnitLevel || view.organisationUnitLevel;
-		view.parentOrganisationUnit = config.parentOrganisationUnit || view.parentOrganisationUnit;
-		view.parentLevel = config.parentLevel || view.parentLevel;
-		view.parentGraph = config.parentGraph || view.parentGraph;
-		view.opacity = config.opacity || view.opacity;
-
-		return view;
-	},
-
-	getLegendConfig: function() {
-		return;
-	},
-
-	getImageLegendConfig: function() {
-		return;
-	},
-
-    updateOptions: function(newOptions) {
-        var oldOptions = OpenLayers.Util.extend({}, this.options);
-        this.addOptions(newOptions);
-        if (newOptions) {
-            this.setClassification();
-        }
-    },
-
-    createColorInterpolation: function() {
-        var numColors = this.classification.bins.length;
-
-		this.colorInterpolation = mapfish.ColorRgb.getColorsArrayByRgbInterpolation(this.colors[0], this.colors[1], numColors);
-    },
-
-    setClassification: function() {
-        var values = [];
-        for (var i = 0; i < this.layer.features.length; i++) {
-            values.push(this.layer.features[i].attributes[this.indicator]);
-        }
-
-        var distOptions = {
-            labelGenerator: this.options.labelGenerator
-        };
-        var dist = new mapfish.GeoStat.Distribution(values, distOptions);
-
-		this.minVal = dist.minVal;
-        this.maxVal = dist.maxVal;
-
-        this.classification = dist.classify(
-            this.method,
-            this.numClasses,
-            null
-        );
-
-        this.createColorInterpolation();
-    },
-
-    applyClassification: function(options) {
-        this.updateOptions(options);
-
-		var calculateRadius = OpenLayers.Function.bind(
-			function(feature) {
-				var value = feature.attributes[this.indicator];
-                var size = (value - this.minVal) / (this.maxVal - this.minVal) *
-					(this.maxSize - this.minSize) + this.minSize;
-                return size || this.minSize;
-            },	this
-		);
-		this.extendStyle(null, {'pointRadius': '${calculateRadius}'}, {'calculateRadius': calculateRadius});
-
-        var boundsArray = this.classification.getBoundsArray();
-        var rules = new Array(boundsArray.length-1);
-        for (var i = 0; i < boundsArray.length-1; i++) {
-            var rule = new OpenLayers.Rule({
-                symbolizer: {fillColor: this.colorInterpolation[i].toHexString()},
-                filter: new OpenLayers.Filter.Comparison({
-                    type: OpenLayers.Filter.Comparison.BETWEEN,
-                    property: this.indicator,
-                    lowerBoundary: boundsArray[i],
-                    upperBoundary: boundsArray[i + 1]
-                })
-            });
-            rules[i] = rule;
-        }
-
-        this.extendStyle(rules);
-        mapfish.GeoStat.prototype.applyClassification.apply(this, arguments);
-    },
-
-    updateLegend: function() {
-
-    },
-
-    CLASS_NAME: "mapfish.GeoStat.Boundary"
-});
-
 mapfish.GeoStat.Facility = OpenLayers.Class(mapfish.GeoStat, {
 
     classification: null,
@@ -331,6 +181,306 @@
     CLASS_NAME: "mapfish.GeoStat.Facility"
 });
 
+mapfish.GeoStat.Event = OpenLayers.Class(mapfish.GeoStat, {
+
+    colors: [new mapfish.ColorRgb(120, 120, 0), new mapfish.ColorRgb(255, 0, 0)],
+    method: mapfish.GeoStat.Distribution.CLASSIFY_BY_QUANTILS,
+    numClasses: 5,
+	minSize: 3,
+	maxSize: 20,
+	minVal: null,
+	maxVal: null,
+    defaultSymbolizer: {'fillOpacity': 1},
+    classification: null,
+    colorInterpolation: null,
+
+    gis: null,
+    view: null,
+    featureStore: Ext.create('Ext.data.Store', {
+		fields: ['id', 'name'],
+		features: [],
+		loadFeatures: function(features) {
+			if (features && features.length) {
+				var data = [];
+				for (var i = 0; i < features.length; i++) {
+					data.push([features[i].attributes.id, features[i].attributes.name]);
+				}
+				this.loadData(data);
+				this.sortStore();
+
+				this.features = features;
+			}
+			else {
+				this.removeAll();
+			}
+		},
+		sortStore: function() {
+			this.sort('name', 'ASC');
+		}
+	}),
+
+    initialize: function(map, options) {
+        mapfish.GeoStat.prototype.initialize.apply(this, arguments);
+    },
+
+    getLoader: function() {
+		return GIS.core.LayerLoaderEvent(this.gis, this.layer);
+	},
+
+	reset: function() {
+		this.layer.destroyFeatures();
+
+		if (this.layer.widget) {
+			this.layer.widget.reset();
+		}
+	},
+
+	extendView: function(view, config) {
+		view = view || this.view;
+
+		view.organisationUnitLevel = config.organisationUnitLevel || view.organisationUnitLevel;
+		view.parentOrganisationUnit = config.parentOrganisationUnit || view.parentOrganisationUnit;
+		view.parentLevel = config.parentLevel || view.parentLevel;
+		view.parentGraph = config.parentGraph || view.parentGraph;
+		view.opacity = config.opacity || view.opacity;
+
+		return view;
+	},
+
+	getLegendConfig: function() {
+		return;
+	},
+
+	getImageLegendConfig: function() {
+		return;
+	},
+
+    updateOptions: function(newOptions) {
+        var oldOptions = OpenLayers.Util.extend({}, this.options);
+        this.addOptions(newOptions);
+        if (newOptions) {
+            this.setClassification();
+        }
+    },
+
+    createColorInterpolation: function() {
+        var numColors = this.classification.bins.length;
+
+		this.colorInterpolation = mapfish.ColorRgb.getColorsArrayByRgbInterpolation(this.colors[0], this.colors[1], numColors);
+    },
+
+    setClassification: function() {
+        var values = [];
+        for (var i = 0; i < this.layer.features.length; i++) {
+            values.push(this.layer.features[i].attributes[this.indicator]);
+        }
+
+        var distOptions = {
+            labelGenerator: this.options.labelGenerator
+        };
+        var dist = new mapfish.GeoStat.Distribution(values, distOptions);
+
+		this.minVal = dist.minVal;
+        this.maxVal = dist.maxVal;
+
+        this.classification = dist.classify(
+            this.method,
+            this.numClasses,
+            null
+        );
+
+        this.createColorInterpolation();
+    },
+
+    applyClassification: function(options) {
+        this.updateOptions(options);
+
+		var calculateRadius = OpenLayers.Function.bind(
+			function(feature) {
+				var value = feature.attributes[this.indicator];
+                var size = (value - this.minVal) / (this.maxVal - this.minVal) *
+					(this.maxSize - this.minSize) + this.minSize;
+                return size || this.minSize;
+            },	this
+		);
+		this.extendStyle(null, {'pointRadius': '${calculateRadius}'}, {'calculateRadius': calculateRadius});
+
+        var boundsArray = this.classification.getBoundsArray();
+        var rules = new Array(boundsArray.length-1);
+        for (var i = 0; i < boundsArray.length-1; i++) {
+            var rule = new OpenLayers.Rule({
+                symbolizer: {fillColor: this.colorInterpolation[i].toHexString()},
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.BETWEEN,
+                    property: this.indicator,
+                    lowerBoundary: boundsArray[i],
+                    upperBoundary: boundsArray[i + 1]
+                })
+            });
+            rules[i] = rule;
+        }
+
+        this.extendStyle(rules);
+        mapfish.GeoStat.prototype.applyClassification.apply(this, arguments);
+    },
+
+    updateLegend: function() {
+
+    },
+
+    CLASS_NAME: "mapfish.GeoStat.Event"
+});
+
+mapfish.GeoStat.Boundary = OpenLayers.Class(mapfish.GeoStat, {
+
+    colors: [new mapfish.ColorRgb(120, 120, 0), new mapfish.ColorRgb(255, 0, 0)],
+    method: mapfish.GeoStat.Distribution.CLASSIFY_BY_QUANTILS,
+    numClasses: 5,
+	minSize: 3,
+	maxSize: 20,
+	minVal: null,
+	maxVal: null,
+    defaultSymbolizer: {'fillOpacity': 1},
+    classification: null,
+    colorInterpolation: null,
+
+    gis: null,
+    view: null,
+    featureStore: Ext.create('Ext.data.Store', {
+		fields: ['id', 'name'],
+		features: [],
+		loadFeatures: function(features) {
+			if (features && features.length) {
+				var data = [];
+				for (var i = 0; i < features.length; i++) {
+					data.push([features[i].attributes.id, features[i].attributes.name]);
+				}
+				this.loadData(data);
+				this.sortStore();
+
+				this.features = features;
+			}
+			else {
+				this.removeAll();
+			}
+		},
+		sortStore: function() {
+			this.sort('name', 'ASC');
+		}
+	}),
+
+    initialize: function(map, options) {
+        mapfish.GeoStat.prototype.initialize.apply(this, arguments);
+    },
+
+    getLoader: function() {
+		return GIS.core.LayerLoaderBoundary(this.gis, this.layer);
+	},
+
+	reset: function() {
+		this.layer.destroyFeatures();
+
+		if (this.layer.widget) {
+			this.layer.widget.reset();
+		}
+	},
+
+	extendView: function(view, config) {
+		view = view || this.view;
+
+		view.organisationUnitLevel = config.organisationUnitLevel || view.organisationUnitLevel;
+		view.parentOrganisationUnit = config.parentOrganisationUnit || view.parentOrganisationUnit;
+		view.parentLevel = config.parentLevel || view.parentLevel;
+		view.parentGraph = config.parentGraph || view.parentGraph;
+		view.opacity = config.opacity || view.opacity;
+
+		return view;
+	},
+
+	getLegendConfig: function() {
+		return;
+	},
+
+	getImageLegendConfig: function() {
+		return;
+	},
+
+    updateOptions: function(newOptions) {
+        var oldOptions = OpenLayers.Util.extend({}, this.options);
+        this.addOptions(newOptions);
+        if (newOptions) {
+            this.setClassification();
+        }
+    },
+
+    createColorInterpolation: function() {
+        var numColors = this.classification.bins.length;
+
+		this.colorInterpolation = mapfish.ColorRgb.getColorsArrayByRgbInterpolation(this.colors[0], this.colors[1], numColors);
+    },
+
+    setClassification: function() {
+        var values = [];
+        for (var i = 0; i < this.layer.features.length; i++) {
+            values.push(this.layer.features[i].attributes[this.indicator]);
+        }
+
+        var distOptions = {
+            labelGenerator: this.options.labelGenerator
+        };
+        var dist = new mapfish.GeoStat.Distribution(values, distOptions);
+
+		this.minVal = dist.minVal;
+        this.maxVal = dist.maxVal;
+
+        this.classification = dist.classify(
+            this.method,
+            this.numClasses,
+            null
+        );
+
+        this.createColorInterpolation();
+    },
+
+    applyClassification: function(options) {
+        this.updateOptions(options);
+
+		var calculateRadius = OpenLayers.Function.bind(
+			function(feature) {
+				var value = feature.attributes[this.indicator];
+                var size = (value - this.minVal) / (this.maxVal - this.minVal) *
+					(this.maxSize - this.minSize) + this.minSize;
+                return size || this.minSize;
+            },	this
+		);
+		this.extendStyle(null, {'pointRadius': '${calculateRadius}'}, {'calculateRadius': calculateRadius});
+
+        var boundsArray = this.classification.getBoundsArray();
+        var rules = new Array(boundsArray.length-1);
+        for (var i = 0; i < boundsArray.length-1; i++) {
+            var rule = new OpenLayers.Rule({
+                symbolizer: {fillColor: this.colorInterpolation[i].toHexString()},
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.BETWEEN,
+                    property: this.indicator,
+                    lowerBoundary: boundsArray[i],
+                    upperBoundary: boundsArray[i + 1]
+                })
+            });
+            rules[i] = rule;
+        }
+
+        this.extendStyle(rules);
+        mapfish.GeoStat.prototype.applyClassification.apply(this, arguments);
+    },
+
+    updateLegend: function() {
+
+    },
+
+    CLASS_NAME: "mapfish.GeoStat.Boundary"
+});
+
 mapfish.GeoStat.createThematic = function(name) {
 
 	mapfish.GeoStat[name] = OpenLayers.Class(mapfish.GeoStat, {

=== 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-12-05 16:34:40 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css	2013-12-18 12:48:13 +0000
@@ -35,6 +35,8 @@
  * GIS Label
  *
  * Tooltip
+ *
+ * GIS Accordion
 */
 
 
@@ -124,6 +126,14 @@
 	display: none;
 }
 
+.gis-form-item-label-top {
+	padding-left: 2px;
+	float: none;
+	clear: none;
+	display: block;
+	margin-bottom: 2px !important;
+}
+
 
 /*----------------------------------------------------------------------------
  * Openlayers
@@ -291,25 +301,99 @@
 }
 
 
+/*----------------------------------------------------------------------------
+ * GIS Multiselect
+ *--------------------------------------------------------------------------*/
+
+.ns-multiselect {
+    color: #111;
+}
+
+.ns-toolbar-multiselect-left .x-docked-top {
+	border-top-left-radius: 1px;
+}
+.ns-toolbar-multiselect-right .x-docked-top {
+	border-top-right-radius: 1px;
+}
+.ns-toolbar-multiselect-leftright .x-docked-top {
+	border-top-left-radius: 1px;
+	border-top-right-radius: 1px;
+}
+
+	/* Multiselect docked bar font size */
+.ns-toolbar-multiselect-left .ns-toolbar-multiselect-left-label,
+.ns-toolbar-multiselect-right .ns-toolbar-multiselect-right-label,
+.ns-toolbar-multiselect-leftright .ns-toolbar-multiselect-leftright-label {
+    font-size: 11px;
+    color: #000;
+}
+.ns-toolbar-multiselect-left .ns-toolbar-multiselect-left-label {
+	padding-left: 6px;
+}
+.ns-toolbar-multiselect-right .ns-toolbar-multiselect-right-label {
+    padding-right: 7px;
+}
+.ns-toolbar-multiselect-leftright .ns-toolbar-multiselect-leftright-label {
+    padding-left: 4px;
+}
+
+	/* Multiselect boundlist */
+.ns-toolbar-multiselect-left .x-boundlist-item-over,
+.ns-toolbar-multiselect-right .x-boundlist-item-over {
+    background-color: transparent;
+    border-color: transparent;
+}
+.ns-toolbar-multiselect-left .x-boundlist-selected,
+.ns-toolbar-multiselect-right .x-boundlist-selected {
+    background-color: #e5e5e5;
+    border-color: #e5e5e5;
+}
+
 
 /*----------------------------------------------------------------------------
  * Panel
  *--------------------------------------------------------------------------*/
 
 .x-panel-header	{ /* Panel header */
-	height: 30px;
-	padding: 7px 4px 4px 7px;
+/*
+    height: 30px;
+*/
+	padding: 7px 4px 7px 7px;
     border: 0 none;
 }
 
 
 /*----------------------------------------------------------------------------
+ * GIS Panel
+ *--------------------------------------------------------------------------*/
+
+.gis-panel-title-data,
+.gis-panel-title-period,
+.gis-panel-title-organisationunit {
+	background-repeat: no-repeat;
+	padding-left: 20px;
+    font-weight: bold;
+    height: 17px;
+}
+
+.gis-panel-title-data {
+	background-image: url(../images/data.png);
+}
+.gis-panel-title-period {
+	background-image: url(../images/period.png);
+}
+.gis-panel-title-organisationunit {
+	background-image: url(../images/organisationunit.png);
+}
+
+
+/*----------------------------------------------------------------------------
  * GIS form
  *--------------------------------------------------------------------------*/
 
 .gis-form-subtitle,
 .gis-form-subtitle-first { /* Subtitle panel */
-	margin-bottom: 6px;
+	margin-bottom: 3px;
 }
 .gis-form-subtitle {
 	margin-top: 6px;
@@ -400,6 +484,17 @@
 	width: 18px !important;
 }
 
+.gis-button-combotrigger {
+    background-image: url('../images/trigger.gif');
+    background-position: 0 0;
+    width: 17px;
+}
+.gis-button-combotrigger-disabled,
+.gis-button-combotrigger-disabled * {
+    opacity: 0.8;
+    cursor: default !important;
+}
+
 
 /*----------------------------------------------------------------------------
  * Toolbar
@@ -418,16 +513,22 @@
 
 	/* Toolbar btn */
 	.x-toolbar .x-btn-default-toolbar-small-icon button,
+	.x-toolbar .gis-btn-icon-facility,
+	.x-toolbar .gis-btn-icon-event,
 	.x-toolbar .gis-btn-icon-boundary,
 	.x-toolbar .gis-btn-icon-thematic1,
 	.x-toolbar .gis-btn-icon-thematic2,
 	.x-toolbar .gis-btn-icon-thematic3,
-	.x-toolbar .gis-btn-icon-thematic4,
-	.x-toolbar .gis-btn-icon-facility,
-	.x-toolbar .gis-btn-icon-symbol {
+	.x-toolbar .gis-btn-icon-thematic4 {
 		width: 24px !important;
 		height: 24px !important;
 	}
+	.x-toolbar .gis-btn-icon-facility {
+		background: url('../images/facility_20.png') no-repeat;
+	}
+	.x-toolbar .gis-btn-icon-event {
+		background: url('../images/event_20.png') no-repeat;
+	}
 	.x-toolbar .gis-btn-icon-boundary {
 		background: url('../images/boundary_20.png') no-repeat;
 	}
@@ -443,12 +544,6 @@
 	.x-toolbar .gis-btn-icon-thematic4 {
 		background: url('../images/thematic4_20.png') no-repeat;
 	}
-	.x-toolbar .gis-btn-icon-facility {
-		background: url('../images/facility_20.png') no-repeat;
-	}
-	.x-toolbar .gis-btn-icon-symbol {
-		background: url('../images/symbol_20.png') no-repeat;
-	}
 
 		/* Toolbar btn menu */
 		.gis-toolbar-btn-menu { /* Align menu */
@@ -650,6 +745,12 @@
 	letter-spacing: 1px;
 }
 
+.gis-window-title-icon-facility {
+	background: url('../images/facility_14.png') no-repeat;
+}
+.gis-window-title-icon-event {
+	background: url('../images/event_14.png') no-repeat;
+}
 .gis-window-title-icon-boundary {
 	background: url('../images/boundary_14.png') no-repeat;
 }
@@ -665,12 +766,6 @@
 .gis-window-title-icon-thematic4 {
 	background: url('../images/thematic4_14.png') no-repeat;
 }
-.gis-window-title-icon-facility {
-	background: url('../images/facility_14.png') no-repeat;
-}
-.gis-window-title-icon-symbol {
-	background: url('../images/symbol_14.png') no-repeat;
-}
 
 .gis-window-title-icon-labels {
 	background: url('../images/labels_14.png') no-repeat;
@@ -907,3 +1002,75 @@
 	padding: 12px 14px 12px 30px;
 	opacity: 0.65;
 }
+
+
+/*----------------------------------------------------------------------------
+ * GIS Accordion
+ *--------------------------------------------------------------------------*/
+
+	/* accordion title bar, shared */
+.gis-accordion .x-accordion-item .x-accordion-hd {
+	padding: 6px 5px 4px 8px;
+	border: 0 none;
+	cursor: pointer;
+	border-radius: 0;
+    background-image: none;
+    background-color: #e0e0e0;
+    background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dedede), color-stop(100%, #e6e6e6)) !important;
+    background-image: -webkit-linear-gradient(top, #dddddd, #e6e6e6) !important;
+    background-image: -moz-linear-gradient(top, #dddddd, #e6e6e6) !important;
+    background-image: -o-linear-gradient(top, #dddddd, #e6e6e6) !important;
+    background-image: -ms-linear-gradient(top, #dddddd, #e6e6e6) !important;
+    background-image: linear-gradient(top, #dddddd, #e6e6e6) !important;
+}
+	/* accordion title dock, default, collapsed */
+.gis-accordion .collapsed .x-accordion-hd {
+	padding-bottom: 5px !important;
+}
+
+	/* accordion title dock outer, shared */
+.gis-accordion .x-accordion-item {
+	border-radius: 1px;
+}
+	/* accordion title dock outer, default */
+.gis-accordion .x-accordion-item {
+	border: 1px solid #c5c5c5;
+	border-bottom: 0 none;
+}
+	/* accordion title dock outer, last */
+.gis-accordion .gis-accordion-last {
+	border: 1px solid #c5c5c5;
+}
+
+	/* accordion title dock text, shared */
+.gis-accordion .x-accordion-hd .x-panel-header-text {
+	font-weight: normal;
+	cursor: pointer;
+}
+
+	/* accordion item body */
+.gis-accordion .x-accordion-body {
+	padding: 2px 2px 0px;
+	border-top: 1px solid #c5c5c5 !important;
+}
+
+.gis-accordion .x-accordion-hd-sibling-expanded {
+	-moz-box-shadow: none;
+	-webkit-box-shadow: none;
+	-o-box-shadow: none;
+	box-shadow: none;
+}
+
+.gis-accordion .gis-toolbar-multiselect-left, .gis-accordion .gis-toolbar-multiselect-right {
+	margin-bottom: 0;
+}
+
+	/* accordion combo box */
+.gis-accordion .gis-combo .x-form-text, .gis-accordion .gis-combo .x-form-trigger {
+	height: 24px;
+	padding-top: 1px;
+}
+	/* accordion combo box label */
+.gis-accordion .gis-combo .x-form-item-label {
+	padding: 4px 0 0;
+}

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/jsonInitialize.vm'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/jsonInitialize.vm	2013-12-03 09:00:43 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/jsonInitialize.vm	2013-12-09 11:30:45 +0000
@@ -442,7 +442,8 @@
 "financial_july": "$encoder.jsEscape($i18n.getString( 'financial_july' ) , "'")",
 "financial_april": "$encoder.jsEscape($i18n.getString( 'financial_april' ) , "'")",
 "relative": "$encoder.jsEscape($i18n.getString( 'relative' ) , "'")",
-"reporting_rates": "$encoder.jsEscape($i18n.getString( 'reporting_rates' ) , "'")"
+"reporting_rates": "$encoder.jsEscape($i18n.getString( 'reporting_rates' ) , "'")",
+"event_layer": "$encoder.jsEscape($i18n.getString( 'event_layer' ) , "'")"
 }
 }
 #if($callback)

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/chart_14.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/chart_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/chart_14.png	2013-12-09 14:13:05 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/map_14.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/map_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/map_14.png	2013-12-09 14:13:05 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/table_14.png'
Binary files dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/table_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/images/table_14.png	2013-12-09 14:13:05 +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-12-19 09:48:29 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-12-20 13:39:55 +0000
@@ -1000,17 +1000,20 @@
 			enableKeyEvents: true,
 			currentValue: '',
 			listeners: {
-				keyup: function() {
-					if (this.getValue() !== this.currentValue) {
-						this.currentValue = this.getValue();
-
-						var value = this.getValue(),
-							url = value ? ns.core.init.contextPath + '/api/reportTables/query/' + value + '.json?viewClass=sharing&links=false' : null,
-							store = ns.app.stores.reportTable;
-
-						store.page = 1;
-						store.loadStore(url);
-					}
+				keyup: {
+					fn: function() {
+						if (this.getValue() !== this.currentValue) {
+							this.currentValue = this.getValue();
+
+							var value = this.getValue(),
+								url = value ? ns.core.init.contextPath + '/api/reportTables/query/' + value + '.json?viewClass=sharing&links=false' : null,
+								store = ns.app.stores.reportTable;
+
+							store.page = 1;
+							store.loadStore(url);
+						}
+					},
+					buffer: 100
 				}
 			}
 		});
@@ -5250,7 +5253,7 @@
 						levels.push(parseInt(ouRecords[i].id.split('-')[1]));
 					}
 					else if (ouRecords[i].id.substr(0,8) === 'OU_GROUP') {
-						groups.push(parseInt(ouRecords[i].id.split('-')[1]));
+						groups.push(ouRecords[i].id.split('-')[1]);
 					}
 					else {
 						orgunits.push(ouRecords[i].id);

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/chart_14.png'
Binary files dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/chart_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/chart_14.png	2013-12-09 14:13:05 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/map_14.png'
Binary files dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/map_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/map_14.png	2013-12-09 14:13:05 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/table_14.png'
Binary files dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/table_14.png	2013-07-22 15:03:42 +0000 and dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/table_14.png	2013-12-09 14:13:05 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/app.js	2013-12-08 12:44:13 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/app.js	2013-12-16 11:18:47 +0000
@@ -613,17 +613,20 @@
 			enableKeyEvents: true,
 			currentValue: '',
 			listeners: {
-				keyup: function() {
-					if (this.getValue() !== this.currentValue) {
-						this.currentValue = this.getValue();
-
-						var value = this.getValue(),
-							url = value ? ns.core.init.contextPath + '/api/charts/query/' + value + '.json?viewClass=sharing&links=false' : null,
-							store = ns.app.stores.chart;
-
-						store.page = 1;
-						store.loadStore(url);
-					}
+				keyup: {
+					fn: function() {
+						if (this.getValue() !== this.currentValue) {
+							this.currentValue = this.getValue();
+
+							var value = this.getValue(),
+								url = value ? ns.core.init.contextPath + '/api/charts/query/' + value + '.json?viewClass=sharing&links=false' : null,
+								store = ns.app.stores.chart;
+
+							store.page = 1;
+							store.loadStore(url);
+						}
+					},
+					buffer: 100
 				}
 			}
 		});


Follow ups