diff --git a/demo/src/app/geo/import-export/import-export.component.html b/demo/src/app/geo/import-export/import-export.component.html index 58e32a0dd9..1826387b45 100644 --- a/demo/src/app/geo/import-export/import-export.component.html +++ b/demo/src/app/geo/import-export/import-export.component.html @@ -13,7 +13,7 @@ - + diff --git a/demo/src/app/geo/import-export/import-export.component.ts b/demo/src/app/geo/import-export/import-export.component.ts index d0cc61f2bb..362eb2ddfa 100644 --- a/demo/src/app/geo/import-export/import-export.component.ts +++ b/demo/src/app/geo/import-export/import-export.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { LanguageService } from '@igo2/core'; import { IgoMap, LayerService } from '@igo2/geo'; +import { WorkspaceStore } from '@igo2/common'; @Component({ selector: 'app-import-export', @@ -22,6 +23,8 @@ export class AppImportExportComponent { zoom: 9 }; + public store = new WorkspaceStore([]); + constructor( private languageService: LanguageService, private layerService: LayerService diff --git a/packages/geo/src/lib/import-export/import-export/import-export.component.html b/packages/geo/src/lib/import-export/import-export/import-export.component.html index 2d5fa5c857..a84b8882a9 100644 --- a/packages/geo/src/lib/import-export/import-export/import-export.component.html +++ b/packages/geo/src/lib/import-export/import-export/import-export.component.html @@ -132,6 +132,22 @@

{{'igo.geo.importExportForm.exportNoLayersExportable' | translate}}

+
+ + {{'igo.geo.importExportForm.exportCombineResults' | translate}} + +
+ +
+ + {{'igo.geo.importExportForm.exportSeparator' | translate}} + +
+
{ + let geomTypesCSV: { geometryType: string, features: any[] }[] = []; + let featuresCSV: any[] = []; + let filename: string = ""; + + for (const [layerIndex, layer] of data.layers.entries()) { const lay = this.map.getLayerById(layer); - let filename = lay.title; - if (data.name !== undefined) { - filename = data.name; + if (!(data.format === ExportFormat.CSVsemicolon || data.format === ExportFormat.CSVcomma) + || !data.combineLayers || data.layers.length === 1) { + filename = lay.title; + if (data.name) { + filename = data.name; + } + } else { + filename = this.languageService.translate.instant('igo.geo.export.combinedLayers'); } const dSOptions: DataSourceOptions = lay.dataSource.options; if (data.format === ExportFormat.URL && dSOptions.download && (dSOptions.download.url || dSOptions.download.dynamicUrl)) { @@ -531,7 +540,6 @@ export class ImportExportComponent implements OnDestroy, OnInit { geomTypes.forEach(geomType => { geomType.features.forEach(feature => { const radius: number = feature.get('rad'); - if (radius) { const center4326: Array = [feature.get('longitude'), feature.get('latitude')]; const circle = circular(center4326, radius, 500); @@ -550,6 +558,33 @@ export class ImportExportComponent implements OnDestroy, OnInit { const message = translate.instant('igo.geo.export.gpx.error.poly.text'); this.messageService.error(message, title, { timeOut: 20000 }); } + } else if ((data.format === ExportFormat.CSVsemicolon || data.format === ExportFormat.CSVcomma) && data.combineLayers) { + geomTypes.forEach(geomType => geomTypesCSV.push(geomType)); + + if (layerIndex !== data.layers.length - 1) { + continue; + } else { + let previousFeature = undefined; + geomTypesCSV.forEach(geomType => { + geomType.features.forEach(currentFeature => { + if (data.separator) { + if (previousFeature) { + if (currentFeature.get('_featureStore').layer.options.title !== + previousFeature.get('_featureStore').layer.options.title) { + const titleEmptyRows = this.createTitleEmptyRows(previousFeature, currentFeature); + featuresCSV.push(titleEmptyRows[2]); + featuresCSV.push(titleEmptyRows[1]); + } + } else { + const titleEmptyRows = this.createTitleEmptyRows(currentFeature, currentFeature); + featuresCSV.push(titleEmptyRows[0]); + } + } + featuresCSV.push(currentFeature); + previousFeature = currentFeature; + }); + }); + } } if (geomTypes.length === 0) { @@ -559,29 +594,72 @@ export class ImportExportComponent implements OnDestroy, OnInit { this.messageService.error(message, title, { timeOut: 20000 }); } else { - geomTypes.map(geomType => - this.exportService.export(geomType.features, data.format, filename + geomType.geometryType, data.encoding, this.map.projection) - .subscribe( - () => {}, - (error: Error) => this.onFileExportError(error), - () => { - this.onFileExportSuccess(); - - geomType.features.forEach(feature => { - const radius: number = feature.get('rad'); - - if (radius) { - const point = new olPoint([feature.get('longitude'), feature.get('latitude')]); - point.transform('EPSG:4326', feature.get('_projection')); - feature.setGeometry(point); - } - }); - - this.loading$.next(false); + if (!(data.format === ExportFormat.CSVsemicolon || data.format === ExportFormat.CSVcomma) || !data.combineLayers) { + geomTypes.map(geomType => + this.exportService.export(geomType.features, data.format, filename + geomType.geometryType, data.encoding, this.map.projection) + .subscribe( + () => {}, + (error: Error) => this.onFileExportError(error), + () => { + this.onFileExportSuccess(); + + geomType.features.forEach(feature => { + this.circleToPoint(feature); + }); + + this.loading$.next(false); } - )); + )); + } + } + }; + if ((data.format === ExportFormat.CSVsemicolon || data.format === ExportFormat.CSVcomma) && data.combineLayers) { + this.exportService.export(featuresCSV, data.format, filename, data.encoding, this.map.projection) + .subscribe( + () => {}, + (error: Error) => this.onFileExportError(error), + () => { + this.onFileExportSuccess(); + + featuresCSV.forEach(feature => { + this.circleToPoint(feature); + }); + + this.loading$.next(false); + } + ); + } + } + + private createTitleEmptyRows(previousFeature, currentFeature) { + const titleRow = previousFeature.clone(); + const titleRowWithArrow = previousFeature.clone(); + const emptyRow = previousFeature.clone(); + const previousFeatureKeys: Array = previousFeature.getKeys(); + const firstKey: string = previousFeatureKeys[1]; + previousFeatureKeys.forEach(key => { + if (key === firstKey) { + titleRow.set(key, currentFeature.get('_featureStore').layer.options.title, true); + titleRowWithArrow.set(key, currentFeature.get('_featureStore').layer.options.title + " ===================>", true); + emptyRow.unset(key, true); + } else { + titleRow.unset(key, true); + titleRowWithArrow.unset(key, true); + emptyRow.unset(key, true); } }); + const titleEmptyRows = [titleRow, titleRowWithArrow, emptyRow]; + return titleEmptyRows; + } + + private circleToPoint(feature) { + const radius: number = feature.get('rad'); + + if (radius) { + const point = new olPoint([feature.get('longitude'), feature.get('latitude')]); + point.transform('EPSG:4326', feature.get('_projection')); + feature.setGeometry(point); + } } private buildForm() { @@ -595,6 +673,8 @@ export class ImportExportComponent implements OnDestroy, OnInit { layers: [[], [Validators.required]], layersWithSelection: [[]], encoding: [EncodingFormat.UTF8, [Validators.required]], + combineLayers: [true, [Validators.required]], + separator: [false, [Validators.required]], featureInMapExtent: [false, [Validators.required]], name: ['', [Validators.required]] }); @@ -604,6 +684,8 @@ export class ImportExportComponent implements OnDestroy, OnInit { layers: [[], [Validators.required]], layersWithSelection: [[]], encoding: [EncodingFormat.UTF8, [Validators.required]], + combineLayers: [true, [Validators.required]], + separator: [false, [Validators.required]], featureInMapExtent: [false, [Validators.required]], }); } diff --git a/packages/geo/src/lib/import-export/shared/export.interface.ts b/packages/geo/src/lib/import-export/shared/export.interface.ts index 584324f492..139e541df3 100644 --- a/packages/geo/src/lib/import-export/shared/export.interface.ts +++ b/packages/geo/src/lib/import-export/shared/export.interface.ts @@ -6,6 +6,7 @@ export interface ExportOptions { layers: string[]; layersWithSelection?: string[]; name?: string; + combineLayers?: boolean; + separator?: boolean; featureInMapExtent?: boolean; - circlesToPolygons?: boolean; } diff --git a/packages/geo/src/locale/en.geo.json b/packages/geo/src/locale/en.geo.json index 6e9792b7d9..16479a025c 100644 --- a/packages/geo/src/locale/en.geo.json +++ b/packages/geo/src/locale/en.geo.json @@ -113,16 +113,18 @@ "encoding": { "LATIN1": "LATIN-1", "UTF8": "UTF-8" - } + }, + "combinedLayers": "combinedLayers" }, "importExportForm": { "exportButton": "Export", "exportButtonLink": "Open the link", "exportButtonLinks": "Open the links", - "exportCircleToPolygon": "Transform Circle entities in polygons", + "exportCombineResults": "Combine layers into one file", "exportFormatPlaceholder": "Format", "exportLayerPlaceholder": "Layer", "exportFileNamePlaceholder": "Filename", + "exportSeparator": "Insert separator (empty row) between layers", "encodingPlaceholder": "Encoding", "exportTabTitle": "Export", "exportFeatureInExtent": "Export only features in map extent", @@ -382,8 +384,8 @@ "notification": "notification ...", "uturnText": "Make u-turn and head {{translatedDirection}} on {{route}}", "unknown": "???", - - "cntSuffix": { + + "cntSuffix": { "first": "st", "secondAndMore": "rd" }, diff --git a/packages/geo/src/locale/fr.geo.json b/packages/geo/src/locale/fr.geo.json index 4f599d7be8..7fff7cf9dd 100644 --- a/packages/geo/src/locale/fr.geo.json +++ b/packages/geo/src/locale/fr.geo.json @@ -113,16 +113,18 @@ "encoding": { "LATIN1": "LATIN-1", "UTF8": "UTF-8" - } + }, + "combinedLayers": "couchesCombinees" }, "importExportForm": { "exportButton": "Exporter", "exportButtonLink": "Ouvrir le lien", "exportButtonLinks": "Ouvrir les liens", - "exportCircleToPolygon": "Transformer les entités de type Cercle en polygones", + "exportCombineResults": "Combiner les couches dans un seul fichier", "exportFormatPlaceholder": "Format", "exportLayerPlaceholder": "Couche(s)", "exportFileNamePlaceholder": "Nom du fichier", + "exportSeparator": "Insérer un séparateur (ligne vide) entre les couches", "encodingPlaceholder": "Encodage", "exportTabTitle": "Exporter", "exportFeatureInExtent": "Seulement les entités contenues dans la carte", @@ -381,8 +383,8 @@ "notification": "notification ...", "uturnText": "Faire demi-tour et continuer en direction {{translatedDirection}} sur {{route}}", "unknown": "???", - - "cntSuffix": { + + "cntSuffix": { "first": "ère", "secondAndMore": "e" }, diff --git a/packages/integration/src/lib/filter/spatial-filter-tool/spatial-filter-tool.component.ts b/packages/integration/src/lib/filter/spatial-filter-tool/spatial-filter-tool.component.ts index f62de313f8..5898be6b9a 100644 --- a/packages/integration/src/lib/filter/spatial-filter-tool/spatial-filter-tool.component.ts +++ b/packages/integration/src/lib/filter/spatial-filter-tool/spatial-filter-tool.component.ts @@ -135,8 +135,11 @@ export class SpatialFilterToolComponent implements OnInit, OnDestroy { activateExportTool() { const ids = []; + const re = new RegExp('^Zone \\d+'); for (const layer of this.layers) { - ids.push(layer.id); + if (!layer.title.match(re)) { + ids.push(layer.id); + } } this.importExportState.setMode(ImportExportMode.export); this.importExportState.setsExportOptions({ layers: ids } as ExportOptions);