From ce04656c92df378da547cbe710f18493e4f807d5 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sat, 26 Mar 2022 11:53:45 +0100 Subject: [PATCH] Refactoring and integrate in public page --- .../portfolio/portfolio-service.strategy.ts | 3 +- .../src/app/portfolio/portfolio.controller.ts | 5 +- .../app/portfolio/portfolio.service-new.ts | 15 +++--- .../allocations/allocations-page.component.ts | 48 +++++++++---------- .../allocations/allocations-page.html | 19 +++++--- .../app/pages/public/public-page.component.ts | 37 ++++++++++++++ .../src/app/pages/public/public-page.html | 28 ++++++++++- .../app/pages/public/public-page.module.ts | 2 + apps/client/src/styles.scss | 4 -- .../portfolio-position.interface.ts | 3 +- .../portfolio-public-details.interface.ts | 1 + libs/common/src/lib/types/index.ts | 2 + libs/common/src/lib/types/market.type.ts | 1 + libs/ui/src/lib/value/value.component.ts | 2 +- 14 files changed, 122 insertions(+), 48 deletions(-) create mode 100644 libs/common/src/lib/types/market.type.ts diff --git a/apps/api/src/app/portfolio/portfolio-service.strategy.ts b/apps/api/src/app/portfolio/portfolio-service.strategy.ts index 49ec0422f..a85b28852 100644 --- a/apps/api/src/app/portfolio/portfolio-service.strategy.ts +++ b/apps/api/src/app/portfolio/portfolio-service.strategy.ts @@ -13,8 +13,9 @@ export class PortfolioServiceStrategy { @Inject(REQUEST) private readonly request: RequestWithUser ) {} - public get() { + public get(newCalculationEngine?: boolean) { if ( + newCalculationEngine || this.request.user?.Settings?.settings?.['isNewCalculationEngine'] === true ) { return this.portfolioServiceNew; diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 2d7993859..1bb42a0ed 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -120,7 +120,7 @@ export class PortfolioController { const { accounts, holdings, hasErrors } = await this.portfolioServiceStrategy - .get() + .get(true) .getDetails(impersonationId, this.request.user.id, range); if (hasErrors || hasNotDefinedValuesInObject(holdings)) { @@ -277,7 +277,7 @@ export class PortfolioController { } const { holdings } = await this.portfolioServiceStrategy - .get() + .get(true) .getDetails(access.userId, access.userId); const portfolioPublicDetails: PortfolioPublicDetails = { @@ -304,6 +304,7 @@ export class PortfolioController { allocationCurrent: portfolioPosition.allocationCurrent, countries: hasDetails ? portfolioPosition.countries : [], currency: portfolioPosition.currency, + markets: portfolioPosition.markets, name: portfolioPosition.name, sectors: hasDetails ? portfolioPosition.sectors : [], value: portfolioPosition.value / totalValue diff --git a/apps/api/src/app/portfolio/portfolio.service-new.ts b/apps/api/src/app/portfolio/portfolio.service-new.ts index f74cd2719..63b8544a8 100644 --- a/apps/api/src/app/portfolio/portfolio.service-new.ts +++ b/apps/api/src/app/portfolio/portfolio.service-new.ts @@ -40,6 +40,7 @@ import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.in import type { AccountWithValue, DateRange, + Market, OrderWithAccount, RequestWithUser } from '@ghostfolio/common/types'; @@ -384,23 +385,23 @@ export class PortfolioServiceNew { const symbolProfile = symbolProfileMap[item.symbol]; const dataProviderResponse = dataProviderResponses[item.symbol]; - const markets = { - DEVELOPED_MARKETS: 0, - EMERGING_MARKETS: 0, - OTHER_MARKETS: 0 + const markets: { [key in Market]: number } = { + developedMarkets: 0, + emergingMarkets: 0, + otherMarkets: 0 }; for (const country of symbolProfile.countries) { if (developedMarkets.includes(country.code)) { - markets.DEVELOPED_MARKETS = new Big(markets.DEVELOPED_MARKETS) + markets.developedMarkets = new Big(markets.developedMarkets) .plus(country.weight) .toNumber(); } else if (emergingMarkets.includes(country.code)) { - markets.EMERGING_MARKETS = new Big(markets.EMERGING_MARKETS) + markets.emergingMarkets = new Big(markets.emergingMarkets) .plus(country.weight) .toNumber(); } else { - markets.OTHER_MARKETS = new Big(markets.OTHER_MARKETS) + markets.otherMarkets = new Big(markets.otherMarkets) .plus(country.weight) .toNumber(); } diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index c9267defd..e0636dc7d 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -14,7 +14,7 @@ import { User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { ToggleOption } from '@ghostfolio/common/types'; +import { Market, ToggleOption } from '@ghostfolio/common/types'; import { Account, AssetClass, DataSource } from '@prisma/client'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, Subscription } from 'rxjs'; @@ -43,7 +43,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { public hasImpersonationId: boolean; public hasPermissionToCreateOrder: boolean; public markets: { - [market: string]: { name: string; value: number }; + [key in Market]: { name: string; value: number }; }; public period = 'current'; public periodOptions: ToggleOption[] = [ @@ -164,16 +164,16 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { } }; this.markets = { - DEVELOPED_MARKETS: { - name: 'DEVELOPED_MARKETS', + developedMarkets: { + name: 'developedMarkets', value: 0 }, - EMERGING_MARKETS: { - name: 'EMERGING_MARKETS', + emergingMarkets: { + name: 'emergingMarkets', value: 0 }, - OTHER_MARKETS: { - name: 'OTHER_MARKETS', + otherMarkets: { + name: 'otherMarkets', value: 0 } }; @@ -236,14 +236,14 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { // Prepare analysis data by continents, countries and sectors except for cash if (position.countries.length > 0) { - this.markets['DEVELOPED_MARKETS'].value += - position.markets['DEVELOPED_MARKETS'] * + this.markets['developedMarkets'].value += + position.markets['developedMarkets'] * (aPeriod === 'original' ? position.investment : position.value); - this.markets['EMERGING_MARKETS'].value += - position.markets['EMERGING_MARKETS'] * + this.markets['emergingMarkets'].value += + position.markets['emergingMarkets'] * (aPeriod === 'original' ? position.investment : position.value); - this.markets['OTHER_MARKETS'].value += - position.markets['OTHER_MARKETS'] * + this.markets['otherMarkets'].value += + position.markets['otherMarkets'] * (aPeriod === 'original' ? position.investment : position.value); for (const country of position.countries) { @@ -323,16 +323,16 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { } const marketsTotal = - this.markets['DEVELOPED_MARKETS'].value + - this.markets['EMERGING_MARKETS'].value + - this.markets['OTHER_MARKETS'].value; - - this.markets['DEVELOPED_MARKETS'].value = - this.markets['DEVELOPED_MARKETS'].value / marketsTotal; - this.markets['EMERGING_MARKETS'].value = - this.markets['EMERGING_MARKETS'].value / marketsTotal; - this.markets['OTHER_MARKETS'].value = - this.markets['OTHER_MARKETS'].value / marketsTotal; + this.markets.developedMarkets.value + + this.markets.emergingMarkets.value + + this.markets.otherMarkets.value; + + this.markets.developedMarkets.value = + this.markets.developedMarkets.value / marketsTotal; + this.markets.emergingMarkets.value = + this.markets.emergingMarkets.value / marketsTotal; + this.markets.otherMarkets.value = + this.markets.otherMarkets.value / marketsTotal; } public onChangePeriod(aValue: string) { diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html index 0abb19837..c34eebadd 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html @@ -191,26 +191,31 @@ [isInPercent]="hasImpersonationId || user.settings.isRestrictedView" >
-
+
-
+
-
+
diff --git a/apps/client/src/app/pages/public/public-page.component.ts b/apps/client/src/app/pages/public/public-page.component.ts index a3ac43721..aea98e471 100644 --- a/apps/client/src/app/pages/public/public-page.component.ts +++ b/apps/client/src/app/pages/public/public-page.component.ts @@ -7,6 +7,7 @@ import { PortfolioPosition, PortfolioPublicDetails } from '@ghostfolio/common/interfaces'; +import { Market } from '@ghostfolio/common/types'; import { StatusCodes } from 'http-status-codes'; import { DeviceDetectorService } from 'ngx-device-detector'; import { EMPTY, Subject } from 'rxjs'; @@ -26,6 +27,9 @@ export class PublicPageComponent implements OnInit { [code: string]: { name: string; value: number }; }; public deviceType: string; + public markets: { + [key in Market]: { name: string; value: number }; + }; public portfolioPublicDetails: PortfolioPublicDetails; public positions: { [symbol: string]: Pick; @@ -96,6 +100,20 @@ export class PublicPageComponent implements OnInit { value: 0 } }; + this.markets = { + developedMarkets: { + name: 'developedMarkets', + value: 0 + }, + emergingMarkets: { + name: 'emergingMarkets', + value: 0 + }, + otherMarkets: { + name: 'otherMarkets', + value: 0 + } + }; this.positions = {}; this.sectors = { [UNKNOWN_KEY]: { @@ -123,6 +141,13 @@ export class PublicPageComponent implements OnInit { }; if (position.countries.length > 0) { + this.markets.developedMarkets.value += + position.markets.developedMarkets * position.value; + this.markets.emergingMarkets.value += + position.markets.emergingMarkets * position.value; + this.markets.otherMarkets.value += + position.markets.otherMarkets * position.value; + for (const country of position.countries) { const { code, continent, name, weight } = country; @@ -176,6 +201,18 @@ export class PublicPageComponent implements OnInit { value: position.value }; } + + const marketsTotal = + this.markets.developedMarkets.value + + this.markets.emergingMarkets.value + + this.markets.otherMarkets.value; + + this.markets.developedMarkets.value = + this.markets.developedMarkets.value / marketsTotal; + this.markets.emergingMarkets.value = + this.markets.emergingMarkets.value / marketsTotal; + this.markets.otherMarkets.value = + this.markets.otherMarkets.value / marketsTotal; } public ngOnDestroy() { diff --git a/apps/client/src/app/pages/public/public-page.html b/apps/client/src/app/pages/public/public-page.html index 49edef614..5af657d67 100644 --- a/apps/client/src/app/pages/public/public-page.html +++ b/apps/client/src/app/pages/public/public-page.html @@ -79,12 +79,38 @@ [countries]="countries" [isInPercent]="true" > +
+
+ +
+
+ +
+
+ +
+
-
+

Would you like to refine your personal investment strategy? diff --git a/apps/client/src/app/pages/public/public-page.module.ts b/apps/client/src/app/pages/public/public-page.module.ts index e7818ede2..21a3b4f7b 100644 --- a/apps/client/src/app/pages/public/public-page.module.ts +++ b/apps/client/src/app/pages/public/public-page.module.ts @@ -4,6 +4,7 @@ import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; +import { GfValueModule } from '@ghostfolio/ui/value'; import { PublicPageRoutingModule } from './public-page-routing.module'; import { PublicPageComponent } from './public-page.component'; @@ -14,6 +15,7 @@ import { PublicPageComponent } from './public-page.component'; imports: [ CommonModule, GfPortfolioProportionChartModule, + GfValueModule, GfWorldMapChartModule, MatButtonModule, MatCardModule, diff --git a/apps/client/src/styles.scss b/apps/client/src/styles.scss index 81fefd2ee..ed670f1d4 100644 --- a/apps/client/src/styles.scss +++ b/apps/client/src/styles.scss @@ -184,10 +184,6 @@ ngx-skeleton-loader { text-decoration: underline !important; } -.width-auto { - width: auto; -} - .with-info-message { height: calc(100vh - 5rem - 3.5rem) !important; } diff --git a/libs/common/src/lib/interfaces/portfolio-position.interface.ts b/libs/common/src/lib/interfaces/portfolio-position.interface.ts index 65dc563aa..9250e5ff6 100644 --- a/libs/common/src/lib/interfaces/portfolio-position.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-position.interface.ts @@ -1,5 +1,6 @@ import { MarketState } from '@ghostfolio/api/services/interfaces/interfaces'; import { AssetClass, AssetSubClass, DataSource } from '@prisma/client'; +import { Market } from '../types'; import { Country } from './country.interface'; import { Sector } from './sector.interface'; @@ -19,7 +20,7 @@ export interface PortfolioPosition { marketChange?: number; marketChangePercent?: number; marketPrice: number; - markets?: { [market: string]: number }; + markets?: { [key in Market]: number }; marketState: MarketState; name: string; netPerformance: number; diff --git a/libs/common/src/lib/interfaces/portfolio-public-details.interface.ts b/libs/common/src/lib/interfaces/portfolio-public-details.interface.ts index b24df034e..10fb4edfd 100644 --- a/libs/common/src/lib/interfaces/portfolio-public-details.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-public-details.interface.ts @@ -8,6 +8,7 @@ export interface PortfolioPublicDetails { | 'allocationCurrent' | 'countries' | 'currency' + | 'markets' | 'name' | 'sectors' | 'value' diff --git a/libs/common/src/lib/types/index.ts b/libs/common/src/lib/types/index.ts index 6953b5863..40ba51272 100644 --- a/libs/common/src/lib/types/index.ts +++ b/libs/common/src/lib/types/index.ts @@ -2,6 +2,7 @@ import type { AccessWithGranteeUser } from './access-with-grantee-user.type'; import { AccountWithValue } from './account-with-value.type'; import type { DateRange } from './date-range.type'; import type { Granularity } from './granularity.type'; +import { Market } from './market.type'; import type { OrderWithAccount } from './order-with-account.type'; import type { RequestWithUser } from './request-with-user.type'; import { ToggleOption } from './toggle-option.type'; @@ -11,6 +12,7 @@ export type { AccountWithValue, DateRange, Granularity, + Market, OrderWithAccount, RequestWithUser, ToggleOption diff --git a/libs/common/src/lib/types/market.type.ts b/libs/common/src/lib/types/market.type.ts new file mode 100644 index 000000000..d6981d256 --- /dev/null +++ b/libs/common/src/lib/types/market.type.ts @@ -0,0 +1 @@ +export type Market = 'developedMarkets' | 'emergingMarkets' | 'otherMarkets'; diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts index 29863e9bd..c0be260c0 100644 --- a/libs/ui/src/lib/value/value.component.ts +++ b/libs/ui/src/lib/value/value.component.ts @@ -21,7 +21,7 @@ export class ValueComponent implements OnChanges { @Input() isCurrency = false; @Input() isPercent = false; @Input() label = ''; - @Input() locale = ''; + @Input() locale = 'en-US'; @Input() position = ''; @Input() precision: number | undefined; @Input() size: 'large' | 'medium' | 'small' = 'small';