Feature/add form validation against DTO for activity and account (#3230)

* Add form validation against DTO for activity and account

* Update changelog
pull/3281/head
Fedron 2 months ago committed by GitHub
parent 5d4e2fba8c
commit 9241c04d5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- Added a form validation against the DTO in the create or update account dialog
- Added a form validation against the DTO in the create or update activity dialog
### Changed
- Moved the dividend calculations into the portfolio calculator

@ -1,6 +1,7 @@
import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto';
import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto';
import { DataService } from '@ghostfolio/client/services/data.service';
import { validateObjectForForm } from '@ghostfolio/client/util/form.util';
import { Currency } from '@ghostfolio/common/interfaces';
import {
@ -102,7 +103,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
this.dialogRef.close();
}
public onSubmit() {
public async onSubmit() {
const account: CreateAccountDto | UpdateAccountDto = {
balance: this.accountForm.controls['balance'].value,
comment: this.accountForm.controls['comment'].value,
@ -113,13 +114,29 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
platformId: this.accountForm.controls['platformId'].value?.id ?? null
};
if (this.data.account.id) {
(account as UpdateAccountDto).id = this.data.account.id;
} else {
delete (account as CreateAccountDto).id;
}
try {
if (this.data.account.id) {
(account as UpdateAccountDto).id = this.data.account.id;
await validateObjectForForm({
classDto: UpdateAccountDto,
form: this.accountForm,
object: account
});
} else {
delete (account as CreateAccountDto).id;
await validateObjectForForm({
classDto: CreateAccountDto,
form: this.accountForm,
object: account
});
}
this.dialogRef.close({ account });
this.dialogRef.close({ account });
} catch (error) {
console.error(error);
}
}
public ngOnDestroy() {

@ -1,6 +1,7 @@
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
import { DataService } from '@ghostfolio/client/services/data.service';
import { validateObjectForForm } from '@ghostfolio/client/util/form.util';
import { getDateFormatString } from '@ghostfolio/common/helper';
import { translate } from '@ghostfolio/ui/i18n';
@ -451,7 +452,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
);
}
public onSubmit() {
public async onSubmit() {
const activity: CreateOrderDto | UpdateOrderDto = {
accountId: this.activityForm.controls['accountId'].value,
assetClass: this.activityForm.controls['assetClass'].value,
@ -474,14 +475,32 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
unitPrice: this.activityForm.controls['unitPrice'].value
};
if (this.data.activity.id) {
(activity as UpdateOrderDto).id = this.data.activity.id;
} else {
(activity as CreateOrderDto).updateAccountBalance =
this.activityForm.controls['updateAccountBalance'].value;
}
try {
if (this.data.activity.id) {
(activity as UpdateOrderDto).id = this.data.activity.id;
this.dialogRef.close({ activity });
await validateObjectForForm({
classDto: UpdateOrderDto,
form: this.activityForm,
ignoreFields: ['dataSource', 'date'],
object: activity as UpdateOrderDto
});
} else {
(activity as CreateOrderDto).updateAccountBalance =
this.activityForm.controls['updateAccountBalance'].value;
await validateObjectForForm({
classDto: CreateOrderDto,
form: this.activityForm,
ignoreFields: ['dataSource', 'date'],
object: activity
});
}
this.dialogRef.close({ activity });
} catch (error) {
console.error(error);
}
}
public ngOnDestroy() {

@ -0,0 +1,38 @@
import { FormGroup } from '@angular/forms';
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
export async function validateObjectForForm<T>({
classDto,
form,
ignoreFields = [],
object
}: {
classDto: { new (): T };
form: FormGroup;
ignoreFields?: string[];
object: T;
}): Promise<void> {
const objectInstance = plainToInstance(classDto, object);
const errors = await validate(objectInstance as object);
const nonIgnoredErrors = errors.filter(({ property }) => {
return !ignoreFields.includes(property);
});
if (nonIgnoredErrors.length === 0) {
return Promise.resolve();
}
for (const { constraints, property } of nonIgnoredErrors) {
const formControl = form.get(property);
if (formControl) {
formControl.setErrors({
validationError: Object.values(constraints)[0]
});
}
}
return Promise.reject(nonIgnoredErrors);
}
Loading…
Cancel
Save