From 32df7620d90c65102e97d9495eb60955b2bb2373 Mon Sep 17 00:00:00 2001 From: Manushreshta B L <77065548+M27afk@users.noreply.github.com> Date: Tue, 17 Oct 2023 22:03:22 +0530 Subject: [PATCH] Add support for creating asset profiles with MANUAL data source (#2479) * Add support for creating asset profiles with MANUAL data source * Refactoring * Update changelog --------- Co-authored-by: Thomas <4159106+dtslvr@users.noreply.github.com> --- CHANGELOG.md | 1 + apps/api/src/app/admin/admin.controller.ts | 7 ++- apps/api/src/app/admin/admin.service.ts | 11 +++- ...create-asset-profile-dialog.component.scss | 3 + .../create-asset-profile-dialog.component.ts | 62 +++++++++++++++---- .../create-asset-profile-dialog.html | 38 +++++++++--- .../create-asset-profile-dialog.module.ts | 4 ++ 7 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.scss diff --git a/CHANGELOG.md b/CHANGELOG.md index ba9a7d75..2c3f4dd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added the endpoint `GET api/v1/account/:id/balances` which provides historical cash balances - Added support to search for an asset profile by `isin`, `name` and `symbol` as an administrator (experimental) +- Added support for creating asset profiles with `MANUAL` data source ### Changed diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 30270d0c..a19b17d4 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -398,8 +398,11 @@ export class AdminController { StatusCodes.FORBIDDEN ); } - - return this.adminService.addAssetProfile({ dataSource, symbol }); + return this.adminService.addAssetProfile({ + dataSource, + symbol, + currency: this.request.user.Settings.settings.baseCurrency + }); } @Delete('profile-data/:dataSource/:symbol') diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index 173854ea..84ae5934 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -41,10 +41,19 @@ export class AdminService { ) {} public async addAssetProfile({ + currency, dataSource, symbol - }: UniqueAsset): Promise { + }: UniqueAsset & { currency?: string }): Promise { try { + if (dataSource === 'MANUAL') { + return this.symbolProfileService.add({ + currency, + dataSource, + symbol + }); + } + const assetProfiles = await this.dataProviderService.getAssetProfiles([ { dataSource, symbol } ]); diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.scss b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.scss new file mode 100644 index 00000000..5d4e87f3 --- /dev/null +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts index c3c2fb2e..eea8898c 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts @@ -1,15 +1,15 @@ import { ChangeDetectionStrategy, - ChangeDetectorRef, Component, - Inject, OnDestroy, OnInit } from '@angular/core'; import { + AbstractControl, FormBuilder, FormControl, FormGroup, + ValidationErrors, Validators } from '@angular/forms'; import { MatDialogRef } from '@angular/material/dialog'; @@ -19,35 +19,75 @@ import { AdminService } from '@ghostfolio/client/services/admin.service'; changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, selector: 'gf-create-asset-profile-dialog', + styleUrls: ['./create-asset-profile-dialog.component.scss'], templateUrl: 'create-asset-profile-dialog.html' }) export class CreateAssetProfileDialog implements OnInit, OnDestroy { public createAssetProfileForm: FormGroup; + public mode: 'auto' | 'manual'; public constructor( public readonly adminService: AdminService, - public readonly changeDetectorRef: ChangeDetectorRef, public readonly dialogRef: MatDialogRef, public readonly formBuilder: FormBuilder ) {} public ngOnInit() { - this.createAssetProfileForm = this.formBuilder.group({ - searchSymbol: new FormControl(null, [Validators.required]) - }); + this.createAssetProfileForm = this.formBuilder.group( + { + addSymbol: new FormControl(null, [Validators.required]), + searchSymbol: new FormControl(null, [Validators.required]) + }, + { + validators: this.atLeastOneValid + } + ); + + this.mode = 'auto'; } public onCancel() { this.dialogRef.close(); } + public onRadioChange(mode: 'auto' | 'manual') { + this.mode = mode; + } + public onSubmit() { - this.dialogRef.close({ - dataSource: - this.createAssetProfileForm.controls['searchSymbol'].value.dataSource, - symbol: this.createAssetProfileForm.controls['searchSymbol'].value.symbol - }); + this.mode === 'auto' + ? this.dialogRef.close({ + dataSource: + this.createAssetProfileForm.controls['searchSymbol'].value + .dataSource, + symbol: + this.createAssetProfileForm.controls['searchSymbol'].value.symbol + }) + : this.dialogRef.close({ + dataSource: 'MANUAL', + symbol: this.createAssetProfileForm.controls['addSymbol'].value + }); } public ngOnDestroy() {} + + private atLeastOneValid(control: AbstractControl): ValidationErrors { + const addSymbolControl = control.get('addSymbol'); + const searchSymbolControl = control.get('searchSymbol'); + + if (addSymbolControl.valid && searchSymbolControl.valid) { + return { atLeastOneValid: true }; + } + + if ( + addSymbolControl.valid || + !addSymbolControl || + searchSymbolControl.valid || + !searchSymbolControl + ) { + return { atLeastOneValid: false }; + } + + return { atLeastOneValid: true }; + } } diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html index 43eadf93..e7ed9352 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6,13 +6,35 @@ >

Add Asset Profile

- - Name, symbol or ISIN - - +
+ + + + + + + +
+ +
+ + Name, symbol or ISIN + + +
+
+ + Symbol + + +
@@ -20,7 +42,7 @@ color="primary" mat-flat-button type="submit" - [disabled]="!createAssetProfileForm.valid" + [disabled]="createAssetProfileForm.hasError('atLeastOneValid')" > Save diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts index e99d8f78..2d50200c 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts @@ -4,6 +4,8 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatRadioModule } from '@angular/material/radio'; import { GfSymbolAutocompleteModule } from '@ghostfolio/ui/symbol-autocomplete'; import { CreateAssetProfileDialog } from './create-asset-profile-dialog.component'; @@ -17,6 +19,8 @@ import { CreateAssetProfileDialog } from './create-asset-profile-dialog.componen MatDialogModule, MatButtonModule, MatFormFieldModule, + MatInputModule, + MatRadioModule, ReactiveFormsModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA]