-
Notifications
You must be signed in to change notification settings - Fork 395
Expand file tree
/
Copy pathSearchProviderMixin.ts
More file actions
114 lines (92 loc) · 3.1 KB
/
SearchProviderMixin.ts
File metadata and controls
114 lines (92 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { debounce } from "lodash-es";
import { action, makeObservable, observable } from "mobx";
import AbstractConstructor from "../../Core/AbstractConstructor";
import Model from "../../Models/Definition/Model";
import SearchProviderResult from "../../Models/SearchProviders/SearchProviderResults";
import SearchProviderTraits from "../../Traits/SearchProviders/SearchProviderTraits";
type SearchProviderModel = Model<SearchProviderTraits>;
function SearchProviderMixin<
T extends AbstractConstructor<SearchProviderModel>
>(Base: T) {
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: SearchProviderResult
): Promise<void>;
@action
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)) {
this._debouncedSearch.cancel();
this.searchResult.isSearching = false;
this.searchResult.message = {
content: "translate#viewModels.searchMinCharacters",
params: {
count: this.minCharacters
}
};
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);
this.searchResult.isWaitingToStartSearch = false;
this.searchResult.isSearching = true;
await this.doSearch(searchText, this.searchResult);
this.searchResult.isSearching = false;
}
private shouldRunSearch(searchText: string) {
if (
searchText === undefined ||
/^\s*$/.test(searchText) ||
(this.minCharacters && searchText.length < this.minCharacters)
) {
return false;
}
return true;
}
get hasSearchProviderMixin() {
return true;
}
}
return SearchProviderMixin;
}
namespace SearchProviderMixin {
export interface Instance
extends InstanceType<ReturnType<typeof SearchProviderMixin>> {}
export function isMixedInto(model: any): model is Instance {
return model && model.hasSearchProviderMixin;
}
}
export default SearchProviderMixin;