Browse Source

Task/allow editing country and sector data for all assets (#6284)

* Allow editing country and sector data for all assets

* Update changelog
pull/6699/head^2
Omkar Gujja 6 days ago
committed by GitHub
parent
commit
c202671287
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 7
      CHANGELOG.md
  2. 6
      apps/api/src/app/admin/admin.service.ts
  3. 10
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  4. 46
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  5. 13
      libs/common/src/lib/utils/form.util.ts
  6. 4
      libs/common/src/lib/utils/index.ts

7
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

6
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: {

10
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<AssetClass>(undefined),
assetSubClass: new FormControl<AssetSubClass>(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: ''
});

46
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -393,30 +393,28 @@
></textarea>
</mat-form-field>
</div>
@if (assetProfile?.dataSource === 'MANUAL') {
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Sectors</mat-label>
<textarea
cdkTextareaAutosize
formControlName="sectors"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Countries</mat-label>
<textarea
cdkTextareaAutosize
formControlName="countries"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
}
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Sectors</mat-label>
<textarea
cdkTextareaAutosize
formControlName="sectors"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Countries</mat-label>
<textarea
cdkTextareaAutosize
formControlName="countries"
matInput
type="text"
></textarea>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Url</mat-label>

13
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<T>({
classDto,

4
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 };

Loading…
Cancel
Save