Browse Source

Feature/restructure page hierarchy (#259)

* Introduce portfolio group, remove tools

* Extract allocations to separate page

* Update changelog
pull/263/head
Thomas 4 years ago
committed by GitHub
parent
commit
f743c03e17
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      CHANGELOG.md
  2. 55
      apps/client/src/app/app-routing.module.ts
  3. 35
      apps/client/src/app/components/header/header.component.html
  4. 2
      apps/client/src/app/components/no-transactions-info/no-transactions-info.component.html
  5. 2
      apps/client/src/app/components/positions-table/positions-table.component.html
  6. 2
      apps/client/src/app/pages/home/home-page.html
  7. 15
      apps/client/src/app/pages/portfolio/allocations/allocations-page-routing.module.ts
  8. 25
      apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
  9. 34
      apps/client/src/app/pages/portfolio/allocations/allocations-page.html
  10. 12
      apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts
  11. 12
      apps/client/src/app/pages/portfolio/allocations/allocations-page.scss
  12. 0
      apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts
  13. 92
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  14. 20
      apps/client/src/app/pages/portfolio/analysis/analysis-page.html
  15. 21
      apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts
  16. 9
      apps/client/src/app/pages/portfolio/analysis/analysis-page.scss
  17. 6
      apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts
  18. 44
      apps/client/src/app/pages/portfolio/portfolio-page.component.ts
  19. 83
      apps/client/src/app/pages/portfolio/portfolio-page.html
  20. 12
      apps/client/src/app/pages/portfolio/portfolio-page.module.ts
  21. 0
      apps/client/src/app/pages/portfolio/portfolio-page.scss
  22. 0
      apps/client/src/app/pages/portfolio/report/report-page-routing.module.ts
  23. 0
      apps/client/src/app/pages/portfolio/report/report-page.component.ts
  24. 0
      apps/client/src/app/pages/portfolio/report/report-page.html
  25. 0
      apps/client/src/app/pages/portfolio/report/report-page.module.ts
  26. 0
      apps/client/src/app/pages/portfolio/report/report-page.scss
  27. 2
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts
  28. 0
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html
  29. 0
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.module.ts
  30. 0
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.scss
  31. 0
      apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/interfaces/interfaces.ts
  32. 0
      apps/client/src/app/pages/portfolio/transactions/transactions-page-routing.module.ts
  33. 0
      apps/client/src/app/pages/portfolio/transactions/transactions-page.component.ts
  34. 0
      apps/client/src/app/pages/portfolio/transactions/transactions-page.html
  35. 0
      apps/client/src/app/pages/portfolio/transactions/transactions-page.module.ts
  36. 0
      apps/client/src/app/pages/portfolio/transactions/transactions-page.scss
  37. 21
      apps/client/src/app/pages/tools/tools-page.component.ts
  38. 43
      apps/client/src/app/pages/tools/tools-page.html
  39. 2
      apps/client/src/app/pages/zen/zen-page.html

4
CHANGELOG.md

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Changed
- Restructured the page hierarchy
### Fixed ### Fixed
- Fixed an issue with the currency conversion of the market price in the position detail dialog - Fixed an issue with the currency conversion of the market price in the position detail dialog

55
apps/client/src/app/app-routing.module.ts

@ -53,57 +53,66 @@ const routes: Routes = [
import('./pages/home/home-page.module').then((m) => m.HomePageModule) import('./pages/home/home-page.module').then((m) => m.HomePageModule)
}, },
{ {
path: 'pricing', path: 'portfolio',
loadChildren: () => loadChildren: () =>
import('./pages/pricing/pricing-page.module').then( import('./pages/portfolio/portfolio-page.module').then(
(m) => m.PricingPageModule (m) => m.PortfolioPageModule
) )
}, },
{ {
path: 'register', path: 'portfolio/allocations',
loadChildren: () => loadChildren: () =>
import('./pages/register/register-page.module').then( import('./pages/portfolio/allocations/allocations-page.module').then(
(m) => m.RegisterPageModule (m) => m.AllocationsPageModule
) )
}, },
{ {
path: 'resources', path: 'portfolio/analysis',
loadChildren: () => loadChildren: () =>
import('./pages/resources/resources-page.module').then( import('./pages/portfolio/analysis/analysis-page.module').then(
(m) => m.ResourcesPageModule (m) => m.AnalysisPageModule
) )
}, },
{ {
path: 'start', path: 'portfolio/report',
loadChildren: () => loadChildren: () =>
import('./pages/landing/landing-page.module').then( import('./pages/portfolio/report/report-page.module').then(
(m) => m.LandingPageModule (m) => m.ReportPageModule
) )
}, },
{ {
path: 'tools', path: 'portfolio/transactions',
loadChildren: () => loadChildren: () =>
import('./pages/tools/tools-page.module').then((m) => m.ToolsPageModule) import('./pages/portfolio/transactions/transactions-page.module').then(
(m) => m.TransactionsPageModule
)
}, },
{ {
path: 'tools/analysis', path: 'pricing',
loadChildren: () => loadChildren: () =>
import('./pages/tools/analysis/analysis-page.module').then( import('./pages/pricing/pricing-page.module').then(
(m) => m.AnalysisPageModule (m) => m.PricingPageModule
) )
}, },
{ {
path: 'tools/report', path: 'register',
loadChildren: () => loadChildren: () =>
import('./pages/tools/report/report-page.module').then( import('./pages/register/register-page.module').then(
(m) => m.ReportPageModule (m) => m.RegisterPageModule
) )
}, },
{ {
path: 'transactions', path: 'resources',
loadChildren: () => loadChildren: () =>
import('./pages/transactions/transactions-page.module').then( import('./pages/resources/resources-page.module').then(
(m) => m.TransactionsPageModule (m) => m.ResourcesPageModule
)
},
{
path: 'start',
loadChildren: () =>
import('./pages/landing/landing-page.module').then(
(m) => m.LandingPageModule
) )
}, },
{ {

35
apps/client/src/app/components/header/header.component.html

@ -22,27 +22,22 @@
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': 'font-weight-bold': currentRoute === 'portfolio',
currentRoute === 'analysis' || 'text-decoration-underline': currentRoute === 'portfolio'
currentRoute === 'report' ||
currentRoute === 'tools',
'text-decoration-underline':
currentRoute === 'analysis' ||
currentRoute === 'report' ||
currentRoute === 'tools'
}" }"
[routerLink]="['/tools']" [routerLink]="['/portfolio']"
>Tools</a >Portfolio</a
> >
<a <a
*ngIf="user?.settings?.viewMode !== 'DEFAULT'"
class="d-none d-sm-block mx-1" class="d-none d-sm-block mx-1"
i18n i18n
mat-flat-button mat-flat-button
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'transactions', 'font-weight-bold': currentRoute === 'portfolio',
'text-decoration-underline': currentRoute === 'transactions' 'text-decoration-underline': currentRoute === 'portfolio'
}" }"
[routerLink]="['/transactions']" [routerLink]="['/portfolio', 'transactions']"
>Transactions</a >Transactions</a
> >
<a <a
@ -166,22 +161,20 @@
i18n i18n
mat-menu-item mat-menu-item
[ngClass]="{ [ngClass]="{
'font-weight-bold': 'font-weight-bold': currentRoute === 'portfolio'
currentRoute === 'analysis' ||
currentRoute === 'report' ||
currentRoute === 'tools'
}" }"
[routerLink]="['/tools']" [routerLink]="['/portfolio']"
>Tools</a >Portfolio</a
> >
<a <a
*ngIf="user?.settings?.viewMode !== 'DEFAULT'"
class="d-block d-sm-none" class="d-block d-sm-none"
i18n i18n
mat-menu-item mat-menu-item
[ngClass]="{ [ngClass]="{
'font-weight-bold': currentRoute === 'transactions' 'font-weight-bold': currentRoute === 'portfolio'
}" }"
[routerLink]="['/transactions']" [routerLink]="['/portfolio', 'transactions']"
>Transactions</a >Transactions</a
> >
<a <a

2
apps/client/src/app/components/no-transactions-info/no-transactions-info.component.html

@ -5,7 +5,7 @@
<a <a
class="align-items-center justify-content-center" class="align-items-center justify-content-center"
color="primary" color="primary"
[routerLink]="['/transactions']" [routerLink]="['/portfolio', 'transactions']"
mat-button mat-button
> >
<span i18n>Time to add your first transaction.</span> <span i18n>Time to add your first transaction.</span>

2
apps/client/src/app/components/positions-table/positions-table.component.html

@ -111,7 +111,7 @@
class="my-3 text-center" class="my-3 text-center"
> >
<button i18n mat-stroked-button (click)="onShowAllPositions()"> <button i18n mat-stroked-button (click)="onShowAllPositions()">
Show all positions... Show all...
</button> </button>
</div> </div>

2
apps/client/src/app/pages/home/home-page.html

@ -79,7 +79,7 @@
<ion-icon name="wallet-outline" size="large"></ion-icon> <ion-icon name="wallet-outline" size="large"></ion-icon>
</ng-template> </ng-template>
<div class="container justify-content-center pb-3 px-3 positions"> <div class="container justify-content-center pb-3 px-3 positions">
<h3 class="d-flex justify-content-center mb-3" i18n>Positions</h3> <h3 class="d-flex justify-content-center mb-3" i18n>Holdings</h3>
<div class="row"> <div class="row">
<div class="align-items-center col"> <div class="align-items-center col">
<div class="pb-2 text-center"> <div class="pb-2 text-center">

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

