Browse Source

Add percentage visualization of the active filter

pull/1268/head
Thomas 3 years ago
parent
commit
597b1608b2
  1. 15
      apps/api/src/app/portfolio/portfolio.controller.ts
  2. 49
      apps/api/src/app/portfolio/portfolio.service.ts
  3. 8
      apps/api/src/interceptors/redact-values-in-response.interceptor.ts
  4. 11
      apps/client/src/app/pages/portfolio/allocations/allocations-page.html
  5. 4
      apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts
  6. 5
      apps/client/src/app/pages/portfolio/allocations/allocations-page.scss
  7. 3
      libs/common/src/lib/interfaces/portfolio-details.interface.ts

15
apps/api/src/app/portfolio/portfolio.controller.ts

@ -168,8 +168,14 @@ export class PortfolioController {
})
];
const { accounts, holdings, hasErrors } =
await this.portfolioService.getDetails(
const {
accounts,
filteredValueInBaseCurrency,
filteredValueInPercentage,
hasErrors,
holdings,
totalValueInBaseCurrency
} = await this.portfolioService.getDetails(
impersonationId,
this.request.user.id,
range,
@ -234,8 +240,11 @@ export class PortfolioController {
return {
accounts,
filteredValueInBaseCurrency,
filteredValueInPercentage,
hasError,
holdings
holdings,
totalValueInBaseCurrency
};
}

49
apps/api/src/app/portfolio/portfolio.service.ts

@ -474,12 +474,21 @@ export class PortfolioService {
});
const holdings: PortfolioDetails['holdings'] = {};
const totalInvestment = currentPositions.totalInvestment.plus(
const totalInvestmentInBaseCurrency = currentPositions.totalInvestment.plus(
cashDetails.balanceInBaseCurrency
);
const totalValue = currentPositions.currentValue.plus(
let filteredValueInBaseCurrency = currentPositions.currentValue;
if (
aFilters?.length === 0 ||
(aFilters?.length === 1 &&
aFilters[0].type === 'ASSET_CLASS' &&
aFilters[0].id === 'CASH')
) {
filteredValueInBaseCurrency = filteredValueInBaseCurrency.plus(
cashDetails.balanceInBaseCurrency
);
}
const dataGatheringItems = currentPositions.positions.map((position) => {
return {
@ -540,10 +549,12 @@ export class PortfolioService {
holdings[item.symbol] = {
markets,
allocationCurrent: totalValue.eq(0)
allocationCurrent: filteredValueInBaseCurrency.eq(0)
? 0
: value.div(totalValue).toNumber(),
allocationInvestment: item.investment.div(totalInvestment).toNumber(),
: value.div(filteredValueInBaseCurrency).toNumber(),
allocationInvestment: item.investment
.div(totalInvestmentInBaseCurrency)
.toNumber(),
assetClass: symbolProfile.assetClass,
assetSubClass: symbolProfile.assetSubClass,
countries: symbolProfile.countries,
@ -577,8 +588,8 @@ export class PortfolioService {
cashDetails,
emergencyFund,
userCurrency,
investment: totalInvestment,
value: totalValue
investment: totalInvestmentInBaseCurrency,
value: filteredValueInBaseCurrency
});
for (const symbol of Object.keys(cashPositions)) {
@ -594,7 +605,18 @@ export class PortfolioService {
filters: aFilters
});
return { accounts, holdings, hasErrors: currentPositions.hasErrors };
const summary = await this.getSummary(userId);
return {
accounts,
holdings,
filteredValueInBaseCurrency: filteredValueInBaseCurrency.toNumber(),
filteredValueInPercentage: summary.netWorth
? filteredValueInBaseCurrency.div(summary.netWorth).toNumber()
: 0,
hasErrors: currentPositions.hasErrors,
totalValueInBaseCurrency: summary.netWorth
};
}
public async getPosition(
@ -920,11 +942,9 @@ export class PortfolioService {
}
public async getPerformance(
aImpersonationId: string,
userId: string,
aDateRange: DateRange = 'max'
): Promise<PortfolioPerformanceResponse> {
const userId = await this.getUserId(aImpersonationId, this.request.user.id);
const { portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
userId
@ -1082,12 +1102,11 @@ export class PortfolioService {
};
}
public async getSummary(aImpersonationId: string): Promise<PortfolioSummary> {
const userCurrency = this.request.user.Settings.settings.baseCurrency;
const userId = await this.getUserId(aImpersonationId, this.request.user.id);
public async getSummary(userId: string): Promise<PortfolioSummary> {
const user = await this.userService.user({ id: userId });
const userCurrency = this.request.user.Settings.settings.baseCurrency;
const performanceInformation = await this.getPerformance(aImpersonationId);
const performanceInformation = await this.getPerformance(userId);
const { balanceInBaseCurrency } = await this.accountService.getCashDetails({
userId,

8
apps/api/src/interceptors/redact-values-in-response.interceptor.ts

@ -41,6 +41,14 @@ export class RedactValuesInResponseInterceptor<T>
return activity;
});
}
if (data.filteredValueInBaseCurrency) {
data.filteredValueInBaseCurrency = null;
}
if (data.totalValueInBaseCurrency) {
data.totalValueInBaseCurrency = null;
}
}
return data;

11
apps/client/src/app/pages/portfolio/allocations/allocations-page.html

@ -10,6 +10,17 @@
></gf-activities-filter>
</div>
</div>
<div class="row mb-4">
<div class="col">
<div class="px-1">
<mat-progress-bar
mode="determinate"
[title]="(portfolioDetails?.filteredValueInPercentage * 100) + '%'"
[value]="portfolioDetails?.filteredValueInPercentage * 100"
></mat-progress-bar>
</div>
</div>
</div>
<div class="proportion-charts row">
<div class="col-md-4">
<mat-card class="mb-3">

4
apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts

@ -1,6 +1,7 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
@ -22,7 +23,8 @@ import { AllocationsPageComponent } from './allocations-page.component';
GfToggleModule,
GfWorldMapChartModule,
GfValueModule,
MatCardModule
MatCardModule,
MatProgressBarModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

5
apps/client/src/app/pages/portfolio/allocations/allocations-page.scss

@ -28,4 +28,9 @@
}
}
}
.mat-progress-bar {
border-radius: 0.25rem;
height: 0.5rem;
}
}

3
libs/common/src/lib/interfaces/portfolio-details.interface.ts

@ -10,5 +10,8 @@ export interface PortfolioDetails {
original: number;
};
};
filteredValueInBaseCurrency?: number;
filteredValueInPercentage: number;
holdings: { [symbol: string]: PortfolioPosition };
totalValueInBaseCurrency?: number;
}

Loading…
Cancel
Save