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 * @require plugins/Tool.js 12 * @require GeoExt/widgets/Action.js 13 */ 14 15 /** 16 * @namespace framework.plugins 17 */ 18 Ext.ns("framework.plugins"); 19 20 /** 21 * Class for template and map saving management. 22 * Calls servlet for digest creation and file storing on server side. 23 * @name_ MapLinker 24 * @class Class for template and map saving management. 25 * @constructor 26 * @extends <a target="_blank" href="http://gxp.opengeo.org/master/doc/lib/plugins/Tool.html">gxp.plugins.Tool</a> 27 */ 28 framework.plugins.MapLinker = Ext.extend(gxp.plugins.Tool, 29 /** 30 * @lends framework.plugins.MapLinker.prototype 31 */ 32 { 33 /** 34 * framework_maplinker plugin type. 35 * @public 36 * @type String 37 */ 38 ptype: 'framework_maplinker', 39 40 /** 41 * Together with 'iconClsPrefix' define the icons of the buttons created 42 * @public 43 * @type String 44 */ 45 mode: 'map', 46 47 /** 48 * The prefix of the names of the css classes that define the icons of the buttons created 49 * to activate the mapLinker. You must define a class in your CSS file called with the value 50 * of the expression this.iconClsPrefix+this.mode that specifies the above mentioned icon. 51 * @public 52 * @type String 53 */ 54 iconClsPrefix: "gxp-icon-", 55 56 /** 57 * the base Ajax Url for ajax request 58 * default "" 59 * @public 60 * @type String 61 */ 62 baseUrl: "", 63 64 /** 65 * the custom Url for saved map 66 * default "" 67 * @public 68 * @type String 69 */ 70 customUrl: "", 71 72 /** 73 * Text for zoom in action tooltip (i18n). 74 * @public 75 * @type string 76 */ 77 tooltipText: "Create link map", 78 79 /** 80 * featureLayers container 81 * @public 82 * @type Array(Object) 83 */ 84 featureLayers: new Array(), 85 86 /** private: method[addActions] 87 * 88 */ 89 90 /** Adds actions to be performed on click. 91 * @public 92 */ 93 addActions: function() { 94 var map = this.target.mapPanel.map; 95 var self = this; 96 var action = new GeoExt.Action({ 97 iconCls: this.iconClsPrefix + self.mode, 98 tooltip: this.tooltipText, 99 map: map, 100 handler: function() { 101 //aggiungo i dati relativi ai layer vettoriali 102 if (self.mode === 'map') { 103 self.saveMap(); 104 } else { 105 Ext.Msg.prompt('Name', 'Nome con cui salvare il template:', function(btn, text) { 106 if (btn == 'ok') { 107 if (Ext.isEmpty(text)) { 108 Ext.Msg.alert('Errore', 'Il nome inserito è vuoto'); 109 } else { 110 text = text.trim().toLowerCase(); 111 if (text === 'default') { 112 Ext.Msg.alert('Errore', 'Il nome template "default" è riservato'); 113 } else { 114 self.saveTemplate(text); 115 } 116 } 117 118 } else { 119 Ext.Msg.alert('Info', 'Salvataggio annullato dall\'utente'); 120 } 121 122 }); 123 } 124 } 125 }); 126 return framework.plugins.MapLinker.superclass.addActions.apply(this, [action]); 127 }, 128 129 /** 130 * Sets plugin modality to 'template'. 131 * @public 132 */ 133 templateMode: function() { 134 this.mode = 'template'; 135 this.actions[0].items[0].setIconClass(this.iconClsPrefix + "template"); 136 }, 137 138 /** 139 * Sets plugin modality to 'map'. 140 * @public 141 */ 142 mapMode: function() { 143 this.mode = 'map'; 144 this.actions[0].items[0].setIconClass(this.iconClsPrefix + "map"); 145 }, 146 147 /** 148 * Saves a template serializing its content in json. 149 * @public 150 * @param {String} templateName name of template to be saved 151 * @param {boolan} forceWrite write file whitout prompting even it already exists 152 */ 153 saveTemplate: function(templateName, forceWrite) { 154 var self = this; 155 this.getDigest(function(digest) { 156 Ext.Ajax.request({ 157 method: 'POST', 158 url: self.baseUrl + 'Save', 159 params: {hash: digest, content: self.toJson(), template: templateName, force: forceWrite}, 160 success: function(response, opts) { 161 var obj = Ext.util.JSON.decode(response.responseText); 162 if (Ext.isDefined(obj.fileExists)) { 163 Ext.MessageBox.confirm('Attenzione', templateName + ' già presente.<BR/>' + 164 'Si desidera sovrascriverlo?', function(btn) { 165 if (btn == 'yes') { 166 //chiamata con force = true 167 self.saveTemplate(templateName, true); 168 } else { 169 Ext.Msg.alert('Info','Salvataggio annullato dall\'utente'); 170 } 171 }); 172 } else { 173 if (Ext.isDefined(obj.id)) { 174 self.useMapConfiguration(obj.id); 175 } else { 176 Ext.MessageBox.alert('Errore', obj.error); 177 } 178 } 179 }, 180 failure: function(response, opts) { 181 Ext.MessageBox.alert('Errore', 'server-side failure with status code ' + response.status); 182 console.log('server-side failure with status code ' + response.status); 183 } 184 }); 185 }); 186 }, 187 188 /** 189 * Saves a map serializing its content in json creating a new map id. 190 * @public 191 */ 192 saveMap: function() { 193 var self = this; 194 var _layers = this.target.mapPanel.map.layers; 195 this.getDigest(function(digest) { 196 Ext.Ajax.request({ 197 method: 'POST', 198 url: self.baseUrl + 'Save', 199 params: {hash: digest, content: self.toJson()}, 200 success: function(response, opts) { 201 var obj = Ext.util.JSON.decode(response.responseText); 202 if (Ext.isDefined(obj.id)) { 203 self.useMapConfiguration(obj.id); 204 } else { 205 Ext.MessageBox.alert('Errore', obj.error); 206 } 207 }, 208 failure: function(response, opts) { 209 Ext.MessageBox.alert('Errore', 'server-side failure with status code ' + response.status); 210 console.log('server-side failure with status code ' + response.status); 211 } 212 }); 213 }); 214 }, 215 216 /** 217 * Requests a digest based on client ip. 218 * @public 219 * @param {function} onSuccess function to be called when the digest has been received 220 */ 221 getDigest: function(onSuccess) { 222 Ext.Ajax.request({ 223 method: 'GET', 224 url: this.baseUrl + 'Digest', 225 success: function(response, opts) { 226 var obj = Ext.util.JSON.decode(response.responseText); 227 if (Ext.isDefined(obj.value)) { 228 onSuccess(obj.value); 229 } else { 230 Ext.MessageBox.alert('Errore', obj.error); 231 } 232 }, 233 failure: function(response, opts) { 234 Ext.MessageBox.alert('Errore', 'server-side failure with status code ' + response.status); 235 console.log('server-side failure with status code ' + response.status); 236 } 237 }); 238 }, 239 240 /** 241 * Function to be override to change the default behavior. 242 * @public 243 * @param {number} id id of current map configuration 244 */ 245 useMapConfiguration: function(id) { 246 this.showLinkDialog(id); 247 }, 248 249 /** 250 * Shows a window containg a link for template/map sharing. 251 * @public 252 * @param {String} name Name of template/map saved 253 */ 254 showLinkDialog: function(name) { 255 var link = this.target.getBaseUrl() + this.customUrl + '?map=' + name; 256 var frame = "<iframe width='600' height='600' frameborder='0' scrolling='no' marginheight='0' marginwidth='0'" + 257 "src='"+link+"&framemode=1' class='link'></iframe>"; 258 var pnl = new Ext.Panel({ 259 title: this.mapInfoText, 260 html: '<div class="mapLinker">'+ 261 '<h2>Link mappa</h2>'+ 262 '<p>'+ 263 '<input type="text" onclick="this.focus();this.select();" value="' + link + '" readonly="1" />'+ 264 '</p>'+ 265 '<h2>Copia e incolla l\'HTML da incorporare nel sito web</h2>'+ 266 '<p>'+ 267 '<textarea onclick="this.focus();this.select();" readonly="1">' + frame + '</textarea>'+ 268 '</p>'+ 269 '</div>', 270 height: 'auto', 271 width: 'auto' 272 }); 273 274 275 var win = new Ext.Window({ 276 title: "Condivisione mappa", 277 modal: true, 278 layout: "fit", 279 width: 342, 280 height: 230, 281 items: [pnl] 282 }); 283 win.show(); 284 }, 285 286 /** 287 * Get serialization of data to be saved. 288 * @public 289 */ 290 toJson: function() { 291 var layers = this.target.mapPanel.map.layers; 292 var extraData = new Object(); 293 extraData.backgroundColor = Ext.get(this.target.mapPanel.map.getViewport()).getStyle('background-color'); 294 extraData.layers = new Array(); 295 extraData.groups = this.target.layer_group; 296 if(this.target.mapPanel.map.searchName === 'routing' && this.target.tools.boxrouting && this.target.tools.boxrouting.routingpanel.xmlRequest.length > 0){ 297 extraData.routingSearchXmlRequest = this.target.tools.boxrouting.routingpanel.xmlRequest; 298 extraData.routingDestination = this.target.tools.boxrouting.routingpanel.endLocationCombo.lastSelectionText; 299 extraData.routingType = this.target.tools.boxrouting.routingpanel.routePreference; 300 } 301 var self = this; 302 Ext.each(layers, function(el, i) { 303 if (self.featureLayers.indexOf(el.name) !== -1) { 304 extraData.layers.push({name: el.name, features: el.features, type: 'featureLayer'}); 305 } 306 }); 307 this.target.customData = extraData; 308 return this.target.serialize(); 309 } 310 }); 311 312 Ext.preg(framework.plugins.MapLinker.prototype.ptype, framework.plugins.MapLinker); 313