Browse Source

Bugfix/improve symbol lookup (#322)

* Improve symbol lookup

* Update changelog
pull/323/head
Thomas Kaul 3 years ago
committed by GitHub
parent
commit
6386786ac0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 12
      apps/api/src/app/symbol/symbol.controller.ts
  3. 6
      apps/api/src/app/symbol/symbol.service.ts
  4. 50
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts
  5. 2
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html

1
CHANGELOG.md

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Filtered out positions without any quantity in the positions table
- Improved the symbol lookup: allow saving with valid symbol in create or edit transaction dialog
## 1.43.0 - 24.08.2021

12
apps/api/src/app/symbol/symbol.controller.ts

@ -11,6 +11,7 @@ import {
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { isEmpty } from 'lodash';
import { LookupItem } from './interfaces/lookup-item.interface';
import { SymbolItem } from './interfaces/symbol-item.interface';
@ -48,6 +49,15 @@ export class SymbolController {
@Get(':symbol')
@UseGuards(AuthGuard('jwt'))
public async getPosition(@Param('symbol') symbol): Promise<SymbolItem> {
return this.symbolService.get(symbol);
const result = await this.symbolService.get(symbol);
if (!result || isEmpty(result)) {
throw new HttpException(
getReasonPhrase(StatusCodes.NOT_FOUND),
StatusCodes.NOT_FOUND
);
}
return result;
}
}

6
apps/api/src/app/symbol/symbol.service.ts

@ -15,8 +15,9 @@ export class SymbolService {
public async get(aSymbol: string): Promise<SymbolItem> {
const response = await this.dataProviderService.get([aSymbol]);
const { currency, dataSource, marketPrice } = response[aSymbol];
const { currency, dataSource, marketPrice } = response[aSymbol] ?? {};
if (currency && dataSource && marketPrice) {
return {
dataSource,
marketPrice,
@ -24,6 +25,9 @@ export class SymbolService {
};
}
return undefined;
}
public async lookup(aQuery: string): Promise<{ items: LookupItem[] }> {
const results: { items: LookupItem[] } = { items: [] };

50
apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts

@ -11,8 +11,9 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { DataService } from '@ghostfolio/client/services/data.service';
import { Currency } from '@prisma/client';
import { Observable, Subject } from 'rxjs';
import { EMPTY, Observable, Subject } from 'rxjs';
import {
catchError,
debounceTime,
distinctUntilChanged,
startWith,
@ -49,7 +50,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
@Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateTransactionDialogParams
) {}
ngOnInit() {
public ngOnInit() {
const { currencies, platforms } = this.dataService.fetchInfo();
this.currencies = currencies;
@ -84,17 +85,45 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
this.data.transaction.unitPrice = this.currentMarketPrice;
}
public onBlurSymbol() {
const symbol = this.searchSymbolCtrl.value;
this.updateSymbol(symbol);
}
public onCancel(): void {
this.dialogRef.close();
}
public onUpdateSymbol(event: MatAutocompleteSelectedEvent) {
this.updateSymbol(event.option.value);
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private updateSymbol(symbol: string) {
this.isLoading = true;
this.data.transaction.symbol = event.option.value;
this.data.transaction.symbol = symbol;
this.dataService
.fetchSymbolItem(this.data.transaction.symbol)
.pipe(takeUntil(this.unsubscribeSubject))
.pipe(
catchError(() => {
this.data.transaction.currency = null;
this.data.transaction.dataSource = null;
this.data.transaction.unitPrice = null;
this.isLoading = false;
this.changeDetectorRef.markForCheck();
return EMPTY;
}),
takeUntil(this.unsubscribeSubject)
)
.subscribe(({ currency, dataSource, marketPrice }) => {
this.data.transaction.currency = currency;
this.data.transaction.dataSource = dataSource;
@ -105,17 +134,4 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
this.changeDetectorRef.markForCheck();
});
}
public onUpdateSymbolByTyping(value: string) {
this.data.transaction.currency = null;
this.data.transaction.dataSource = null;
this.data.transaction.unitPrice = null;
this.data.transaction.symbol = value;
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
}

2
apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html

@ -29,7 +29,7 @@
required
[formControl]="searchSymbolCtrl"
[matAutocomplete]="auto"
(change)="onUpdateSymbolByTyping($event.target.value)"
(blur)="onBlurSymbol()"
/>
<mat-autocomplete
#auto="matAutocomplete"

Loading…
Cancel
Save