Feature/add filters to analytics page (#1559)
* Add filters to analysis page * Update changelog
This commit is contained in:
parent
dd7a6f1562
commit
b20fa55b79
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added support for filtering on the analysis page
|
||||||
- Added the price to the `Subscription` database schema
|
- Added the price to the `Subscription` database schema
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -189,11 +189,21 @@ export class PortfolioController {
|
|||||||
@UseGuards(AuthGuard('jwt'))
|
@UseGuards(AuthGuard('jwt'))
|
||||||
public async getDividends(
|
public async getDividends(
|
||||||
@Headers('impersonation-id') impersonationId: string,
|
@Headers('impersonation-id') impersonationId: string,
|
||||||
|
@Query('accounts') filterByAccounts?: string,
|
||||||
|
@Query('assetClasses') filterByAssetClasses?: string,
|
||||||
|
@Query('groupBy') groupBy?: GroupBy,
|
||||||
@Query('range') dateRange: DateRange = 'max',
|
@Query('range') dateRange: DateRange = 'max',
|
||||||
@Query('groupBy') groupBy?: GroupBy
|
@Query('tags') filterByTags?: string
|
||||||
): Promise<PortfolioDividends> {
|
): Promise<PortfolioDividends> {
|
||||||
|
const filters = this.apiService.buildFiltersFromQueryParams({
|
||||||
|
filterByAccounts,
|
||||||
|
filterByAssetClasses,
|
||||||
|
filterByTags
|
||||||
|
});
|
||||||
|
|
||||||
let dividends = await this.portfolioService.getDividends({
|
let dividends = await this.portfolioService.getDividends({
|
||||||
dateRange,
|
dateRange,
|
||||||
|
filters,
|
||||||
groupBy,
|
groupBy,
|
||||||
impersonationId
|
impersonationId
|
||||||
});
|
});
|
||||||
@ -229,11 +239,21 @@ export class PortfolioController {
|
|||||||
@UseGuards(AuthGuard('jwt'))
|
@UseGuards(AuthGuard('jwt'))
|
||||||
public async getInvestments(
|
public async getInvestments(
|
||||||
@Headers('impersonation-id') impersonationId: string,
|
@Headers('impersonation-id') impersonationId: string,
|
||||||
|
@Query('accounts') filterByAccounts?: string,
|
||||||
|
@Query('assetClasses') filterByAssetClasses?: string,
|
||||||
|
@Query('groupBy') groupBy?: GroupBy,
|
||||||
@Query('range') dateRange: DateRange = 'max',
|
@Query('range') dateRange: DateRange = 'max',
|
||||||
@Query('groupBy') groupBy?: GroupBy
|
@Query('tags') filterByTags?: string
|
||||||
): Promise<PortfolioInvestments> {
|
): Promise<PortfolioInvestments> {
|
||||||
|
const filters = this.apiService.buildFiltersFromQueryParams({
|
||||||
|
filterByAccounts,
|
||||||
|
filterByAssetClasses,
|
||||||
|
filterByTags
|
||||||
|
});
|
||||||
|
|
||||||
let investments = await this.portfolioService.getInvestments({
|
let investments = await this.portfolioService.getInvestments({
|
||||||
dateRange,
|
dateRange,
|
||||||
|
filters,
|
||||||
groupBy,
|
groupBy,
|
||||||
impersonationId
|
impersonationId
|
||||||
});
|
});
|
||||||
@ -271,10 +291,20 @@ export class PortfolioController {
|
|||||||
@Version('2')
|
@Version('2')
|
||||||
public async getPerformanceV2(
|
public async getPerformanceV2(
|
||||||
@Headers('impersonation-id') impersonationId: string,
|
@Headers('impersonation-id') impersonationId: string,
|
||||||
@Query('range') dateRange: DateRange = 'max'
|
@Query('accounts') filterByAccounts?: string,
|
||||||
|
@Query('assetClasses') filterByAssetClasses?: string,
|
||||||
|
@Query('range') dateRange: DateRange = 'max',
|
||||||
|
@Query('tags') filterByTags?: string
|
||||||
): Promise<PortfolioPerformanceResponse> {
|
): Promise<PortfolioPerformanceResponse> {
|
||||||
|
const filters = this.apiService.buildFiltersFromQueryParams({
|
||||||
|
filterByAccounts,
|
||||||
|
filterByAssetClasses,
|
||||||
|
filterByTags
|
||||||
|
});
|
||||||
|
|
||||||
const performanceInformation = await this.portfolioService.getPerformance({
|
const performanceInformation = await this.portfolioService.getPerformance({
|
||||||
dateRange,
|
dateRange,
|
||||||
|
filters,
|
||||||
impersonationId,
|
impersonationId,
|
||||||
userId: this.request.user.id
|
userId: this.request.user.id
|
||||||
});
|
});
|
||||||
@ -329,12 +359,22 @@ export class PortfolioController {
|
|||||||
@UseInterceptors(TransformDataSourceInResponseInterceptor)
|
@UseInterceptors(TransformDataSourceInResponseInterceptor)
|
||||||
public async getPositions(
|
public async getPositions(
|
||||||
@Headers('impersonation-id') impersonationId: string,
|
@Headers('impersonation-id') impersonationId: string,
|
||||||
@Query('range') dateRange: DateRange = 'max'
|
@Query('accounts') filterByAccounts?: string,
|
||||||
|
@Query('assetClasses') filterByAssetClasses?: string,
|
||||||
|
@Query('range') dateRange: DateRange = 'max',
|
||||||
|
@Query('tags') filterByTags?: string
|
||||||
): Promise<PortfolioPositions> {
|
): Promise<PortfolioPositions> {
|
||||||
const result = await this.portfolioService.getPositions(
|
const filters = this.apiService.buildFiltersFromQueryParams({
|
||||||
impersonationId,
|
filterByAccounts,
|
||||||
dateRange
|
filterByAssetClasses,
|
||||||
);
|
filterByTags
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await this.portfolioService.getPositions({
|
||||||
|
dateRange,
|
||||||
|
filters,
|
||||||
|
impersonationId
|
||||||
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
impersonationId ||
|
impersonationId ||
|
||||||
|
@ -210,16 +210,19 @@ export class PortfolioService {
|
|||||||
|
|
||||||
public async getDividends({
|
public async getDividends({
|
||||||
dateRange,
|
dateRange,
|
||||||
|
filters,
|
||||||
groupBy,
|
groupBy,
|
||||||
impersonationId
|
impersonationId
|
||||||
}: {
|
}: {
|
||||||
dateRange: DateRange;
|
dateRange: DateRange;
|
||||||
|
filters?: Filter[];
|
||||||
groupBy?: GroupBy;
|
groupBy?: GroupBy;
|
||||||
impersonationId: string;
|
impersonationId: string;
|
||||||
}): Promise<InvestmentItem[]> {
|
}): Promise<InvestmentItem[]> {
|
||||||
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
||||||
|
|
||||||
const activities = await this.orderService.getOrders({
|
const activities = await this.orderService.getOrders({
|
||||||
|
filters,
|
||||||
userId,
|
userId,
|
||||||
types: ['DIVIDEND'],
|
types: ['DIVIDEND'],
|
||||||
userCurrency: this.request.user.Settings.settings.baseCurrency
|
userCurrency: this.request.user.Settings.settings.baseCurrency
|
||||||
@ -248,10 +251,12 @@ export class PortfolioService {
|
|||||||
|
|
||||||
public async getInvestments({
|
public async getInvestments({
|
||||||
dateRange,
|
dateRange,
|
||||||
|
filters,
|
||||||
groupBy,
|
groupBy,
|
||||||
impersonationId
|
impersonationId
|
||||||
}: {
|
}: {
|
||||||
dateRange: DateRange;
|
dateRange: DateRange;
|
||||||
|
filters?: Filter[];
|
||||||
groupBy?: GroupBy;
|
groupBy?: GroupBy;
|
||||||
impersonationId: string;
|
impersonationId: string;
|
||||||
}): Promise<InvestmentItem[]> {
|
}): Promise<InvestmentItem[]> {
|
||||||
@ -259,6 +264,7 @@ export class PortfolioService {
|
|||||||
|
|
||||||
const { portfolioOrders, transactionPoints } =
|
const { portfolioOrders, transactionPoints } =
|
||||||
await this.getTransactionPoints({
|
await this.getTransactionPoints({
|
||||||
|
filters,
|
||||||
userId,
|
userId,
|
||||||
includeDrafts: true
|
includeDrafts: true
|
||||||
});
|
});
|
||||||
@ -343,11 +349,13 @@ export class PortfolioService {
|
|||||||
|
|
||||||
public async getChart({
|
public async getChart({
|
||||||
dateRange = 'max',
|
dateRange = 'max',
|
||||||
|
filters,
|
||||||
impersonationId,
|
impersonationId,
|
||||||
userCurrency,
|
userCurrency,
|
||||||
userId
|
userId
|
||||||
}: {
|
}: {
|
||||||
dateRange?: DateRange;
|
dateRange?: DateRange;
|
||||||
|
filters?: Filter[];
|
||||||
impersonationId: string;
|
impersonationId: string;
|
||||||
userCurrency: string;
|
userCurrency: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
@ -356,6 +364,7 @@ export class PortfolioService {
|
|||||||
|
|
||||||
const { portfolioOrders, transactionPoints } =
|
const { portfolioOrders, transactionPoints } =
|
||||||
await this.getTransactionPoints({
|
await this.getTransactionPoints({
|
||||||
|
filters,
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -397,15 +406,15 @@ export class PortfolioService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getDetails({
|
public async getDetails({
|
||||||
impersonationId,
|
|
||||||
dateRange = 'max',
|
dateRange = 'max',
|
||||||
filters,
|
filters,
|
||||||
|
impersonationId,
|
||||||
userId,
|
userId,
|
||||||
withExcludedAccounts = false
|
withExcludedAccounts = false
|
||||||
}: {
|
}: {
|
||||||
impersonationId: string;
|
|
||||||
dateRange?: DateRange;
|
dateRange?: DateRange;
|
||||||
filters?: Filter[];
|
filters?: Filter[];
|
||||||
|
impersonationId: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
withExcludedAccounts?: boolean;
|
withExcludedAccounts?: boolean;
|
||||||
}): Promise<PortfolioDetails & { hasErrors: boolean }> {
|
}): Promise<PortfolioDetails & { hasErrors: boolean }> {
|
||||||
@ -850,14 +859,20 @@ export class PortfolioService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getPositions(
|
public async getPositions({
|
||||||
aImpersonationId: string,
|
dateRange = 'max',
|
||||||
aDateRange: DateRange = 'max'
|
filters,
|
||||||
): Promise<{ hasErrors: boolean; positions: Position[] }> {
|
impersonationId
|
||||||
const userId = await this.getUserId(aImpersonationId, this.request.user.id);
|
}: {
|
||||||
|
dateRange?: DateRange;
|
||||||
|
filters?: Filter[];
|
||||||
|
impersonationId: string;
|
||||||
|
}): Promise<{ hasErrors: boolean; positions: Position[] }> {
|
||||||
|
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
||||||
|
|
||||||
const { portfolioOrders, transactionPoints } =
|
const { portfolioOrders, transactionPoints } =
|
||||||
await this.getTransactionPoints({
|
await this.getTransactionPoints({
|
||||||
|
filters,
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -877,7 +892,7 @@ export class PortfolioService {
|
|||||||
portfolioCalculator.setTransactionPoints(transactionPoints);
|
portfolioCalculator.setTransactionPoints(transactionPoints);
|
||||||
|
|
||||||
const portfolioStart = parseDate(transactionPoints[0].date);
|
const portfolioStart = parseDate(transactionPoints[0].date);
|
||||||
const startDate = this.getStartDate(aDateRange, portfolioStart);
|
const startDate = this.getStartDate(dateRange, portfolioStart);
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
startDate
|
startDate
|
||||||
);
|
);
|
||||||
@ -928,10 +943,12 @@ export class PortfolioService {
|
|||||||
|
|
||||||
public async getPerformance({
|
public async getPerformance({
|
||||||
dateRange = 'max',
|
dateRange = 'max',
|
||||||
|
filters,
|
||||||
impersonationId,
|
impersonationId,
|
||||||
userId
|
userId
|
||||||
}: {
|
}: {
|
||||||
dateRange?: DateRange;
|
dateRange?: DateRange;
|
||||||
|
filters?: Filter[];
|
||||||
impersonationId: string;
|
impersonationId: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
}): Promise<PortfolioPerformanceResponse> {
|
}): Promise<PortfolioPerformanceResponse> {
|
||||||
@ -941,6 +958,7 @@ export class PortfolioService {
|
|||||||
|
|
||||||
const { portfolioOrders, transactionPoints } =
|
const { portfolioOrders, transactionPoints } =
|
||||||
await this.getTransactionPoints({
|
await this.getTransactionPoints({
|
||||||
|
filters,
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -996,6 +1014,7 @@ export class PortfolioService {
|
|||||||
|
|
||||||
const historicalDataContainer = await this.getChart({
|
const historicalDataContainer = await this.getChart({
|
||||||
dateRange,
|
dateRange,
|
||||||
|
filters,
|
||||||
impersonationId,
|
impersonationId,
|
||||||
userCurrency,
|
userCurrency,
|
||||||
userId
|
userId
|
||||||
|
@ -8,6 +8,7 @@ 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';
|
||||||
import {
|
import {
|
||||||
|
Filter,
|
||||||
HistoricalDataItem,
|
HistoricalDataItem,
|
||||||
Position,
|
Position,
|
||||||
User
|
User
|
||||||
@ -15,12 +16,13 @@ import {
|
|||||||
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface';
|
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface';
|
||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
import { DateRange, GroupBy, ToggleOption } from '@ghostfolio/common/types';
|
import { DateRange, GroupBy, ToggleOption } from '@ghostfolio/common/types';
|
||||||
import { DataSource, SymbolProfile } from '@prisma/client';
|
import { translate } from '@ghostfolio/ui/i18n';
|
||||||
|
import { AssetClass, DataSource, SymbolProfile } from '@prisma/client';
|
||||||
import { differenceInDays } from 'date-fns';
|
import { differenceInDays } from 'date-fns';
|
||||||
import { sortBy } from 'lodash';
|
import { sortBy } from 'lodash';
|
||||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
host: { class: 'page' },
|
host: { class: 'page' },
|
||||||
@ -29,6 +31,8 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
templateUrl: './analysis-page.html'
|
templateUrl: './analysis-page.html'
|
||||||
})
|
})
|
||||||
export class AnalysisPageComponent implements OnDestroy, OnInit {
|
export class AnalysisPageComponent implements OnDestroy, OnInit {
|
||||||
|
public activeFilters: Filter[] = [];
|
||||||
|
public allFilters: Filter[];
|
||||||
public benchmarkDataItems: HistoricalDataItem[] = [];
|
public benchmarkDataItems: HistoricalDataItem[] = [];
|
||||||
public benchmarks: Partial<SymbolProfile>[];
|
public benchmarks: Partial<SymbolProfile>[];
|
||||||
public bottom3: Position[];
|
public bottom3: Position[];
|
||||||
@ -37,6 +41,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
public deviceType: string;
|
public deviceType: string;
|
||||||
public dividendsByMonth: InvestmentItem[];
|
public dividendsByMonth: InvestmentItem[];
|
||||||
public dividendTimelineDataLabel = $localize`Dividend`;
|
public dividendTimelineDataLabel = $localize`Dividend`;
|
||||||
|
public filters$ = new Subject<Filter[]>();
|
||||||
public firstOrderDate: Date;
|
public firstOrderDate: Date;
|
||||||
public hasImpersonationId: boolean;
|
public hasImpersonationId: boolean;
|
||||||
public investments: InvestmentItem[];
|
public investments: InvestmentItem[];
|
||||||
@ -50,6 +55,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
];
|
];
|
||||||
public performanceDataItems: HistoricalDataItem[];
|
public performanceDataItems: HistoricalDataItem[];
|
||||||
public performanceDataItemsInPercentage: HistoricalDataItem[];
|
public performanceDataItemsInPercentage: HistoricalDataItem[];
|
||||||
|
public placeholder = '';
|
||||||
public portfolioEvolutionDataLabel = $localize`Deposit`;
|
public portfolioEvolutionDataLabel = $localize`Deposit`;
|
||||||
public top3: Position[];
|
public top3: Position[];
|
||||||
public user: User;
|
public user: User;
|
||||||
@ -95,12 +101,63 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
this.hasImpersonationId = !!aId;
|
this.hasImpersonationId = !!aId;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.filters$
|
||||||
|
.pipe(
|
||||||
|
distinctUntilChanged(),
|
||||||
|
map((filters) => {
|
||||||
|
this.activeFilters = filters;
|
||||||
|
this.placeholder =
|
||||||
|
this.activeFilters.length <= 0
|
||||||
|
? $localize`Filter by account or tag...`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
}),
|
||||||
|
takeUntil(this.unsubscribeSubject)
|
||||||
|
)
|
||||||
|
.subscribe(() => {});
|
||||||
|
|
||||||
this.userService.stateChanged
|
this.userService.stateChanged
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe((state) => {
|
.subscribe((state) => {
|
||||||
if (state?.user) {
|
if (state?.user) {
|
||||||
this.user = state.user;
|
this.user = state.user;
|
||||||
|
|
||||||
|
const accountFilters: Filter[] = this.user.accounts
|
||||||
|
.filter(({ accountType }) => {
|
||||||
|
return accountType === 'SECURITIES';
|
||||||
|
})
|
||||||
|
.map(({ id, name }) => {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
label: name,
|
||||||
|
type: 'ACCOUNT'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const assetClassFilters: Filter[] = [];
|
||||||
|
for (const assetClass of Object.keys(AssetClass)) {
|
||||||
|
assetClassFilters.push({
|
||||||
|
id: assetClass,
|
||||||
|
label: translate(assetClass),
|
||||||
|
type: 'ASSET_CLASS'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagFilters: Filter[] = this.user.tags.map(({ id, name }) => {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
label: name,
|
||||||
|
type: 'TAG'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.allFilters = [
|
||||||
|
...accountFilters,
|
||||||
|
...assetClassFilters,
|
||||||
|
...tagFilters
|
||||||
|
];
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -198,6 +255,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchPortfolioPerformance({
|
.fetchPortfolioPerformance({
|
||||||
|
filters: this.activeFilters,
|
||||||
range: this.user?.settings?.dateRange
|
range: this.user?.settings?.dateRange
|
||||||
})
|
})
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
@ -235,6 +293,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchDividends({
|
.fetchDividends({
|
||||||
|
filters: this.activeFilters,
|
||||||
groupBy: 'month',
|
groupBy: 'month',
|
||||||
range: this.user?.settings?.dateRange
|
range: this.user?.settings?.dateRange
|
||||||
})
|
})
|
||||||
@ -247,6 +306,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchInvestments({
|
.fetchInvestments({
|
||||||
|
filters: this.activeFilters,
|
||||||
groupBy: 'month',
|
groupBy: 'month',
|
||||||
range: this.user?.settings?.dateRange
|
range: this.user?.settings?.dateRange
|
||||||
})
|
})
|
||||||
@ -258,7 +318,10 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchPositions({ range: this.user?.settings?.dateRange })
|
.fetchPositions({
|
||||||
|
filters: this.activeFilters,
|
||||||
|
range: this.user?.settings?.dateRange
|
||||||
|
})
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(({ positions }) => {
|
.subscribe(({ positions }) => {
|
||||||
const positionsSorted = sortBy(
|
const positionsSorted = sortBy(
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
(change)="onChangeDateRange($event.value)"
|
(change)="onChangeDateRange($event.value)"
|
||||||
></gf-toggle>
|
></gf-toggle>
|
||||||
</div>
|
</div>
|
||||||
|
<gf-activities-filter
|
||||||
|
[allFilters]="allFilters"
|
||||||
|
[isLoading]="isLoadingBenchmarkComparator || isLoadingInvestmentChart"
|
||||||
|
[placeholder]="placeholder"
|
||||||
|
(valueChanged)="filters$.next($event)"
|
||||||
|
></gf-activities-filter>
|
||||||
<div class="mb-5 row">
|
<div class="mb-5 row">
|
||||||
<div class="col-lg">
|
<div class="col-lg">
|
||||||
<gf-benchmark-comparator
|
<gf-benchmark-comparator
|
||||||
|
@ -4,6 +4,7 @@ import { MatCardModule } from '@angular/material/card';
|
|||||||
import { GfBenchmarkComparatorModule } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.module';
|
import { GfBenchmarkComparatorModule } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.module';
|
||||||
import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module';
|
import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module';
|
||||||
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
|
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
|
||||||
|
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
|
||||||
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator';
|
||||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||||
@ -16,6 +17,7 @@ import { AnalysisPageComponent } from './analysis-page.component';
|
|||||||
imports: [
|
imports: [
|
||||||
AnalysisPageRoutingModule,
|
AnalysisPageRoutingModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
GfActivitiesFilterModule,
|
||||||
GfBenchmarkComparatorModule,
|
GfBenchmarkComparatorModule,
|
||||||
GfInvestmentChartModule,
|
GfInvestmentChartModule,
|
||||||
GfPremiumIndicatorModule,
|
GfPremiumIndicatorModule,
|
||||||
|
@ -102,14 +102,20 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchDividends({
|
public fetchDividends({
|
||||||
|
filters,
|
||||||
groupBy = 'month',
|
groupBy = 'month',
|
||||||
range
|
range
|
||||||
}: {
|
}: {
|
||||||
|
filters?: Filter[];
|
||||||
groupBy?: GroupBy;
|
groupBy?: GroupBy;
|
||||||
range: DateRange;
|
range: DateRange;
|
||||||
}) {
|
}) {
|
||||||
|
let params = this.buildFiltersAsQueryParams({ filters });
|
||||||
|
params = params.append('groupBy', groupBy);
|
||||||
|
params = params.append('range', range);
|
||||||
|
|
||||||
return this.http.get<PortfolioDividends>('/api/v1/portfolio/dividends', {
|
return this.http.get<PortfolioDividends>('/api/v1/portfolio/dividends', {
|
||||||
params: { groupBy, range }
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,15 +197,21 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchInvestments({
|
public fetchInvestments({
|
||||||
|
filters,
|
||||||
groupBy = 'month',
|
groupBy = 'month',
|
||||||
range
|
range
|
||||||
}: {
|
}: {
|
||||||
|
filters?: Filter[];
|
||||||
groupBy?: GroupBy;
|
groupBy?: GroupBy;
|
||||||
range: DateRange;
|
range: DateRange;
|
||||||
}) {
|
}) {
|
||||||
|
let params = this.buildFiltersAsQueryParams({ filters });
|
||||||
|
params = params.append('groupBy', groupBy);
|
||||||
|
params = params.append('range', range);
|
||||||
|
|
||||||
return this.http.get<PortfolioInvestments>(
|
return this.http.get<PortfolioInvestments>(
|
||||||
'/api/v1/portfolio/investments',
|
'/api/v1/portfolio/investments',
|
||||||
{ params: { groupBy, range } }
|
{ params }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,12 +236,17 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchPositions({
|
public fetchPositions({
|
||||||
|
filters,
|
||||||
range
|
range
|
||||||
}: {
|
}: {
|
||||||
|
filters?: Filter[];
|
||||||
range: DateRange;
|
range: DateRange;
|
||||||
}): Observable<PortfolioPositions> {
|
}): Observable<PortfolioPositions> {
|
||||||
|
let params = this.buildFiltersAsQueryParams({ filters });
|
||||||
|
params = params.append('range', range);
|
||||||
|
|
||||||
return this.http.get<PortfolioPositions>('/api/v1/portfolio/positions', {
|
return this.http.get<PortfolioPositions>('/api/v1/portfolio/positions', {
|
||||||
params: { range }
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,12 +301,19 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchPortfolioPerformance({
|
public fetchPortfolioPerformance({
|
||||||
|
filters,
|
||||||
range
|
range
|
||||||
}: {
|
}: {
|
||||||
|
filters?: Filter[];
|
||||||
range: DateRange;
|
range: DateRange;
|
||||||
}): Observable<PortfolioPerformanceResponse> {
|
}): Observable<PortfolioPerformanceResponse> {
|
||||||
|
let params = this.buildFiltersAsQueryParams({ filters });
|
||||||
|
params = params.append('range', range);
|
||||||
|
|
||||||
return this.http
|
return this.http
|
||||||
.get<any>(`/api/v2/portfolio/performance`, { params: { range } })
|
.get<any>(`/api/v2/portfolio/performance`, {
|
||||||
|
params
|
||||||
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
map((response) => {
|
map((response) => {
|
||||||
if (response.firstOrderDate) {
|
if (response.firstOrderDate) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user