Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions lib/ModelMixins/SearchProviders/LocationSearchProviderMixin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { action, makeObservable } from "mobx";
import { action, makeObservable, override } from "mobx";
import Ellipsoid from "terriajs-cesium/Source/Core/Ellipsoid";
import CesiumMath from "terriajs-cesium/Source/Core/Math";
import Rectangle from "terriajs-cesium/Source/Core/Rectangle";
Expand Down Expand Up @@ -32,8 +32,23 @@ function LocationSearchProviderMixin<
@action
showWarning() {}

supportsAutocomplete(): boolean {
return true;
async search(searchText: string, manuallyTriggered?: boolean) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doubt: Could you explain when manuallyTriggered is true and why we need to differentiate both?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manuallyTriggered is when the user presses enter to start the search; in that case, we need to cancel the debounce and run the search without waiting

if (!this.autocompleteEnabled && !manuallyTriggered) {
this.searchResult.isSearching = false;
this.searchResult.isWaitingToStartSearch = false;
this.searchResult.message = {
content: "translate#viewModels.enterToStartSearch"
};

return;
}

await super.search(searchText, manuallyTriggered);
}

@override
get autocompleteEnabled() {
return super.autocompleteEnabled ?? true;
}
}

Expand Down
64 changes: 51 additions & 13 deletions lib/ModelMixins/SearchProviders/SearchProviderMixin.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { action, makeObservable } from "mobx";
import { fromPromise } from "mobx-utils";
import { debounce } from "lodash-es";
import { action, makeObservable, observable } from "mobx";
import AbstractConstructor from "../../Core/AbstractConstructor";
import Model from "../../Models/Definition/Model";
import SearchProviderResults from "../../Models/SearchProviders/SearchProviderResults";
import SearchProviderResult from "../../Models/SearchProviders/SearchProviderResults";
import SearchProviderTraits from "../../Traits/SearchProviders/SearchProviderTraits";

