diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts
index c97bbf113..0aa3c3093 100644
--- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts
+++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts
@@ -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/validation.util';
import { Currency } from '@ghostfolio/common/interfaces';
import {
@@ -115,8 +116,14 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
if (this.data.account.id) {
(account as UpdateAccountDto).id = this.data.account.id;
+ validateObjectForForm(account, UpdateAccountDto, this.accountForm, () => {
+ this.dialogRef.close({ account });
+ });
} else {
delete (account as CreateAccountDto).id;
+ validateObjectForForm(account, CreateAccountDto, this.accountForm, () => {
+ this.dialogRef.close({ account });
+ });
}
this.dialogRef.close({ account });
diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html
index e2981462f..007835a21 100644
--- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html
+++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html
@@ -18,6 +18,9 @@
matInput
(keydown.enter)="$event.stopPropagation()"
/>
+
+ {{ accountForm.controls['name'].errors?.validationError }}
+
@@ -27,6 +30,11 @@
formControlName="currency"
[currencies]="currencies"
/>
+
+ {{ accountForm.controls['currency'].errors?.validationError }}
+
@@ -41,6 +49,11 @@
{{
accountForm.controls['currency']?.value?.value
}}
+
+ {{ accountForm.controls['balance'].errors?.validationError }}
+
@@ -71,6 +84,11 @@
}
+
+ {{ accountForm.controls['platformId'].errors?.validationError }}
+
@@ -83,6 +101,11 @@
matInput
(keyup.enter)="$event.stopPropagation()"
>
+
+ {{ accountForm.controls['comment'].errors?.validationError }}
+
@@ -95,6 +118,11 @@
Account ID
+
+ {{ accountForm.controls['accountId'].errors?.validationError }}
+
}
diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
index 21a2ca920..ac966d221 100644
--- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
+++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
@@ -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/validation.util';
import { getDateFormatString } from '@ghostfolio/common/helper';
import { translate } from '@ghostfolio/ui/i18n';
@@ -19,7 +20,8 @@ import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AssetClass, AssetSubClass, Tag, Type } from '@prisma/client';
-import { isUUID } from 'class-validator';
+import { plainToInstance } from 'class-transformer';
+import { Validator, isUUID, validate } from 'class-validator';
import { isToday } from 'date-fns';
import { EMPTY, Observable, Subject, lastValueFrom, of } from 'rxjs';
import { catchError, delay, map, startWith, takeUntil } from 'rxjs/operators';
@@ -459,7 +461,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
comment: this.activityForm.controls['comment'].value,
currency: this.activityForm.controls['currency'].value,
customCurrency: this.activityForm.controls['currencyOfUnitPrice'].value,
- date: this.activityForm.controls['date'].value,
+ date: (this.activityForm.controls['date'].value as Date).toISOString(),
dataSource: this.activityForm.controls['dataSource'].value,
fee: this.activityForm.controls['fee'].value,
quantity: this.activityForm.controls['quantity'].value,
@@ -476,12 +478,16 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
if (this.data.activity.id) {
(activity as UpdateOrderDto).id = this.data.activity.id;
+ validateObjectForForm(activity, UpdateOrderDto, this.activityForm, () => {
+ this.dialogRef.close({ activity });
+ });
} else {
(activity as CreateOrderDto).updateAccountBalance =
this.activityForm.controls['updateAccountBalance'].value;
+ validateObjectForForm(activity, CreateOrderDto, this.activityForm, () => {
+ this.dialogRef.close({ activity });
+ });
}
-
- this.dialogRef.close({ activity });
}
public ngOnDestroy() {
diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
index 79ea7647a..37391a482 100644
--- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
+++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
@@ -71,6 +71,11 @@
>
+
+ {{ activityForm.controls['tye'].errors?.validationError }}
+
@@ -103,6 +108,11 @@
+
+ {{ activityForm.controls['accountId'].errors?.validationError }}
+
@@ -124,6 +134,11 @@
formControlName="searchSymbol"
[isLoading]="isLoading"
/>
+
+ {{ activityForm.controls['searchSymbol'].errors?.validationError }}
+
Name
+
+ {{ activityForm.controls['name'].errors?.validationError }}
+
@@ -147,12 +167,22 @@
currency
}}
+
+ {{ activityForm.controls['currency'].errors?.validationError }}
+
Data Source
+
+ {{ activityForm.controls['dataSource'].errors?.validationError }}
+
@@ -167,6 +197,11 @@
/>
+
+ {{ activityForm.controls['date'].errors?.validationError }}
+
Quantity
+
+ {{ activityForm.controls['quantity'].errors?.validationError }}
+
{{
activityForm.controls['currency'].value
}}
+
+ {{ activityForm.controls['unitPrice'].errors?.validationError }}
+
{{
activityForm.controls['currency'].value
}}
+
+ {{ activityForm.controls['fee'].errors?.validationError }}
+
@@ -324,6 +372,11 @@
matInput
(keyup.enter)="$event.stopPropagation()"
>
+
+ {{ activityForm.controls['comment'].errors?.validationError }}
+
{{ assetClass.label }}
+
+ {{ activityForm.controls['assetClass'].errors?.validationError }}
+
{{ assetSubClass.label }}
+
+ {{ activityForm.controls['assetSubClass'].errors?.validationError }}
+
diff --git a/apps/client/src/app/util/validation.util.ts b/apps/client/src/app/util/validation.util.ts
new file mode 100644
index 000000000..42172345a
--- /dev/null
+++ b/apps/client/src/app/util/validation.util.ts
@@ -0,0 +1,27 @@
+import { FormGroup } from '@angular/forms';
+import { plainToInstance } from 'class-transformer';
+import { validate } from 'class-validator';
+
+export function validateObjectForForm(
+ obj: T,
+ ctor: { new (): T },
+ form: FormGroup,
+ onSuccess: () => void
+): void {
+ const objInstance = plainToInstance(ctor, obj);
+
+ validate(objInstance as object).then((errors) => {
+ if (errors.length === 0) {
+ onSuccess();
+ } else {
+ errors.forEach((error) => {
+ const formControl = form.get(error.property);
+ if (formControl) {
+ formControl.setErrors({
+ validationError: Object.values(error.constraints)[0]
+ });
+ }
+ });
+ }
+ });
+}