Skip to content

Commit

Permalink
feat(geo): add modularity for search and direction (#1669)
Browse files Browse the repository at this point in the history
* feat(geo): add modularity for search and direction
BREAKING CHANGE:
- SearchState and SearchService no more provided in root. They depend on the SearchSource who are no more provided in the root.
- Analytics capability is provided with the SearchService directly.
- DirectionModule, provideDirectionsSourceService is removed, use the provideDirection.
  • Loading branch information
alecarn committed May 15, 2024
1 parent f82944f commit cd199eb
Show file tree
Hide file tree
Showing 27 changed files with 252 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Provider } from '@angular/core';

export interface DirectionsSourceOptions extends BaseDirectionsSourceOptions {
osrm?: OsrmDirectionsSourceOptions;
logo?: string;
Expand All @@ -21,3 +23,12 @@ export interface BaseDirectionsSourceOptionsProfileAuthorization {
url: string;
property: string;
}

export interface DirectionSourceFeature<KindT extends DirectionSourceKind> {
kind: KindT;
providers: Provider[];
}

export enum DirectionSourceKind {
OSRM = 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { HttpClient } from '@angular/common/http';
import { ConfigService } from '@igo2/core/config';

import { DirectionsSource } from './directions-source';
import {
DirectionSourceFeature,
DirectionSourceKind
} from './directions-source.interface';
import { OsrmDirectionsSource } from './osrm-directions-source';

export function osrmDirectionsSourcesFactory(
Expand All @@ -20,3 +24,10 @@ export function provideOsrmDirectionsSource() {
deps: [HttpClient, ConfigService]
};
}

export function withOsrmSource(): DirectionSourceFeature<DirectionSourceKind.OSRM> {
return {
kind: DirectionSourceKind.OSRM,
providers: [provideOsrmDirectionsSource()]
};
}
6 changes: 1 addition & 5 deletions packages/geo/src/lib/directions/directions.module.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { ModuleWithProviders, NgModule } from '@angular/core';

import { IgoSearchModule } from '../search/search.module';
import { DirectionsButtonsComponent } from './directions-buttons/directions-buttons.component';
import { DirectionsInputsComponent } from './directions-inputs/directions-inputs.component';
import { DirectionsResultsComponent } from './directions-results/directions-results.component';
import { DirectionsComponent } from './directions.component';
import { provideDirectionsSourceService } from './shared/directions-source.service';

@NgModule({
imports: [
IgoSearchModule.forRoot(),
DirectionsComponent,
DirectionsInputsComponent,
DirectionsButtonsComponent,
Expand All @@ -20,8 +17,7 @@ import { provideDirectionsSourceService } from './shared/directions-source.servi
DirectionsInputsComponent,
DirectionsButtonsComponent,
DirectionsResultsComponent
],
providers: [provideDirectionsSourceService()]
]
})
export class IgoDirectionsModule {
/**
Expand Down
26 changes: 26 additions & 0 deletions packages/geo/src/lib/directions/directions.provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Provider } from '@angular/core';

import {
DirectionSourceFeature,
DirectionSourceKind
} from './directions-sources';
import { DirectionsService } from './shared';
import { provideDirectionsSourceService } from './shared/directions-source.service';

export function provideDirection(
...sources: DirectionSourceFeature<DirectionSourceKind>[]
): Provider[] {
const providers: Provider[] = [
{
provide: DirectionsService,
useClass: DirectionsService
},
provideDirectionsSourceService()
];

for (const source of sources) {
providers.push(...source.providers);
}

return providers;
}
1 change: 1 addition & 0 deletions packages/geo/src/lib/directions/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './shared';
export * from './directions.component';
export * from './directions.provider';
export * from './directions-sources';
export * from './directions-inputs';
export * from './directions-buttons';
Expand Down
4 changes: 1 addition & 3 deletions packages/geo/src/lib/directions/shared/directions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ import {
formatInstruction
} from './directions.utils';

@Injectable({
providedIn: 'root'
})
@Injectable()
export class DirectionsService {
constructor(
private directionsSourceService: DirectionsSourceService,
Expand Down
1 change: 1 addition & 0 deletions packages/geo/src/lib/query/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './query.enums';
export * from './query.interfaces';
export * from './query.utils';
export * from './query-search-source';
export * from './query-search-source.providers';
3 changes: 3 additions & 0 deletions packages/geo/src/lib/search/search.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export const SEARCH_DIRECTIVES = [
]
})
export class IgoSearchModule {
/**
* @deprecated import the provideSearch() directly and add the source in the provider property
*/
static forRoot(): ModuleWithProviders<IgoSearchModule> {
return {
ngModule: IgoSearchModule,
Expand Down
1 change: 1 addition & 0 deletions packages/geo/src/lib/search/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './search.enums';
export * from './search.provider';
export * from './search.interfaces';
export * from './search-pointer-summary.directive';
export * from './search.service';
Expand Down
36 changes: 36 additions & 0 deletions packages/geo/src/lib/search/shared/search.provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Provider } from '@angular/core';

import { provideSearchSourceService } from './search-source-service.providers';
import { SearchService } from './search.service';
import {
SearchSourceFeature,
SearchSourceKind
} from './sources/source.interfaces';

interface ISearchProviderOptions {
/** Share the search term with analytics tracking */
analytics?: boolean;
}

export function provideSearch(
sources: SearchSourceFeature<SearchSourceKind>[],
options?: ISearchProviderOptions
): Provider[] {
const providers: Provider[] = [
options?.analytics && {
provide: 'searchAnalytics',
useValue: options.analytics
},
{
provide: SearchService,
useClass: SearchService
},
provideSearchSourceService()
].filter(Boolean);

for (const source of sources) {
providers.push(...source.providers);
}

return providers;
}
39 changes: 33 additions & 6 deletions packages/geo/src/lib/search/shared/search.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Injectable } from '@angular/core';
import {
Inject,
Injectable,
Optional,
WritableSignal,
effect,
signal
} from '@angular/core';

import { AnalyticsService } from '@igo2/core/analytics';
import { StorageService } from '@igo2/core/storage';

import { MapService } from '../../map/shared/map.service';
Expand All @@ -24,15 +32,32 @@ import {
* keeps internal state of the researches it performed
* and the results they yielded.
*/
@Injectable({
providedIn: 'root'
})
@Injectable()
export class SearchService {
searchTerm: WritableSignal<string> = signal(null);

constructor(
private searchSourceService: SearchSourceService,
private mapService: MapService,
private storageService: StorageService
) {}
private storageService: StorageService,
private analyticsService: AnalyticsService,
@Inject('searchAnalytics')
@Optional()
analytics: boolean
) {
if (analytics) {
this.handleAnalytics();
}
}

private handleAnalytics(): void {
effect(() => {
const term = this.searchTerm();
if (term != null) {
this.analyticsService.trackSearch(term, null);
}
});
}

/**
* Perform a research by text
Expand All @@ -44,6 +69,8 @@ export class SearchService {
return [];
}

this.searchTerm.set(term);

const proj = this.mapService.getMap()?.projection || 'EPSG:3857';
const response = stringToLonLat(term, proj, {
forceNA: options.forceNA
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { StorageService } from '@igo2/core/storage';

import { CadastreSearchSource } from './cadastre';
import { SearchSource } from './source';
import { SearchSourceFeature, SearchSourceKind } from './source.interfaces';

/**
* Cadastre search source factory
Expand Down Expand Up @@ -36,3 +37,10 @@ export function provideCadastreSearchSource() {
deps: [HttpClient, LanguageService, StorageService, ConfigService]
};
}

export function withCadastreSource(): SearchSourceFeature<SearchSourceKind.Cadastre> {
return {
kind: SearchSourceKind.Cadastre,
providers: [provideCadastreSearchSource()]
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
CoordinatesSearchResultFormatter
} from './coordinates';
import { SearchSource } from './source';
import { SearchSourceFeature, SearchSourceKind } from './source.interfaces';

/**
* Coordinate search result formatter factory
Expand Down Expand Up @@ -60,3 +61,13 @@ export function provideCoordinatesReverseSearchSource() {
deps: [ConfigService, LanguageService, StorageService, ProjectionService]
};
}

export function withCoordinatesReverseSource(): SearchSourceFeature<SearchSourceKind.CoordinatesReverse> {
return {
kind: SearchSourceKind.CoordinatesReverse,
providers: [
provideCoordinatesReverseSearchSource(),
provideDefaultCoordinatesSearchResultFormatter()
]
};
}
27 changes: 24 additions & 3 deletions packages/geo/src/lib/search/shared/sources/icherche.providers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http';
import { Injector } from '@angular/core';
import { Injector, Provider } from '@angular/core';

import { ConfigService } from '@igo2/core/config';
import { LanguageService } from '@igo2/core/language';
Expand All @@ -11,6 +11,7 @@ import {
IChercheSearchSource
} from './icherche';
import { SearchSource } from './source';
import { SearchSourceFeature, SearchSourceKind } from './source.interfaces';

/**
* ICherche search result formatter factory
Expand All @@ -25,7 +26,7 @@ export function defaultIChercheSearchResultFormatterFactory(
/**
* Function that returns a provider for the ICherche search result formatter
*/
export function provideDefaultIChercheSearchResultFormatter() {
export function provideDefaultIChercheSearchResultFormatter(): Provider {
return {
provide: IChercheSearchResultFormatter,
useFactory: defaultIChercheSearchResultFormatterFactory,
Expand Down Expand Up @@ -58,7 +59,7 @@ export function ichercheSearchSourceFactory(
/**
* Function that returns a provider for the ICherche search source
*/
export function provideIChercheSearchSource() {
export function provideIChercheSearchSource(): Provider {
return {
provide: SearchSource,
useFactory: ichercheSearchSourceFactory,
Expand All @@ -74,6 +75,16 @@ export function provideIChercheSearchSource() {
};
}

export function withIChercheSource(): SearchSourceFeature<SearchSourceKind.ICherche> {
return {
kind: SearchSourceKind.ICherche,
providers: [
provideIChercheSearchSource(),
provideDefaultIChercheSearchResultFormatter()
]
};
}

/**
* IChercheReverse search source factory
* @ignore
Expand Down Expand Up @@ -105,3 +116,13 @@ export function provideIChercheReverseSearchSource() {
deps: [HttpClient, LanguageService, StorageService, ConfigService, Injector]
};
}

export function withIChercheReverseSource(): SearchSourceFeature<SearchSourceKind.IChercheReverse> {
return {
kind: SearchSourceKind.IChercheReverse,
providers: [
provideIChercheReverseSearchSource(),
provideDefaultIChercheSearchResultFormatter()
]
};
}
2 changes: 1 addition & 1 deletion packages/geo/src/lib/search/shared/sources/icherche.ts
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ export class IChercheSearchSource extends SearchSource implements TextSearch {
const hashtags = term.match(/(#[A-Za-z]+)/g) || [];
let keep = false;
keep = hashtags.some((hashtag) => {
const hashtagKey = hashtag.substring(1);
const hashtagKey = String(hashtag).substring(1);
return this.hashtagsLieuxToKeep.some(
(h) =>
h
Expand Down
11 changes: 11 additions & 0 deletions packages/geo/src/lib/search/shared/sources/ilayer.providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { StorageService } from '@igo2/core/storage';

import { ILayerSearchResultFormatter, ILayerSearchSource } from './ilayer';
import { SearchSource } from './source';
import { SearchSourceFeature, SearchSourceKind } from './source.interfaces';

/**
* ILayer search result formatter factory
Expand Down Expand Up @@ -65,3 +66,13 @@ export function provideILayerSearchSource() {
]
};
}

export function withILayerSource(): SearchSourceFeature<SearchSourceKind.ILayer> {
return {
kind: SearchSourceKind.ILayer,
providers: [
provideILayerSearchSource(),
provideILayerSearchResultFormatter()
]
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { StorageService } from '@igo2/core/storage';

import { NominatimSearchSource } from './nominatim';
import { SearchSource } from './source';
import { SearchSourceFeature, SearchSourceKind } from './source.interfaces';

/**
* Nominatim search source factory
Expand Down Expand Up @@ -33,3 +34,10 @@ export function provideNominatimSearchSource() {
deps: [HttpClient, ConfigService, StorageService]
};
}

export function withNominatimSource(): SearchSourceFeature<SearchSourceKind.Nominatim> {
return {
kind: SearchSourceKind.Nominatim,
providers: [provideNominatimSearchSource()]
};
}
Loading

0 comments on commit cd199eb

Please sign in to comment.