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