import { getLocale } from '@ghostfolio/common/helper'; import { HoldingWithParents } from '@ghostfolio/common/interfaces'; import { GfValueComponent } from '@ghostfolio/ui/value'; import { animate, state, style, transition, trigger } from '@angular/animations'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, Input, OnChanges, OnDestroy, ViewChild } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatTooltipModule } from '@angular/material/tooltip'; import { get } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; const { blue, cyan, grape, green, indigo, lime, orange, pink, red, teal, violet, yellow } = require('open-color'); @Component({ animations: [ trigger('detailExpand', [ state('collapsed,void', style({ height: '0px', minHeight: '0' })), state('expanded', style({ height: '*' })), transition( 'expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)') ) ]) ], changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, GfValueComponent, MatButtonModule, MatPaginatorModule, MatSortModule, MatTableModule, MatTooltipModule, NgxSkeletonLoaderModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-top-holdings', standalone: true, styleUrls: ['./top-holdings.component.scss'], templateUrl: './top-holdings.component.html' }) export class GfTopHoldingsComponent implements OnChanges, OnDestroy { @Input() baseCurrency: string; @Input() locale = getLocale(); @Input() pageSize = Number.MAX_SAFE_INTEGER; @Input() topHoldings: HoldingWithParents[]; @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; private colorMap: { [symbol: string]: string; } = {}; public dataSource = new MatTableDataSource(); public displayedColumns: string[] = [ 'name', 'valueInBaseCurrency', 'allocationInPercentage' ]; public displayedHoldingParentColumns: string[] = [ 'name', 'symbol', 'valueInBaseCurrency', 'allocationInPercentage' ]; public isLoading = true; private unsubscribeSubject = new Subject(); private colorPaletteIndex = 0; private colorPalette = [ blue[5], teal[5], lime[5], orange[5], pink[5], violet[5], indigo[5], cyan[5], green[5], yellow[5], red[5], grape[5] ]; public getColor(symbol) { if (this.colorMap[symbol]) { // Reuse color return this.colorMap[symbol]; } else { const color = this.colorPalette[this.colorPaletteIndex]; this.colorPaletteIndex = this.colorPaletteIndex < this.colorPalette.length ? this.colorPaletteIndex + 1 : 0; this.colorMap[symbol] = color; return color; } } public ngOnChanges() { this.isLoading = true; this.dataSource = new MatTableDataSource(this.topHoldings); this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; this.dataSource.sortingDataAccessor = get; if (this.topHoldings) { this.isLoading = false; } } public onShowAllHoldings() { this.pageSize = Number.MAX_SAFE_INTEGER; setTimeout(() => { this.dataSource.paginator = this.paginator; }); } public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } }