* Fix state handling of currency selector component * Update changelog
This commit is contained in:
parent
b12ac1fe84
commit
60ef46accf
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed an issue with the initial annual interest rate in the _FIRE_ calculator
|
- Fixed an issue with the initial annual interest rate in the _FIRE_ calculator
|
||||||
|
- Fixed the state handling in the currency selector
|
||||||
|
|
||||||
## 2.83.0 - 2024-05-30
|
## 2.83.0 - 2024-05-30
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import { ghostfolioScraperApiSymbolPrefix } from '@ghostfolio/common/config';
|
|||||||
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||||
import {
|
import {
|
||||||
AdminMarketDataDetails,
|
AdminMarketDataDetails,
|
||||||
Currency,
|
|
||||||
UniqueAsset
|
UniqueAsset
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { translate } from '@ghostfolio/ui/i18n';
|
import { translate } from '@ghostfolio/ui/i18n';
|
||||||
@ -73,7 +72,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
|
|||||||
public countries: {
|
public countries: {
|
||||||
[code: string]: { name: string; value: number };
|
[code: string]: { name: string; value: number };
|
||||||
};
|
};
|
||||||
public currencies: Currency[] = [];
|
public currencies: string[] = [];
|
||||||
public ghostfolioScraperApiSymbolPrefix = ghostfolioScraperApiSymbolPrefix;
|
public ghostfolioScraperApiSymbolPrefix = ghostfolioScraperApiSymbolPrefix;
|
||||||
public isBenchmark = false;
|
public isBenchmark = false;
|
||||||
public marketDataDetails: MarketData[] = [];
|
public marketDataDetails: MarketData[] = [];
|
||||||
@ -102,10 +101,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
|
|||||||
const { benchmarks, currencies } = this.dataService.fetchInfo();
|
const { benchmarks, currencies } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
this.benchmarks = benchmarks;
|
this.benchmarks = benchmarks;
|
||||||
this.currencies = currencies.map((currency) => ({
|
this.currencies = currencies;
|
||||||
label: currency,
|
|
||||||
value: currency
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
@ -293,9 +289,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
|
|||||||
assetClass: this.assetProfileForm.get('assetClass').value,
|
assetClass: this.assetProfileForm.get('assetClass').value,
|
||||||
assetSubClass: this.assetProfileForm.get('assetSubClass').value,
|
assetSubClass: this.assetProfileForm.get('assetSubClass').value,
|
||||||
comment: this.assetProfileForm.get('comment').value || null,
|
comment: this.assetProfileForm.get('comment').value || null,
|
||||||
currency: (<Currency>(
|
currency: this.assetProfileForm.get('currency').value,
|
||||||
(<unknown>this.assetProfileForm.get('currency').value)
|
|
||||||
))?.value,
|
|
||||||
name: this.assetProfileForm.get('name').value,
|
name: this.assetProfileForm.get('name').value,
|
||||||
url: this.assetProfileForm.get('url').value || null
|
url: this.assetProfileForm.get('url').value || null
|
||||||
};
|
};
|
||||||
@ -343,8 +337,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
|
|||||||
' ' +
|
' ' +
|
||||||
price +
|
price +
|
||||||
' ' +
|
' ' +
|
||||||
(<Currency>(<unknown>this.assetProfileForm.get('currency').value))
|
this.assetProfileForm.get('currency').value
|
||||||
?.value
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto
|
|||||||
import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto';
|
import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto';
|
||||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
import { validateObjectForForm } from '@ghostfolio/client/util/form.util';
|
import { validateObjectForForm } from '@ghostfolio/client/util/form.util';
|
||||||
import { Currency } from '@ghostfolio/common/interfaces';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
@ -33,7 +32,7 @@ import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces';
|
|||||||
})
|
})
|
||||||
export class CreateOrUpdateAccountDialog implements OnDestroy {
|
export class CreateOrUpdateAccountDialog implements OnDestroy {
|
||||||
public accountForm: FormGroup;
|
public accountForm: FormGroup;
|
||||||
public currencies: Currency[] = [];
|
public currencies: string[] = [];
|
||||||
public filteredPlatforms: Observable<Platform[]>;
|
public filteredPlatforms: Observable<Platform[]>;
|
||||||
public platforms: Platform[];
|
public platforms: Platform[];
|
||||||
|
|
||||||
@ -49,10 +48,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
|
|||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
const { currencies, platforms } = this.dataService.fetchInfo();
|
const { currencies, platforms } = this.dataService.fetchInfo();
|
||||||
|
|
||||||
this.currencies = currencies.map((currency) => ({
|
this.currencies = currencies;
|
||||||
label: currency,
|
|
||||||
value: currency
|
|
||||||
}));
|
|
||||||
this.platforms = platforms;
|
this.platforms = platforms;
|
||||||
|
|
||||||
this.accountForm = this.formBuilder.group({
|
this.accountForm = this.formBuilder.group({
|
||||||
@ -107,7 +103,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
|
|||||||
const account: CreateAccountDto | UpdateAccountDto = {
|
const account: CreateAccountDto | UpdateAccountDto = {
|
||||||
balance: this.accountForm.get('balance').value,
|
balance: this.accountForm.get('balance').value,
|
||||||
comment: this.accountForm.get('comment').value || null,
|
comment: this.accountForm.get('comment').value || null,
|
||||||
currency: this.accountForm.get('currency').value?.value,
|
currency: this.accountForm.get('currency').value,
|
||||||
id: this.accountForm.get('accountId').value,
|
id: this.accountForm.get('accountId').value,
|
||||||
isExcluded: this.accountForm.get('isExcluded').value,
|
isExcluded: this.accountForm.get('isExcluded').value,
|
||||||
name: this.accountForm.get('name').value,
|
name: this.accountForm.get('name').value,
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export interface Currency {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
@ -11,7 +11,6 @@ import type { BenchmarkMarketDataDetails } from './benchmark-market-data-details
|
|||||||
import type { BenchmarkProperty } from './benchmark-property.interface';
|
import type { BenchmarkProperty } from './benchmark-property.interface';
|
||||||
import type { Benchmark } from './benchmark.interface';
|
import type { Benchmark } from './benchmark.interface';
|
||||||
import type { Coupon } from './coupon.interface';
|
import type { Coupon } from './coupon.interface';
|
||||||
import type { Currency } from './currency.interface';
|
|
||||||
import type { DataProviderInfo } from './data-provider-info.interface';
|
import type { DataProviderInfo } from './data-provider-info.interface';
|
||||||
import type { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface';
|
import type { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface';
|
||||||
import type { Export } from './export.interface';
|
import type { Export } from './export.interface';
|
||||||
@ -66,7 +65,6 @@ export {
|
|||||||
BenchmarkProperty,
|
BenchmarkProperty,
|
||||||
BenchmarkResponse,
|
BenchmarkResponse,
|
||||||
Coupon,
|
Coupon,
|
||||||
Currency,
|
|
||||||
DataProviderInfo,
|
DataProviderInfo,
|
||||||
EnhancedSymbolProfile,
|
EnhancedSymbolProfile,
|
||||||
Export,
|
Export,
|
||||||
|
@ -8,12 +8,11 @@
|
|||||||
|
|
||||||
<mat-autocomplete
|
<mat-autocomplete
|
||||||
#currencyAutocomplete="matAutocomplete"
|
#currencyAutocomplete="matAutocomplete"
|
||||||
[displayWith]="displayFn"
|
|
||||||
(optionSelected)="onUpdateCurrency($event)"
|
(optionSelected)="onUpdateCurrency($event)"
|
||||||
>
|
>
|
||||||
@for (currencyItem of filteredCurrencies; track currencyItem) {
|
@for (currency of filteredCurrencies; track currency) {
|
||||||
<mat-option class="line-height-1" [value]="currencyItem">
|
<mat-option class="line-height-1" [value]="currency">
|
||||||
{{ currencyItem.label }}
|
{{ currency }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
}
|
}
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { Currency } from '@ghostfolio/common/interfaces';
|
|
||||||
import { AbstractMatFormField } from '@ghostfolio/ui/shared/abstract-mat-form-field';
|
import { AbstractMatFormField } from '@ghostfolio/ui/shared/abstract-mat-form-field';
|
||||||
|
|
||||||
import { FocusMonitor } from '@angular/cdk/a11y';
|
import { FocusMonitor } from '@angular/cdk/a11y';
|
||||||
@ -59,10 +58,10 @@ import { map, startWith, takeUntil } from 'rxjs/operators';
|
|||||||
templateUrl: 'currency-selector.component.html'
|
templateUrl: 'currency-selector.component.html'
|
||||||
})
|
})
|
||||||
export class GfCurrencySelectorComponent
|
export class GfCurrencySelectorComponent
|
||||||
extends AbstractMatFormField<Currency>
|
extends AbstractMatFormField<string>
|
||||||
implements OnInit, OnDestroy
|
implements OnInit, OnDestroy
|
||||||
{
|
{
|
||||||
@Input() private currencies: Currency[] = [];
|
@Input() private currencies: string[] = [];
|
||||||
@Input() private formControlName: string;
|
@Input() private formControlName: string;
|
||||||
|
|
||||||
@ViewChild(MatInput) private input: MatInput;
|
@ViewChild(MatInput) private input: MatInput;
|
||||||
@ -71,7 +70,7 @@ export class GfCurrencySelectorComponent
|
|||||||
public currencyAutocomplete: MatAutocomplete;
|
public currencyAutocomplete: MatAutocomplete;
|
||||||
|
|
||||||
public control = new FormControl();
|
public control = new FormControl();
|
||||||
public filteredCurrencies: Currency[] = [];
|
public filteredCurrencies: string[] = [];
|
||||||
|
|
||||||
private unsubscribeSubject = new Subject<void>();
|
private unsubscribeSubject = new Subject<void>();
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ export class GfCurrencySelectorComponent
|
|||||||
const control = formGroup.get(this.formControlName);
|
const control = formGroup.get(this.formControlName);
|
||||||
|
|
||||||
if (control) {
|
if (control) {
|
||||||
this.value = this.currencies.find(({ value }) => {
|
this.value = this.currencies.find((value) => {
|
||||||
return value === control.value;
|
return value === control.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -107,8 +106,8 @@ export class GfCurrencySelectorComponent
|
|||||||
this.control.valueChanges
|
this.control.valueChanges
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
if (super.value?.value) {
|
if (super.value) {
|
||||||
super.value.value = null;
|
super.value = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -125,10 +124,6 @@ export class GfCurrencySelectorComponent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public displayFn(currency: Currency) {
|
|
||||||
return currency?.label ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public get empty() {
|
public get empty() {
|
||||||
return this.input?.empty;
|
return this.input?.empty;
|
||||||
}
|
}
|
||||||
@ -146,17 +141,12 @@ export class GfCurrencySelectorComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onUpdateCurrency(event: MatAutocompleteSelectedEvent) {
|
public onUpdateCurrency(event: MatAutocompleteSelectedEvent) {
|
||||||
super.value = {
|
super.value = event.option.value;
|
||||||
label: event.option.value.label,
|
|
||||||
value: event.option.value.value
|
|
||||||
} as Currency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public set value(value: Currency) {
|
public set value(value: string) {
|
||||||
const newValue =
|
this.control.setValue(value);
|
||||||
typeof value === 'object' && value !== null ? { ...value } : value;
|
super.value = value;
|
||||||
this.control.setValue(newValue);
|
|
||||||
super.value = newValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
public ngOnDestroy() {
|
||||||
@ -166,21 +156,16 @@ export class GfCurrencySelectorComponent
|
|||||||
this.unsubscribeSubject.complete();
|
this.unsubscribeSubject.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private filter(value: Currency | string) {
|
private filter(value: string) {
|
||||||
const filterValue =
|
const filterValue = value?.toLowerCase();
|
||||||
typeof value === 'string'
|
|
||||||
? value?.toLowerCase()
|
|
||||||
: value?.value.toLowerCase();
|
|
||||||
|
|
||||||
return this.currencies.filter((currency) => {
|
return this.currencies.filter((currency) => {
|
||||||
return currency.value.toLowerCase().startsWith(filterValue);
|
return currency.toLowerCase().startsWith(filterValue);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateRequired() {
|
private validateRequired() {
|
||||||
const requiredCheck = super.required
|
const requiredCheck = super.required ? !super.value : false;
|
||||||
? !super.value?.label || !super.value?.value
|
|
||||||
: false;
|
|
||||||
|
|
||||||
if (requiredCheck) {
|
if (requiredCheck) {
|
||||||
this.ngControl.control.setErrors({ invalidData: true });
|
this.ngControl.control.setErrors({ invalidData: true });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user