Browse Source

Various improvements

pull/3537/head
Thomas Kaul 1 year ago
parent
commit
0092bf4eea
  1. 6
      apps/api/src/app/user/update-user-setting.dto.ts
  2. 6
      apps/client/src/app/components/rule/rule.component.html
  3. 4
      apps/client/src/app/components/rule/rule.component.ts
  4. 16
      apps/client/src/app/components/rules/rules.component.html
  5. 2
      apps/client/src/app/components/rules/rules.component.ts
  6. 9
      apps/client/src/app/components/rules/rules.module.ts
  7. 97
      apps/client/src/app/pages/portfolio/fire/fire-page.component.ts
  8. 29
      apps/client/src/app/pages/portfolio/fire/fire-page.html
  9. 7
      libs/common/src/lib/interfaces/user-settings.interface.ts
  10. 12
      libs/common/src/lib/interfaces/x-ray-rule.interface.ts
  11. 4
      libs/common/src/lib/types/index.ts
  12. 12
      libs/common/src/lib/types/x-ray-rules-settings.type.ts

6
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;
}

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

@ -21,8 +21,10 @@
>
@if (rule?.value === true) {
<ion-icon name="checkmark-circle-outline" />
} @else {
} @else if (rule?.isActive === true) {
<ion-icon name="warning-outline" />
} @else {
<ion-icon class="text-muted" name="remove-circle-outline" />
}
</div>
}
@ -50,6 +52,7 @@
<div class="evaluation">{{ rule?.evaluation }}</div>
</div>
<div>
@if (hasPermissionToUpdateUserSettings) {
<button
class="mx-1 no-min-width px-2"
mat-button
@ -67,6 +70,7 @@
}
</button>
</mat-menu>
}
</div>
}
</div>

4
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);
}
}

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

@ -1,21 +1,19 @@
<div class="container p-0">
<div class="row no-gutters">
<div class="col">
@if (hasPermissionToCreateOrder && rules === null) {
<mat-card appearance="outlined" class="my-2 text-center">
<mat-card-content>
<gf-no-transactions-info-indicator [hasBorder]="false" />
</mat-card-content>
</mat-card>
}
@if (isLoading) {
<gf-rule [isLoading]="true" />
}
@if (rules !== null && rules !== undefined) {
@for (rule of rules; track rule.key) {
<gf-rule [rule]="rule" (ruleUpdated)="onRuleUpdated($event)" />
<gf-rule
[hasPermissionToUpdateUserSettings]="
hasPermissionToUpdateUserSettings
"
[rule]="rule"
(ruleUpdated)="onRuleUpdated($event)"
/>
}
}
</div>

2
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[];

9
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 {}

97
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;
}
}

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

@ -125,7 +125,9 @@
}
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[hasPermissionToUpdateUserSettings]="
hasPermissionToUpdateUserSettings
"
[isLoading]="isLoadingPortfolioReport"
[rules]="emergencyFundRules"
(rulesUpdated)="onRulesUpdated($event)"
@ -139,7 +141,9 @@
}
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[hasPermissionToUpdateUserSettings]="
hasPermissionToUpdateUserSettings
"
[isLoading]="isLoadingPortfolioReport"
[rules]="currencyClusterRiskRules"
(rulesUpdated)="onRulesUpdated($event)"
@ -153,13 +157,15 @@
}
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[hasPermissionToUpdateUserSettings]="
hasPermissionToUpdateUserSettings
"
[isLoading]="isLoadingPortfolioReport"
[rules]="accountClusterRiskRules"
(rulesUpdated)="onRulesUpdated($event)"
/>
</div>
<div>
<div class="mb-4">
<h4 class="align-items-center d-flex m-0">
<span i18n>Fees</span>
@if (user?.subscription?.type === 'Basic') {
@ -167,7 +173,9 @@
}
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[hasPermissionToUpdateUserSettings]="
hasPermissionToUpdateUserSettings
"
[isLoading]="isLoadingPortfolioReport"
[rules]="feeRules"
(rulesUpdated)="onRulesUpdated($event)"
@ -175,14 +183,11 @@
</div>
@if (inactiveRules?.length > 0) {
<div>
<h4 class="align-items-center d-flex m-0">
<span i18n>Inactive</span>
@if (user?.subscription?.type === 'Basic') {
<gf-premium-indicator class="ml-1" />
}
</h4>
<h4 class="m-0" i18n>Inactive</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[hasPermissionToUpdateUserSettings]="
hasPermissionToUpdateUserSettings
"
[isLoading]="isLoadingPortfolioReport"
[rules]="inactiveRules"
(rulesUpdated)="onRulesUpdated($event)"

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

@ -2,11 +2,10 @@ import {
ColorScheme,
DateRange,
HoldingsViewMode,
ViewMode
ViewMode,
XRayRulesSettings
} from '@ghostfolio/common/types';
import { XRayRules } from './x-ray-rule.interface';
export interface UserSettings {
annualInterestRate?: number;
baseCurrency?: string;
@ -25,5 +24,5 @@ export interface UserSettings {
retirementDate?: string;
savingsRate?: number;
viewMode?: ViewMode;
xRayRules?: XRayRules;
xRayRules?: XRayRulesSettings;
}

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

@ -1,12 +0,0 @@
export interface XRayRules {
AccountClusterRiskCurrentInvestment?: Rule;
AccountClusterRiskSingleAccount?: Rule;
CurrencyClusterRiskBaseCurrencyCurrentInvestment?: Rule;
CurrencyClusterRiskCurrentInvestment?: Rule;
EmergencyFundSetup?: Rule;
FeeRatioInitialInvestment?: Rule;
}
interface Rule {
isActive: boolean;
}

4
libs/common/src/lib/types/index.ts

@ -19,6 +19,7 @@ import type { SubscriptionOffer } from './subscription-offer.type';
import type { ToggleOption } from './toggle-option.type';
import type { UserWithSettings } from './user-with-settings.type';
import type { ViewMode } from './view-mode.type';
import type { XRayRulesSettings } from './x-ray-rules-settings.type';
export type {
AccessType,
@ -41,5 +42,6 @@ export type {
SubscriptionOffer,
ToggleOption,
UserWithSettings,
ViewMode
ViewMode,
XRayRulesSettings
};

12
libs/common/src/lib/types/x-ray-rules-settings.type.ts

@ -0,0 +1,12 @@
export type XRayRulesSettings = {
AccountClusterRiskCurrentInvestment?: RuleSettings;
AccountClusterRiskSingleAccount?: RuleSettings;
CurrencyClusterRiskBaseCurrencyCurrentInvestment?: RuleSettings;
CurrencyClusterRiskCurrentInvestment?: RuleSettings;
EmergencyFundSetup?: RuleSettings;
FeeRatioInitialInvestment?: RuleSettings;
};
interface RuleSettings {
isActive: boolean;
}
Loading…
Cancel
Save