-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #776 from geonetwork/mv-add-from-wfs
[Map-Viewer] Add layer from WFS service
- Loading branch information
Showing
16 changed files
with
286 additions
and
2 deletions.
There are no files selected for viewing
Empty file.
37 changes: 37 additions & 0 deletions
37
libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<div class="flex items-center mb-5"> | ||
<gn-ui-text-input | ||
[(value)]="wfsUrl" | ||
(valueChange)="urlChange.next($event)" | ||
[hint]="'map.wfs.urlInput.hint' | translate" | ||
class="w-96" | ||
> | ||
</gn-ui-text-input> | ||
</div> | ||
|
||
<div *ngIf="errorMessage" class="text-red-500 mt-2"> | ||
{{ errorMessage }} | ||
</div> | ||
|
||
<div *ngIf="loading"> | ||
<p class="loading-message" translate>map.loading.service</p> | ||
</div> | ||
|
||
<div *ngIf="!loading && layers.length > 0"> | ||
<h2 class="font-bold" translate>map.layers.available</h2> | ||
<ng-container *ngFor="let layer of layers"> | ||
<div class="flex items-center justify-between my-2 layer-item-tree"> | ||
<p class="max-w-xs overflow-hidden overflow-ellipsis whitespace-nowrap"> | ||
{{ layer.title }} | ||
</p> | ||
<gn-ui-button | ||
*ngIf="layer.name" | ||
class="layer-add-btn" | ||
type="primary" | ||
(buttonClick)="addLayer(layer)" | ||
extraClass="text-sm !px-2 !py-1" | ||
translate | ||
><span translate> map.layer.add </span></gn-ui-button | ||
> | ||
</div> | ||
</ng-container> | ||
</div> |
165 changes: 165 additions & 0 deletions
165
libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing' | ||
import { AddLayerFromWfsComponent } from './add-layer-from-wfs.component' | ||
import { MapFacade } from '../+state/map.facade' | ||
import { TranslateModule } from '@ngx-translate/core' | ||
import { By } from '@angular/platform-browser' | ||
|
||
jest.mock('@camptocamp/ogc-client', () => ({ | ||
WfsEndpoint: class { | ||
constructor(private url) {} | ||
isReady() { | ||
if (this.url.indexOf('error') > -1) { | ||
return Promise.reject(new Error('Something went wrong')) | ||
} | ||
if (this.url.indexOf('wait') > -1) { | ||
return new Promise(() => { | ||
// do nothing | ||
}) | ||
} | ||
return Promise.resolve(this) | ||
} | ||
getFeatureTypes() { | ||
return [ | ||
{ | ||
name: 'ft1', | ||
title: 'Feature Type 1', | ||
}, | ||
{ | ||
name: 'ft2', | ||
title: 'Feature Type 2', | ||
}, | ||
{ | ||
name: 'ft3', | ||
title: 'Feature Type 3', | ||
}, | ||
] | ||
} | ||
}, | ||
})) | ||
|
||
class MapFacadeMock { | ||
addLayer = jest.fn() | ||
} | ||
|
||
describe('AddLayerFromWfsComponent', () => { | ||
let component: AddLayerFromWfsComponent | ||
let fixture: ComponentFixture<AddLayerFromWfsComponent> | ||
let mapFacade: MapFacade | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
imports: [TranslateModule.forRoot()], | ||
declarations: [AddLayerFromWfsComponent], | ||
providers: [ | ||
{ | ||
provide: MapFacade, | ||
useClass: MapFacadeMock, | ||
}, | ||
], | ||
}).compileComponents() | ||
|
||
mapFacade = TestBed.inject(MapFacade) | ||
fixture = TestBed.createComponent(AddLayerFromWfsComponent) | ||
component = fixture.componentInstance | ||
}) | ||
|
||
it('should create', () => { | ||
fixture.detectChanges() | ||
expect(component).toBeTruthy() | ||
expect(component.errorMessage).toBeFalsy() | ||
expect(component.loading).toBe(false) | ||
expect(component.layers.length).toBe(0) | ||
}) | ||
|
||
describe('loadLayers', () => { | ||
describe('while layers are loading', () => { | ||
beforeEach(() => { | ||
component.wfsUrl = 'http://my.service.org/wait' | ||
component.loadLayers() | ||
}) | ||
it('shows only a "loading" message', () => { | ||
expect(component.errorMessage).toBeFalsy() | ||
expect(component.loading).toBe(true) | ||
expect(component.layers).toEqual([]) | ||
}) | ||
}) | ||
describe('valid WFS service', () => { | ||
beforeEach(() => { | ||
component.wfsUrl = 'http://my.service.org/wfs' | ||
component.loadLayers() | ||
}) | ||
it('shows all layers', () => { | ||
expect(component.errorMessage).toBeFalsy() | ||
expect(component.loading).toBe(false) | ||
expect(component.layers).toEqual([ | ||
{ | ||
name: 'ft1', | ||
title: 'Feature Type 1', | ||
}, | ||
{ | ||
name: 'ft2', | ||
title: 'Feature Type 2', | ||
}, | ||
{ | ||
name: 'ft3', | ||
title: 'Feature Type 3', | ||
}, | ||
]) | ||
}) | ||
it('should show a Add button for each layer', () => { | ||
fixture.detectChanges() | ||
const layerElts = fixture.debugElement.queryAll( | ||
By.css('.layer-item-tree') | ||
) | ||
expect(layerElts.length).toBe(3) | ||
const hasButtons = layerElts.map( | ||
(layerElt) => !!layerElt.query(By.css('.layer-add-btn')) | ||
) | ||
expect(hasButtons).toEqual([true, true, true]) | ||
}) | ||
}) | ||
describe('error loading layers', () => { | ||
beforeEach(() => { | ||
component.wfsUrl = 'http://my.service.org/error' | ||
component.loadLayers() | ||
}) | ||
it('shows an error message', () => { | ||
expect(component.errorMessage).toBeTruthy() | ||
expect(component.loading).toBe(false) | ||
expect(component.layers.length).toBe(0) | ||
}) | ||
}) | ||
describe('error and then valid service', () => { | ||
beforeEach(async () => { | ||
component.wfsUrl = 'http://my.service.org/error' | ||
await component.loadLayers().catch(() => { | ||
// do nothing | ||
}) | ||
component.wfsUrl = 'http://my.service.org/wfs' | ||
await component.loadLayers() | ||
}) | ||
it('shows no error', () => { | ||
expect(component.errorMessage).toBeFalsy() | ||
expect(component.loading).toBe(false) | ||
expect(component.layers).not.toEqual([]) | ||
}) | ||
}) | ||
}) | ||
describe('addLayer', () => { | ||
beforeEach(() => { | ||
component.wfsUrl = 'http://my.service.org/wfs' | ||
component.addLayer({ | ||
name: 'ft1', | ||
title: 'Feature Type 1', | ||
}) | ||
}) | ||
it('should add the selected layer in the current map context', () => { | ||
expect(mapFacade.addLayer).toHaveBeenCalledWith({ | ||
name: 'ft1', | ||
title: 'Feature Type 1', | ||
url: 'http://my.service.org/wfs', | ||
type: 'wfs', | ||
}) | ||
}) | ||
}) | ||
}) |
64 changes: 64 additions & 0 deletions
64
libs/feature/map/src/lib/add-layer-from-wfs/add-layer-from-wfs.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core' | ||
import { WfsEndpoint, WfsFeatureTypeBrief } from '@camptocamp/ogc-client' | ||
import { Subject } from 'rxjs' | ||
import { | ||
MapContextLayerModel, | ||
MapContextLayerTypeEnum, | ||
} from '../map-context/map-context.model' | ||
import { MapFacade } from '../+state/map.facade' | ||
import { debounceTime } from 'rxjs/operators' | ||
|
||
@Component({ | ||
selector: 'gn-ui-add-layer-from-wfs', | ||
templateUrl: './add-layer-from-wfs.component.html', | ||
styleUrls: ['./add-layer-from-wfs.component.css'], | ||
}) | ||
export class AddLayerFromWfsComponent implements OnInit { | ||
wfsUrl = '' | ||
loading = false | ||
layers: WfsFeatureTypeBrief[] = [] | ||
wfsEndpoint: WfsEndpoint | null = null | ||
urlChange = new Subject<string>() | ||
errorMessage: string | null = null | ||
|
||
constructor( | ||
private mapFacade: MapFacade, | ||
private changeDetectorRef: ChangeDetectorRef | ||
) {} | ||
|
||
ngOnInit() { | ||
this.urlChange.pipe(debounceTime(700)).subscribe(() => this.loadLayers()) | ||
} | ||
|
||
async loadLayers() { | ||
this.errorMessage = null | ||
try { | ||
this.loading = true | ||
|
||
if (this.wfsUrl.trim() === '') { | ||
this.layers = [] | ||
return | ||
} | ||
|
||
this.wfsEndpoint = await new WfsEndpoint(this.wfsUrl).isReady() | ||
this.layers = this.wfsEndpoint.getFeatureTypes() | ||
console.log(this.layers) | ||
} catch (error) { | ||
const err = error as Error | ||
this.layers = [] | ||
this.errorMessage = 'Error loading layers: ' + err.message | ||
} finally { | ||
this.loading = false | ||
this.changeDetectorRef.markForCheck() | ||
} | ||
} | ||
|
||
addLayer(layer: WfsFeatureTypeBrief) { | ||
const layerToAdd: MapContextLayerModel = { | ||
name: layer.name, | ||
url: this.wfsUrl.toString(), | ||
type: MapContextLayerTypeEnum.WFS, | ||
} | ||
this.mapFacade.addLayer({ ...layerToAdd, title: layer.title }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters