Browse Source

Cleanups, move x rules updated to fire component

pull/3537/head
Sonlis 1 year ago
committed by Thomas Kaul
parent
commit
6bc6c21eaa
  1. 7
      apps/api/src/app/portfolio/rules.service.ts
  2. 4
      apps/api/src/app/user/update-user-setting.dto.ts
  3. 1
      apps/api/src/app/user/user.controller.ts
  4. 23
      apps/client/src/app/components/rule/rule.component.html
  5. 39
      apps/client/src/app/components/rule/rule.component.ts
  6. 4
      apps/client/src/app/components/rules/rules.component.html
  7. 14
      apps/client/src/app/components/rules/rules.component.ts
  8. 24
      apps/client/src/app/pages/portfolio/fire/fire-page.component.ts
  9. 4
      apps/client/src/app/pages/portfolio/fire/fire-page.html
  10. 1
      libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts
  11. 4
      libs/common/src/lib/interfaces/user-settings.interface.ts
  12. 2
      libs/common/src/lib/interfaces/x-ray-rule.interface.ts

7
apps/api/src/app/portfolio/rules.service.ts

@ -17,14 +17,17 @@ export class RulesService {
const { evaluation, value } = rule.evaluate( const { evaluation, value } = rule.evaluate(
rule.getSettings(aUserSettings) rule.getSettings(aUserSettings)
); );
return { return {
evaluation, evaluation,
value, isActive: true,
key: rule.getKey(), key: rule.getKey(),
name: rule.getName() name: rule.getName(),
value
}; };
} else { } else {
return { return {
isActive: false,
key: rule.getKey(), key: rule.getKey(),
name: rule.getName() name: rule.getName()
}; };

4
apps/api/src/app/user/update-user-setting.dto.ts

@ -1,5 +1,5 @@
import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code'; import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code';
import { xRayRules } from '@ghostfolio/common/interfaces/x-ray-rule.interface'; import { XRayRules } from '@ghostfolio/common/interfaces/x-ray-rule.interface';
import type { import type {
ColorScheme, ColorScheme,
DateRange, DateRange,
@ -105,5 +105,5 @@ export class UpdateUserSettingDto {
viewMode?: ViewMode; viewMode?: ViewMode;
@IsOptional() @IsOptional()
xRayRules?: xRayRules; xRayRules?: XRayRules;
} }

1
apps/api/src/app/user/user.controller.ts

@ -155,6 +155,7 @@ export class UserController {
delete userSettings[key]; delete userSettings[key];
} }
} }
return this.userService.updateUserSetting({ return this.userService.updateUserSetting({
userSettings, userSettings,
userId: this.request.user.id userId: this.request.user.id

23
apps/client/src/app/components/rule/rule.component.html

@ -16,16 +16,13 @@
class="align-items-center d-flex icon-container mr-2 px-2" class="align-items-center d-flex icon-container mr-2 px-2"
[ngClass]="{ [ngClass]="{
okay: rule?.value === true, okay: rule?.value === true,
warn: rule?.value === false, warn: rule?.value === false
disabled: rule?.value === undefined
}" }"
> >
@if (rule?.value === true) { @if (rule?.value === true) {
<ion-icon name="checkmark-circle-outline" /> <ion-icon name="checkmark-circle-outline" />
} @else if (rule?.value === false) {
<ion-icon name="warning-outline" />
} @else { } @else {
<ion-icon name="close-outline" /> <ion-icon name="warning-outline" />
} }
</div> </div>
} }
@ -53,10 +50,10 @@
<div class="evaluation"> <div class="evaluation">
@if (rule?.evaluation) { @if (rule?.evaluation) {
{{ rule?.evaluation }} {{ rule?.evaluation }}
} @else {
Rule is disabled
} }
<div class="float-right"> </div>
</div>
<div>
<button <button
class="mx-1 no-min-width px-2" class="mx-1 no-min-width px-2"
mat-button mat-button
@ -66,19 +63,15 @@
<ion-icon name="ellipsis-horizontal" /> <ion-icon name="ellipsis-horizontal" />
</button> </button>
<mat-menu #accountMenu="matMenu" xPosition="before"> <mat-menu #accountMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="onUpdateAccount(rule)"> <button mat-menu-item (click)="onUpdateRule(rule)">
<span class="align-items-center d-flex">
@if (rule?.evaluation) { @if (rule?.evaluation) {
Disable <ng-container i18n>Deactivate</ng-container>
} @else { } @else {
Enable <ng-container i18n>Activate</ng-container>
} }
</span>
</button> </button>
</mat-menu> </mat-menu>
</div> </div>
</div>
</div>
} }
</div> </div>
</div> </div>

