From 0a01898e27c2fa9e4e8f0479e478198a7792957a Mon Sep 17 00:00:00 2001 From: matrottier Date: Thu, 25 Jul 2019 09:41:24 -0400 Subject: [PATCH] feat(search): add Searchsource settings (#370) * issue #349 * add setting nominatim * ajout de conf pour les services, stop propagation click, fix lint * ajout d'une distance pour la recherche * ajout traduction setting * typing and dusting * feat(geo.search) new compoenent search-settings * style(geo.search.search-selector) lint * style(geo.search.search-selector) moved to search-setting * style(geo.search) improve code --- demo/src/app/geo/search/search.component.ts | 2 +- .../search-bar/search-bar.component.html | 12 +- .../search-bar/search-bar.component.scss | 19 +- .../search/search-bar/search-bar.module.ts | 5 +- .../search-selector.component.html | 2 +- .../search-selector.component.ts | 1 + .../search-settings.component.html | 63 +++++++ .../search-settings.component.scss | 14 ++ .../search-settings.component.spec.ts | 25 +++ .../search-settings.component.ts | 81 +++++++++ .../search-settings/search-settings.module.ts | 35 ++++ packages/geo/src/lib/search/search.module.ts | 7 +- .../search/shared/search-source.service.ts | 5 + .../src/lib/search/shared/sources/icherche.ts | 168 +++++++++++++++++- .../lib/search/shared/sources/nominatim.ts | 60 ++++++- .../shared/sources/source.interfaces.ts | 13 ++ .../src/lib/search/shared/sources/source.ts | 37 +++- packages/geo/src/locale/en.geo.json | 16 +- packages/geo/src/locale/fr.geo.json | 16 +- 19 files changed, 549 insertions(+), 32 deletions(-) create mode 100644 packages/geo/src/lib/search/search-settings/search-settings.component.html create mode 100644 packages/geo/src/lib/search/search-settings/search-settings.component.scss create mode 100644 packages/geo/src/lib/search/search-settings/search-settings.component.spec.ts create mode 100644 packages/geo/src/lib/search/search-settings/search-settings.component.ts create mode 100644 packages/geo/src/lib/search/search-settings/search-settings.module.ts diff --git a/demo/src/app/geo/search/search.component.ts b/demo/src/app/geo/search/search.component.ts index 4604885ee3..54359a03d0 100644 --- a/demo/src/app/geo/search/search.component.ts +++ b/demo/src/app/geo/search/search.component.ts @@ -205,7 +205,7 @@ export class AppSearchComponent implements OnInit, OnDestroy { onSearchCoordinate() { this.searchStore.clear(); - const results = this.searchService.reverseSearch(this.lonlat); + const results = this.searchService.reverseSearch(this.lonlat, {distance: 100}); for (const i in results) { if (results.length > 0) { diff --git a/packages/geo/src/lib/search/search-bar/search-bar.component.html b/packages/geo/src/lib/search/search-bar/search-bar.component.html index 4d7a6c319d..6bb4ac4170 100644 --- a/packages/geo/src/lib/search/search-bar/search-bar.component.html +++ b/packages/geo/src/lib/search/search-bar/search-bar.component.html @@ -27,10 +27,14 @@ *ngIf="!empty"> + + + + + - - + diff --git a/packages/geo/src/lib/search/search-bar/search-bar.component.scss b/packages/geo/src/lib/search/search-bar/search-bar.component.scss index 614ec5d153..653f6fb120 100644 --- a/packages/geo/src/lib/search/search-bar/search-bar.component.scss +++ b/packages/geo/src/lib/search/search-bar/search-bar.component.scss @@ -15,7 +15,7 @@ :host ::ng-deep div.mat-form-field-infix { left: $igo-padding; right: $igo-padding; - padding: 0 0 12px 0 !important; + padding: 0 0 12px 0 !important; } :host ::ng-deep div.mat-form-field-underline { @@ -25,6 +25,8 @@ .igo-search-bar-container { position: relative; width: 100%; + display: inline-flex; + overflow: hidden; } .igo-search-bar-container > mat-form-field { @@ -36,12 +38,12 @@ } .search-bar-buttons { - position: absolute; - right: 40px; + position: relative; + right: 0px; + display: inline-flex; top: 0; & > button:nth-child(2)::before { content: ''; - position: absolute; left: 0px; top: 5px; border-right: 1px solid #ddd; @@ -50,10 +52,13 @@ } igo-search-selector { - display: inline-block; background-color: #fff; - position: absolute; - right: 0; + top: 0; + border-radius: 0; +} + +igo-search-settings { + background-color: #fff; top: 0; border-radius: 0; } diff --git a/packages/geo/src/lib/search/search-bar/search-bar.module.ts b/packages/geo/src/lib/search/search-bar/search-bar.module.ts index 61c27f84d1..ba08efa4e2 100644 --- a/packages/geo/src/lib/search/search-bar/search-bar.module.ts +++ b/packages/geo/src/lib/search/search-bar/search-bar.module.ts @@ -15,6 +15,7 @@ import { import { IgoLanguageModule } from '@igo2/core'; import { IgoSearchSelectorModule } from '../search-selector/search-selector.module'; +import { IgoSearchSettingsModule } from '../search-settings/search-settings.module'; import { SearchBarComponent } from './search-bar.component'; import { SearchUrlParamDirective } from './search-url-param.directive'; @@ -33,11 +34,11 @@ import { SearchUrlParamDirective } from './search-url-param.directive'; MatFormFieldModule, MatInputModule, IgoLanguageModule, - IgoSearchSelectorModule + IgoSearchSelectorModule, + IgoSearchSettingsModule ], exports: [ SearchBarComponent, - SearchBarComponent ], declarations: [ SearchBarComponent, diff --git a/packages/geo/src/lib/search/search-selector/search-selector.component.html b/packages/geo/src/lib/search/search-selector/search-selector.component.html index bd985846f2..fad9b790c7 100644 --- a/packages/geo/src/lib/search/search-selector/search-selector.component.html +++ b/packages/geo/src/lib/search/search-selector/search-selector.component.html @@ -13,7 +13,6 @@ + diff --git a/packages/geo/src/lib/search/search-selector/search-selector.component.ts b/packages/geo/src/lib/search/search-selector/search-selector.component.ts index 4ccaaf8c62..fa6f557ee8 100644 --- a/packages/geo/src/lib/search/search-selector/search-selector.component.ts +++ b/packages/geo/src/lib/search/search-selector/search-selector.component.ts @@ -9,6 +9,7 @@ import { import { SEARCH_TYPES } from '../shared/search.enums'; import { SearchSourceService } from '../shared/search-source.service'; +import { SearchSource } from '../shared/sources/source'; /** * This component allows a user to select a search type yo enable. In it's diff --git a/packages/geo/src/lib/search/search-settings/search-settings.component.html b/packages/geo/src/lib/search/search-settings/search-settings.component.html new file mode 100644 index 0000000000..84efd38e34 --- /dev/null +++ b/packages/geo/src/lib/search/search-settings/search-settings.component.html @@ -0,0 +1,63 @@ +
+ + + + + + + + + + + + + {{settingValue.title}} + + + + + {{settingValue.title}} + + + + + + + +
diff --git a/packages/geo/src/lib/search/search-settings/search-settings.component.scss b/packages/geo/src/lib/search/search-settings/search-settings.component.scss new file mode 100644 index 0000000000..dd230b40af --- /dev/null +++ b/packages/geo/src/lib/search/search-settings/search-settings.component.scss @@ -0,0 +1,14 @@ +@import '../../../../../core/src/style/partial/core.variables'; + +.igo-search-settings-button ::ng-deep div.mat-button-ripple-round { + border-radius: 0; +} + +.igo-search-settings-radio-group { + display: inline-flex; + flex-direction: column; +} + +.igo-search-settings-radio-group mat-radio-button { + margin: $igo-margin; +} diff --git a/packages/geo/src/lib/search/search-settings/search-settings.component.spec.ts b/packages/geo/src/lib/search/search-settings/search-settings.component.spec.ts new file mode 100644 index 0000000000..3e15623a2b --- /dev/null +++ b/packages/geo/src/lib/search/search-settings/search-settings.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchSettingsComponent } from './search-settings.component'; + +describe('SearchSettingsComponent', () => { + let component: SearchSettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SearchSettingsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchSettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/packages/geo/src/lib/search/search-settings/search-settings.component.ts b/packages/geo/src/lib/search/search-settings/search-settings.component.ts new file mode 100644 index 0000000000..0566824232 --- /dev/null +++ b/packages/geo/src/lib/search/search-settings/search-settings.component.ts @@ -0,0 +1,81 @@ +import {MatCheckboxChange, MatRadioChange } from '@angular/material'; + +import { + Component, + Input, + Output, + EventEmitter, + OnInit, + ChangeDetectionStrategy +} from '@angular/core'; + +import { SearchSourceService } from '../shared/search-source.service'; +import { SearchSource } from '../shared/sources/source'; +import { SearchSourceSettings, SettingOptions } from '../shared/sources/source.interfaces'; + +/** + * This component allows a user to select a search type yo enable. In it's + * current version, only one search type can be selected at once (radio). If + * this component were to support more than one search source enabled (checkbox), + * the searchbar component would require a small change to it's + * placeholder getter. The search source service already supports having + * more than one search source enabled. + */ +@Component({ + selector: 'igo-search-settings', + templateUrl: './search-settings.component.html', + styleUrls: ['./search-settings.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchSettingsComponent { + + /** + * Event emitted when the enabled search type changes + */ + @Output() change = new EventEmitter(); + + constructor(private searchSourceService: SearchSourceService) {} + + /** + * Get all search sources + * @internal + */ + getSearchSources(): SearchSource[] { + return this.searchSourceService.getSources(); + } + + /** + * Triggered when a setting is checked (checkbox style) + * @internal + */ + settingsValueCheckedCheckbox( + event: MatCheckboxChange, + source: SearchSource, + setting: SearchSourceSettings, + settingValue: SettingOptions + ) { + settingValue.enabled = event.checked; + source.setParamFromSetting(setting); + } + + /** + * Triggered when a setting is checked (radiobutton style) + * @internal + */ + settingsValueCheckedRadioButton( + event: MatRadioChange, + source: SearchSource, + setting: SearchSourceSettings, + settingValue: SettingOptions + ) { + setting.values.forEach( conf => { + if (conf.value !== settingValue.value) { + conf.enabled = !event.source.checked; + } else { + conf.enabled = event.source.checked; + } + }); + source.setParamFromSetting(setting); + } + +} diff --git a/packages/geo/src/lib/search/search-settings/search-settings.module.ts b/packages/geo/src/lib/search/search-settings/search-settings.module.ts new file mode 100644 index 0000000000..53e48eafde --- /dev/null +++ b/packages/geo/src/lib/search/search-settings/search-settings.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SearchSettingsComponent } from './search-settings.component'; +import { + MatTooltipModule, + MatIconModule, + MatButtonModule, + MatMenuModule, + MatRadioModule, + MatCheckboxModule +} from '@angular/material'; + +import { IgoLanguageModule } from '@igo2/core'; + +import { IgoSearchSelectorModule } from '../search-selector/search-selector.module'; + +/** + * @ignore + */ +@NgModule({ + declarations: [SearchSettingsComponent], + imports: [ + CommonModule, + MatTooltipModule, + MatIconModule, + MatButtonModule, + MatMenuModule, + MatRadioModule, + MatCheckboxModule, + IgoSearchSelectorModule, + IgoLanguageModule + ], + exports: [SearchSettingsComponent] +}) +export class IgoSearchSettingsModule { } diff --git a/packages/geo/src/lib/search/search.module.ts b/packages/geo/src/lib/search/search.module.ts index c22be7f770..9b6119dcf5 100644 --- a/packages/geo/src/lib/search/search.module.ts +++ b/packages/geo/src/lib/search/search.module.ts @@ -8,18 +8,21 @@ import { provideDefaultCoordinatesSearchResultFormatter } from './shared/sources import { IgoSearchBarModule } from './search-bar/search-bar.module'; import { IgoSearchSelectorModule } from './search-selector/search-selector.module'; import { IgoSearchResultsModule } from './search-results/search-results.module'; +import { IgoSearchSettingsModule } from './search-settings/search-settings.module'; @NgModule({ imports: [ CommonModule, IgoSearchBarModule, IgoSearchSelectorModule, - IgoSearchResultsModule + IgoSearchResultsModule, + IgoSearchSettingsModule ], exports: [ IgoSearchBarModule, IgoSearchSelectorModule, - IgoSearchResultsModule + IgoSearchResultsModule, + IgoSearchSettingsModule ], declarations: [] }) diff --git a/packages/geo/src/lib/search/shared/search-source.service.ts b/packages/geo/src/lib/search/shared/search-source.service.ts index 13fbb592c9..2f778ba0bb 100644 --- a/packages/geo/src/lib/search/shared/search-source.service.ts +++ b/packages/geo/src/lib/search/shared/search-source.service.ts @@ -1,4 +1,5 @@ import { SearchSource } from './sources/source'; +import { SearchSourceSettings } from './sources/source.interfaces'; /** * Service where all available search sources are registered. @@ -39,4 +40,8 @@ export class SearchSourceService { } }); } + + setParamFromSetting(source: SearchSource, setting: SearchSourceSettings) { + source.setParamFromSetting(setting); + } } diff --git a/packages/geo/src/lib/search/shared/sources/icherche.ts b/packages/geo/src/lib/search/shared/sources/icherche.ts index 9ab182db3a..433798f804 100644 --- a/packages/geo/src/lib/search/shared/sources/icherche.ts +++ b/packages/geo/src/lib/search/shared/sources/icherche.ts @@ -67,7 +67,120 @@ export class IChercheSearchSource extends SearchSource implements TextSearch { protected getDefaultOptions(): SearchSourceOptions { return { title: 'ICherche Québec', - searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/geocode' + searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/geocode', + settings: [ + { + type: 'checkbox', + title: 'results type', + name: 'type', + values: [ + { + title: 'Adresse', + value: 'adresse', + enabled: true + }, + { + title: 'Ancienne adresse', + value: 'ancienne_adresse', + enabled: true + }, + { + title: 'Code Postal', + value: 'code_postal', + enabled: true + }, + { + title: 'Route', + value: 'route', + enabled: true + }, + { + title: 'Municipalité', + value: 'municipalite', + enabled: true + }, + { + title: 'Ancienne municipalité', + value: 'ancienne_municipalite', + enabled: true + }, + { + title: 'mrc', + value: 'mrc', + enabled: true + }, + { + title: 'Région administrative', + value: 'region_administrative', + enabled: true + } + ] + }, + { + type: 'radiobutton', + title: 'results limit', + name: 'limit', + values: [ + { + title: '1', + value: 1, + enabled: false + }, + { + title: '5', + value: 5, + enabled: true + }, + { + title: '10', + value: 10, + enabled: false + }, + { + title: '25', + value: 25, + enabled: false + }, + { + title: '50', + value: 50, + enabled: false + } + ] + }, + { + type: 'radiobutton', + title: 'trust level', + name: 'ecmax', + values: [ + { + title: '1', + value: 1, + enabled: false + }, + { + title: '15', + value: 15, + enabled: true + }, + { + title: '50', + value: 50, + enabled: false + }, + { + title: '75', + value: 75, + enabled: false + }, + { + title: '100', + value: 100, + enabled: false + } + ] + } + ] }; } @@ -91,9 +204,7 @@ export class IChercheSearchSource extends SearchSource implements TextSearch { fromObject: Object.assign( { q: term, - geometries: 'geom', - type: - 'adresse,code_postal,route,municipalite,mrc,region_administrative' + geometries: 'geom' }, this.params, options.params || {} @@ -165,8 +276,48 @@ export class IChercheReverseSearchSource extends SearchSource protected getDefaultOptions(): SearchSourceOptions { return { - title: 'ICherche Québec', - searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/xy' + title: 'ICherche Québec (Géocodage inversé)', + searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/xy', + + settings: [ + { + type: 'checkbox', + title: 'results type', + name: 'type', + values: [ + { + title: 'Adresse', + value: 'adresse', + enabled: true + }, + { + title: 'Route', + value: 'route', + enabled: false + }, + { + title: 'Arrondissement', + value: 'arrondissement', + enabled: false + }, + { + title: 'Municipalité', + value: 'municipalite', + enabled: true + }, + { + title: 'mrc', + value: 'mrc', + enabled: true + }, + { + title: 'Région administrative', + value: 'regadmin', + enabled: true + } + ] + } + ] }; } @@ -197,9 +348,8 @@ export class IChercheReverseSearchSource extends SearchSource fromObject: Object.assign( { loc: lonLat.join(','), - distance: distance ? String(distance) : '', - geometries: 'geom', - type: 'adresse,municipalite,mrc,regadmin' + distance: distance ? String(distance) : '100', + geometries: 'geom' }, this.params, options.params || {} diff --git a/packages/geo/src/lib/search/shared/sources/nominatim.ts b/packages/geo/src/lib/search/shared/sources/nominatim.ts index 09cf953d20..b72ae23196 100644 --- a/packages/geo/src/lib/search/shared/sources/nominatim.ts +++ b/packages/geo/src/lib/search/shared/sources/nominatim.ts @@ -33,7 +33,65 @@ export class NominatimSearchSource extends SearchSource implements TextSearch { protected getDefaultOptions(): SearchSourceOptions { return { title: 'Nominatim (OSM)', - searchUrl: 'https://nominatim.openstreetmap.org/search' + searchUrl: 'https://nominatim.openstreetmap.org/search', + settings: [ + { + type: 'radiobutton', + title: 'results limit', + name: 'limit', + values: [ + { + title: '10', + value: 10, + enabled: true + }, + { + title: '20', + value: 20, + enabled: false + }, + { + title: '50', + value: 50, + enabled: false + } + ] + }, + { + type: 'radiobutton', + title: 'country limitation', + name: 'countrycode', + values: [ + { + title: 'Canada', + value: 'CA', + enabled: true + }, + { + title: 'Le monde', + value: null, + enabled: false + } + ] + }, + { + type: 'radiobutton', + title: 'multiple object', + name: 'dedupe', + values: [ + { + title: 'Oui', + value: 0, + enabled: false + }, + { + title: 'Non', + value: 1, + enabled: true + } + ] + } + ] }; } diff --git a/packages/geo/src/lib/search/shared/sources/source.interfaces.ts b/packages/geo/src/lib/search/shared/sources/source.interfaces.ts index bee31533b3..3be4dcb330 100644 --- a/packages/geo/src/lib/search/shared/sources/source.interfaces.ts +++ b/packages/geo/src/lib/search/shared/sources/source.interfaces.ts @@ -7,8 +7,21 @@ export interface SearchSourceOptions { distance?: number; zoomMaxOnSelect?: number; params?: { [key: string]: string }; + settings?: SearchSourceSettings[]; } +export interface SearchSourceSettings { + type: 'radiobutton'|'checkbox'; + values: SettingOptions[]; + title: string; + name: string; +} + +export interface SettingOptions { + value: string|number; + enabled: boolean; + title: string; +} export interface TextSearchOptions { params?: { [key: string]: string }; } diff --git a/packages/geo/src/lib/search/shared/sources/source.ts b/packages/geo/src/lib/search/shared/sources/source.ts index c7c988dc45..8b36cf78cf 100644 --- a/packages/geo/src/lib/search/shared/sources/source.ts +++ b/packages/geo/src/lib/search/shared/sources/source.ts @@ -4,7 +4,8 @@ import { SearchResult } from '../search.interfaces'; import { SearchSourceOptions, TextSearchOptions, - ReverseSearchOptions + ReverseSearchOptions, + SearchSourceSettings } from './source.interfaces'; /** @@ -83,6 +84,35 @@ export class SearchSource { return this.options.params === undefined ? {} : this.options.params; } + /** + * Search settings + */ + get settings(): SearchSourceSettings[] { + return this.options.settings === undefined ? [] : this.options.settings; + } + + setParamFromSetting(setting: SearchSourceSettings) { + switch (setting.type) { + case 'radiobutton': + setting.values.forEach( conf => { + if (conf.enabled) { + this.options.params = Object.assign( (this.options.params || {}), + { [setting.name] : conf.value } ); + } + }); + break; + case 'checkbox': + const confValue = setting.values + .filter((conf) => conf.enabled) + .map((conf) => conf.value) + .join(','); + + this.options.params = Object.assign( (this.options.params || {}), + { [setting.name] : confValue } ); + break; + } + } + /** * Search results display order */ @@ -92,6 +122,11 @@ export class SearchSource { constructor(options: SearchSourceOptions) { this.options = Object.assign({}, this.getDefaultOptions(), options); + + // Set Default Params from Settings + this.settings.forEach( setting => { + this.setParamFromSetting(setting); + }); } } diff --git a/packages/geo/src/locale/en.geo.json b/packages/geo/src/locale/en.geo.json index e42e86a8d2..84f22e88e4 100644 --- a/packages/geo/src/locale/en.geo.json +++ b/packages/geo/src/locale/en.geo.json @@ -143,7 +143,7 @@ "A4": "A4", "A5": "A5", "Letter": "Letter", - "Legal": "Legal" + "Legal": "Legal" }, "imageFormat": "Image format", "orientation" : "Orientation", @@ -215,7 +215,19 @@ "url": "URL" } }, - "menu.tooltip": "Search Options" + "menu.tooltip": "Search Options", + "settings": { + "title": "Settings" + }, + "searchSources": { + "settings": { + "results type": "Results type", + "trust level": "Trust level", + "results limit": "Limit", + "multiple object": "Multiple object", + "country limitation": "Limitation (country)" + } + } }, "geometry": { "geometry": "Geometry", diff --git a/packages/geo/src/locale/fr.geo.json b/packages/geo/src/locale/fr.geo.json index 94fe6b161e..4c450d93fc 100644 --- a/packages/geo/src/locale/fr.geo.json +++ b/packages/geo/src/locale/fr.geo.json @@ -143,7 +143,7 @@ "A4": "A4", "A5": "A5", "Letter": "Lettre", - "Legal": "Légal" + "Legal": "Légal" }, "imageFormat": "Format de l'image", "orientation" : "Orientation", @@ -216,7 +216,19 @@ "url": "URL" } }, - "menu.tooltip": "Options de recherche" + "menu.tooltip": "Options de recherche", + "settings": { + "title": "Paramètres" + }, + "searchSources": { + "settings": { + "results type": "Type de résultat", + "trust level": "Niveau de confiance", + "results limit": "Limite", + "multiple object": "Objet multiple", + "country limitation": "Limitation (pays)" + } + } }, "geometry": { "geometry": "Geometrie",