1 /**
  2  * @fileOverview  
  3  * Copyright (c) 2013 Regione Autonoma della Sardegna
  4  * Published under the GPL license.<br>
  5  * See <a href="https://sardegnageoportale.it/webgis/license.txt">https://sardegnageoportale.it/webgis/license.txt</a>
  6  * for the full text of the license.
  7  * @version 0.1
  8  */
  9 
 10 /**
 11  * @namespace framework.widgets.search
 12  */
 13 Ext.namespace("framework.widgets.search");
 14 
 15 /** api: (define)
 16  *  module = framework.widgets.search
 17  *  class = LayersGridPanel
 18  *  base_link = `Ext.Panel <http://dev.sencha.com/deploy/ext-3.3.1/docs/?class=Ext.Panel>`_
 19  */
 20 
 21 
 22 /**
 23  * A Panel designed to hold a Ext.grid.GridPanel. It makes layers search by custom parameters.
 24  * @name_ LayersGridPanel
 25  * @class A Panel designed to hold a Ext.grid.GridPanel. It makes layers search by custom parameters.
 26  * @constructor
 27  @extends <a target="_blank" href="http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.Panel">Ext.Panel</a>
 28  */
 29 framework.widgets.search.LayersGridPanel = Ext.extend(Ext.Panel,
 30         /** 
 31          * @lends framework.widgets.search.LayersGridPanel.prototype 
 32          */
 33                 {
 34                     /** api: title
 35                      *  
 36                      *  Default title of the panel. If not set
 37                      *  the value ``Feature Info`` will be used.
 38                      * @public
 39                      * @type String
 40                      */
 41                     title: null,
 42                     /** api: config[infoFormat]
 43                      *  
 44                      *  Default GFI INFO_FORMAT parameter, may be overruled per Layer object infoFormat WMS param. If not set
 45                      *  the value ``application/vnd.ogc.gml`` will be used.
 46                      *  @public
 47                      *  @type String
 48                      */
 49                     infoFormat: 'application/vnd.ogc.gml',
 50                     /** Internal vars */
 51                     /** api: config[map]
 52                      *  
 53                      *  A configured map or a configuration object
 54                      *  @public
 55                      *  @type OpenLayers.Map or Object
 56                      */
 57                     map: null,
 58                     /** Init the component creating a store and object'events.
 59                      * @private
 60                      */
 61                     initComponent: function() {
 62 
 63                         Ext.apply(this, {
 64                             layout: "fit"
 65                         });
 66 
 67                         this.loadNum = 0;
 68 
 69                         this.format = new OpenLayers.Format.WMSGetFeatureInfo();
 70 
 71                         this.display = this.displayGrid;
 72 
 73                         this.grid = new Ext.grid.GridPanel({
 74                             store: new Ext.data.ArrayStore({
 75                                 fields: [
 76                                     {name: 'id'},
 77                                     {name: 'progressivo'},
 78                                     {name: 'nome'},
 79                                     {name: 'metadato'},
 80                                     {name: 'anno'},
 81                                     {name: 'tipologia'},
 82                                     {name: 'selectedLayer'},
 83                                     {name: 'note'}
 84                                 ],
 85                                 data: [],
 86                                 listeners: {
 87                                     update: function(obj, record, operation) {
 88                                         if (record.data.selectedLayer == true) {
 89 
 90                                             var cqlFilter = this.searchLayerFilterGeometry?"INTERSECTS(SHAPE," + this.map.boundRicerca + ")":null;
 91                                             var layer = new OpenLayers.Layer.WMS(record.data.nome,
 92                                                     this.geoServerUrl + 'wms',
 93                                                     {
 94                                                         LAYERS: this.workspaceGeoServer + ':' + record.data.id,
 95                                                         STYLES: '',
 96                                                         format: "image/png",
 97                                                         transparent: true,
 98                                                         tiled: true,
 99                                                         INFO_FORMAT: this.infoFormat,
100                                                         visibility: true
101                                                         , cql_filter: cqlFilter
102                                                     },
103                                                     {
104                                                         tileOptions: {maxGetUrlLength: 2048},
105                                                         isBaseLayer: false
106                                                     }
107                                             );
108                                             layer.tipologia = record.data.tipologia;
109                                             layer.metadato = record.data.metadato;
110                                             layer.anno = record.data.anno;
111                                             layer.note = record.data.note;
112                                             if (!this.loadingLayer) {
113                                                 this.loadingLayer = new Ext.LoadMask(
114                                                         this.map.div, {
115                                                             msg: 'caricamento ...'
116                                                         }
117                                                 );
118                                             }
119 
120                                             layer.events.register('loadstart', this, function() {
121                                                 this.loadingLayer.show();
122                                             });
123                                             layer.events.register('loadend', this, function() {
124                                                 this.loadingLayer.hide();
125                                             });
126                                             this.map.addLayer(layer);
127                                             this.layersSearchOnMap[record.data.id] = layer;
128                                         } else {
129                                             this.map.removeLayer(this.layersSearchOnMap[record.data.id]);
130                                             delete this.layersSearchOnMap[record.data.id];
131                                         }
132                                         // attiva/disattiva il controllo getFeatureInfo
133                                         if (Object.keys(this.layersSearchOnMap).length == 1) {
134                                             Ext.getCmp(this.btnGetFeatureInfo).toggle(true);
135                                             this.layerShadowExtent.removeAllFeatures({silent: true});
136                                             if (window.popupAddr) {
137                                                 window.popupAddr.close();
138                                                 window.popupAddr.destroy();
139                                                 delete window.popupAddr;
140                                             }
141                                         } else if (Object.keys(this.layersSearchOnMap).length == 0) {
142                                             Ext.getCmp(this.btnGetFeatureInfo).toggle(false);
143                                         }
144                                     }, scope: this
145                                 }
146                             }),
147                             colModel: new Ext.grid.ColumnModel({
148                                 defaults: {
149                                     width: 120,
150                                     sortable: true
151                                 },
152                                 columns: [
153                                     {id: 'id', width: 20, sortable: true, dataIndex: 'progressivo'},
154                                     {description: 'description', header: 'Nome', sortable: true, dataIndex: 'nome'},
155                                     {xtype: 'checkcolumn', header: 'Select', width: 25, dataIndex: 'selectedLayer', father: this}
156                                 ]
157                             }),
158                             viewConfig: {
159                                 forceFit: true
160                             },
161                             sm: new Ext.grid.RowSelectionModel({singleSelect: true}),
162                             preventBodyReset: true,
163                             autoScroll: true,
164                             autoWidth: true,
165                             autoHeight: true,
166                             frame: true,
167                             title: 'Ricerca',
168                             iconCls: 'icon-grid'
169                         });
170 
171                         this.noResultPanel = new Ext.Panel({
172                             html: '<div class="hr-html-panel-body"><pre>Nessun layer trovato!</pre></div>',
173                             title: 'Ricerca',
174                             preventBodyReset: true,
175                             autoScroll: true,
176                             hidden: true
177                         });
178 
179                         this.items = [this.grid, this.noResultPanel];
180 
181 
182 
183                         framework.widgets.search.LayersGridPanel.superclass.initComponent.call(this);
184 
185                         if (!this.map)
186                             this.map = this.target.mapPanel.map;
187                     },
188                     /** Create a query string for the wfs call
189                      * @private
190                      */
191                     buildWMSOptions: function(productType, yearFrom, yearTo) {
192                         var params = {};
193                         var cqlFilter = '';
194 
195                         if (productType.length > 0) {
196                             cqlFilter = "TIPOLOGIA='" + productType + "' AND ";
197                         }
198                         if (yearFrom != "") {
199                             cqlFilter = cqlFilter + "ANNO >= " + yearFrom + " AND ";
200                         }
201                         if (yearTo != "") {
202                             cqlFilter = cqlFilter + "ANNO <= " + yearTo + " AND ";
203                         }
204 
205                         cqlFilter = cqlFilter + "INTERSECTS(SHAPE," + this.map.boundRicerca + ")";
206 
207                         params["typename"] = this.layerShadow;
208                         params["SERVICE"] = "WFS";
209                         params["VERSION"] = "1.0.0";
210                         params["REQUEST"] = "GetFeature";
211                         params["SRS"] = "3A3003";
212                         params["cql_filter"] = cqlFilter;
213                         return params;
214                     },
215                     /** execute layer search and fill a gridPanel with the result
216                      * @public
217                      * @param {String} productType type of product to search
218                      * @param {Number} yearFrom search product for year
219                      * @param {Number} yearTo search product to year
220                      */
221                     searchFeature: function(productType, yearFrom, yearTo) {
222                         var self = this;
223                         var sUrl = "";
224                         if (this.proxy)
225                             sUrl = this.proxy + escape(this.url);
226                         else
227                             sUrl = this.url;
228                         //this.father.resultPanel.searchFeature(this.father.cmbProductType.getValue(),years[0],years[1]);
229                         if (!this.busyMask) {
230                             this.busyMask = new Ext.LoadMask(
231                                     this.map.div, {
232                                         msg: 'ricerca in corso ...'
233                                     }
234                             );
235                         }
236                         this.noResultPanel.hide();
237                         this.grid.hide();
238                         this.busyMask.show();
239                         Ext.Ajax.request({
240                             url: sUrl,
241                             method: 'POST',
242                             params: self.buildWMSOptions(productType, yearFrom, yearTo),
243                             success: function(result, request) {
244                                 var features = self.format.read(result.responseText);
245                                 var evt = {};
246                                 evt.features = features;
247                                 self.busyMask.hide();
248                                 if (evt.features.length > 0)
249                                     self.displayGrid(evt);
250                                 else {
251                                     self.noResultPanel.show();
252                                 }
253                             },
254                             failure: function(result, request) {
255                                 self.busyMask.hide();
256                                 alert('error in ajax request');
257                             }
258                         });
259 
260                     },
261                     /***
262                      * private: method[displayGrid]
263                      * Fill up gridPanel with features in input
264                      * @private
265                      */
266                     displayGrid: function(evt) {
267                         if (this.map.activeSearchPanel) {
268                             this.map.activeSearchPanel.remove(this.map.activeSearchPanel.tabPanel);
269                         }
270                         this.map.activeSearchPanel = this;
271 
272                         Ext.getCmp(this.btnGetFeatureInfo).toggle(false);
273 
274                         this.removeLayersOldSearch();
275 
276                         var data = [];
277                         var objData = {};
278                         var productName = '';
279                         var productTitle = '';
280                         var count = 0;
281                         for (var i = 0; i < evt.features.length; i++) {
282                             productName = evt.features[i].attributes.PRODUCT;
283                             if (evt.features[i].attributes.NOME)
284                                 productTitle = evt.features[i].attributes.NOME;
285                             else
286                                 productTitle = productName;
287                             if (!objData[productName]) {
288                                 objData[productName] = 'ok';
289                                 data.push([productName, ++count, productTitle, evt.features[i].attributes.METADATO, evt.features[i].attributes.ANNO, evt.features[i].attributes.TIPOLOGIA, false, evt.features[i].attributes.NOTE]);
290                             }
291                         }
292                         this.grid.store.loadData(data);
293                         this.grid.show();
294 
295                     },
296                     /***
297                      * private: method[removeLayersOldSearch]
298                      * Clean the map from search layer
299                      * @private
300                      */
301                     removeLayersOldSearch: function() {
302                         if (this.layersSearchOnMap) {
303                             for (var layer in this.layersSearchOnMap) {
304                                 this.map.removeLayer(this.layersSearchOnMap[layer]);
305                             }
306                         }
307                         this.map.events.triggerEvent('cleanSearchObjects');
308                         this.layersSearchOnMap = {};
309                     },
310                     /***
311                      * private: method[getPoligonMapExtent]
312                      * Get a poligon query string from extent (OpenLayers.Bounds)
313                      * @private
314                      */
315                     getPoligonMapExtent: function() {
316                         var extent = this.map.boundRicerca;
317                         if (extent instanceof OpenLayers.Geometry.MultiPolygon || extent instanceof OpenLayers.Geometry.Polygon) {
318                             return extent;
319                         }
320                         return extent.left + "," + extent.top + " " + extent.right + "," + extent.top + " " + extent.right + "," + extent.bottom +
321                                 " " + extent.left + "," + extent.bottom + " " + extent.left + "," + extent.top;
322                     }
323                 })
324 
325         /** api: xtype = framework_layersgridpanel */
326         Ext.reg('framework_layersgridpanel', framework.widgets.search.LayersGridPanel);
327 
328 
329