Feature/extend public page (#445)
* Extend public page * Update changelog
This commit is contained in:
parent
e7fb31d1a6
commit
1397cd62a8
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- Added more details to the public page (currencies, sectors, continents and regions)
|
||||
- Added a `Dockerfile` and documentation to build a _Docker_ image
|
||||
|
||||
## 1.66.0 - 30.10.2021
|
||||
|
@ -266,18 +266,27 @@ export class PortfolioController {
|
||||
@Res() res: Response
|
||||
): Promise<PortfolioPublicDetails> {
|
||||
const access = await this.accessService.access({ id: accessId });
|
||||
const user = await this.userService.user({
|
||||
id: access.userId
|
||||
});
|
||||
|
||||
if (!access) {
|
||||
res.status(StatusCodes.NOT_FOUND);
|
||||
return <any>res.json({ accounts: {}, holdings: {} });
|
||||
}
|
||||
|
||||
let hasDetails = true;
|
||||
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
|
||||
hasDetails = user.subscription.type === 'Premium';
|
||||
}
|
||||
|
||||
const { holdings } = await this.portfolioService.getDetails(
|
||||
access.userId,
|
||||
access.userId
|
||||
);
|
||||
|
||||
const portfolioPublicDetails: PortfolioPublicDetails = {
|
||||
hasDetails,
|
||||
holdings: {}
|
||||
};
|
||||
|
||||
@ -298,9 +307,10 @@ export class PortfolioController {
|
||||
if (portfolioPosition.assetClass === 'EQUITY') {
|
||||
portfolioPublicDetails.holdings[symbol] = {
|
||||
allocationCurrent: portfolioPosition.allocationCurrent,
|
||||
countries: [],
|
||||
countries: hasDetails ? portfolioPosition.countries : [],
|
||||
currency: portfolioPosition.currency,
|
||||
name: portfolioPosition.name,
|
||||
sectors: [],
|
||||
sectors: hasDetails ? portfolioPosition.sectors : [],
|
||||
value: portfolioPosition.value / totalValue
|
||||
};
|
||||
}
|
||||
|
@ -159,9 +159,9 @@
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<gf-portfolio-proportion-chart
|
||||
[keys]="['name']"
|
||||
[baseCurrency]="user?.settings?.baseCurrency"
|
||||
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
|
||||
[keys]="['name']"
|
||||
[locale]="user?.settings?.locale"
|
||||
[maxItems]="10"
|
||||
[positions]="countries"
|
||||
|
@ -27,7 +27,7 @@ export class PublicPageComponent implements OnInit {
|
||||
public deviceType: string;
|
||||
public portfolioPublicDetails: PortfolioPublicDetails;
|
||||
public positions: {
|
||||
[symbol: string]: Pick<PortfolioPosition, 'name' | 'value'>;
|
||||
[symbol: string]: Pick<PortfolioPosition, 'currency' | 'name' | 'value'>;
|
||||
};
|
||||
public sectors: {
|
||||
[name: string]: { name: string; value: number };
|
||||
@ -117,6 +117,7 @@ export class PublicPageComponent implements OnInit {
|
||||
|
||||
this.positions[symbol] = {
|
||||
value,
|
||||
currency: position.currency,
|
||||
name: position.name
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
<div class="proportion-charts row">
|
||||
<div class="col-md-12 allocations-by-symbol">
|
||||
<mat-card class="mb-3">
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="text-truncate" i18n>Symbols</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<gf-portfolio-proportion-chart
|
||||
class="mx-auto"
|
||||
@ -20,6 +23,65 @@
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div *ngIf="portfolioPublicDetails?.hasDetails" class="col-md-4">
|
||||
<mat-card class="mb-3">
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="text-truncate" i18n>Currencies</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<gf-portfolio-proportion-chart
|
||||
[isInPercent]="true"
|
||||
[keys]="['currency']"
|
||||
[maxItems]="10"
|
||||
[positions]="positions"
|
||||
></gf-portfolio-proportion-chart>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div *ngIf="portfolioPublicDetails?.hasDetails" class="col-md-4">
|
||||
<mat-card class="mb-3">
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="text-truncate" i18n>Sectors</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<gf-portfolio-proportion-chart
|
||||
[isInPercent]="true"
|
||||
[keys]="['name']"
|
||||
[maxItems]="10"
|
||||
[positions]="sectors"
|
||||
></gf-portfolio-proportion-chart>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div *ngIf="portfolioPublicDetails?.hasDetails" class="col-md-4">
|
||||
<mat-card class="mb-3">
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="text-truncate" i18n>Continents</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<gf-portfolio-proportion-chart
|
||||
[isInPercent]="true"
|
||||
[keys]="['name']"
|
||||
[positions]="continents"
|
||||
></gf-portfolio-proportion-chart>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="portfolioPublicDetails?.hasDetails" class="row world-map-chart">
|
||||
<div class="col-lg">
|
||||
<mat-card class="mb-3">
|
||||
<mat-card-header class="overflow-hidden w-100">
|
||||
<mat-card-title class="text-truncate" i18n>Regions</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<gf-world-map-chart
|
||||
[countries]="countries"
|
||||
[isInPercent]="true"
|
||||
></gf-world-map-chart>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-5">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
|
@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
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 { PublicPageRoutingModule } from './public-page-routing.module';
|
||||
@ -13,6 +14,7 @@ import { PublicPageComponent } from './public-page.component';
|
||||
imports: [
|
||||
CommonModule,
|
||||
GfPortfolioProportionChartModule,
|
||||
GfWorldMapChartModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
PublicPageRoutingModule
|
||||
|
@ -2,9 +2,19 @@
|
||||
color: rgb(var(--dark-primary-text));
|
||||
display: block;
|
||||
|
||||
.allocations-by-symbol {
|
||||
gf-portfolio-proportion-chart {
|
||||
max-width: 80vh;
|
||||
}
|
||||
}
|
||||
|
||||
.world-map-chart {
|
||||
.mat-card {
|
||||
.mat-card-content {
|
||||
aspect-ratio: 16 / 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:host-context(.is-dark-theme) {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 289 KiB |
@ -1,10 +1,16 @@
|
||||
import { PortfolioPosition } from '@ghostfolio/common/interfaces';
|
||||
|
||||
export interface PortfolioPublicDetails {
|
||||
hasDetails: boolean;
|
||||
holdings: {
|
||||
[symbol: string]: Pick<
|
||||
PortfolioPosition,
|
||||
'allocationCurrent' | 'countries' | 'name' | 'sectors' | 'value'
|
||||
| 'allocationCurrent'
|
||||
| 'countries'
|
||||
| 'currency'
|
||||
| 'name'
|
||||
| 'sectors'
|
||||
| 'value'
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
@ -318,10 +318,10 @@ export class PortfolioProportionChartComponent
|
||||
type: 'doughnut'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Color palette, inspired by https://yeun.github.io/open-color
|
||||
|
Loading…
x
Reference in New Issue
Block a user