diff --git a/apps/api/src/app/user/update-user-setting.dto.ts b/apps/api/src/app/user/update-user-setting.dto.ts index ff4adb476..6ea6d7427 100644 --- a/apps/api/src/app/user/update-user-setting.dto.ts +++ b/apps/api/src/app/user/update-user-setting.dto.ts @@ -1,10 +1,10 @@ import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code'; -import { XRayRules } from '@ghostfolio/common/interfaces/x-ray-rule.interface'; import type { ColorScheme, DateRange, HoldingsViewMode, - ViewMode + ViewMode, + XRayRulesSettings } from '@ghostfolio/common/types'; import { @@ -105,5 +105,5 @@ export class UpdateUserSettingDto { viewMode?: ViewMode; @IsOptional() - xRayRules?: XRayRules; + xRayRules?: XRayRulesSettings; } diff --git a/apps/client/src/app/components/rule/rule.component.html b/apps/client/src/app/components/rule/rule.component.html index db2d45a8a..80b442b7b 100644 --- a/apps/client/src/app/components/rule/rule.component.html +++ b/apps/client/src/app/components/rule/rule.component.html @@ -21,8 +21,10 @@ > @if (rule?.value === true) { - } @else { + } @else if (rule?.isActive === true) { + } @else { + } } @@ -50,23 +52,25 @@
{{ rule?.evaluation }}
- - - - + + + + }
} diff --git a/apps/client/src/app/components/rule/rule.component.ts b/apps/client/src/app/components/rule/rule.component.ts index 2a2d578a6..da45fd0d2 100644 --- a/apps/client/src/app/components/rule/rule.component.ts +++ b/apps/client/src/app/components/rule/rule.component.ts @@ -17,6 +17,7 @@ import { styleUrls: ['./rule.component.scss'] }) export class RuleComponent implements OnInit { + @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; @Input() rule: PortfolioReportRule; @@ -27,11 +28,12 @@ export class RuleComponent implements OnInit { public ngOnInit() {} public onUpdateRule(rule: PortfolioReportRule) { - let settings: UpdateUserSettingDto = { + const settings: UpdateUserSettingDto = { xRayRules: { [rule.key]: { isActive: !rule.isActive } } }; + this.ruleUpdated.emit(settings); } } diff --git a/apps/client/src/app/components/rules/rules.component.html b/apps/client/src/app/components/rules/rules.component.html index 643cfcadd..31e61bfc2 100644 --- a/apps/client/src/app/components/rules/rules.component.html +++ b/apps/client/src/app/components/rules/rules.component.html @@ -1,21 +1,19 @@
- @if (hasPermissionToCreateOrder && rules === null) { - - - - - - } - @if (isLoading) { } @if (rules !== null && rules !== undefined) { @for (rule of rules; track rule.key) { - + } }
diff --git a/apps/client/src/app/components/rules/rules.component.ts b/apps/client/src/app/components/rules/rules.component.ts index ec8aad7c2..b8493e7be 100644 --- a/apps/client/src/app/components/rules/rules.component.ts +++ b/apps/client/src/app/components/rules/rules.component.ts @@ -16,7 +16,7 @@ import { styleUrls: ['./rules.component.scss'] }) export class RulesComponent { - @Input() hasPermissionToCreateOrder: boolean; + @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; @Input() rules: PortfolioReportRule[]; diff --git a/apps/client/src/app/components/rules/rules.module.ts b/apps/client/src/app/components/rules/rules.module.ts index 26ed1d83e..c62cbc3bd 100644 --- a/apps/client/src/app/components/rules/rules.module.ts +++ b/apps/client/src/app/components/rules/rules.module.ts @@ -1,5 +1,4 @@ import { GfRuleModule } from '@ghostfolio/client/components/rule/rule.module'; -import { GfNoTransactionsInfoComponent } from '@ghostfolio/ui/no-transactions-info'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -11,13 +10,7 @@ import { RulesComponent } from './rules.component'; @NgModule({ declarations: [RulesComponent], exports: [RulesComponent], - imports: [ - CommonModule, - GfNoTransactionsInfoComponent, - GfRuleModule, - MatButtonModule, - MatCardModule - ], + imports: [CommonModule, GfRuleModule, MatButtonModule, MatCardModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class GfRulesModule {} diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts index 6c9239c70..3a24de9cb 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts @@ -28,11 +28,10 @@ export class FirePageComponent implements OnDestroy, OnInit { public feeRules: PortfolioReportRule[]; public fireWealth: Big; public hasImpersonationId: boolean; - public hasPermissionToCreateOrder: boolean; public hasPermissionToUpdateUserSettings: boolean; + public inactiveRules: PortfolioReportRule[]; public isLoading = false; public isLoadingPortfolioReport = false; - public inactiveRules: PortfolioReportRule[]; public user: User; public withdrawalRatePerMonth: Big; public withdrawalRatePerYear: Big; @@ -71,7 +70,6 @@ export class FirePageComponent implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); }); - this.initializePortfolioReport(); this.impersonationStorageService .onChangeHasImpersonation() .pipe(takeUntil(this.unsubscribeSubject)) @@ -85,11 +83,6 @@ export class FirePageComponent implements OnDestroy, OnInit { if (state?.user) { this.user = state.user; - this.hasPermissionToCreateOrder = hasPermission( - this.user.permissions, - permissions.createOrder - ); - this.hasPermissionToUpdateUserSettings = this.user.subscription?.type === 'Basic' ? false @@ -101,34 +94,8 @@ export class FirePageComponent implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); } }); - } - - public initializePortfolioReport() { - this.isLoadingPortfolioReport = true; - - this.dataService - .fetchPortfolioReport() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((portfolioReport) => { - this.inactiveRules = this.mergeInactiveRules(portfolioReport); - this.accountClusterRiskRules = - portfolioReport.rules['accountClusterRisk'].filter( - (rule) => rule.isActive - ) || null; - this.currencyClusterRiskRules = - portfolioReport.rules['currencyClusterRisk'].filter( - (rule) => rule.isActive - ) || null; - this.emergencyFundRules = - portfolioReport.rules['emergencyFund'].filter( - (rule) => rule.isActive - ) || null; - this.feeRules = - portfolioReport.rules['fees'].filter((rule) => rule.isActive) || null; - this.isLoadingPortfolioReport = false; - this.changeDetectorRef.markForCheck(); - }); + this.initializePortfolioReport(); } public onAnnualInterestRateChange(annualInterestRate: number) { @@ -220,21 +187,63 @@ export class FirePageComponent implements OnDestroy, OnInit { }); } - public mergeInactiveRules(report: PortfolioReport): PortfolioReportRule[] { + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } + + private initializePortfolioReport() { + this.isLoadingPortfolioReport = true; + + this.dataService + .fetchPortfolioReport() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((portfolioReport) => { + this.inactiveRules = this.mergeInactiveRules(portfolioReport); + + this.accountClusterRiskRules = + portfolioReport.rules['accountClusterRisk']?.filter( + ({ isActive }) => { + return isActive; + } + ) ?? null; + + this.currencyClusterRiskRules = + portfolioReport.rules['currencyClusterRisk']?.filter( + ({ isActive }) => { + return isActive; + } + ) ?? null; + + this.emergencyFundRules = + portfolioReport.rules['emergencyFund']?.filter(({ isActive }) => { + return isActive; + }) ?? null; + + this.feeRules = + portfolioReport.rules['fees']?.filter(({ isActive }) => { + return isActive; + }) ?? null; + + this.isLoadingPortfolioReport = false; + + this.changeDetectorRef.markForCheck(); + }); + } + + private mergeInactiveRules(report: PortfolioReport): PortfolioReportRule[] { let inactiveRules: PortfolioReportRule[] = []; + for (const category in report.rules) { const rulesArray = report.rules[category]; + inactiveRules = inactiveRules.concat( - rulesArray.filter((rule) => !rule.isActive) + rulesArray.filter(({ isActive }) => { + return !isActive; + }) ); - rulesArray.filter((rule) => rule.isActive); } - console.log(inactiveRules); - return inactiveRules; - } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); + return inactiveRules; } } diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.html b/apps/client/src/app/pages/portfolio/fire/fire-page.html index e24add5dd..c6f0e581f 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.html +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -125,7 +125,9 @@ }
-
+

Fees @if (user?.subscription?.type === 'Basic') { @@ -167,7 +173,9 @@ }

@if (inactiveRules?.length > 0) {
-

- Inactive - @if (user?.subscription?.type === 'Basic') { - - } -

+

Inactive