Feature/add business logic of rule settings (#3826)

* Add business logic of rule settings

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
pull/3829/head^2
Shaunak Das 3 months ago committed by GitHub
parent 1b2a7dc2e4
commit 24a3d92da0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- Added support to customize the rule thresholds in the _X-ray_ section (experimental)
### Changed
- Improved the language localization for German (`de`)

@ -1,4 +1,5 @@
import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code';
import { PortfolioReportRule } from '@ghostfolio/common/interfaces';
import type {
ColorScheme,
DateRange,

@ -76,11 +76,11 @@ export class AccountClusterRiskCurrentInvestment extends Rule<Settings> {
};
}
public getSettings(aUserSettings: UserSettings): Settings {
public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings {
return {
baseCurrency: aUserSettings.baseCurrency,
isActive: aUserSettings.xRayRules[this.getKey()].isActive,
thresholdMax: 0.5
baseCurrency,
isActive: xRayRules[this.getKey()].isActive,
thresholdMax: xRayRules[this.getKey()]?.thresholdMax ?? 0.5
};
}
}

@ -34,9 +34,9 @@ export class AccountClusterRiskSingleAccount extends Rule<RuleSettings> {
};
}
public getSettings(aUserSettings: UserSettings): RuleSettings {
public getSettings({ xRayRules }: UserSettings): RuleSettings {
return {
isActive: aUserSettings.xRayRules[this.getKey()].isActive
isActive: xRayRules[this.getKey()].isActive
};
}
}

@ -62,10 +62,10 @@ export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule<Setti
};
}
public getSettings(aUserSettings: UserSettings): Settings {
public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings {
return {
baseCurrency: aUserSettings.baseCurrency,
isActive: aUserSettings.xRayRules[this.getKey()].isActive
baseCurrency,
isActive: xRayRules[this.getKey()].isActive
};
}
}

@ -62,11 +62,11 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule<Settings> {
};
}
public getSettings(aUserSettings: UserSettings): Settings {
public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings {
return {
baseCurrency: aUserSettings.baseCurrency,
isActive: aUserSettings.xRayRules[this.getKey()].isActive,
thresholdMax: 0.5
baseCurrency,
isActive: xRayRules[this.getKey()].isActive,
thresholdMax: xRayRules[this.getKey()]?.thresholdMax ?? 0.5
};
}
}

@ -19,7 +19,7 @@ export class EmergencyFundSetup extends Rule<Settings> {
}
public evaluate(ruleSettings: Settings) {
if (this.emergencyFund < ruleSettings.thresholdMin) {
if (!this.emergencyFund) {
return {
evaluation: 'No emergency fund has been set up',
value: false
@ -32,16 +32,14 @@ export class EmergencyFundSetup extends Rule<Settings> {
};
}
public getSettings(aUserSettings: UserSettings): Settings {
public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings {
return {
baseCurrency: aUserSettings.baseCurrency,
isActive: aUserSettings.xRayRules[this.getKey()].isActive,
thresholdMin: 0
baseCurrency,
isActive: xRayRules[this.getKey()].isActive
};
}
}
interface Settings extends RuleSettings {
baseCurrency: string;
thresholdMin: number;
}

@ -43,11 +43,11 @@ export class FeeRatioInitialInvestment extends Rule<Settings> {
};
}
public getSettings(aUserSettings: UserSettings): Settings {
public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings {
return {
baseCurrency: aUserSettings.baseCurrency,
isActive: aUserSettings.xRayRules[this.getKey()].isActive,
thresholdMax: 0.01
baseCurrency,
isActive: xRayRules[this.getKey()].isActive,
thresholdMax: xRayRules[this.getKey()]?.thresholdMax ?? 0.01
};
}
}

@ -2,6 +2,7 @@ import { PortfolioReportRule } from '@ghostfolio/common/interfaces';
import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import {
MAT_DIALOG_DATA,
@ -16,6 +17,7 @@ import { IRuleSettingsDialogParams } from './interfaces/interfaces';
@Component({
imports: [
CommonModule,
FormsModule,
MatButtonModule,
MatDialogModule,
MatFormFieldModule,

@ -1,23 +1,37 @@
<div mat-dialog-title>{{ data.rule.name }}</div>
<div class="py-3" mat-dialog-content>
<mat-form-field appearance="outline" class="w-100">
<mat-form-field
appearance="outline"
class="w-100"
[ngClass]="{ 'd-none': settings.thresholdMin === undefined }"
>
<mat-label i18n>Threshold Min</mat-label>
<input matInput name="thresholdMin" type="number" />
<input
matInput
name="thresholdMin"
type="number"
[(ngModel)]="settings.thresholdMin"
/>
</mat-form-field>
<mat-form-field appearance="outline" class="w-100">
<mat-form-field
appearance="outline"
class="w-100"
[ngClass]="{ 'd-none': settings.thresholdMax === undefined }"
>
<mat-label i18n>Threshold Max</mat-label>
<input matInput name="thresholdMax" type="number" />
<input
matInput
name="thresholdMax"
type="number"
[(ngModel)]="settings.thresholdMax"
/>
</mat-form-field>
</div>
<div align="end" mat-dialog-actions>
<button i18n mat-button (click)="dialogRef.close()">Close</button>
<button
color="primary"
mat-flat-button
(click)="dialogRef.close({ settings })"
>
<button color="primary" mat-flat-button (click)="dialogRef.close(settings)">
<ng-container i18n>Save</ng-container>
</button>
</div>

@ -62,7 +62,7 @@
<ion-icon name="ellipsis-horizontal" />
</button>
<mat-menu #rulesMenu="matMenu" xPosition="before">
@if (rule?.isActive && !isEmpty(rule.settings) && false) {
@if (rule?.isActive && !isEmpty(rule.settings)) {
<button mat-menu-item (click)="onCustomizeRule(rule)">
<ng-container i18n>Customize</ng-container>...
</button>

@ -55,16 +55,15 @@ export class RuleComponent implements OnInit {
dialogRef
.afterClosed()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(
({ settings }: { settings: PortfolioReportRule['settings'] }) => {
.subscribe((settings: PortfolioReportRule['settings']) => {
if (settings) {
console.log(settings);
// TODO
// this.ruleUpdated.emit(settings);
this.ruleUpdated.emit({
xRayRules: {
[rule.key]: settings
}
});
}
);
});
}
public onUpdateRule(rule: PortfolioReportRule) {

@ -134,8 +134,6 @@ export class FirePageComponent implements OnDestroy, OnInit {
}
public onRulesUpdated(event: UpdateUserSettingDto) {
this.isLoading = true;
this.dataService
.putUserSetting(event)
.pipe(takeUntil(this.unsubscribeSubject))

@ -1,3 +1,5 @@
import { PortfolioReportRule } from '@ghostfolio/common/interfaces';
export type XRayRulesSettings = {
AccountClusterRiskCurrentInvestment?: RuleSettings;
AccountClusterRiskSingleAccount?: RuleSettings;
@ -7,6 +9,6 @@ export type XRayRulesSettings = {
FeeRatioInitialInvestment?: RuleSettings;
};
interface RuleSettings {
interface RuleSettings extends Pick<PortfolioReportRule, 'settings'> {
isActive: boolean;
}

Loading…
Cancel
Save