You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.3 KiB
177 lines
5.3 KiB
import { ConfirmationDialogType } from '@ghostfolio/common/enums';
|
|
import {
|
|
getLocale,
|
|
getLowercase,
|
|
resolveMarketCondition
|
|
} from '@ghostfolio/common/helper';
|
|
import {
|
|
AssetProfileIdentifier,
|
|
Benchmark,
|
|
User
|
|
} from '@ghostfolio/common/interfaces';
|
|
import { NotificationService } from '@ghostfolio/ui/notifications';
|
|
|
|
import {
|
|
CUSTOM_ELEMENTS_SCHEMA,
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
DestroyRef,
|
|
computed,
|
|
effect,
|
|
inject,
|
|
input,
|
|
output,
|
|
viewChild
|
|
} from '@angular/core';
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
import { MatButtonModule } from '@angular/material/button';
|
|
import { MatDialog } from '@angular/material/dialog';
|
|
import { MatMenuModule } from '@angular/material/menu';
|
|
import { MatSort, MatSortModule } from '@angular/material/sort';
|
|
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
|
import { IonIcon } from '@ionic/angular/standalone';
|
|
import { addIcons } from 'ionicons';
|
|
import { ellipsisHorizontal, trashOutline } from 'ionicons/icons';
|
|
import { isNumber } from 'lodash';
|
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
|
|
|
import { translate } from '../i18n';
|
|
import { GfTrendIndicatorComponent } from '../trend-indicator/trend-indicator.component';
|
|
import { GfValueComponent } from '../value/value.component';
|
|
import { GfBenchmarkDetailDialogComponent } from './benchmark-detail-dialog/benchmark-detail-dialog.component';
|
|
import { BenchmarkDetailDialogParams } from './benchmark-detail-dialog/interfaces/interfaces';
|
|
|
|
@Component({
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
imports: [
|
|
GfTrendIndicatorComponent,
|
|
GfValueComponent,
|
|
IonIcon,
|
|
MatButtonModule,
|
|
MatMenuModule,
|
|
MatSortModule,
|
|
MatTableModule,
|
|
NgxSkeletonLoaderModule,
|
|
RouterModule
|
|
],
|
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
selector: 'gf-benchmark',
|
|
styleUrls: ['./benchmark.component.scss'],
|
|
templateUrl: './benchmark.component.html'
|
|
})
|
|
export class GfBenchmarkComponent {
|
|
public readonly benchmarks = input.required<Benchmark[]>();
|
|
public readonly deviceType = input.required<string>();
|
|
public readonly hasPermissionToDeleteItem = input<boolean>();
|
|
public readonly locale = input(getLocale());
|
|
public readonly showSymbol = input(true);
|
|
public readonly user = input<User>();
|
|
|
|
public readonly itemDeleted = output<AssetProfileIdentifier>();
|
|
|
|
protected readonly sort = viewChild(MatSort);
|
|
|
|
protected readonly dataSource = new MatTableDataSource<Benchmark>([]);
|
|
protected readonly displayedColumns = computed(() => {
|
|
return [
|
|
'name',
|
|
...(this.user()?.settings?.isExperimentalFeatures
|
|
? ['trend50d', 'trend200d']
|
|
: []),
|
|
'date',
|
|
'change',
|
|
'marketCondition',
|
|
'actions'
|
|
];
|
|
});
|
|
protected isLoading = true;
|
|
protected readonly isNumber = isNumber;
|
|
protected readonly resolveMarketCondition = resolveMarketCondition;
|
|
protected readonly translate = translate;
|
|
|
|
private readonly destroyRef = inject(DestroyRef);
|
|
private readonly dialog = inject(MatDialog);
|
|
private readonly notificationService = inject(NotificationService);
|
|
private readonly route = inject(ActivatedRoute);
|
|
private readonly router = inject(Router);
|
|
|
|
public constructor() {
|
|
effect(() => {
|
|
const benchmarks = this.benchmarks();
|
|
|
|
if (benchmarks) {
|
|
this.dataSource.data = benchmarks;
|
|
this.dataSource.sortingDataAccessor = getLowercase;
|
|
|
|
this.dataSource.sort = this.sort() ?? null;
|
|
|
|
this.isLoading = false;
|
|
}
|
|
});
|
|
|
|
this.route.queryParams
|
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
.subscribe((params) => {
|
|
if (
|
|
params['benchmarkDetailDialog'] &&
|
|
params['dataSource'] &&
|
|
params['symbol']
|
|
) {
|
|
this.openBenchmarkDetailDialog({
|
|
dataSource: params['dataSource'],
|
|
symbol: params['symbol']
|
|
});
|
|
}
|
|
});
|
|
|
|
addIcons({ ellipsisHorizontal, trashOutline });
|
|
}
|
|
|
|
protected onDeleteItem({ dataSource, symbol }: AssetProfileIdentifier) {
|
|
this.notificationService.confirm({
|
|
confirmFn: () => {
|
|
this.itemDeleted.emit({ dataSource, symbol });
|
|
},
|
|
confirmType: ConfirmationDialogType.Warn,
|
|
title: $localize`Do you really want to delete this item?`
|
|
});
|
|
}
|
|
|
|
protected onOpenBenchmarkDialog({
|
|
dataSource,
|
|
symbol
|
|
}: AssetProfileIdentifier) {
|
|
this.router.navigate([], {
|
|
queryParams: { dataSource, symbol, benchmarkDetailDialog: true }
|
|
});
|
|
}
|
|
|
|
private openBenchmarkDetailDialog({
|
|
dataSource,
|
|
symbol
|
|
}: AssetProfileIdentifier) {
|
|
const dialogRef = this.dialog.open<
|
|
GfBenchmarkDetailDialogComponent,
|
|
BenchmarkDetailDialogParams
|
|
>(GfBenchmarkDetailDialogComponent, {
|
|
data: {
|
|
dataSource,
|
|
symbol,
|
|
colorScheme: this.user()?.settings?.colorScheme,
|
|
deviceType: this.deviceType(),
|
|
locale: this.locale()
|
|
},
|
|
height: this.deviceType() === 'mobile' ? '98vh' : undefined,
|
|
width: this.deviceType() === 'mobile' ? '100vw' : '50rem'
|
|
});
|
|
|
|
dialogRef
|
|
.afterClosed()
|
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
.subscribe(() => {
|
|
this.router.navigate(['.'], { relativeTo: this.route });
|
|
});
|
|
}
|
|
}
|