Merge pull request 'Add expand/collapse for Top/Bottom secion off portfolio analysis page' (#1) from add-expand-topbottom into main

Reviewed-on: #1
This commit is contained in:
Kyle Yasuda 2024-08-08 19:38:58 -07:00
commit 7462ccd612
5 changed files with 84 additions and 10 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
sync.sh
# compiled output
/out-tsc
/tmp

View File

@ -2,6 +2,7 @@ import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.com
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 { MatPaginator, PageEvent } from '@angular/material/paginator';
import {
HistoricalDataItem,
PortfolioInvestments,
@ -31,6 +32,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
public benchmarkDataItems: HistoricalDataItem[] = [];
public benchmarks: Partial<SymbolProfile>[];
public bottom3: PortfolioPosition[];
public bottomx: PortfolioPosition[];
public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS;
public daysInMarket: number;
public deviceType: string;
@ -56,9 +58,17 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
public portfolioEvolutionDataLabel = $localize`Investment`;
public streaks: PortfolioInvestments['streaks'];
public top3: PortfolioPosition[];
public topx: PortfolioPosition[];
public positions: PortfolioPosition[];
public positionsReversed: PortfolioPosition[];
public unitCurrentStreak: string;
public unitLongestStreak: string;
public user: User;
public showAllTop: boolean = false;
public showAllBottom: boolean = false;
public pageSize: number = 10;
public pageIndexTop: number = 0;
public pageIndexBottom: number = 0;
private unsubscribeSubject = new Subject<void>();
@ -73,6 +83,25 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
this.benchmarks = benchmarks;
}
public pageChanged(event: PageEvent, section: 'top' | 'bottom') {
const newPageIndex = event.pageIndex;
if (section === 'top') {
this.pageIndexTop = newPageIndex;
} else if (section === 'bottom') {
this.pageIndexBottom = newPageIndex;
}
}
public toggleList(l: string) {
if (l === 'top') {
this.showAllTop = !this.showAllTop;
this.pageIndexTop = 0;
} else if (l === 'bottom') {
this.showAllBottom = !this.showAllBottom;
this.pageIndexBottom = 0;
}
}
get savingsRate() {
const savingsRatePerMonth =
this.hasImpersonationId || this.user.settings.isRestrictedView
@ -257,14 +286,17 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
'netPerformancePercentWithCurrencyEffect'
).reverse();
this.top3 = holdingsSorted.slice(0, 3);
this.topx = holdingsSorted.slice(0, 5);
if (holdings?.length > 3) {
this.bottom3 = holdingsSorted.slice(-3).reverse();
if (holdings?.length > 5) {
this.bottomx = holdingsSorted.slice(-5).reverse();
} else {
this.bottom3 = [];
this.bottomx = [];
}
this.positions = [...holdingsSorted]
this.positionsReversed = [...holdingsSorted].reverse();
this.changeDetectorRef.markForCheck();
});

View File

@ -168,7 +168,7 @@
</mat-card-header>
<mat-card-content>
<ol class="mb-0 ml-1 pl-3">
@for (holding of top3; track holding) {
<div *ngFor="let holding of (showAllTop ? positions.slice(pageIndexTop * pageSize, (pageIndexTop + 1) * pageSize) : positions | slice:0:5); track holding">
<li class="py-1">
<a
class="d-flex"
@ -192,10 +192,10 @@
</div>
</a>
</li>
}
</div>
</ol>
<div>
@if (!top3) {
@if (!topx) {
<ngx-skeleton-loader
animation="pulse"
[theme]="{
@ -206,7 +206,23 @@
}
</div>
</mat-card-content>
<mat-paginator
*ngIf="showAllTop && positions.length > 10"
[length]="positions.length"
[pageSize]="pageSize"
[pageSizeOptions]="[10, 20, 30, 40]"
(page)="pageChanged($event, 'top')"
>
</mat-paginator>
</mat-card>
<button
class="toggle-performance-list"
color="{{showAllTop ? 'accent' : 'primary'}}"
mat-button
(click)="toggleList('top')"
>
{{ showAllTop ? 'Collapse' : 'Expand' }}
</button>
</div>
<div class="col-md-6">
<mat-card appearance="outlined" class="mb-3">
@ -217,7 +233,7 @@
</mat-card-header>
<mat-card-content>
<ol class="mb-0 ml-1 pl-3">
@for (holding of bottom3; track holding) {
<div *ngFor="let holding of (showAllBottom ? positionsReversed.slice(pageIndexBottom * pageSize, (pageIndexBottom + 1) * pageSize) : positionsReversed | slice:0:5); track holding">
<li class="py-1">
<a
class="d-flex"
@ -241,10 +257,10 @@
</div>
</a>
</li>
}
</div>
</ol>
<div>
@if (!bottom3) {
@if (!bottomx) {
<ngx-skeleton-loader
animation="pulse"
[theme]="{
@ -255,7 +271,23 @@
}
</div>
</mat-card-content>
<mat-paginator
*ngIf="showAllBottom && positionsReversed.length > 10"
[length]="positions.length"
[pageSize]="pageSize"
[pageSizeOptions]="[10, 20, 30, 40]"
(page)="pageChanged($event, 'bottom')"
>
</mat-paginator>
</mat-card>
<button
class="toggle-performance-list"
color="{{showAllBottom ? 'accent' : 'primary'}}"
mat-button
(click)="toggleList('bottom')"
>
{{ showAllBottom ? 'Collapse' : 'Expand' }}
</button>
</div>
</div>

View File

@ -4,6 +4,8 @@ import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.modu
import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { GfValueComponent } from '@ghostfolio/ui/value';
import { MatButtonModule } from '@angular/material/button';
import { MatPaginatorModule } from '@angular/material/paginator';
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
@ -25,6 +27,8 @@ import { AnalysisPageComponent } from './analysis-page.component';
GfToggleModule,
GfValueComponent,
MatCardModule,
MatButtonModule,
MatPaginatorModule,
NgxSkeletonLoaderModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]

View File

@ -4,4 +4,8 @@
.chart-container {
aspect-ratio: 16 / 9;
}
.toggle-performance-list {
margin-bottom: 1rem;
}
}