|
|
@ -3,6 +3,7 @@ import { |
|
|
ghostfolioPrefix, |
|
|
ghostfolioPrefix, |
|
|
PROPERTY_CURRENCIES |
|
|
PROPERTY_CURRENCIES |
|
|
} from '@ghostfolio/common/config'; |
|
|
} from '@ghostfolio/common/config'; |
|
|
|
|
|
import type { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; |
|
|
import { AdminService, DataService } from '@ghostfolio/ui/services'; |
|
|
import { AdminService, DataService } from '@ghostfolio/ui/services'; |
|
|
import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; |
|
|
import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; |
|
|
|
|
|
|
|
|
@ -11,6 +12,7 @@ import { |
|
|
ChangeDetectorRef, |
|
|
ChangeDetectorRef, |
|
|
Component, |
|
|
Component, |
|
|
DestroyRef, |
|
|
DestroyRef, |
|
|
|
|
|
inject, |
|
|
OnInit |
|
|
OnInit |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
@ -18,7 +20,6 @@ import { |
|
|
AbstractControl, |
|
|
AbstractControl, |
|
|
FormBuilder, |
|
|
FormBuilder, |
|
|
FormControl, |
|
|
FormControl, |
|
|
FormGroup, |
|
|
|
|
|
FormsModule, |
|
|
FormsModule, |
|
|
ReactiveFormsModule, |
|
|
ReactiveFormsModule, |
|
|
ValidationErrors, |
|
|
ValidationErrors, |
|
|
@ -34,7 +35,10 @@ import { DataSource } from '@prisma/client'; |
|
|
import { isISO4217CurrencyCode } from 'class-validator'; |
|
|
import { isISO4217CurrencyCode } from 'class-validator'; |
|
|
import { switchMap } from 'rxjs'; |
|
|
import { switchMap } from 'rxjs'; |
|
|
|
|
|
|
|
|
import { CreateAssetProfileDialogMode } from './interfaces/interfaces'; |
|
|
import type { |
|
|
|
|
|
CreateAssetProfileDialogMode, |
|
|
|
|
|
CreateAssetProfileForm |
|
|
|
|
|
} from './interfaces/interfaces'; |
|
|
|
|
|
|
|
|
@Component({ |
|
|
@Component({ |
|
|
changeDetection: ChangeDetectionStrategy.OnPush, |
|
|
changeDetection: ChangeDetectionStrategy.OnPush, |
|
|
@ -54,32 +58,44 @@ import { CreateAssetProfileDialogMode } from './interfaces/interfaces'; |
|
|
templateUrl: 'create-asset-profile-dialog.html' |
|
|
templateUrl: 'create-asset-profile-dialog.html' |
|
|
}) |
|
|
}) |
|
|
export class GfCreateAssetProfileDialogComponent implements OnInit { |
|
|
export class GfCreateAssetProfileDialogComponent implements OnInit { |
|
|
public createAssetProfileForm: FormGroup; |
|
|
protected createAssetProfileForm: CreateAssetProfileForm; |
|
|
public ghostfolioPrefix = `${ghostfolioPrefix}_`; |
|
|
protected readonly ghostfolioPrefix = `${ghostfolioPrefix}_`; |
|
|
public mode: CreateAssetProfileDialogMode; |
|
|
protected mode: CreateAssetProfileDialogMode; |
|
|
|
|
|
|
|
|
private customCurrencies: string[]; |
|
|
private customCurrencies: string[]; |
|
|
private dataSourceForExchangeRates: DataSource; |
|
|
private dataSourceForExchangeRates: DataSource; |
|
|
|
|
|
|
|
|
public constructor( |
|
|
private readonly adminService = inject(AdminService); |
|
|
public readonly adminService: AdminService, |
|
|
private readonly changeDetectorRef = inject(ChangeDetectorRef); |
|
|
private readonly changeDetectorRef: ChangeDetectorRef, |
|
|
private readonly dataService = inject(DataService); |
|
|
private readonly dataService: DataService, |
|
|
private readonly destroyRef = inject(DestroyRef); |
|
|
private readonly destroyRef: DestroyRef, |
|
|
private readonly dialogRef = |
|
|
public readonly dialogRef: MatDialogRef<GfCreateAssetProfileDialogComponent>, |
|
|
inject<MatDialogRef<GfCreateAssetProfileDialogComponent>>(MatDialogRef); |
|
|
public readonly formBuilder: FormBuilder |
|
|
private readonly formBuilder = inject(FormBuilder); |
|
|
) {} |
|
|
|
|
|
|
|
|
protected get showCurrencyErrorMessage() { |
|
|
|
|
|
const addCurrencyFormControl = |
|
|
|
|
|
this.createAssetProfileForm.controls.addCurrency; |
|
|
|
|
|
|
|
|
|
|
|
if (addCurrencyFormControl.hasError('invalidCurrency')) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public ngOnInit() { |
|
|
public ngOnInit() { |
|
|
this.initialize(); |
|
|
this.initialize(); |
|
|
|
|
|
|
|
|
this.createAssetProfileForm = this.formBuilder.group( |
|
|
this.createAssetProfileForm = this.formBuilder.group( |
|
|
{ |
|
|
{ |
|
|
addCurrency: new FormControl(null, [ |
|
|
addCurrency: new FormControl<string | null>(null, [ |
|
|
this.iso4217CurrencyCodeValidator() |
|
|
this.iso4217CurrencyCodeValidator() |
|
|
]), |
|
|
]), |
|
|
addSymbol: new FormControl(null, [Validators.required]), |
|
|
addSymbol: new FormControl<string | null>(null, [Validators.required]), |
|
|
searchSymbol: new FormControl(null, [Validators.required]) |
|
|
searchSymbol: new FormControl<AssetProfileIdentifier | null>(null, [ |
|
|
|
|
|
Validators.required |
|
|
|
|
|
]) |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
validators: this.atLeastOneValid |
|
|
validators: this.atLeastOneValid |
|
|
@ -104,12 +120,11 @@ export class GfCreateAssetProfileDialogComponent implements OnInit { |
|
|
this.dialogRef.close({ |
|
|
this.dialogRef.close({ |
|
|
addAssetProfile: true, |
|
|
addAssetProfile: true, |
|
|
dataSource: |
|
|
dataSource: |
|
|
this.createAssetProfileForm.get('searchSymbol').value.dataSource, |
|
|
this.createAssetProfileForm.controls.searchSymbol.value?.dataSource, |
|
|
symbol: this.createAssetProfileForm.get('searchSymbol').value.symbol |
|
|
symbol: this.createAssetProfileForm.controls.searchSymbol.value?.symbol |
|
|
}); |
|
|
}); |
|
|
} else if (this.mode === 'currency') { |
|
|
} else if (this.mode === 'currency') { |
|
|
const currency = this.createAssetProfileForm.get('addCurrency') |
|
|
const currency = this.createAssetProfileForm.controls.addCurrency.value; |
|
|
.value as string; |
|
|
|
|
|
|
|
|
|
|
|
const currencies = Array.from( |
|
|
const currencies = Array.from( |
|
|
new Set([...this.customCurrencies, currency]) |
|
|
new Set([...this.customCurrencies, currency]) |
|
|
@ -139,26 +154,15 @@ export class GfCreateAssetProfileDialogComponent implements OnInit { |
|
|
this.dialogRef.close({ |
|
|
this.dialogRef.close({ |
|
|
addAssetProfile: true, |
|
|
addAssetProfile: true, |
|
|
dataSource: 'MANUAL', |
|
|
dataSource: 'MANUAL', |
|
|
symbol: `${this.ghostfolioPrefix}${this.createAssetProfileForm.get('addSymbol').value}` |
|
|
symbol: `${this.ghostfolioPrefix}${this.createAssetProfileForm.controls.addSymbol.value}` |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public get showCurrencyErrorMessage() { |
|
|
private atLeastOneValid(control: CreateAssetProfileForm): ValidationErrors { |
|
|
const addCurrencyFormControl = |
|
|
const addCurrencyControl = control.controls.addCurrency; |
|
|
this.createAssetProfileForm.get('addCurrency'); |
|
|
const addSymbolControl = control.controls.addSymbol; |
|
|
|
|
|
const searchSymbolControl = control.controls.searchSymbol; |
|
|
if (addCurrencyFormControl.hasError('invalidCurrency')) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private atLeastOneValid(control: AbstractControl): ValidationErrors { |
|
|
|
|
|
const addCurrencyControl = control.get('addCurrency'); |
|
|
|
|
|
const addSymbolControl = control.get('addSymbol'); |
|
|
|
|
|
const searchSymbolControl = control.get('searchSymbol'); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
if ( |
|
|
addCurrencyControl.valid && |
|
|
addCurrencyControl.valid && |
|
|
@ -170,11 +174,8 @@ export class GfCreateAssetProfileDialogComponent implements OnInit { |
|
|
|
|
|
|
|
|
if ( |
|
|
if ( |
|
|
addCurrencyControl.valid || |
|
|
addCurrencyControl.valid || |
|
|
!addCurrencyControl || |
|
|
|
|
|
addSymbolControl.valid || |
|
|
addSymbolControl.valid || |
|
|
!addSymbolControl || |
|
|
searchSymbolControl.valid |
|
|
searchSymbolControl.valid || |
|
|
|
|
|
!searchSymbolControl |
|
|
|
|
|
) { |
|
|
) { |
|
|
return { atLeastOneValid: false }; |
|
|
return { atLeastOneValid: false }; |
|
|
} |
|
|
} |
|
|
@ -189,11 +190,14 @@ export class GfCreateAssetProfileDialogComponent implements OnInit { |
|
|
.subscribe(({ dataProviders, settings }) => { |
|
|
.subscribe(({ dataProviders, settings }) => { |
|
|
this.customCurrencies = settings[PROPERTY_CURRENCIES] as string[]; |
|
|
this.customCurrencies = settings[PROPERTY_CURRENCIES] as string[]; |
|
|
|
|
|
|
|
|
const { dataSource } = dataProviders.find(({ useForExchangeRates }) => { |
|
|
const { dataSource } = |
|
|
return useForExchangeRates; |
|
|
dataProviders.find(({ useForExchangeRates }) => { |
|
|
}); |
|
|
return useForExchangeRates; |
|
|
|
|
|
}) ?? {}; |
|
|
|
|
|
|
|
|
this.dataSourceForExchangeRates = dataSource; |
|
|
if (dataSource) { |
|
|
|
|
|
this.dataSourceForExchangeRates = dataSource; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.changeDetectorRef.markForCheck(); |
|
|
this.changeDetectorRef.markForCheck(); |
|
|
}); |
|
|
}); |
|
|
|