mirror of https://github.com/ghostfolio/ghostfolio
committed by
GitHub
22 changed files with 497 additions and 52 deletions
@ -0,0 +1,3 @@ |
|||||
|
:host { |
||||
|
display: block; |
||||
|
} |
@ -0,0 +1,112 @@ |
|||||
|
import { |
||||
|
ChangeDetectionStrategy, |
||||
|
ChangeDetectorRef, |
||||
|
Component, |
||||
|
Inject, |
||||
|
OnDestroy, |
||||
|
OnInit |
||||
|
} from '@angular/core'; |
||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; |
||||
|
import { DataService } from '@ghostfolio/client/services/data.service'; |
||||
|
import { UserService } from '@ghostfolio/client/services/user/user.service'; |
||||
|
import { downloadAsFile } from '@ghostfolio/common/helper'; |
||||
|
import { User } from '@ghostfolio/common/interfaces'; |
||||
|
import { OrderWithAccount } from '@ghostfolio/common/types'; |
||||
|
import { AccountType } from '@prisma/client'; |
||||
|
import { format, parseISO } from 'date-fns'; |
||||
|
import { Subject } from 'rxjs'; |
||||
|
import { takeUntil } from 'rxjs/operators'; |
||||
|
|
||||
|
import { AccountDetailDialogParams } from './interfaces/interfaces'; |
||||
|
|
||||
|
@Component({ |
||||
|
host: { class: 'd-flex flex-column h-100' }, |
||||
|
selector: 'gf-account-detail-dialog', |
||||
|
changeDetection: ChangeDetectionStrategy.OnPush, |
||||
|
templateUrl: 'account-detail-dialog.html', |
||||
|
styleUrls: ['./account-detail-dialog.component.scss'] |
||||
|
}) |
||||
|
export class AccountDetailDialog implements OnDestroy, OnInit { |
||||
|
public accountType: AccountType; |
||||
|
public name: string; |
||||
|
public orders: OrderWithAccount[]; |
||||
|
public platformName: string; |
||||
|
public user: User; |
||||
|
public valueInBaseCurrency: number; |
||||
|
|
||||
|
private unsubscribeSubject = new Subject<void>(); |
||||
|
|
||||
|
public constructor( |
||||
|
private changeDetectorRef: ChangeDetectorRef, |
||||
|
@Inject(MAT_DIALOG_DATA) public data: AccountDetailDialogParams, |
||||
|
private dataService: DataService, |
||||
|
public dialogRef: MatDialogRef<AccountDetailDialog>, |
||||
|
private userService: UserService |
||||
|
) { |
||||
|
this.userService.stateChanged |
||||
|
.pipe(takeUntil(this.unsubscribeSubject)) |
||||
|
.subscribe((state) => { |
||||
|
if (state?.user) { |
||||
|
this.user = state.user; |
||||
|
|
||||
|
this.changeDetectorRef.markForCheck(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public ngOnInit(): void { |
||||
|
this.dataService |
||||
|
.fetchAccount(this.data.accountId) |
||||
|
.pipe(takeUntil(this.unsubscribeSubject)) |
||||
|
.subscribe(({ accountType, name, Platform, valueInBaseCurrency }) => { |
||||
|
this.accountType = accountType; |
||||
|
this.name = name; |
||||
|
this.platformName = Platform?.name; |
||||
|
this.valueInBaseCurrency = valueInBaseCurrency; |
||||
|
|
||||
|
this.changeDetectorRef.markForCheck(); |
||||
|
}); |
||||
|
|
||||
|
this.dataService |
||||
|
.fetchActivities({ |
||||
|
filters: [{ id: this.data.accountId, type: 'ACCOUNT' }] |
||||
|
}) |
||||
|
.pipe(takeUntil(this.unsubscribeSubject)) |
||||
|
.subscribe(({ activities }) => { |
||||
|
this.orders = activities; |
||||
|
|
||||
|
this.changeDetectorRef.markForCheck(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public onClose(): void { |
||||
|
this.dialogRef.close(); |
||||
|
} |
||||
|
|
||||
|
public onExport() { |
||||
|
this.dataService |
||||
|
.fetchExport( |
||||
|
this.orders.map((order) => { |
||||
|
return order.id; |
||||
|
}) |
||||
|
) |
||||
|
.pipe(takeUntil(this.unsubscribeSubject)) |
||||
|
.subscribe((data) => { |
||||
|
downloadAsFile({ |
||||
|
content: data, |
||||
|
fileName: `ghostfolio-export-${this.name |
||||
|
.replace(/\s+/g, '-') |
||||
|
.toLowerCase()}-${format( |
||||
|
parseISO(data.meta.date), |
||||
|
'yyyyMMddHHmm' |
||||
|
)}.json`,
|
||||
|
format: 'json' |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public ngOnDestroy() { |
||||
|
this.unsubscribeSubject.next(); |
||||
|
this.unsubscribeSubject.complete(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
<gf-dialog-header |
||||
|
mat-dialog-title |
||||
|
position="center" |
||||
|
[deviceType]="data.deviceType" |
||||
|
[title]="name" |
||||
|
(closeButtonClicked)="onClose()" |
||||
|
></gf-dialog-header> |
||||
|
|
||||
|
<div class="flex-grow-1" mat-dialog-content> |
||||
|
<div class="container p-0"> |
||||
|
<div class="row"> |
||||
|
<div class="col-12 d-flex justify-content-center mb-3"> |
||||
|
<gf-value |
||||
|
size="large" |
||||
|
[currency]="user?.settings?.baseCurrency" |
||||
|
[locale]="user?.settings?.locale" |
||||
|
[value]="valueInBaseCurrency" |
||||
|
></gf-value> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-6 mb-3"> |
||||
|
<gf-value |
||||
|
label="Account Type" |
||||
|
size="medium" |
||||
|
[value]="accountType" |
||||
|
></gf-value> |
||||
|
</div> |
||||
|
<div class="col-6 mb-3"> |
||||
|
<gf-value |
||||
|
label="Platform" |
||||
|
size="medium" |
||||
|
[value]="platformName" |
||||
|
></gf-value> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div *ngIf="orders?.length > 0" class="row"> |
||||
|
<div class="col mb-3"> |
||||
|
<div class="h5 mb-0" i18n>Activities</div> |
||||
|
<gf-activities-table |
||||
|
[activities]="orders" |
||||
|
[baseCurrency]="user?.settings?.baseCurrency" |
||||
|
[deviceType]="data.deviceType" |
||||
|
[hasPermissionToCreateActivity]="false" |
||||
|
[hasPermissionToExportActivities]="!hasImpersonationId" |
||||
|
[hasPermissionToFilter]="false" |
||||
|
[hasPermissionToImportActivities]="false" |
||||
|
[hasPermissionToOpenDetails]="false" |
||||
|
[locale]="user?.settings?.locale" |
||||
|
[showActions]="false" |
||||
|
[showSymbolColumn]="false" |
||||
|
(export)="onExport()" |
||||
|
></gf-activities-table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<gf-dialog-footer |
||||
|
mat-dialog-actions |
||||
|
[deviceType]="data.deviceType" |
||||
|
(closeButtonClicked)="onClose()" |
||||
|
></gf-dialog-footer> |
@ -0,0 +1,29 @@ |
|||||
|
import { CommonModule } from '@angular/common'; |
||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; |
||||
|
import { MatButtonModule } from '@angular/material/button'; |
||||
|
import { MatDialogModule } from '@angular/material/dialog'; |
||||
|
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; |
||||
|
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; |
||||
|
import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module'; |
||||
|
import { GfValueModule } from '@ghostfolio/ui/value'; |
||||
|
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; |
||||
|
|
||||
|
import { AccountDetailDialog } from './account-detail-dialog.component'; |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [AccountDetailDialog], |
||||
|
exports: [], |
||||
|
imports: [ |
||||
|
CommonModule, |
||||
|
GfActivitiesTableModule, |
||||
|
GfDialogFooterModule, |
||||
|
GfDialogHeaderModule, |
||||
|
GfValueModule, |
||||
|
MatButtonModule, |
||||
|
MatDialogModule, |
||||
|
NgxSkeletonLoaderModule |
||||
|
], |
||||
|
providers: [], |
||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA] |
||||
|
}) |
||||
|
export class GfAccountDetailDialogModule {} |
@ -0,0 +1,5 @@ |
|||||
|
export interface AccountDetailDialogParams { |
||||
|
accountId: string; |
||||
|
deviceType: string; |
||||
|
hasImpersonationId: boolean; |
||||
|
} |
Loading…
Reference in new issue