Skip to content

Commit

Permalink
feat(import-export): import service returns features and both service…
Browse files Browse the repository at this point in the history
…s let the parent component handle errors. Also, use ogre when possible.
  • Loading branch information
cbourget committed May 2, 2019
1 parent 74ee97f commit 10bb152
Show file tree
Hide file tree
Showing 16 changed files with 626 additions and 355 deletions.
21 changes: 9 additions & 12 deletions packages/common/src/lib/drag-drop/drag-drop.directive.ts
Expand Up @@ -11,20 +11,14 @@ import {
selector: '[igoDragAndDrop]'
})
export class DragAndDropDirective {
@Input()
get allowed_extensions() {
return this._allowedExtensions;
}
set allowed_extensions(value: Array<string>) {
this._allowedExtensions = value;
}
protected _allowedExtensions: Array<string> = [];

@Input() allowedExtensions: Array<string> = [];

@Output() protected filesDropped: EventEmitter<File[]> = new EventEmitter();

@Output() protected filesInvalid: EventEmitter<File[]> = new EventEmitter();
@HostBinding('style.background') private background = 'inherit';

constructor() {}
@HostBinding('style.background') private background = 'inherit';

@HostListener('dragover', ['$event'])
public onDragOver(evt) {
Expand Down Expand Up @@ -64,8 +58,11 @@ export class DragAndDropDirective {
for (const file of files) {
const ext = file.name.split('.')[file.name.split('.').length - 1];
if (
this.allowed_extensions.lastIndexOf(ext) !== -1 &&
file.size !== 0
this.allowedExtensions.length === 0 ||
(
this.allowedExtensions.lastIndexOf(ext) !== -1 &&
file.size !== 0
)
) {
filesObj.valid.push(file);
} else {
Expand Down
Expand Up @@ -13,10 +13,15 @@
</div>

<div class="igo-form-button-group">
<button mat-raised-button type="button" (click)="inputFile.click()">
<button mat-raised-button type="button" (click)="fileInput.click()">
{{'igo.geo.importExportForm.importButton' | translate}}
</button>
<input #inputFile type="file" [style.display]="'none'" (change)="loadFile($event.target.files)">
<input
#fileInput
type="file"
[style.display]="'none'"
(click)="fileInput.value = null"
(change)="importFiles($event.target.files)">
</div>
</form>
</mat-tab>
Expand Down Expand Up @@ -53,7 +58,7 @@
mat-raised-button
type="button"
[disabled]="!form.valid"
(click)="handleFormSubmit(form.value)">
(click)="handleExportFormSubmit(form.value)">
{{'igo.geo.importExportForm.exportButton' | translate}}
</button>
</div>
Expand Down
Expand Up @@ -2,57 +2,76 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Subscription } from 'rxjs';


import { MessageService, LanguageService } from '@igo2/core';

import { Feature } from '../../feature/shared/feature.interfaces';
import { IgoMap } from '../../map/shared/map';
import { Layer } from '../../layer/shared/layers/layer';
import { VectorLayer } from '../../layer/shared/layers/vector-layer';
import { ExportOptions } from '../shared/import-export.interface';
import { ExportFormat } from '../shared/import-export.type';
import { ImportExportService } from '../shared/import-export.service';

import { handleFileImportSuccess, handleFileImportError } from '../shared/import.utils';
import { ExportOptions } from '../shared/export.interface';
import { ExportFormat } from '../shared/export.type';
import { ExportService } from '../shared/export.service';
import { ImportService } from '../shared/import.service';

@Component({
selector: 'igo-import-export',
templateUrl: './import-export.component.html',
styleUrls: ['./import-export.component.scss']
})
export class ImportExportComponent implements OnDestroy, OnInit {

public form: FormGroup;
public formats = ExportFormat;
public layers: VectorLayer[];
public inputProj: string;
public inputProj: string = 'EPSG:4326';

private layers$$: Subscription;

@Input()
get map(): IgoMap {
return this._map;
}
set map(value: IgoMap) {
this._map = value;
}
private _map: IgoMap;
@Input() map: IgoMap;

constructor(
private importExportService: ImportExportService,
private importService: ImportService,
private exportService: ExportService,
private languageService: LanguageService,
private messageService: MessageService,
private formBuilder: FormBuilder
) {
this.buildForm();
}

loadFile(files: Array<File>) {
this.importExportService.import(files, this.inputProj);
}

handleFormSubmit(data: ExportOptions) {
this.importExportService.export(data);
ngOnInit() {
this.layers$$ = this.map.layers$.subscribe(layers => {
this.layers = layers
.filter((layer: Layer) => {
return layer instanceof VectorLayer && layer.exportable === true;
}) as VectorLayer[];
});
}

ngOnDestroy() {
this.layers$$.unsubscribe();
}

ngOnInit() {
this.layers$$ = this.map.layers$.subscribe(layers => {
this.layers = (layers
.filter(layer => layer instanceof VectorLayer)) as VectorLayer[];
});
importFiles(files: File[]) {
for (const file of files) {
this.importService
.import(file, this.inputProj)
.subscribe(
(features: Feature[]) => this.onFileImportSuccess(file, features),
(error: Error) => this.onFileImportError(file)
);
}
}

handleExportFormSubmit(data: ExportOptions) {
const layer = this.map.getLayerById(data.layer);
const olFeatures = layer.dataSource.ol.getFeatures();
this.exportService
.export(olFeatures, data.format, layer.title, this.map.projection)
.subscribe(() => {});
}

private buildForm() {
Expand All @@ -61,4 +80,12 @@ export class ImportExportComponent implements OnDestroy, OnInit {
layer: ['', [Validators.required]]
});
}

private onFileImportSuccess(file: File, features: Feature[]) {
handleFileImportSuccess(file, features, this.map, this.messageService, this.languageService);
}

private onFileImportError(file: File) {
handleFileImportError(file, this.messageService, this.languageService);
}
}
@@ -1,21 +1,47 @@
import { Directive, EventEmitter, HostListener } from '@angular/core';
import { Directive, HostListener, EventEmitter, OnInit, OnDestroy } from '@angular/core';

import { Subscription } from 'rxjs';

import { MessageService, LanguageService } from '@igo2/core';
import { DragAndDropDirective } from '@igo2/common';
import { ImportExportService } from './import-export.service';

import { Feature } from '../../feature/shared/feature.interfaces';
import { IgoMap } from '../../map/shared/map';
import { MapBrowserComponent } from '../../map/map-browser/map-browser.component';
import { ImportService } from './import.service';
import { handleFileImportSuccess, handleFileImportError } from '../shared/import.utils';

@Directive({
selector: '[igoDropGeoFile]'
})
export class DropGeoFileDirective extends DragAndDropDirective {
protected allowedExtensions: Array<string> = [];
export class DropGeoFileDirective extends DragAndDropDirective implements OnInit, OnDestroy {

protected filesDropped: EventEmitter<File[]> = new EventEmitter();
protected filesInvalid: EventEmitter<File[]> = new EventEmitter();

constructor(importExportService: ImportExportService) {
private filesDropped$$: Subscription;

get map(): IgoMap {
return this.component.map;
}

constructor(
private component: MapBrowserComponent,
private importService: ImportService,
private languageService: LanguageService,
private messageService: MessageService
) {
super();
this.allowedExtensions = ['zip', 'geojson', 'kml', 'gpx', 'gml', 'json'];
this.filesDropped.subscribe(f => importExportService.import(f));
this.filesInvalid.subscribe(f => importExportService.onFilesInvalid(f));
}

ngOnInit() {
this.filesDropped$$ = this.filesDropped.subscribe((files: File[]) => {
this.onFilesDropped(files);
});
}

ngOnDestroy() {
this.filesDropped$$.unsubscribe();
}

@HostListener('dragover', ['$event'])
Expand All @@ -32,4 +58,23 @@ export class DropGeoFileDirective extends DragAndDropDirective {
public onDrop(evt) {
super.onDrop(evt);
}

private onFilesDropped(files: File[]) {
for (const file of files) {
this.importService
.import(file)
.subscribe(
(features: Feature[]) => this.onFileImportSuccess(file, features),
(error: Error) => this.onFileImportError(file)
);
}
}

private onFileImportSuccess(file: File, features: Feature[]) {
handleFileImportSuccess(file, features, this.map, this.messageService, this.languageService);
}

private onFileImportError(file: File) {
handleFileImportError(file, this.messageService, this.languageService);
}
}
8 changes: 8 additions & 0 deletions packages/geo/src/lib/import-export/shared/export.errors.ts
@@ -0,0 +1,8 @@
export class ExportError extends Error {}

export class ExportInvalidFileError extends ExportError {
constructor() {
super('Invalid file.');
Object.setPrototypeOf(this, ExportInvalidFileError.prototype);
}
}
6 changes: 6 additions & 0 deletions packages/geo/src/lib/import-export/shared/export.interface.ts
@@ -0,0 +1,6 @@
import { ExportFormat } from './export.type';

export interface ExportOptions {
format: ExportFormat;
layer: string;
}

0 comments on commit 10bb152

Please sign in to comment.