From 1304de205067021fa67900eb195271afd8907c80 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 9 Oct 2024 19:24:31 +0200 Subject: [PATCH] Restructure XRayRulesSettings --- apps/api/src/app/portfolio/rules.service.ts | 9 ++-- apps/api/src/app/user/user.service.ts | 47 ++++++++++++++----- .../current-investment.ts | 4 +- .../account-cluster-risk/single-account.ts | 2 +- .../base-currency-current-investment.ts | 2 +- .../current-investment.ts | 4 +- .../emergency-fund/emergency-fund-setup.ts | 2 +- .../fees/fee-ratio-initial-investment.ts | 4 +- .../interfaces/interfaces.ts | 2 + .../rule-settings-dialog.component.ts | 6 +-- .../app/components/rule/rule.component.html | 6 ++- .../src/app/components/rule/rule.component.ts | 12 ++--- .../app/components/rules/rules.component.html | 1 + .../app/components/rules/rules.component.ts | 4 +- .../portfolio/fire/fire-page.component.ts | 5 ++ .../app/pages/portfolio/fire/fire-page.html | 5 ++ .../portfolio-report-rule.interface.ts | 4 +- .../lib/types/x-ray-rules-settings.type.ts | 2 + 18 files changed, 83 insertions(+), 38 deletions(-) diff --git a/apps/api/src/app/portfolio/rules.service.ts b/apps/api/src/app/portfolio/rules.service.ts index fd9d794b2..6c46db0a0 100644 --- a/apps/api/src/app/portfolio/rules.service.ts +++ b/apps/api/src/app/portfolio/rules.service.ts @@ -6,6 +6,7 @@ import { } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; +import { isNumber } from 'lodash'; @Injectable() export class RulesService { @@ -27,10 +28,10 @@ export class RulesService { isActive: true, key: rule.getKey(), name: rule.getName(), - settings: { - thresholdMax: settings['thresholdMax'], - thresholdMin: settings['thresholdMin'] - } + settings: { + thresholdMax: isNumber(settings['thresholdMax']) ? true : false, + thresholdMin: isNumber(settings['thresholdMin']) ? true : false + } as PortfolioReportRule['settings'] }; } else { return { diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 0f76b9540..c4808c711 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -2,6 +2,12 @@ import { OrderService } from '@ghostfolio/api/app/order/order.service'; import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service'; import { environment } from '@ghostfolio/api/environments/environment'; import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event'; +import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/current-investment'; +import { AccountClusterRiskSingleAccount } from '@ghostfolio/api/models/rules/account-cluster-risk/single-account'; +import { CurrencyClusterRiskBaseCurrencyCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/base-currency-current-investment'; +import { CurrencyClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/current-investment'; +import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup'; +import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; @@ -200,17 +206,36 @@ export class UserService { (user.Settings.settings as UserSettings).viewMode = 'DEFAULT'; } - // Set default values for X-ray rules - if (!(user.Settings.settings as UserSettings).xRayRules) { - (user.Settings.settings as UserSettings).xRayRules = { - AccountClusterRiskCurrentInvestment: { isActive: true }, - AccountClusterRiskSingleAccount: { isActive: true }, - CurrencyClusterRiskBaseCurrencyCurrentInvestment: { isActive: true }, - CurrencyClusterRiskCurrentInvestment: { isActive: true }, - EmergencyFundSetup: { isActive: true }, - FeeRatioInitialInvestment: { isActive: true } - }; - } + // TODO + (user.Settings.settings as UserSettings).xRayRules = { + AccountClusterRiskCurrentInvestment: + new AccountClusterRiskCurrentInvestment(undefined, {}).getSettings( + user.Settings.settings + ), + AccountClusterRiskSingleAccount: new AccountClusterRiskSingleAccount( + undefined, + {} + ).getSettings(user.Settings.settings), + CurrencyClusterRiskBaseCurrencyCurrentInvestment: + new CurrencyClusterRiskBaseCurrencyCurrentInvestment( + undefined, + undefined + ).getSettings(user.Settings.settings), + CurrencyClusterRiskCurrentInvestment: + new CurrencyClusterRiskCurrentInvestment( + undefined, + undefined + ).getSettings(user.Settings.settings), + EmergencyFundSetup: new EmergencyFundSetup( + undefined, + undefined + ).getSettings(user.Settings.settings), + FeeRatioInitialInvestment: new FeeRatioInitialInvestment( + undefined, + undefined, + undefined + ).getSettings(user.Settings.settings) + }; let currentPermissions = getPermissions(user.role); diff --git a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts index 13680270e..82044a975 100644 --- a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts @@ -79,8 +79,8 @@ export class AccountClusterRiskCurrentInvestment extends Rule { public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, - isActive: xRayRules[this.getKey()].isActive, - thresholdMax: xRayRules[this.getKey()]?.thresholdMax ?? 0.5 + isActive: xRayRules?.[this.getKey()].isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.5 }; } } diff --git a/apps/api/src/models/rules/account-cluster-risk/single-account.ts b/apps/api/src/models/rules/account-cluster-risk/single-account.ts index feaaf4e38..85aec28c9 100644 --- a/apps/api/src/models/rules/account-cluster-risk/single-account.ts +++ b/apps/api/src/models/rules/account-cluster-risk/single-account.ts @@ -36,7 +36,7 @@ export class AccountClusterRiskSingleAccount extends Rule { public getSettings({ xRayRules }: UserSettings): RuleSettings { return { - isActive: xRayRules[this.getKey()].isActive + isActive: xRayRules?.[this.getKey()].isActive ?? true }; } } diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts index 39ee8b88d..fb0b3a533 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts @@ -64,7 +64,7 @@ export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule { public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, - isActive: xRayRules[this.getKey()].isActive, - thresholdMax: xRayRules[this.getKey()]?.thresholdMax ?? 0.5 + isActive: xRayRules?.[this.getKey()].isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.5 }; } } diff --git a/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts b/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts index 819b8bd7b..88d2c2738 100644 --- a/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts +++ b/apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts @@ -35,7 +35,7 @@ export class EmergencyFundSetup extends Rule { public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, - isActive: xRayRules[this.getKey()].isActive + isActive: xRayRules?.[this.getKey()].isActive ?? true }; } } diff --git a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts index 9b1961ed6..dda8f66d5 100644 --- a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts +++ b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts @@ -46,8 +46,8 @@ export class FeeRatioInitialInvestment extends Rule { public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { return { baseCurrency, - isActive: xRayRules[this.getKey()].isActive, - thresholdMax: xRayRules[this.getKey()]?.thresholdMax ?? 0.01 + isActive: xRayRules?.[this.getKey()].isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.01 }; } } diff --git a/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts index a409ab503..7eee7e52d 100644 --- a/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts @@ -1,5 +1,7 @@ import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; +import { XRayRulesSettings } from '@ghostfolio/common/types'; export interface IRuleSettingsDialogParams { rule: PortfolioReportRule; + settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; } diff --git a/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts b/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts index 265d3c941..7cff5e70f 100644 --- a/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts +++ b/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts @@ -1,4 +1,4 @@ -import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; +import { XRayRulesSettings } from '@ghostfolio/common/types'; import { CommonModule } from '@angular/common'; import { Component, Inject } from '@angular/core'; @@ -29,12 +29,12 @@ import { IRuleSettingsDialogParams } from './interfaces/interfaces'; templateUrl: './rule-settings-dialog.html' }) export class GfRuleSettingsDialogComponent { - public settings: PortfolioReportRule['settings']; + public settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; public constructor( @Inject(MAT_DIALOG_DATA) public data: IRuleSettingsDialogParams, public dialogRef: MatDialogRef ) { - this.settings = this.data.rule.settings; + this.settings = this.data.settings; } } diff --git a/apps/client/src/app/components/rule/rule.component.html b/apps/client/src/app/components/rule/rule.component.html index 5491933c0..85dd3a490 100644 --- a/apps/client/src/app/components/rule/rule.component.html +++ b/apps/client/src/app/components/rule/rule.component.html @@ -62,7 +62,11 @@ - @if (rule?.isActive && !isEmpty(rule.settings)) { + @if ( + rule?.isActive && + (rule?.settings.thresholdMax >= 0 || + rule?.settings.thresholdMin >= 0) + ) { diff --git a/apps/client/src/app/components/rule/rule.component.ts b/apps/client/src/app/components/rule/rule.component.ts index 6e6c368f0..99abf110c 100644 --- a/apps/client/src/app/components/rule/rule.component.ts +++ b/apps/client/src/app/components/rule/rule.component.ts @@ -1,5 +1,6 @@ import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; +import { XRayRulesSettings } from '@ghostfolio/common/types'; import { ChangeDetectionStrategy, @@ -10,7 +11,6 @@ import { Output } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; -import { isEmpty } from 'lodash'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; @@ -27,11 +27,10 @@ export class RuleComponent implements OnInit { @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; @Input() rule: PortfolioReportRule; + @Input() settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; @Output() ruleUpdated = new EventEmitter(); - public isEmpty = isEmpty; - private deviceType: string; private unsubscribeSubject = new Subject(); @@ -46,9 +45,10 @@ export class RuleComponent implements OnInit { public onCustomizeRule(rule: PortfolioReportRule) { const dialogRef = this.dialog.open(GfRuleSettingsDialogComponent, { - data: { - rule - }, + data: { + rule, + settings: this.settings + } as IRuleSettingsDialogParams, width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); diff --git a/apps/client/src/app/components/rules/rules.component.html b/apps/client/src/app/components/rules/rules.component.html index 31e61bfc2..28343673d 100644 --- a/apps/client/src/app/components/rules/rules.component.html +++ b/apps/client/src/app/components/rules/rules.component.html @@ -12,6 +12,7 @@ hasPermissionToUpdateUserSettings " [rule]="rule" + [settings]="settings?.[rule.key]" (ruleUpdated)="onRuleUpdated($event)" /> } diff --git a/apps/client/src/app/components/rules/rules.component.ts b/apps/client/src/app/components/rules/rules.component.ts index b8493e7be..fb2ef1cdb 100644 --- a/apps/client/src/app/components/rules/rules.component.ts +++ b/apps/client/src/app/components/rules/rules.component.ts @@ -1,5 +1,6 @@ import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; +import { XRayRulesSettings } from '@ghostfolio/common/types'; import { ChangeDetectionStrategy, @@ -19,11 +20,10 @@ export class RulesComponent { @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; @Input() rules: PortfolioReportRule[]; + @Input() settings: XRayRulesSettings; @Output() rulesUpdated = new EventEmitter(); - public constructor() {} - public onRuleUpdated(event: UpdateUserSettingDto) { this.rulesUpdated.emit(event); } 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 10a2eb604..54f65b531 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 @@ -138,6 +138,11 @@ export class FirePageComponent implements OnDestroy, OnInit { .putUserSetting(event) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { + this.userService + .get(true) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + this.initializePortfolioReport(); }); } 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 b0fade836..c4a521a8c 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.html +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -132,6 +132,7 @@ " [isLoading]="isLoadingPortfolioReport" [rules]="emergencyFundRules" + [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" /> @@ -150,6 +151,7 @@ " [isLoading]="isLoadingPortfolioReport" [rules]="currencyClusterRiskRules" + [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" /> @@ -168,6 +170,7 @@ " [isLoading]="isLoadingPortfolioReport" [rules]="accountClusterRiskRules" + [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" /> @@ -186,6 +189,7 @@ " [isLoading]="isLoadingPortfolioReport" [rules]="feeRules" + [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" /> @@ -200,6 +204,7 @@ " [isLoading]="isLoadingPortfolioReport" [rules]="inactiveRules" + [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" /> diff --git a/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts b/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts index 29cbb4a8f..a32aa62b3 100644 --- a/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts @@ -4,8 +4,8 @@ export interface PortfolioReportRule { key: string; name: string; settings?: { - thresholdMax?: number; - thresholdMin?: number; + thresholdMax: boolean; + thresholdMin: boolean; }; value?: boolean; } diff --git a/libs/common/src/lib/types/x-ray-rules-settings.type.ts b/libs/common/src/lib/types/x-ray-rules-settings.type.ts index a55487f0b..db91aeeef 100644 --- a/libs/common/src/lib/types/x-ray-rules-settings.type.ts +++ b/libs/common/src/lib/types/x-ray-rules-settings.type.ts @@ -11,4 +11,6 @@ export type XRayRulesSettings = { interface RuleSettings extends Pick { isActive: boolean; + thresholdMax?: number; + thresholdMin?: number; }