Source: widgets/SpwAddDataFromFile.js

Retour à la documentation
/**
 * @class spw.widgets.SpwAddDataFromFile
 */
define([
        "dojo/_base/declare", "spw/api/SpwBaseTemplatedWidget", "dojo/dom-construct",
        "dijit/layout/BorderContainer", "dijit/layout/ContentPane", "dojo/on",
        "dojo/_base/lang", "dojo/text!./templates/SpwAddDataFromFile.html",
        "spw/api/MessageManager", "dojo/dom-style", "dojo/_base/array", "spw/api/ViewUtils",
        "spw/api/Utils", "dojo/promise/all", "dojo/Deferred", "esri/graphic", "esri/geometry/Point",
        "esri/symbols/PictureMarkerSymbol", "dojo/_base/Color", "spw/libs/jszip", "dojo/query", "dojo/_base/config",
        "spw/libs/shp", "spw/api/GeometryUtils", "dojo/i18n!./nls/SpwAddDataFromFile", "esri/geometry/Extent",

        "dojo/store/Memory", "dijit/form/ComboBox", "dijit/form/TextBox", "dijit/form/Button", "dijit/form/DropDownButton",
    	"dojox/widget/ColorPicker"
    ],
    function(declare, SpwBaseTemplatedWidget, domConstruct, BorderContainer, ContentPane,
             on, lang, tmpl, MessageManager, domStyle, array, ViewUtils, Utils, all, Deferred,
             Graphic, Point, PictureMarkerSymbol, Color,JSZIP, query, dojoConfig, shp, GeometryUtils, labels, Extent) {

        return declare("spw.widgets.SpwAddDataFromFile", [SpwBaseTemplatedWidget], /** @lends spw.widgets.SpwAddDataFromFile.prototype */ {

            //@schema.begin
            jsonSchema: {
                "description":"Ce widget permet de charger le contenu d'un fichier (local ou distant) CSV, GPX ou KML sur la carte. Le fichier CSV doit au minimum contenir un champ de coordonnées Lambert X et un champ de coordonnées Lambert Y. <br/><br/>Exemple : <br/><br/><i>Rue;Numéro;Code postal;Localité;Catégorie Habitation;x;y</i><br /><i>Avenue de la gare;2b;4000;Liège;Cat-B;235875;147760</i><br /><br />Les fichiers GPX et KML doivent, quand à eux, être standards. ",
                "properties": {
                    "xField": {
                        "type": "string",
                        "required": false,
                        "description": "Ce paramètre définit la colonne correspondante à la coordonnée X d'une entrée",
                        "default": "X"
                    },
                    "yField": {
                        "type": "string",
                        "required": false,
                        "description": "Ce paramètre définit la colonne correspondante à la coordonnée Y d'une entrée",
                        "default": "Y"
                    },
                    "graphicType": {
                        "type": "string",
                        "required": false,
                        "enum": ["point"],
                        "description": "Ce paramètre définit le type des géométries (uniquement point pour le moment) dans le cas d'un fichier CSV",
                        "default": "point"
                    },
                    "description": {
                        "type": "string",
                        "required": false,
                        "description": "Description globale du widget (premier bloc de texte)",
                        "default": "Aucune description"
                    },
                    "types": {
                        "type": "array",
                        "required": false,
                        "description": "Décrit les types de fichier supportés et permet d'indiquer une description spécifique à chacun",
                        "anyOf": [{
                            "title": "type",
                            "type": "object",
                            "required": false,
                            "properties": {
                                "name": {
                                    "title": "name",
                                    "type": "string",
                                    "enum": ["CSV", "KML", "GPX", "SHP"],
                                    "description": "Type de fichier"
                                },
                                "description": {
                                    "title": "description",
                                    "type": "string",
                                    "description": "Description pour le type de fichier précisé (HTML)"
                                }
                            }
                        }],
                        "default":[
                            {
                                "name": "CSV",
                                "description": "<p> Pour fonctionner, cet outil a besoin d'un fichier CSV dont : </p> <ul> <li>La première ligne est constituée des titres de champs (noms des colonnes).</li> <li>Parmi les champs du fichier, il doit obligatoirement y figurer un champ nommé \"X\" et un champ nommé \"Y\".</li> <li>Ces champs sont les coordonnées de la donnée. Pour chaque ligne de donnée, les coordonnées doivent être renseignées en Lambert72.</li> </ul> <div> <a href='" + dojoConfig.geoviewerApiUrl + "/viewer/poi.zip" + "' target='_blank' class='downloadCanevasLink'>Télécharger le canevas CSV</a> </div>"
                            },
                            {
                                "name": "KML",
                                "description": "<p>Pour fonctionner, cet outil a besoin d'un fichier KML...</p>"
                            },
                            {
                                "name": "GPX",
                                "description": "<p>Pour fonctionner, cet outil a besoin d'un fichier GPX...</p>"
                            },
                            {
                                "name": "SHP",
				                "description": "<p>Pour fonctionner, cet outil a besoin d'un fichier zip contenant les fichiers .shp, .shx, .prj (pour permettre la reprojection) et .dbf (pour l'attributaire).</p>"
                            }
                        ]
                    }
                }
            },
            //@schema.end

            templateString: tmpl,
            noFileChosen: null,
            CSVCount: 1,
            KMLCount: 1,
            GPXCount: 1,
            SHPCount: 1,

            labels: labels,

	        xField: "x",
	        yField: "y",
	        longField: 'longitude',
	        latField: 'latitude',
	        graphicType: 'point',
	        allowFileImport: true,
            serviceEditable: true,

            "widgetTitle": "Ajouter un fichier",
            "position": "none",
            "activated": true,
            "showTemplate":false,
            "description": "Ajoutez vos données à partir d’un fichier.",
            "types": [
                {
                    "name": "CSV",
                    "description": "<p>"+labels.CSVdescription+"</p><ul><li>"+labels.CSVdescriptionItem1+"</li><li>"+labels.CSVdescriptionItem2+"<ul><li>"+labels.CSVdescriptionItem21+"</li><li>"+labels.CSVdescriptionItem22+"</li><li>"+labels.CSVdescriptionItem23+"</li></ul></li></ul><div> <a href='"+dojoConfig.geoviewerApiUrl + "/viewer/poi.zip"+"' target='_blank' class='downloadCanevasLink'>"+labels.CSVdescriptionItem3+"</a> </div>"
                },
                {
                    "name": "KML",
                    "description": "<p>"+labels.KMLdescription+"</p>"
                },
                {
                    "name": "KMZ",
                    "description": "<p>"+labels.KMZdescription+"</p>"
                },
                {
                    "name": "GPX",
                    "description": "<p>"+labels.GPXdescription+"</p>"
                },
                {
                    "name": "SHP",
                    "description": "<p>"+labels.SHPdescription+"</p>"
                }, {
                    "name": "GEOJSON",
                    "description": "<p>"+labels.GeoJSONdescription+"</p>"
                }
            ],

            typeToAccept: {
                CSV: '.csv',
                KML: '.kml',
                KMZ: '.kmz',
                GPX: '.gpx',
                SHP: '.zip',
                GEOJSON: '.json'
            },

            typeToMapServiceType: {
                CSV: 'CSV_LAYER',
                KML: 'KML_LAYER',
                KMZ: 'KML_LAYER',
                GPX: 'GPX_LAYER',
                SHP: 'SHP_LAYER',
                GEOJSON: 'DRAW_LAYER'
            },

            _fillColor: "#002673",

            _forceColor: false,

            typeCount: 0,

            /**
             * @constructs
             * @param config
             */
            constructor: function(config) {
                this.noFileChosen = "Aucun fichier";
            },

            postCreate: function() {
                this.inherited(arguments);

                this.own(
                    on(this.comboBoxType, 'change', lang.hitch(this, this._comboChanged))
                );

                this.onColorChange(this._fillColor);
                this.colorPickerIcon.set('disabled', !this._forceColor);

                array.forEach(this.types, lang.hitch(this, function(type, idx) {
                    if (type.name == null) {
                        return;
                    }
                    this.comboBoxType.get('store').add(type);

                    if (idx === 0) {
                        this.comboBoxType.set('item', type);
                    }
                }));

                if (!this.allowFileImport) {
                    ViewUtils.hideElement(this.fileImportDiv);
                }
            },

            _showDetails: function(selected) {
                if (selected == null) {
                    return;
                }
                this._restrictInputAccept(selected.name);
                this.detailsNode.innerHTML = selected.description;
            },

            _restrictInputAccept: function(selectedFileType) {
                var accept = this.typeToAccept[selectedFileType];
                if (accept) {
                    this.selectFile.accept = accept;
                }
            },

            _comboChanged: function() {
                this._showDetails(this.comboBoxType.get('item'));
            },

            selectFileChanged: function() {
                if (this.selectFile.files && this.selectFile.files.length > 0) {
                    this.fileName.innerHTML = this.selectFile.files[0].name;
                } else {
                    this.fileName.innerHTML = this.noFileChosen;
                }
            },

            addToSelectionClicked: function() {
                if (this.selectFile.files && this.selectFile.files.length > 0) {
                    this.addDataFromFile();
                } else if (this.textBoxUrl.get('value')) {
                    this.addData();
                } else {
                    MessageManager.getInstance().notifyWarning(this.labels.notifyWarningUrl);
                }
            },

            readShpFile: function(service, data) {
                if (data == null) {
                    service.shpInfo = {
                        url: this.textBoxUrl.get('value')
                    };
                }
                else {
                    // not handled by shapelayer yet
                    service.shpInfo = {
                        shpData: data
                    };
                }
                if (service.shpInfo && service.shpInfo.shpData instanceof Array) {
                    service.shpInfo.shpData = new Uint8Array(service.shpInfo.shpData).buffer;
                }
                Utils.readShpFile(service.shpInfo.shpData).then(
                    lang.hitch(this, function(geojson) {
                        if (Array.isArray(geojson)) {
                            var promises = [];
                            array.forEach(geojson, lang.hitch(this, function(collection) {
                                service.features = array.map(collection.features, function(feature) { return lang.mixin(feature, {srid: 4326}); });
                                service.serviceId = Utils.guid();
                                service.label = collection.fileName;
                                promises.push(this.addDataToMapFromConfig(service, false));
                            }));
                            if (promises.length > 0) {
                                all(promises).then(
                                    lang.hitch(this, function(r) {
                                        if (r && r.length > 0) {
                                            var extents = array.map(r, function(s) {
                                                var ex = s.layer.getExtent();
                                                if (ex) {
                                                    return new Extent(ex);
                                                }
                                                return null;
                                            });
                                            var union = extents[0];
                                            array.forEach(extents, lang.hitch(this, function(e) {
                                                union = union.union(e);
                                            }));
                                            if (union) {
                                                this.spwViewer.get('spwMap').zoomToExtent(union.getExtent());
                                            }
                                        }
                                    })
                                )
                            }
                        } else {
                            service.features = array.map(geojson.features, function(feature) { return lang.mixin(feature, {srid: 4326}); });
                            this.addDataToMapFromConfig(service, true);
                        }
                    }),
                    lang.hitch(this, function(err) {
                        console.error(err);
                    })
                );
            },

            addData: function(data, name) {
                var item = this.comboBoxType.get('item');
                var type = item.name;
                var service = {
                    label: name ? name : ('Données ' + type + ' ' + this[type + 'Count']), //data == null ? this.textBoxUrl.get('value').split('/').pop() : this.selectFile.files[0].name
                    serviceId: Utils.guid(),
                    type: this.typeToMapServiceType[type],
                    visible: true,
                    hasLegend: false,
                    identifiable: true,
                    showTemplate: this.showTemplate,
                    toLoad: true,
                    style: this._forceColor ? {fillColor: this._fillColor}: {},
                    editable: this.serviceEditable
                };
                if (type == 'GEOJSON') {
                    var options = {
                        forceColorCode: this._forceColor ? this._fillColor : null,
                        mapServiceConfig: service
                    };
                    this.spwViewer.get('spwMap').addServiceFromGeoJSONResource(data, options).then(
                        lang.hitch(this, function(r) {
                            this.close();
                        }),
                        lang.hitch(this, function(err) {
                            console.log('Error while adding map service to map ...');
                        })
                    );
                }
                else if (type == 'SHP') {
                    this.readShpFile(service, data);
                }
                else {
                    switch(type) {
                        case 'CSV':
                            service.csvInfo = {
                                showTemplate: this.showTemplate,
                                graphicType: this.graphicType,
                                xField: this.xField,
                                yField: this.yField,
                                latField: this.latField,
                                longField: this.longField,
                                srid: 31370
                            };

                            if (data == null) {
                                service.csvInfo.url = this.textBoxUrl.get('value');
                            }
                            else {
                                service.csvInfo.csvString = data;
                            }
                            break;
                        case 'DRAW':
                            service.geoJsonInfo = data;
                            break;
                        case 'KML':
                        case 'KMZ':
                        case 'GPX':
                            if (data == null) {
                                service.fileInfo = {
                                    url: this.textBoxUrl.get('value')
                                };
                            }
                            else {
                                service.fileInfo = {
                                    rawData: data
                                };
                            }
                            break;

                        case 'SHP':
                            if (data == null) {
                                service.shpInfo = {
                                    url: this.textBoxUrl.get('value')
                                };
                            }
                            else {
                                // not handled by shapelayer yet
                                service.shpInfo = {
                                    shpData: data
                                };
                            }
                            break;
                    }

                    this.addDataToMapFromConfig(service, true);
                }
            },


            addDataToMapFromConfig: function(service, zoomToExtent) {
                var def = new Deferred();
                var mapService = null;
                zoomToExtent = zoomToExtent == true ? true : false;
                try {
                    mapService = this.spwViewer.get('spwMap').addMapService(service);

                    if (mapService.loaded) {
                        if (mapService.layer.getExtent && zoomToExtent) {
                            this.spwViewer.get('spwMap').zoomToExtent(mapService.layer.getExtent());
                        }

                        if (mapService.get('valuesIgnored')) {
                            MessageManager.getInstance().notifyWarning(this.labels.notifyWarningValuesIgnored);
                        }
                        def.resolve(mapService);
                    }
                    else {
                        var handler = null;

                        this.own(
                            handler = on(mapService, mapService.events.MapServiceLoaded, lang.hitch(this, function(m) {
                                if (mapService.layer.getExtent && zoomToExtent) {
                                    this.spwViewer.get('spwMap').zoomToExtent(mapService.layer.getExtent());
                                }

                                if (mapService.get('valuesIgnored')) {
                                    MessageManager.getInstance().notifyWarning(this.labels.notifyWarningValuesIgnored);
                                }

                                if (handler) {
                                    handler.remove();
                                }
                                def.resolve(mapService);
                            }))
                        );
                    }
                    this.currentMapService = mapService;

                    this.close();
                }
                catch (e) {
                    if (e instanceof RangeError) {
                        MessageManager.getInstance().notifyError(this.labels.notifyErrorFileSize);
                    }
                    else {
                        console.error(e);
                        MessageManager.getInstance().notifyError(this.labels.notifyErrorFileGen);
                    }
                    def.reject(mapService);
                    this.spwViewer.get('spwMap').removeMapService(service.serviceId, true);
                }
                return def;
            },


            addDataFromFile: function() {
                this.showLoading();

                var type = this.comboBoxType.get('value');

                var fileReader = new FileReader();

                try {
                    fileReader.onloadend = lang.hitch(this, function(e) {
                        try {
                            this.addData(e.target.result, this.selectFile.files[0].name);
                            this.hideLoading();
                        }
                        catch (e) {
                            if (e instanceof RangeError) {
                                MessageManager.getInstance().notifyError(this.labels.notifyErrorFileSize);
                            }
                            else {
                                console.error(e);
                                MessageManager.getInstance().notifyError(this.labels.notifyErrorFileGen);
                            }

                            this.hideLoading();
                        }
                    });

                    var type = this.comboBoxType.get('value');
                    if (type === 'SHP') {
                        fileReader.readAsArrayBuffer(this.selectFile.files[0]);
                    } else if (type === 'KMZ') {
                        var zip = new JSZIP();
                        zip.loadAsync(this.selectFile.files[0])
                            .then(lang.hitch(this, function(zip) {
                                zip.file("doc.kml").async("string").then(lang.hitch(this, function (data) {
                                    console.log('KMZ DATA:', data);
                                    this.addData(data, this.selectFile.files[0].name);
                                    this.hideLoading();
                                }));
                            }));
                    } else {
                        fileReader.readAsText(this.selectFile.files[0], 'ISO-8859-1');
                    }
                }
                catch (e) {
                    if (e instanceof RangeError) {
                        MessageManager.getInstance().notifyError(this.labels.notifyErrorFileSize);
                    }
                    else {
                        console.error(e);
                        MessageManager.getInstance().notifyError(this.labels.notifyErrorFileGen);
                    }

                    this.hideLoading();
                }
            },

            onColorChange: function(newColor) {
                query(".colorPreviewIcon", this.colorPickerIcon.domNode).forEach(function(node){
                    node.style.backgroundColor = newColor;
                });
                this._fillColor = newColor;
            },

            onClickForceColorCheckbox: function() {
                var forceColor = this.forceColorCheckbox.checked;
                this.colorPickerIcon.set('disabled', !forceColor);
                this._forceColor = forceColor;
            },

            cancelClicked: function() {
                if (this.currentMapService == null) {
                    return;
                }

                this.spwViewer.get('spwMap').removeMapService(this.currentMapService.serviceId);
                this.currentMapService = null;
            }
        });
    });