@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { AllocationsPageComponent } from './allocations-page.component';
const routes: Routes = [
{ path: '', component: AllocationsPageComponent, canActivate: [AuthGuard] }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AllocationsPageRoutingModule {}

25
apps/client/src/app/pages/tools/analysis/analysis-page.component.ts → apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts

@ -4,22 +4,17 @@ 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 { UNKNOWN_KEY } from '@ghostfolio/common/config'; import { UNKNOWN_KEY } from '@ghostfolio/common/config';
import { import { PortfolioPosition, User } from '@ghostfolio/common/interfaces';
PortfolioItem,
PortfolioPosition,
User
} from '@ghostfolio/common/interfaces';
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface';
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 { takeUntil } from 'rxjs/operators';
@Component({ @Component({
selector: 'gf-analysis-page', selector: 'gf-allocations-page',
templateUrl: './analysis-page.html', templateUrl: './allocations-page.html',
styleUrls: ['./analysis-page.scss'] styleUrls: ['./allocations-page.scss']
}) })
export class AnalysisPageComponent implements OnDestroy, OnInit { export class AllocationsPageComponent implements OnDestroy, OnInit {
public accounts: { public accounts: {
[symbol: string]: Pick<PortfolioPosition, 'name'> & { value: number }; [symbol: string]: Pick<PortfolioPosition, 'name'> & { value: number };
}; };
@ -36,7 +31,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
{ label: 'Initial', value: 'original' }, { label: 'Initial', value: 'original' },
{ label: 'Current', value: 'current' } { label: 'Current', value: 'current' }
]; ];
public investments: InvestmentItem[];
public portfolioPositions: { [symbol: string]: PortfolioPosition }; public portfolioPositions: { [symbol: string]: PortfolioPosition };
public positions: { [symbol: string]: any }; public positions: { [symbol: string]: any };
public positionsArray: PortfolioPosition[]; public positionsArray: PortfolioPosition[];
@ -71,15 +65,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
this.hasImpersonationId = !!aId; this.hasImpersonationId = !!aId;
}); });
this.dataService
.fetchInvestments()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((response) => {
this.investments = response;
this.changeDetectorRef.markForCheck();
});
this.dataService this.dataService
.fetchPortfolioPositions({}) .fetchPortfolioPositions({})
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))

34
apps/client/src/app/pages/tools/analysis/analysis-page.html → apps/client/src/app/pages/portfolio/allocations/allocations-page.html

@ -1,16 +1,14 @@
<div class="container"> <div class="container">
<div class="mb-5 row"> <div class="mb-5 row">
<div class="col"> <div class="col">
<h3 class="d-flex justify-content-center mb-3" i18n>Analysis</h3> <h3 class="d-flex justify-content-center mb-3" i18n>Allocations</h3>
<div class="mb-4"> <gf-positions-table
<h4 class="m-0" i18n>Positions</h4> class="mb-4"
<gf-positions-table [baseCurrency]="user?.settings?.baseCurrency"
[baseCurrency]="user?.settings?.baseCurrency" [deviceType]="deviceType"
[deviceType]="deviceType" [locale]="user?.settings?.locale"
[locale]="user?.settings?.locale" [positions]="positionsArray"
[positions]="positionsArray" ></gf-positions-table>
></gf-positions-table>
</div>
</div> </div>
</div> </div>
<div class="proportion-charts row"> <div class="proportion-charts row">
@ -192,20 +190,4 @@
</mat-card> </mat-card>
</div> </div>
</div> </div>
<div class="investment-chart row">
<div class="col-lg">
<mat-card class="mb-3">
<mat-card-header>
<mat-card-title class="align-items-center d-flex" i18n
>Timeline</mat-card-title
>
</mat-card-header>
<mat-card-content>
<gf-investment-chart
[investments]='investments'
></gf-investment-chart>
</mat-card-content>
</mat-card>
</div>
</div>
</div> </div>

12
apps/client/src/app/pages/tools/analysis/analysis-page.module.ts → apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts

