|
|
@ -1,3 +1,4 @@ |
|
|
|
|
|
|
|
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; |
|
|
|
import { DataService } from '@ghostfolio/client/services/data.service'; |
|
|
|
import { LookupItem } from '@ghostfolio/common/interfaces'; |
|
|
@ -34,11 +35,12 @@ import { |
|
|
|
import { MatInput, MatInputModule } from '@angular/material/input'; |
|
|
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; |
|
|
|
import { isString } from 'lodash'; |
|
|
|
import { Subject, tap } from 'rxjs'; |
|
|
|
import { combineLatest, Subject, tap } from 'rxjs'; |
|
|
|
import { |
|
|
|
debounceTime, |
|
|
|
distinctUntilChanged, |
|
|
|
filter, |
|
|
|
startWith, |
|
|
|
switchMap, |
|
|
|
takeUntil |
|
|
|
} from 'rxjs/operators'; |
|
|
@ -77,7 +79,8 @@ export class GfSymbolAutocompleteComponent |
|
|
|
implements OnInit, OnDestroy |
|
|
|
{ |
|
|
|
@Input() private includeIndices = false; |
|
|
|
@Input() public isLoading = false; |
|
|
|
@Input() public isLoadingLocal = false; |
|
|
|
@Input() public isLoadingRemote = false; |
|
|
|
|
|
|
|
@ViewChild(MatInput) private input: MatInput; |
|
|
|
|
|
|
@ -120,29 +123,53 @@ export class GfSymbolAutocompleteComponent |
|
|
|
return isString(query) && query.length > 1; |
|
|
|
}), |
|
|
|
tap(() => { |
|
|
|
this.isLoading = true; |
|
|
|
this.isLoadingRemote = true; |
|
|
|
this.isLoadingLocal = true; |
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
|
}), |
|
|
|
debounceTime(400), |
|
|
|
distinctUntilChanged(), |
|
|
|
takeUntil(this.unsubscribeSubject), |
|
|
|
switchMap((query: string) => { |
|
|
|
return this.dataService.fetchSymbols({ |
|
|
|
switchMap((query: string) => |
|
|
|
combineLatest([ |
|
|
|
this.dataService |
|
|
|
.fetchPortfolioLookup({ |
|
|
|
query |
|
|
|
}) |
|
|
|
.pipe(startWith(undefined)), |
|
|
|
this.dataService |
|
|
|
.fetchSymbols({ |
|
|
|
query, |
|
|
|
includeIndices: this.includeIndices |
|
|
|
}); |
|
|
|
}) |
|
|
|
.pipe(startWith(undefined)) |
|
|
|
]) |
|
|
|
) |
|
|
|
) |
|
|
|
.subscribe((filteredLookupItems) => { |
|
|
|
this.filteredLookupItems = filteredLookupItems.map((lookupItem) => { |
|
|
|
const [localItems, remoteItems]: [LookupItem[], LookupItem[]] = |
|
|
|
filteredLookupItems; |
|
|
|
const uniqueItems = [ |
|
|
|
...new Map( |
|
|
|
(localItems ?? []) |
|
|
|
.concat(remoteItems ?? []) |
|
|
|
.map((item) => [item.symbol, item]) |
|
|
|
).values() |
|
|
|
]; |
|
|
|
this.filteredLookupItems = uniqueItems.map((lookupItem) => { |
|
|
|
return { |
|
|
|
...lookupItem, |
|
|
|
assetSubClassString: translate(lookupItem.assetSubClass) |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
this.isLoading = false; |
|
|
|
if (localItems !== undefined) { |
|
|
|
this.isLoadingLocal = false; |
|
|
|
} |
|
|
|
if (remoteItems !== undefined) { |
|
|
|
this.isLoadingRemote = false; |
|
|
|
} |
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
|
}); |
|
|
|