Browse Source

Bugfix/validation error caused by empty strings in asset profile details dialog (#7509)

* Resolve validation error caused by empty strings

* Update changelog
pull/7511/head
Thomas Kaul 7 days ago
committed by GitHub
parent
commit
c3e70091ae
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 16
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  3. 4
      libs/common/src/lib/dtos/update-asset-profile.dto.ts
  4. 58
      libs/common/src/lib/helper.spec.ts
  5. 20
      libs/common/src/lib/helper.ts

4
CHANGELOG.md

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the language localization for Chinese (`zh`)
### Fixed
- Resolved a validation error caused by empty strings in the asset profile details dialog of the admin control panel
## 3.39.0 - 2026-08-01
### Changed

16
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -11,6 +11,8 @@ import {
DATE_FORMAT,
getCountryName,
getCurrencyFromSymbol,
getStringOrNull,
getStringOrUndefined,
isCurrency
} from '@ghostfolio/common/helper';
import {
@ -568,9 +570,10 @@ export class GfAssetProfileDialogComponent implements OnInit {
this.assetProfileForm.controls.scraperConfiguration.controls.headers
.value ?? '{}'
) as Record<string, string>,
locale:
locale: getStringOrUndefined(
this.assetProfileForm.controls.scraperConfiguration.controls.locale
?.value ?? undefined,
?.value
),
mode:
this.assetProfileForm.controls.scraperConfiguration.controls.mode
?.value ?? undefined,
@ -619,7 +622,7 @@ export class GfAssetProfileDialogComponent implements OnInit {
assetClass: this.assetProfileForm.controls.assetClass.value ?? undefined,
assetSubClass:
this.assetProfileForm.controls.assetSubClass.value ?? undefined,
comment: this.assetProfileForm.controls.comment.value ?? undefined,
comment: getStringOrNull(this.assetProfileForm.controls.comment.value),
currency: this.assetProfileForm.controls.currency.value ?? undefined,
dataGatheringFrequency:
this.assetProfileForm.controls.dataGatheringFrequency.value ??
@ -628,7 +631,7 @@ export class GfAssetProfileDialogComponent implements OnInit {
? this.assetProfileForm.controls.isActive.value
: undefined,
name: this.assetProfileForm.controls.name.value ?? undefined,
url: this.assetProfileForm.controls.url.value ?? undefined
url: getStringOrNull(this.assetProfileForm.controls.url.value)
};
try {
@ -737,9 +740,10 @@ export class GfAssetProfileDialogComponent implements OnInit {
this.assetProfileForm.controls.scraperConfiguration.controls.headers
.value ?? '{}'
) as Record<string, string>,
locale:
locale: getStringOrUndefined(
this.assetProfileForm.controls.scraperConfiguration.controls.locale
?.value ?? undefined,
?.value
),
mode: this.assetProfileForm.controls.scraperConfiguration.controls
.mode?.value,
selector:

4
libs/common/src/lib/dtos/update-asset-profile.dto.ts

@ -35,7 +35,7 @@ export class UpdateAssetProfileDto {
@IsOptional()
@IsString()
comment?: string;
comment?: string | null;
@IsArray()
@IsOptional()
@ -96,5 +96,5 @@ export class UpdateAssetProfileDto {
protocols: ['http', 'https'],
require_protocol: true
})
url?: string;
url?: string | null;
}

58
libs/common/src/lib/helper.spec.ts

@ -1,6 +1,8 @@
import {
extractNumberFromString,
getNumberFormatGroup,
getStringOrNull,
getStringOrUndefined,
isCurrency,
isCurrencySymbol
} from '@ghostfolio/common/helper';
@ -139,6 +141,62 @@ describe('Helper', () => {
});
});
describe('Get string or null', () => {
it('String', () => {
expect(getStringOrNull('https://ghostfol.io')).toEqual(
'https://ghostfol.io'
);
});
it('String (with spaces)', () => {
expect(getStringOrNull(' https://ghostfol.io ')).toEqual(
'https://ghostfol.io'
);
});
it('Empty string', () => {
expect(getStringOrNull('')).toEqual(null);
});
it('Blank string', () => {
expect(getStringOrNull(' ')).toEqual(null);
});
it('Null', () => {
expect(getStringOrNull(null)).toEqual(null);
});
it('Undefined', () => {
expect(getStringOrNull(undefined)).toEqual(null);
});
});
describe('Get string or undefined', () => {
it('String', () => {
expect(getStringOrUndefined('de-DE')).toEqual('de-DE');
});
it('String (with spaces)', () => {
expect(getStringOrUndefined(' de-DE ')).toEqual('de-DE');
});
it('Empty string', () => {
expect(getStringOrUndefined('')).toEqual(undefined);
});
it('Blank string', () => {
expect(getStringOrUndefined(' ')).toEqual(undefined);
});
it('Null', () => {
expect(getStringOrUndefined(null)).toEqual(undefined);
});
it('Undefined', () => {
expect(getStringOrUndefined(undefined)).toEqual(undefined);
});
});
describe('Is currency', () => {
it('ISO 4217 currency code', () => {
expect(isCurrency('USD')).toEqual(true);

20
libs/common/src/lib/helper.ts

@ -397,6 +397,26 @@ export function getStartOfUtcDate(aDate: Date) {
return date;
}
export function getStringOrNull(aString: string | null | undefined) {
const trimmedString = aString?.trim();
if (trimmedString) {
return trimmedString;
}
return null;
}
export function getStringOrUndefined(aString: string | null | undefined) {
const trimmedString = aString?.trim();
if (trimmedString) {
return trimmedString;
}
return undefined;
}
export function getSum(aArray: Big[]) {
if (aArray?.length > 0) {
return aArray.reduce((a, b) => a.plus(b), new Big(0));

Loading…
Cancel
Save