Skip to content

Commit

Permalink
feat (msp search source): Add MSP search source (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
cbourget authored and mbarbeau committed Feb 15, 2017
1 parent c5c2a03 commit 1d4fd47
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 79 deletions.
4 changes: 4 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MaterialModule } from '@angular/material';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';

import { CoreModule } from './core/core.module';
import { SharedModule } from './shared/shared.module';
import { NavigatorModule, NavigatorRoutingModule } from './pages';
Expand Down
21 changes: 16 additions & 5 deletions src/app/core/core.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NgModule, Optional, SkipSelf, ModuleWithProviders } from '@angular/core';
import { Http, Jsonp } from '@angular/http';
import { CommonModule } from '@angular/common';
import { provideStore } from '@ngrx/store';

Expand All @@ -14,6 +15,7 @@ import { SearchService } from './search.service';
import { SearchSourceService } from './search-source.service';
import { SearchSource } from '../search/sources/search-source';
import { SearchSourceNominatim } from '../search/sources/search-source-nominatim';
import { SearchSourceMSP } from '../search/sources/search-source-msp';

export function searchSourceServiceFactory(sources: SearchSource[]) {
return new SearchSourceService(sources);
Expand All @@ -28,11 +30,20 @@ export function provideSearchSourceService() {
}

export function provideSearchSource() {
return [{
provide: SearchSource,
useClass: SearchSourceNominatim,
multi: true
}];
return [
{
provide: SearchSource,
useClass: SearchSourceNominatim,
multi: true,
deps: [Http]
},
{
provide: SearchSource,
useClass: SearchSourceMSP,
multi: true,
deps: [Jsonp]
}
];
}

export function provideAppStore() {
Expand Down
5 changes: 5 additions & 0 deletions src/app/core/search-source.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* tslint:disable:no-unused-variable */
import { TestBed, async, inject } from '@angular/core/testing';
import { HttpModule, JsonpModule } from '@angular/http';
import { SearchSourceService } from './search-source.service';

import {
Expand All @@ -10,6 +11,10 @@ import {
describe('SearchSourceService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpModule,
JsonpModule
],
providers: [
provideSearchSourceService(),
provideSearchSource()
Expand Down
23 changes: 0 additions & 23 deletions src/app/core/search-source.spec.ts

This file was deleted.

5 changes: 3 additions & 2 deletions src/app/core/search.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* tslint:disable:no-unused-variable */
import { TestBed, async, inject } from '@angular/core/testing';
import { SearchService } from './search.service';
import { HttpModule } from '@angular/http';
import { HttpModule, JsonpModule } from '@angular/http';

import { searchResults } from '../reducers';
import {
Expand All @@ -14,7 +14,8 @@ describe('SearchService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpModule
HttpModule,
JsonpModule
],
providers: [
provideAppStore(),
Expand Down
46 changes: 23 additions & 23 deletions src/app/core/search.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,52 @@ import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';

import { SearchSourceService } from './search-source.service';
import { SearchResult } from '../search/shared/search-result.interface';
import { SearchSource } from '../search/sources/search-source';

import { AppStore } from '../app.store';

@Injectable()
export class SearchService {

subscription: Subscription;
subscriptions: Subscription[] = [];

constructor(private http: Http,
private store: Store<AppStore>,
private searchSourceService: SearchSourceService) {
}

search (term?: string) {
search(term?: string) {
const sources = this.searchSourceService.getSources();
const source = sources[0];

const search = source.getSearchParams(term);

if (this.subscription !== undefined) {
this.subscription.unsubscribe();
}
this.subscriptions.forEach((sub: Subscription) => sub.unsubscribe);
this.subscriptions = sources.map((source: SearchSource) =>
this.searchSource(source, term));
}

this.subscription = this.http
.get(source.getSearchUrl(), { search })
.map(res => source.extractData(res))
searchSource(source: SearchSource, term?: string) {
return source.search(term)
.catch(this.handleError)
.subscribe((results: SearchResult[]) => {
this.store.dispatch({
type: 'SET_SEARCH_RESULTS',
payload: results
});
});
.subscribe((results: SearchResult[]) =>
this.handleSearchResults(results, source));
}

clear (term?: string) {
clear(term?: string) {
this.store.dispatch({type: 'CLEAR_SEARCH_RESULTS'});
}

private handleError (error: Response | any) {
private handleSearchResults(results: SearchResult[], source: SearchSource) {
this.store.dispatch({
type: 'UPDATE_SEARCH_RESULTS',
payload: {
results: results,
source: source.getName()
}
});
}

private handleError(error: Response | any) {
// TODO: use a remote logging infrastructure
let errorMessage: string;

Expand Down
1 change: 1 addition & 0 deletions src/app/map/map.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class MapComponent implements OnInit, AfterViewInit {
const feature = format.readFeature(Object.assign({
type: 'Feature'
}, result));

feature.getGeometry().transform('EPSG:4326', destProj);

return feature;
Expand Down
6 changes: 4 additions & 2 deletions src/app/reducers/search-results.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { SearchResult } from '../search/shared/search-result.interface';

export const searchResults = (state: SearchResult[] = [], {type, payload}) => {
switch (type) {
case 'SET_SEARCH_RESULTS':
return payload;
case 'UPDATE_SEARCH_RESULTS':
return state
.filter(result => result.source !== payload.source)
.concat(payload.results);
case 'CLEAR_SEARCH_RESULTS':
return [];
default:
Expand Down
2 changes: 1 addition & 1 deletion src/app/search/search-result/search-result.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<md-list-item>
<md-icon md-list-avatar>{{result.icon}}</md-icon>
<h4 md-line>{{result.title}}</h4>
<h4 md-line>{{result.source}} - {{result.title}}</h4>
</md-list-item>
23 changes: 22 additions & 1 deletion src/app/search/search-tool/search-tool.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export class SearchToolComponent implements ToolComponent, OnInit {

this.store
.select(s => s.searchResults)
.subscribe((results: SearchResult[]) => this.results = results);
.subscribe((results: SearchResult[]) =>
this.handleSearchResults(results));
}

selectResult(result: SearchResult) {
Expand All @@ -42,6 +43,26 @@ export class SearchToolComponent implements ToolComponent, OnInit {
this.store.dispatch({type: 'FOCUS_RESULT', payload: result});
}

private handleSearchResults(results: SearchResult[]) {
const results_ = results.map((result, index) => {
return {index: index, data: result};
});

results_.sort((r1, r2) => {
if (r1.data.source < r2.data.source) {
return -1;
}

if (r1.data.source > r2.data.source) {
return 1;
}

return r1.index - r2.index;
});

this.results = results_.map(result_ => result_.data);
}

}

ToolService.register(SearchToolComponent);
5 changes: 3 additions & 2 deletions src/app/search/shared/search-result.interface.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
export interface SearchResult {
id: string;
source: string;
title: string;
icon?: string;

geometry?: SearchResultGeometry;
bbox?: [number, number, number, number];
properties?: {[key: string]: any};
}

export interface SearchResultGeometry {
type: 'Point' | 'LineString' | 'Polygon';
coordinates: Array<any>;
bbox?: Array<number>;
coordinates: [any];
}
59 changes: 59 additions & 0 deletions src/app/search/sources/search-source-msp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Jsonp, Response, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs/Observable';

import { SearchSource } from './search-source';
import { SearchResult } from '../shared/search-result.interface';

export class SearchSourceMSP extends SearchSource {

static name_: string = 'MSP';
static searchUrl: string = 'icherche/v1/geocodingMaxScore';

constructor(private jsonp: Jsonp) {
super();
}

getName (): string {
return SearchSourceMSP.name_;
}

search (term?: string): Observable<SearchResult[]> {
const search = this.getSearchParams(term);

return this.jsonp
.get(SearchSourceMSP.searchUrl, { search })
.map(res => this.extractData(res));
}

private extractData (response: Response): SearchResult[] {
return response.json().hits.hits.map(this.formatResult);
}

private getSearchParams (term: string): URLSearchParams {
const search = new URLSearchParams();
search.set('q', term);
search.set('nb', '5');
search.set('callback', 'JSONP_CALLBACK');

return search;
}

private formatResult (result: any): SearchResult {
const _source = result._source;

return {
id: result._id,
source: SearchSourceMSP.name_,
title: _source.recherche,
icon: 'place',
properties: {
recherche: _source.recherche,
munnom: _source.munnom,
odogene: _source.odogene
},
geometry: _source.geom,
bbox: _source.extent.coordinates
};
}

}
Loading

0 comments on commit 1d4fd47

Please sign in to comment.