Skip to content

Commit

Permalink
feat(export): added possibility of exporting merged CSV files (#949)
Browse files Browse the repository at this point in the history
* feat(export): export unique CSVs

* added toggle to combine layers

* added empty row toggle

* refactor(export): change label of toggle and add column when exporting csv

* refactor(remove zone when exporting results from spatial filter tool)

* fix(demo): fix import-export lib demo

* lint

* refactor(export): translated filename and csv adjustments

* fix(export): fix hang

* fix(export): add arrow in divider

Co-authored-by: Philippe Lafreniere <[email protected]>
  • Loading branch information
LAMM26 and PhilippeLafreniere18 authored Dec 13, 2021
1 parent b5c93fe commit a24382a
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<igo-zoom-button [map]="map" color="primary"></igo-zoom-button>
</igo-map-browser>

<igo-import-export [map]="map"></igo-import-export>
<igo-import-export [store]="store" [map]="map"></igo-import-export>

</mat-card>

3 changes: 3 additions & 0 deletions demo/src/app/geo/import-export/import-export.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -22,6 +23,8 @@ export class AppImportExportComponent {
zoom: 9
};

public store = new WorkspaceStore([]);

constructor(
private languageService: LanguageService,
private layerService: LayerService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,22 @@ <h4>{{'igo.geo.importExportForm.exportNoLayersExportable' | translate}}</h4>
</mat-form-field>
</div>

<div class="export-combine-layers mat-typography" *ngIf="layers.length > 1 && (form.value.format === 'CSVcomma' || form.value.format === 'CSVsemicolon')">
<mat-slide-toggle
formControlName="combineLayers"
[labelPosition]="'before'">
{{'igo.geo.importExportForm.exportCombineResults' | translate}}
</mat-slide-toggle>
</div>

<div class="export-separator mat-typography" *ngIf="layers.length > 1 && (form.value.format === 'CSVcomma' || form.value.format === 'CSVsemicolon') && form.value.combineLayers">
<mat-slide-toggle
formControlName="separator"
[labelPosition]="'before'">
{{'igo.geo.importExportForm.exportSeparator' | translate}}
</mat-slide-toggle>
</div>

<div class="export-options mat-typography" *ngIf="form.value.format !== 'URL'">
<mat-slide-toggle
formControlName="featureInMapExtent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ igo-spinner {
padding-left: 10px;
}

.export-options {
.export-options, .export-combine-layers, .export-separator {
overflow-x: hidden;

mat-slide-toggle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,20 @@ export class ImportExportComponent implements OnDestroy, OnInit {
this.handlePopup();
}

data.layers.forEach((layer) => {
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)) {
Expand Down Expand Up @@ -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<number> = [feature.get('longitude'), feature.get('latitude')];
const circle = circular(center4326, radius, 500);
Expand All @@ -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) {
Expand All @@ -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<string> = 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() {
Expand All @@ -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]]
});
Expand All @@ -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]],
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface ExportOptions {
layers: string[];
layersWithSelection?: string[];
name?: string;
combineLayers?: boolean;
separator?: boolean;
featureInMapExtent?: boolean;
circlesToPolygons?: boolean;
}
10 changes: 6 additions & 4 deletions packages/geo/src/locale/en.geo.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -382,8 +384,8 @@
"notification": "notification ...",
"uturnText": "Make u-turn and head {{translatedDirection}} on {{route}}",
"unknown": "???",
"cntSuffix": {

"cntSuffix": {
"first": "st",
"secondAndMore": "rd"
},
Expand Down
10 changes: 6 additions & 4 deletions packages/geo/src/locale/fr.geo.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -381,8 +383,8 @@
"notification": "notification ...",
"uturnText": "Faire demi-tour et continuer en direction {{translatedDirection}} sur {{route}}",
"unknown": "???",
"cntSuffix": {

"cntSuffix": {
"first": "ère",
"secondAndMore": "e"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit a24382a

Please sign in to comment.