From c202671287889bc571844c5c1c67b88a1c5cbd74 Mon Sep 17 00:00:00 2001 From: Omkar Gujja <67428719+omkarg01@users.noreply.github.com> Date: Wed, 8 Apr 2026 00:00:14 +0530 Subject: [PATCH] Task/allow editing country and sector data for all assets (#6284) * Allow editing country and sector data for all assets * Update changelog --- CHANGELOG.md | 7 +++ apps/api/src/app/admin/admin.service.ts | 6 +-- .../asset-profile-dialog.component.ts | 10 ++-- .../asset-profile-dialog.html | 46 +++++++++---------- libs/common/src/lib/utils/form.util.ts | 13 +++++- libs/common/src/lib/utils/index.ts | 4 +- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6624570cf..53a358dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Extended the asset profile details dialog in the admin control panel to support editing countries for all asset types +- Extended the asset profile details dialog in the admin control panel to support editing sectors for all asset types + ## 2.253.0 - 2026-03-06 ### Added diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index d2bf6e411..27abb6254 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -625,23 +625,23 @@ export class AdminService { const symbolProfileOverrides = { assetClass: assetClass as AssetClass, assetSubClass: assetSubClass as AssetSubClass, + countries: countries as Prisma.JsonArray, name: name as string, + sectors: sectors as Prisma.JsonArray, url: url as string }; const updatedSymbolProfile: Prisma.SymbolProfileUpdateInput = { comment, - countries, currency, dataSource, holdings, isActive, scraperConfiguration, - sectors, symbol, symbolMapping, ...(dataSource === 'MANUAL' - ? { assetClass, assetSubClass, name, url } + ? { assetClass, assetSubClass, countries, name, sectors, url } : { SymbolProfileOverrides: { upsert: { 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 c0af46e22..6e2dab956 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 @@ -19,7 +19,7 @@ import { User } from '@ghostfolio/common/interfaces'; import { DateRange } from '@ghostfolio/common/types'; -import { validateObjectForForm } from '@ghostfolio/common/utils'; +import { jsonValidator, validateObjectForForm } from '@ghostfolio/common/utils'; import { GfCurrencySelectorComponent } from '@ghostfolio/ui/currency-selector'; import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; import { GfHistoricalMarketDataEditorComponent } from '@ghostfolio/ui/historical-market-data-editor'; @@ -149,7 +149,7 @@ export class GfAssetProfileDialogComponent implements OnInit { assetClass: new FormControl(undefined), assetSubClass: new FormControl(undefined), comment: '', - countries: '', + countries: ['', jsonValidator()], currency: '', historicalData: this.formBuilder.group({ csvString: '' @@ -158,14 +158,14 @@ export class GfAssetProfileDialogComponent implements OnInit { name: ['', Validators.required], scraperConfiguration: this.formBuilder.group({ defaultMarketPrice: null, - headers: JSON.stringify({}), + headers: [JSON.stringify({}), jsonValidator()], locale: '', mode: '', selector: '', url: '' }), - sectors: '', - symbolMapping: '', + sectors: ['', jsonValidator()], + symbolMapping: ['', jsonValidator()], url: '' }); 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 7354ca5f8..9ae7f8064 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 @@ -393,30 +393,28 @@ > - @if (assetProfile?.dataSource === 'MANUAL') { -
- - Sectors - - -
-
- - Countries - - -
- } +
+ + Sectors + + +
+
+ + Countries + + +
Url diff --git a/libs/common/src/lib/utils/form.util.ts b/libs/common/src/lib/utils/form.util.ts index b510e6215..6a6c32b1f 100644 --- a/libs/common/src/lib/utils/form.util.ts +++ b/libs/common/src/lib/utils/form.util.ts @@ -1,6 +1,17 @@ +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; import { FormGroup } from '@angular/forms'; import { plainToInstance } from 'class-transformer'; -import { validate } from 'class-validator'; +import { isJSON, validate } from 'class-validator'; + +export function jsonValidator(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (!isJSON(control.value)) { + return { invalidJson: true }; + } + + return null; + }; +} export async function validateObjectForForm({ classDto, diff --git a/libs/common/src/lib/utils/index.ts b/libs/common/src/lib/utils/index.ts index 2bdd03fdc..371126790 100644 --- a/libs/common/src/lib/utils/index.ts +++ b/libs/common/src/lib/utils/index.ts @@ -1,3 +1,3 @@ -import { validateObjectForForm } from './form.util'; +import { jsonValidator, validateObjectForForm } from './form.util'; -export { validateObjectForForm }; +export { jsonValidator, validateObjectForForm };