type SearchProviderModel = Model<SearchProviderTraits>;
Expand All @@ -13,36 +13,74 @@ function SearchProviderMixin<
abstract class SearchProviderMixin extends Base {
abstract get type(): string;

protected debounceTime = 1000;
private _debouncedSearch: ReturnType<typeof debounce>;

constructor(...args: any[]) {
super(...args);
makeObservable(this);
this.searchResult = new SearchProviderResult(this);

this._debouncedSearch = debounce((searchText: string) => {
this.performSearch(searchText);
}, this.debounceTime);
}

@observable
public searchResult: SearchProviderResult;

protected abstract logEvent(searchText: string): void;

protected abstract doSearch(
searchText: string,
results: SearchProviderResults
results: SearchProviderResult
): Promise<void>;

@action
search(searchText: string): SearchProviderResults {
const result = new SearchProviderResults(this);
cancelSearch() {
this._debouncedSearch.cancel();

this.searchResult.isCanceled = true;
this.searchResult = new SearchProviderResult(this);
}

@action
async search(
searchText: string,
manuallyTriggered?: boolean
): Promise<void> {
this.searchResult.isWaitingToStartSearch = true;
if (!this.shouldRunSearch(searchText)) {
result.resultsCompletePromise = fromPromise(Promise.resolve());
result.message = {
this._debouncedSearch.cancel();

this.searchResult.isSearching = false;
this.searchResult.message = {
content: "translate#viewModels.searchMinCharacters",
params: {
count: this.minCharacters
}
};
return result;
this.searchResult.isWaitingToStartSearch = false;
return;
}

if (manuallyTriggered) {
this._debouncedSearch.cancel();
await this.performSearch(searchText);
} else {
await this._debouncedSearch(searchText);
}
}

@action
private async performSearch(searchText: string): Promise<void> {
this.logEvent(searchText);
result.resultsCompletePromise = fromPromise(
this.doSearch(searchText, result)
);
return result;
this.searchResult.isWaitingToStartSearch = false;
this.searchResult.isSearching = true;

await this.doSearch(searchText, this.searchResult);

this.searchResult.isSearching = false;
}

private shouldRunSearch(searchText: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import URI from "urijs";
import AbstractConstructor from "../../Core/AbstractConstructor";
import zoomRectangleFromPoint from "../../Map/Vector/zoomRectangleFromPoint";
import Model from "../../Models/Definition/Model";
import SearchProviderResults from "../../Models/SearchProviders/SearchProviderResults";
import SearchProviderResult from "../../Models/SearchProviders/SearchProviderResults";
import SearchResult from "../../Models/SearchProviders/SearchResult";
import xml2json from "../../ThirdParty/xml2json";
import WebFeatureServiceSearchProviderTraits from "../../Traits/SearchProviders/WebFeatureServiceSearchProviderTraits";
Expand Down Expand Up @@ -50,7 +50,7 @@ function WebFeatureServiceSearchProviderMixin<

protected doSearch(
searchText: string,
results: SearchProviderResults
results: SearchProviderResult
): Promise<void> {
results.results.length = 0;
results.message = undefined;
Expand Down
4 changes: 2 additions & 2 deletions lib/Models/SearchProviders/BingMapsSearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import BingMapsSearchProviderTraits from "../../Traits/SearchProviders/BingMapsS
import CreateModel from "../Definition/CreateModel";
import Terria from "../Terria";
import CommonStrata from "./../Definition/CommonStrata";
import SearchProviderResults from "./SearchProviderResults";
import SearchProviderResult from "./SearchProviderResults";
import SearchResult from "./SearchResult";

export default class BingMapsSearchProvider extends LocationSearchProviderMixin(
Expand Down Expand Up @@ -65,7 +65,7 @@ export default class BingMapsSearchProvider extends LocationSearchProviderMixin(

protected doSearch(
searchText: string,
searchResults: SearchProviderResults
searchResults: SearchProviderResult
): Promise<void> {
searchResults.results.length = 0;
searchResults.message = undefined;
Expand Down
18 changes: 9 additions & 9 deletions lib/Models/SearchProviders/CatalogSearchProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { autorun, makeObservable, observable, runInAction } from "mobx";
import { autorun, makeObservable, runInAction } from "mobx";
import {
Category,
SearchAction
Expand All @@ -12,7 +12,7 @@ import CommonStrata from "../Definition/CommonStrata";
import CreateModel from "../Definition/CreateModel";
import { BaseModel } from "../Definition/Model";
import Terria from "../Terria";
import SearchProviderResults from "./SearchProviderResults";
import SearchProviderResult from "./SearchProviderResults";
import SearchResult from "./SearchResult";

type UniqueIdString = string;
Expand All @@ -21,7 +21,7 @@ type ResultMap = Map<UniqueIdString, boolean>;
export function loadAndSearchCatalogRecursively(
models: BaseModel[],
searchTextLowercase: string,
searchResults: SearchProviderResults,
searchResults: SearchProviderResult,
resultMap: ResultMap,
iteration: number = 0
): Promise<void> {
Expand Down Expand Up @@ -110,8 +110,7 @@ export default class CatalogSearchProvider extends CatalogSearchProviderMixin(
CreateModel(CatalogSearchProviderTraits)
) {
static readonly type = "catalog-search-provider";
@observable isSearching: boolean = false;
@observable debounceDurationOnceLoaded: number = 300;
debounceTime = 300;

constructor(id: string | undefined, terria: Terria) {
super(id, terria);
Expand Down Expand Up @@ -139,15 +138,15 @@ export default class CatalogSearchProvider extends CatalogSearchProviderMixin(

protected async doSearch(
searchText: string,
searchResults: SearchProviderResults
searchResults: SearchProviderResult
): Promise<void> {
runInAction(() => (this.isSearching = true));
runInAction(() => (searchResults.isSearching = true));

searchResults.results.length = 0;
searchResults.message = undefined;

if (searchText === undefined || /^\s*$/.test(searchText)) {
runInAction(() => (this.isSearching = false));
runInAction(() => (searchResults.isSearching = false));
return Promise.resolve();
}

Expand Down Expand Up @@ -179,7 +178,7 @@ export default class CatalogSearchProvider extends CatalogSearchProviderMixin(
}

runInAction(() => {
this.isSearching = false;
searchResults.isSearching = false;
});

if (searchResults.isCanceled) {
Expand All @@ -197,6 +196,7 @@ export default class CatalogSearchProvider extends CatalogSearchProviderMixin(
};
}
} catch (e) {
console.error(e);
this.terria.raiseErrorToUser(e, {
message: "An error occurred while searching",
severity: TerriaErrorSeverity.Warning
Expand Down
4 changes: 2 additions & 2 deletions lib/Models/SearchProviders/CesiumIonSearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import LocationSearchProviderMixin from "../../ModelMixins/SearchProviders/Locat
import CesiumIonSearchProviderTraits from "../../Traits/SearchProviders/CesiumIonSearchProviderTraits";
import CreateModel from "../Definition/CreateModel";
import Terria from "../Terria";
import SearchProviderResults from "./SearchProviderResults";
import SearchProviderResult from "./SearchProviderResults";
import SearchResult from "./SearchResult";
import CommonStrata from "../Definition/CommonStrata";

Expand Down Expand Up @@ -71,7 +71,7 @@ export default class CesiumIonSearchProvider extends LocationSearchProviderMixin

protected async doSearch(
searchText: string,
searchResults: SearchProviderResults
searchResults: SearchProviderResult
): Promise<void> {
searchResults.results.length = 0;
searchResults.message = undefined;
Expand Down
4 changes: 2 additions & 2 deletions lib/Models/SearchProviders/MapboxSearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import MapboxSearchProviderTraits from "../../Traits/SearchProviders/MapboxSearc
import CommonStrata from "../Definition/CommonStrata";
import CreateModel from "../Definition/CreateModel";
import Terria from "../Terria";
import SearchProviderResults from "./SearchProviderResults";
import SearchProviderResult from "./SearchProviderResults";
import SearchResult from "./SearchResult";

enum MapboxGeocodeDirection {
Expand Down Expand Up @@ -68,7 +68,7 @@ export default class MapboxSearchProvider extends LocationSearchProviderMixin(

protected doSearch(
searchText: string,
searchResults: SearchProviderResults
searchResults: SearchProviderResult
): Promise<void> {
searchResults.results.length = 0;
searchResults.message = undefined;
Expand Down
10 changes: 3 additions & 7 deletions lib/Models/SearchProviders/NominatimSearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import LocationSearchProviderMixin from "../../ModelMixins/SearchProviders/Locat
import NominatimSearchProviderTraits from "../../Traits/SearchProviders/NominatimSearchProviderTraits";
import CreateModel from "../Definition/CreateModel";
import Terria from "../Terria";
import SearchProviderResults from "./SearchProviderResults";
import SearchProviderResult from "./SearchProviderResults";
import SearchResult from "./SearchResult";

export default class NominatimSearchProvider extends LocationSearchProviderMixin(
Expand Down Expand Up @@ -44,9 +44,9 @@ export default class NominatimSearchProvider extends LocationSearchProviderMixin
);
}

protected doSearch(
protected async doSearch(
searchText: string,
searchResults: SearchProviderResults
searchResults: SearchProviderResult
): Promise<void> {
searchResults.results.length = 0;
searchResults.message = undefined;
Expand Down Expand Up @@ -130,10 +130,6 @@ export default class NominatimSearchProvider extends LocationSearchProviderMixin
};
});
}

supportsAutocomplete(): boolean {
return false;
}
}

function createZoomToFunction(
Expand Down
21 changes: 13 additions & 8 deletions lib/Models/SearchProviders/SearchProviderResults.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import { makeObservable, observable } from "mobx";
import { IPromiseBasedObservable, fromPromise } from "mobx-utils";
import { computed, makeObservable, observable } from "mobx";
import SearchProviderMixin from "../../ModelMixins/SearchProviders/SearchProviderMixin";
import SearchResult from "./SearchResult";

export default class SearchProviderResults {
export default class SearchProviderResult<
SeachProviderType = SearchProviderMixin.Instance
> {
@observable results: SearchResult[] = [];
@observable message?: {
content: string;
params?: {
[key: string]: string | number | undefined;
};
};
@observable isWaitingToStartSearch: boolean = false;
@observable _isSearching: boolean = false;
isCanceled = false;
resultsCompletePromise: IPromiseBasedObservable<void> = fromPromise(
Promise.resolve()
);

constructor(readonly searchProvider: SearchProviderMixin.Instance) {
constructor(readonly searchProvider: SeachProviderType) {
makeObservable(this);
}

@computed
get isSearching() {
return this.resultsCompletePromise.state === "pending";
return this._isSearching;
}

set isSearching(value: boolean) {
this._isSearching = value;
}
}
4 changes: 2 additions & 2 deletions lib/Models/SearchProviders/StubSearchProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import primitiveTrait from "../../Traits/Decorators/primitiveTrait";
import LocationSearchProviderTraits from "../../Traits/SearchProviders/LocationSearchProviderTraits";
import CreateModel from "../Definition/CreateModel";
import { ModelConstructorParameters } from "../Definition/Model";
import SearchProviderResults from "./SearchProviderResults";
import SearchProviderResult from "./SearchProviderResults";

export class StubSearchProviderTraits extends LocationSearchProviderTraits {
@primitiveTrait({
Expand Down Expand Up @@ -36,7 +36,7 @@ export default class StubSearchProvider extends SearchProviderMixin(

protected doSearch(
_searchText: string,
_results: SearchProviderResults
_results: SearchProviderResult
): Promise<void> {
return Promise.resolve();
}
Expand Down
Loading
Loading