39
apps/client/src/app/components/rule/rule.component.ts

@ -1,16 +1,14 @@
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { DataService } from '@ghostfolio/client/services/data.service';
import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; import { PortfolioReportRule } from '@ghostfolio/common/interfaces';
import { import {
ChangeDetectorRef,
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
EventEmitter,
Input, Input,
OnInit OnInit,
Output
} from '@angular/core'; } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({ @Component({
selector: 'gf-rule', selector: 'gf-rule',
@ -21,39 +19,18 @@ import { takeUntil } from 'rxjs/operators';
export class RuleComponent implements OnInit { export class RuleComponent implements OnInit {
@Input() isLoading: boolean; @Input() isLoading: boolean;
@Input() rule: PortfolioReportRule; @Input() rule: PortfolioReportRule;
private unsubscribeSubject = new Subject<void>(); @Output() ruleUpdated = new EventEmitter<UpdateUserSettingDto>();
public constructor( public constructor() {}
private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService
) {}
public ngOnInit() {} public ngOnInit() {}
public onUpdateAccount(rule: PortfolioReportRule) { public onUpdateRule(rule: PortfolioReportRule) {
let settings: UpdateUserSettingDto = { let settings: UpdateUserSettingDto = {
xRayRules: { xRayRules: {
[rule.key]: { isActive: !('evaluation' in rule) } [rule.key]: { isActive: !rule.isActive }
} }
}; };
this.dataService this.ruleUpdated.emit(settings);
.putUserSetting(settings)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
this.dataService
.fetchPortfolioReport()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((report) => {
for (const ruleGroup in report.rules) {
for (const singleRule in report.rules[ruleGroup]) {
if (report.rules[ruleGroup][singleRule]['key'] === rule.key) {
this.rule = report.rules[ruleGroup][singleRule];
break;
}
}
}
this.changeDetectorRef.markForCheck();
});
});
} }
} }

4
apps/client/src/app/components/rules/rules.component.html

@ -13,8 +13,8 @@
<gf-rule [isLoading]="true" /> <gf-rule [isLoading]="true" />
} }
@if (rules !== null && rules !== undefined) { @if (rules !== null && rules !== undefined) {
@for (rule of rules; track rule) { @for (rule of rules; track rule.key) {
<gf-rule [rule]="rule" /> <gf-rule [rule]="rule" (ruleUpdated)="onRulesUpdated($event)" />
} }
} }
</div> </div>

14
apps/client/src/app/components/rules/rules.component.ts