@ -1,22 +1,20 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module';
import { PortfolioProportionChartModule } from '@ghostfolio/client/components/portfolio-proportion-chart/portfolio-proportion-chart.module'; import { PortfolioProportionChartModule } from '@ghostfolio/client/components/portfolio-proportion-chart/portfolio-proportion-chart.module';
import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-table/positions-table.module'; import { GfPositionsTableModule } from '@ghostfolio/client/components/positions-table/positions-table.module';
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
import { AnalysisPageRoutingModule } from './analysis-page-routing.module'; import { AllocationsPageRoutingModule } from './allocations-page-routing.module';
import { AnalysisPageComponent } from './analysis-page.component'; import { AllocationsPageComponent } from './allocations-page.component';
@NgModule({ @NgModule({
declarations: [AnalysisPageComponent], declarations: [AllocationsPageComponent],
exports: [], exports: [],
imports: [ imports: [
AnalysisPageRoutingModule, AllocationsPageRoutingModule,
CommonModule, CommonModule,
GfInvestmentChartModule,
GfPositionsTableModule, GfPositionsTableModule,
GfToggleModule, GfToggleModule,
GfWorldMapChartModule, GfWorldMapChartModule,
@ -26,4 +24,4 @@ import { AnalysisPageComponent } from './analysis-page.component';
providers: [], providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]
}) })
export class AnalysisPageModule {} export class AllocationsPageModule {}

12
apps/client/src/app/pages/tools/analysis/analysis-page.scss → apps/client/src/app/pages/portfolio/allocations/allocations-page.scss

@ -1,16 +1,4 @@
:host { :host {
.investment-chart {
.mat-card {
.mat-card-content {
aspect-ratio: 16 / 9;
gf-investment-chart {
height: 100%;
}
}
}
}
.proportion-charts { .proportion-charts {
.mat-card { .mat-card {
.mat-card-content { .mat-card-content {

0
apps/client/src/app/pages/tools/analysis/analysis-page-routing.module.ts → apps/client/src/app/pages/portfolio/analysis/analysis-page-routing.module.ts

92
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -0,0 +1,92 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { ToggleOption } from '@ghostfolio/client/components/toggle/interfaces/toggle-option.type';
import { DataService } from '@ghostfolio/client/services/data.service';
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { PortfolioPosition, User } from '@ghostfolio/common/interfaces';
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'gf-analysis-page',
templateUrl: './analysis-page.html',
styleUrls: ['./analysis-page.scss']
})
export class AnalysisPageComponent implements OnDestroy, OnInit {
public accounts: {
[symbol: string]: Pick<PortfolioPosition, 'name'> & { value: number };
};
public continents: {
[code: string]: { name: string; value: number };
};
public countries: {
[code: string]: { name: string; value: number };
};
public deviceType: string;
public hasImpersonationId: boolean;
public period = 'current';
public periodOptions: ToggleOption[] = [
{ label: 'Initial', value: 'original' },
{ label: 'Current', value: 'current' }
];
public investments: InvestmentItem[];
public portfolioPositions: { [symbol: string]: PortfolioPosition };
public positions: { [symbol: string]: any };
public sectors: {
[name: string]: { name: string; value: number };
};
public user: User;
private unsubscribeSubject = new Subject<void>();
/**
* @constructor
*/
public constructor(
private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService,
private deviceService: DeviceDetectorService,
private impersonationStorageService: ImpersonationStorageService,
private userService: UserService
) {}
/**
* Initializes the controller
*/
public ngOnInit() {
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
this.impersonationStorageService
.onChangeHasImpersonation()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((aId) => {
this.hasImpersonationId = !!aId;
});
this.dataService
.fetchInvestments()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((response) => {
this.investments = response;
this.changeDetectorRef.markForCheck();
});
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => {
if (state?.user) {
this.user = state.user;
this.changeDetectorRef.markForCheck();
}
});
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
}

20
apps/client/src/app/pages/portfolio/analysis/analysis-page.html

@ -0,0 +1,20 @@
<div class="container">
<div class="investment-chart row">
<div class="col-lg">
<h3 class="d-flex justify-content-center mb-3" i18n>Analysis</h3>
<mat-card class="mb-3">
<mat-card-header>
<mat-card-title class="align-items-center d-flex" i18n
>Timeline</mat-card-title
>
</mat-card-header>
<mat-card-content>
<gf-investment-chart
class="h-100"
[investments]="investments"
></gf-investment-chart>
</mat-card-content>
</mat-card>
</div>
</div>
</div>

21
apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts

@ -0,0 +1,21 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module';
import { AnalysisPageRoutingModule } from './analysis-page-routing.module';
import { AnalysisPageComponent } from './analysis-page.component';
@NgModule({
declarations: [AnalysisPageComponent],
exports: [],
imports: [
AnalysisPageRoutingModule,
CommonModule,
GfInvestmentChartModule,
MatCardModule
],
providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AnalysisPageModule {}

9
apps/client/src/app/pages/portfolio/analysis/analysis-page.scss

@ -0,0 +1,9 @@
:host {
.investment-chart {
.mat-card {
.mat-card-content {
aspect-ratio: 16 / 9;
}
}
}
}

6
apps/client/src/app/pages/tools/tools-page-routing.module.ts → apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts

@ -2,14 +2,14 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { ToolsPageComponent } from './tools-page.component'; import { PortfolioPageComponent } from './portfolio-page.component';
const routes: Routes = [ const routes: Routes = [
{ path: '', component: ToolsPageComponent, canActivate: [AuthGuard] } { path: '', component: PortfolioPageComponent, canActivate: [AuthGuard] }
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forChild(routes)], imports: [RouterModule.forChild(routes)],
exports: [RouterModule] exports: [RouterModule]
}) })
export class ToolsPageRoutingModule {} export class PortfolioPageRoutingModule {}

44
apps/client/src/app/pages/portfolio/portfolio-page.component.ts

@ -0,0 +1,44 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'gf-portfolio-page',
templateUrl: './portfolio-page.html',
styleUrls: ['./portfolio-page.scss']
})
export class PortfolioPageComponent implements OnDestroy, OnInit {
public user: User;
private unsubscribeSubject = new Subject<void>();
/**
* @constructor
*/
public constructor(
private changeDetectorRef: ChangeDetectorRef,
private userService: UserService
) {}
/**
* Initializes the controller
*/
public ngOnInit() {
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => {
if (state?.user) {
this.user = state.user;
this.changeDetectorRef.markForCheck();
}
});
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
}

83
apps/client/src/app/pages/portfolio/portfolio-page.html

@ -0,0 +1,83 @@
<div class="container">
<h3 class="d-flex justify-content-center mb-3" i18n>Portfolio</h3>
<div class="row">
<div class="col-xs-12 col-md-6">
<mat-card class="mb-3">
<h4 i18n>Transactions</h4>
<p class="mb-0">Manage your transactions.</p>
<p class="text-right">
<a
color="primary"
i18n
mat-button
[routerLink]="['/portfolio', 'transactions']"
>
Open Transactions →
</a>
</p>
</mat-card>
</div>
<div
*ngIf="user?.settings?.viewMode === 'DEFAULT'"
class="col-xs-12 col-md-6"
>
<mat-card class="mb-3">
<h4 i18n>Allocations</h4>
<p class="mb-0">Check the allocations of your portfolio.</p>
<p class="text-right">
<a
color="primary"
i18n
mat-button
[routerLink]="['/portfolio', 'allocations']"
>
Open Allocations →
</a>
</p>
</mat-card>
</div>
</div>
<div class="row">
<div
*ngIf="user?.settings?.viewMode === 'DEFAULT'"
class="col-xs-12 col-md-6"
>
<mat-card class="mb-3">
<h4 i18n>Analysis</h4>
<p class="mb-0">Ghostfolio Analysis visualizes your portfolio.</p>
<p class="text-right">
<a
color="primary"
i18n
mat-button
[routerLink]="['/portfolio', 'analysis']"
>
Open Analysis →
</a>
</p>
</mat-card>
</div>
<div
*ngIf="user?.settings?.viewMode === 'DEFAULT'"
class="col-xs-12 col-md-6"
>
<mat-card class="mb-3">
<h4 i18n>X-ray</h4>
<p class="mb-0">
Ghostfolio X-ray uses static analysis to identify potential issues and
risks in your portfolio.
</p>
<p class="text-right">
<a
color="primary"
i18n
mat-button
[routerLink]="['/portfolio', 'report']"
>
Open X-ray →
</a>
</p>
</mat-card>
</div>
</div>
</div>

12
apps/client/src/app/pages/tools/tools-page.module.ts → apps/client/src/app/pages/portfolio/portfolio-page.module.ts

@ -4,20 +4,20 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { ToolsPageRoutingModule } from './tools-page-routing.module'; import { PortfolioPageRoutingModule } from './portfolio-page-routing.module';
import { ToolsPageComponent } from './tools-page.component'; import { PortfolioPageComponent } from './portfolio-page.component';
@NgModule({ @NgModule({
declarations: [ToolsPageComponent], declarations: [PortfolioPageComponent],
exports: [], exports: [],
imports: [ imports: [
CommonModule, CommonModule,
MatButtonModule, MatButtonModule,
MatCardModule, MatCardModule,
RouterModule, PortfolioPageRoutingModule,
ToolsPageRoutingModule RouterModule
], ],
providers: [], providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]
}) })
export class ToolsPageModule {} export class PortfolioPageModule {}

0
apps/client/src/app/pages/tools/report/report-page.scss → apps/client/src/app/pages/portfolio/portfolio-page.scss

0
apps/client/src/app/pages/tools/report/report-page-routing.module.ts → apps/client/src/app/pages/portfolio/report/report-page-routing.module.ts

0
apps/client/src/app/pages/tools/report/report-page.component.ts → apps/client/src/app/pages/portfolio/report/report-page.component.ts

0
apps/client/src/app/pages/tools/report/report-page.html → apps/client/src/app/pages/portfolio/report/report-page.html

0
apps/client/src/app/pages/tools/report/report-page.module.ts → apps/client/src/app/pages/portfolio/report/report-page.module.ts

0
apps/client/src/app/pages/tools/tools-page.scss → apps/client/src/app/pages/portfolio/report/report-page.scss

2
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts → apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts

@ -9,6 +9,7 @@ import { FormControl, Validators } from '@angular/forms';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { DataService } from '@ghostfolio/client/services/data.service';
import { Currency } from '@prisma/client'; import { Currency } from '@prisma/client';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { import {
@ -19,7 +20,6 @@ import {
takeUntil takeUntil
} from 'rxjs/operators'; } from 'rxjs/operators';
import { DataService } from '../../../services/data.service';
import { CreateOrUpdateTransactionDialogParams } from './interfaces/interfaces'; import { CreateOrUpdateTransactionDialogParams } from './interfaces/interfaces';
@Component({ @Component({

0
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html → apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html

0
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.module.ts → apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.module.ts

0
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.scss → apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.scss

0
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/interfaces/interfaces.ts → apps/client/src/app/pages/portfolio/transactions/create-or-update-transaction-dialog/interfaces/interfaces.ts

0
apps/client/src/app/pages/transactions/transactions-page-routing.module.ts → apps/client/src/app/pages/portfolio/transactions/transactions-page-routing.module.ts

0
apps/client/src/app/pages/transactions/transactions-page.component.ts → apps/client/src/app/pages/portfolio/transactions/transactions-page.component.ts

0
apps/client/src/app/pages/transactions/transactions-page.html → apps/client/src/app/pages/portfolio/transactions/transactions-page.html

0
apps/client/src/app/pages/transactions/transactions-page.module.ts → apps/client/src/app/pages/portfolio/transactions/transactions-page.module.ts

0
apps/client/src/app/pages/transactions/transactions-page.scss → apps/client/src/app/pages/portfolio/transactions/transactions-page.scss

21
apps/client/src/app/pages/tools/tools-page.component.ts

@ -1,21 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
@Component({
selector: 'gf-tools-page',
templateUrl: './tools-page.html',
styleUrls: ['./tools-page.scss']
})
export class ToolsPageComponent implements OnInit {
private unsubscribeSubject = new Subject<void>();
/**
* @constructor
*/
public constructor() {}
/**
* Initializes the controller
*/
public ngOnInit() {}
}

43
apps/client/src/app/pages/tools/tools-page.html

@ -1,43 +0,0 @@
<div class="container">
<h3 class="d-flex justify-content-center mb-3" i18n>Tools</h3>
<div class="row">
<div class="col-xs-12 col-md-6">
<mat-card class="mb-3">
<h4 i18n>Analysis</h4>
<p class="mb-0">
Ghostfolio Analysis shows your positions and visualizes your
portfolio.
</p>
<p class="text-right">
<a
color="primary"
i18n
mat-button
[routerLink]="['/tools', 'analysis']"
>
Open Analysis →
</a>
</p>
</mat-card>
</div>
<div class="col-xs-12 col-md-6">
<mat-card class="mb-3">
<h4 i18n>X-ray</h4>
<p class="mb-0">
Ghostfolio X-ray uses static analysis to identify potential issues and
risks in your portfolio.
</p>
<p class="text-right">
<a
color="primary"
i18n
mat-button
[routerLink]="['/tools', 'report']"
>
Open X-ray →
</a>
</p>
</mat-card>
</div>
</div>
</div>

2
apps/client/src/app/pages/zen/zen-page.html

@ -60,7 +60,7 @@
<ion-icon name="wallet-outline" size="large"></ion-icon> <ion-icon name="wallet-outline" size="large"></ion-icon>
</ng-template> </ng-template>
<div class="container justify-content-center pb-3 px-3 positions"> <div class="container justify-content-center pb-3 px-3 positions">
<h3 class="d-flex justify-content-center mb-3" i18n>Positions</h3> <h3 class="d-flex justify-content-center mb-3" i18n>Holdings</h3>
<div class="row"> <div class="row">
<div class="align-items-center col"> <div class="align-items-center col">
<mat-card *ngIf="hasPositions === true" class="p-0"> <mat-card *ngIf="hasPositions === true" class="p-0">

Loading…
Cancel
Save