From 0af37ca1d769b8f6d55f7443424b6bf1d5a2cb63 Mon Sep 17 00:00:00 2001 From: Aldrin <53973174+Dhoni77@users.noreply.github.com> Date: Wed, 25 Oct 2023 23:58:51 +0530 Subject: [PATCH] Extend asset profile dialog form (#2535) * Extend asset profile dialog form * Update changelog --- CHANGELOG.md | 4 ++ apps/api/src/app/admin/admin.service.ts | 6 +++ .../src/app/admin/update-asset-profile.dto.ts | 16 ++++++- .../symbol-profile/symbol-profile.service.ts | 12 +++++- .../asset-profile-dialog.component.ts | 36 ++++++++++++---- .../asset-profile-dialog.html | 42 +++++++++++++++++-- .../asset-profile-dialog.module.ts | 2 + apps/client/src/app/services/admin.service.ts | 12 +++++- 8 files changed, 115 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd02ca318..9a6074cfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added support to edit the name, asset class and asset sub class of asset profiles with `MANUAL` data source in the asset profile details dialog of the admin control panel + ### Changed - Improved the style and wording of the position detail dialog diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index 84ae5934c..a42723ba3 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -303,15 +303,21 @@ export class AdminService { } public async patchAssetProfileData({ + assetClass, + assetSubClass, comment, dataSource, + name, scraperConfiguration, symbol, symbolMapping }: Prisma.SymbolProfileUpdateInput & UniqueAsset) { await this.symbolProfileService.updateSymbolProfile({ + assetClass, + assetSubClass, comment, dataSource, + name, scraperConfiguration, symbol, symbolMapping diff --git a/apps/api/src/app/admin/update-asset-profile.dto.ts b/apps/api/src/app/admin/update-asset-profile.dto.ts index 54f2d8f25..a39f8db81 100644 --- a/apps/api/src/app/admin/update-asset-profile.dto.ts +++ b/apps/api/src/app/admin/update-asset-profile.dto.ts @@ -1,11 +1,23 @@ -import { Prisma } from '@prisma/client'; -import { IsObject, IsOptional, IsString } from 'class-validator'; +import { AssetClass, AssetSubClass, Prisma } from '@prisma/client'; +import { IsEnum, IsObject, IsOptional, IsString } from 'class-validator'; export class UpdateAssetProfileDto { + @IsEnum(AssetClass, { each: true }) + @IsOptional() + assetClass?: AssetClass; + + @IsEnum(AssetSubClass, { each: true }) + @IsOptional() + assetSubClass?: AssetSubClass; + @IsString() @IsOptional() comment?: string; + @IsString() + @IsOptional() + name?: string; + @IsObject() @IsOptional() scraperConfiguration?: Prisma.InputJsonObject; diff --git a/apps/api/src/services/symbol-profile/symbol-profile.service.ts b/apps/api/src/services/symbol-profile/symbol-profile.service.ts index b861ccf8f..46a6991cb 100644 --- a/apps/api/src/services/symbol-profile/symbol-profile.service.ts +++ b/apps/api/src/services/symbol-profile/symbol-profile.service.ts @@ -86,14 +86,24 @@ export class SymbolProfileService { } public updateSymbolProfile({ + assetClass, + assetSubClass, comment, dataSource, + name, scraperConfiguration, symbol, symbolMapping }: Prisma.SymbolProfileUpdateInput & UniqueAsset) { return this.prismaService.symbolProfile.update({ - data: { comment, scraperConfiguration, symbolMapping }, + data: { + assetClass, + assetSubClass, + comment, + name, + scraperConfiguration, + symbolMapping + }, where: { dataSource_symbol: { dataSource, symbol } } }); } diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index ccb6f3ccd..c5c2db17a 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -6,7 +6,7 @@ import { OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; +import { FormBuilder, FormControl, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { UpdateAssetProfileDto } from '@ghostfolio/api/app/admin/update-asset-profile.dto'; import { AdminService } from '@ghostfolio/client/services/admin.service'; @@ -17,7 +17,12 @@ import { UniqueAsset } from '@ghostfolio/common/interfaces'; import { translate } from '@ghostfolio/ui/i18n'; -import { MarketData, SymbolProfile } from '@prisma/client'; +import { + AssetClass, + AssetSubClass, + MarketData, + SymbolProfile +} from '@prisma/client'; import { format, parseISO } from 'date-fns'; import { parse as csvToJson } from 'papaparse'; import { Subject } from 'rxjs'; @@ -33,14 +38,23 @@ import { AssetProfileDialogParams } from './interfaces/interfaces'; styleUrls: ['./asset-profile-dialog.component.scss'] }) export class AssetProfileDialog implements OnDestroy, OnInit { - public assetClass: string; + public assetProfileClass: string; + public assetClasses = Object.keys(AssetClass).map((assetClass) => { + return { id: assetClass, label: translate(assetClass) }; + }); + public assetSubClasses = Object.keys(AssetSubClass).map((assetSubClass) => { + return { id: assetSubClass, label: translate(assetSubClass) }; + }); public assetProfile: AdminMarketDataDetails['assetProfile']; public assetProfileForm = this.formBuilder.group({ + assetClass: new FormControl(undefined), + assetSubClass: new FormControl(undefined), comment: '', + name: ['', Validators.required], scraperConfiguration: '', symbolMapping: '' }); - public assetSubClass: string; + public assetProfileSubClass: string; public benchmarks: Partial[]; public countries: { [code: string]: { name: string; value: number }; @@ -86,8 +100,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit { .subscribe(({ assetProfile, marketData }) => { this.assetProfile = assetProfile; - this.assetClass = translate(this.assetProfile?.assetClass); - this.assetSubClass = translate(this.assetProfile?.assetSubClass); + this.assetProfileClass = translate(this.assetProfile?.assetClass); + this.assetProfileSubClass = translate(this.assetProfile?.assetSubClass); this.countries = {}; this.isBenchmark = this.benchmarks.some(({ id }) => { return id === this.assetProfile.id; @@ -114,6 +128,9 @@ export class AssetProfileDialog implements OnDestroy, OnInit { } this.assetProfileForm.setValue({ + name: this.assetProfile.name, + assetClass: this.assetProfile.assetClass, + assetSubClass: this.assetProfile.assetSubClass, comment: this.assetProfile?.comment ?? '', scraperConfiguration: JSON.stringify( this.assetProfile?.scraperConfiguration ?? {} @@ -204,9 +221,12 @@ export class AssetProfileDialog implements OnDestroy, OnInit { } catch {} const assetProfileData: UpdateAssetProfileDto = { + assetClass: this.assetProfileForm.controls['assetClass'].value, + assetSubClass: this.assetProfileForm.controls['assetSubClass'].value, + comment: this.assetProfileForm.controls['comment'].value ?? null, + name: this.assetProfileForm.controls['name'].value, scraperConfiguration, - symbolMapping, - comment: this.assetProfileForm.controls['comment'].value ?? null + symbolMapping }; this.adminService diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html index 66d00e720..755768209 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -112,7 +112,11 @@ >
- Asset Class
@@ -120,8 +124,8 @@ Asset Sub Class @@ -174,6 +178,38 @@ +
+ + Name + + +
+
+ + Asset Class + + + {{ assetClass.label }} + + +
+
+ + Asset Sub Class + + + {{ assetSubClass.label }} + + +
( `/api/v1/admin/profile-data/${dataSource}/${symbol}`, - { comment, scraperConfiguration, symbolMapping } + { + assetClass, + assetSubClass, + comment, + name, + scraperConfiguration, + symbolMapping + } ); }