@ -1,6 +1,13 @@
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; import { PortfolioReportRule } from '@ghostfolio/common/interfaces';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import {
ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
Output
} from '@angular/core';
@Component({ @Component({
selector: 'gf-rules', selector: 'gf-rules',
@ -11,6 +18,11 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
export class RulesComponent { export class RulesComponent {
@Input() hasPermissionToCreateOrder: boolean; @Input() hasPermissionToCreateOrder: boolean;
@Input() rules: PortfolioReportRule[]; @Input() rules: PortfolioReportRule[];
@Output() rulesUpdated = new EventEmitter<UpdateUserSettingDto>();
public constructor() {} public constructor() {}
public onRulesUpdated(event: UpdateUserSettingDto) {
this.rulesUpdated.emit(event);
}
} }

24
apps/client/src/app/pages/portfolio/fire/fire-page.component.ts

@ -1,3 +1,4 @@
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
@ -149,6 +150,29 @@ export class FirePageComponent implements OnDestroy, OnInit {
}); });
} }
public onRulesUpdated(event: UpdateUserSettingDto) {
this.isLoading = true;
this.dataService
.putUserSetting(event)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
this.dataService
.fetchPortfolioReport()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((portfolioReport) => {
this.accountClusterRiskRules =
portfolioReport.rules['accountClusterRisk'] || null;
this.currencyClusterRiskRules =
portfolioReport.rules['currencyClusterRisk'] || null;
this.emergencyFundRules =
portfolioReport.rules['emergencyFund'] || null;
this.feeRules = portfolioReport.rules['fees'] || null;
this.isLoading = false;
this.changeDetectorRef.markForCheck();
});
});
}
public onSavingsRateChange(savingsRate: number) { public onSavingsRateChange(savingsRate: number) {
this.dataService this.dataService
.putUserSetting({ savingsRate }) .putUserSetting({ savingsRate })

4
apps/client/src/app/pages/portfolio/fire/fire-page.html

@ -127,6 +127,7 @@
<gf-rules <gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder" [hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="emergencyFundRules" [rules]="emergencyFundRules"
(rulesUpdated)="onRulesUpdated($event)"
/> />
</div> </div>
<div class="mb-4"> <div class="mb-4">
@ -139,6 +140,7 @@
<gf-rules <gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder" [hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="currencyClusterRiskRules" [rules]="currencyClusterRiskRules"
(rulesUpdated)="onRulesUpdated($event)"
/> />
</div> </div>
<div class="mb-4"> <div class="mb-4">
@ -151,6 +153,7 @@
<gf-rules <gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder" [hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="accountClusterRiskRules" [rules]="accountClusterRiskRules"
(rulesUpdated)="onRulesUpdated($event)"
/> />
</div> </div>
<div> <div>
@ -163,6 +166,7 @@
<gf-rules <gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder" [hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="feeRules" [rules]="feeRules"
(rulesUpdated)="onRulesUpdated($event)"
/> />
</div> </div>
</div> </div>

1
libs/common/src/lib/interfaces/portfolio-report-rule.interface.ts

@ -1,5 +1,6 @@
export interface PortfolioReportRule { export interface PortfolioReportRule {
evaluation?: string; evaluation?: string;
isActive: boolean;
key: string; key: string;
name: string; name: string;
value?: boolean; value?: boolean;

4
libs/common/src/lib/interfaces/user-settings.interface.ts

@ -5,7 +5,7 @@ import {
ViewMode ViewMode
} from '@ghostfolio/common/types'; } from '@ghostfolio/common/types';
import { xRayRules } from './x-ray-rule.interface'; import { XRayRules } from './x-ray-rule.interface';
export interface UserSettings { export interface UserSettings {
annualInterestRate?: number; annualInterestRate?: number;
@ -25,5 +25,5 @@ export interface UserSettings {
retirementDate?: string; retirementDate?: string;
savingsRate?: number; savingsRate?: number;
viewMode?: ViewMode; viewMode?: ViewMode;
xRayRules?: xRayRules; xRayRules?: XRayRules;
} }

2
libs/common/src/lib/interfaces/x-ray-rule.interface.ts

@ -1,4 +1,4 @@
export interface xRayRules { export interface XRayRules {
AccountClusterRiskCurrentInvestment?: Rule; AccountClusterRiskCurrentInvestment?: Rule;
AccountClusterRiskSingleAccount?: Rule; AccountClusterRiskSingleAccount?: Rule;
CurrencyClusterRiskBaseCurrencyCurrentInvestment?: Rule; CurrencyClusterRiskBaseCurrencyCurrentInvestment?: Rule;

Loading…
Cancel
Save