Add pagination to activities table (#1404)
* Add pagination to activities table
This commit is contained in:
parent
3b6e0b20e2
commit
901c997908
@ -29,8 +29,8 @@
|
|||||||
class="align-items-center d-flex justify-content-center"
|
class="align-items-center d-flex justify-content-center"
|
||||||
color="primary"
|
color="primary"
|
||||||
mat-fab
|
mat-fab
|
||||||
[routerLink]="[]"
|
|
||||||
[queryParams]="{ createDialog: true }"
|
[queryParams]="{ createDialog: true }"
|
||||||
|
[routerLink]="[]"
|
||||||
>
|
>
|
||||||
<ion-icon name="add-outline" size="large"></ion-icon>
|
<ion-icon name="add-outline" size="large"></ion-icon>
|
||||||
</a>
|
</a>
|
||||||
|
@ -90,6 +90,10 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-paginator {
|
||||||
|
background-color: rgba(var(--palette-foreground-base-dark), 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
.svgMap-tooltip {
|
.svgMap-tooltip {
|
||||||
background: var(--dark-background);
|
background: var(--dark-background);
|
||||||
|
|
||||||
@ -220,6 +224,14 @@ ngx-skeleton-loader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-paginator {
|
||||||
|
background-color: rgba(var(--palette-foreground-base-light), 0.02);
|
||||||
|
|
||||||
|
.mat-paginator-page-size {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.no-min-width {
|
.no-min-width {
|
||||||
min-width: unset !important;
|
min-width: unset !important;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ export const DATA_GATHERING_QUEUE_PRIORITY_HIGH = 1;
|
|||||||
|
|
||||||
export const DEFAULT_DATE_FORMAT_MONTH_YEAR = 'MMM yyyy';
|
export const DEFAULT_DATE_FORMAT_MONTH_YEAR = 'MMM yyyy';
|
||||||
export const DEFAULT_LANGUAGE_CODE = 'en';
|
export const DEFAULT_LANGUAGE_CODE = 'en';
|
||||||
|
export const DEFAULT_PAGE_SIZE = 50;
|
||||||
|
|
||||||
export const GATHER_ASSET_PROFILE_PROCESS = 'GATHER_ASSET_PROFILE';
|
export const GATHER_ASSET_PROFILE_PROCESS = 'GATHER_ASSET_PROFILE';
|
||||||
export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = {
|
export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = {
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
<div class="activities">
|
<div class="activities">
|
||||||
<table
|
<table
|
||||||
class="gf-table w-100"
|
class="gf-table w-100"
|
||||||
|
mat-table
|
||||||
matSort
|
matSort
|
||||||
matSortActive="date"
|
matSortActive="date"
|
||||||
matSortDirection="desc"
|
matSortDirection="desc"
|
||||||
mat-table
|
|
||||||
[dataSource]="dataSource"
|
[dataSource]="dataSource"
|
||||||
>
|
>
|
||||||
<ng-container matColumnDef="count">
|
<ng-container matColumnDef="count">
|
||||||
@ -27,7 +27,11 @@
|
|||||||
class="d-none d-lg-table-cell px-1 text-right"
|
class="d-none d-lg-table-cell px-1 text-right"
|
||||||
mat-cell
|
mat-cell
|
||||||
>
|
>
|
||||||
{{ dataSource.data.length - i }}
|
{{
|
||||||
|
dataSource.data.length > pageSize
|
||||||
|
? dataSource.data.length - pageSize * pageIndex - i
|
||||||
|
: dataSource.data.length - i
|
||||||
|
}}
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
*matFooterCellDef
|
*matFooterCellDef
|
||||||
@ -51,7 +55,7 @@
|
|||||||
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
|
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
|
||||||
<ng-container i18n>Type</ng-container>
|
<ng-container i18n>Type</ng-container>
|
||||||
</th>
|
</th>
|
||||||
<td *matCellDef="let element" mat-cell class="px-1">
|
<td *matCellDef="let element" class="px-1" mat-cell>
|
||||||
<div
|
<div
|
||||||
class="d-inline-flex p-1 type-badge"
|
class="d-inline-flex p-1 type-badge"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
@ -389,6 +393,10 @@
|
|||||||
<tr
|
<tr
|
||||||
*matRowDef="let row; columns: displayedColumns"
|
*matRowDef="let row; columns: displayedColumns"
|
||||||
mat-row
|
mat-row
|
||||||
|
[ngClass]="{
|
||||||
|
'cursor-pointer':
|
||||||
|
hasPermissionToOpenDetails && !row.isDraft && row.type !== 'ITEM'
|
||||||
|
}"
|
||||||
(click)="
|
(click)="
|
||||||
hasPermissionToOpenDetails &&
|
hasPermissionToOpenDetails &&
|
||||||
!row.isDraft &&
|
!row.isDraft &&
|
||||||
@ -398,10 +406,6 @@
|
|||||||
symbol: row.SymbolProfile.symbol
|
symbol: row.SymbolProfile.symbol
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
[ngClass]="{
|
|
||||||
'cursor-pointer':
|
|
||||||
hasPermissionToOpenDetails && !row.isDraft && row.type !== 'ITEM'
|
|
||||||
}"
|
|
||||||
></tr>
|
></tr>
|
||||||
<tr
|
<tr
|
||||||
*matFooterRowDef="displayedColumns"
|
*matFooterRowDef="displayedColumns"
|
||||||
@ -411,6 +415,18 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<mat-paginator
|
||||||
|
showFirstLastButtons="true"
|
||||||
|
[ngClass]="{
|
||||||
|
'd-none':
|
||||||
|
isLoading ||
|
||||||
|
dataSource.data.length === 0 ||
|
||||||
|
dataSource.data.length <= pageSize
|
||||||
|
}"
|
||||||
|
[pageSize]="pageSize"
|
||||||
|
(page)="onChangePage($event)"
|
||||||
|
></mat-paginator>
|
||||||
|
|
||||||
<ngx-skeleton-loader
|
<ngx-skeleton-loader
|
||||||
*ngIf="isLoading"
|
*ngIf="isLoading"
|
||||||
animation="pulse"
|
animation="pulse"
|
||||||
|
@ -8,10 +8,12 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||||
import { MatSort } from '@angular/material/sort';
|
import { MatSort } from '@angular/material/sort';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
||||||
|
import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config';
|
||||||
import { getDateFormatString } from '@ghostfolio/common/helper';
|
import { getDateFormatString } from '@ghostfolio/common/helper';
|
||||||
import { Filter, UniqueAsset } from '@ghostfolio/common/interfaces';
|
import { Filter, UniqueAsset } from '@ghostfolio/common/interfaces';
|
||||||
import { OrderWithAccount } from '@ghostfolio/common/types';
|
import { OrderWithAccount } from '@ghostfolio/common/types';
|
||||||
@ -37,6 +39,7 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
@Input() hasPermissionToImportActivities: boolean;
|
@Input() hasPermissionToImportActivities: boolean;
|
||||||
@Input() hasPermissionToOpenDetails = true;
|
@Input() hasPermissionToOpenDetails = true;
|
||||||
@Input() locale: string;
|
@Input() locale: string;
|
||||||
|
@Input() pageSize = DEFAULT_PAGE_SIZE;
|
||||||
@Input() showActions: boolean;
|
@Input() showActions: boolean;
|
||||||
@Input() showSymbolColumn = true;
|
@Input() showSymbolColumn = true;
|
||||||
|
|
||||||
@ -47,6 +50,7 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
@Output() exportDrafts = new EventEmitter<string[]>();
|
@Output() exportDrafts = new EventEmitter<string[]>();
|
||||||
@Output() import = new EventEmitter<void>();
|
@Output() import = new EventEmitter<void>();
|
||||||
|
|
||||||
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
@ViewChild(MatSort) sort: MatSort;
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
public allFilters: Filter[];
|
public allFilters: Filter[];
|
||||||
@ -59,6 +63,7 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
public isAfter = isAfter;
|
public isAfter = isAfter;
|
||||||
public isLoading = true;
|
public isLoading = true;
|
||||||
public isUUID = isUUID;
|
public isUUID = isUUID;
|
||||||
|
public pageIndex = 0;
|
||||||
public placeholder = '';
|
public placeholder = '';
|
||||||
public routeQueryParams: Subscription;
|
public routeQueryParams: Subscription;
|
||||||
public searchKeywords: string[] = [];
|
public searchKeywords: string[] = [];
|
||||||
@ -119,12 +124,20 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
return contains;
|
return contains;
|
||||||
};
|
};
|
||||||
|
this.dataSource.paginator = this.paginator;
|
||||||
this.dataSource.sort = this.sort;
|
this.dataSource.sort = this.sort;
|
||||||
|
|
||||||
this.updateFilters();
|
this.updateFilters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onChangePage(page: PageEvent) {
|
||||||
|
this.pageIndex = page.pageIndex;
|
||||||
|
|
||||||
|
this.totalFees = this.getTotalFees();
|
||||||
|
this.totalValue = this.getTotalValue();
|
||||||
|
}
|
||||||
|
|
||||||
public onCloneActivity(aActivity: OrderWithAccount) {
|
public onCloneActivity(aActivity: OrderWithAccount) {
|
||||||
this.activityToClone.emit(aActivity);
|
this.activityToClone.emit(aActivity);
|
||||||
}
|
}
|
||||||
@ -231,6 +244,21 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
return Object.values(fieldValueMap);
|
return Object.values(fieldValueMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getPaginatedData() {
|
||||||
|
if (this.dataSource.data.length > this.pageSize) {
|
||||||
|
const sortedData = this.dataSource.sortData(
|
||||||
|
this.dataSource.filteredData,
|
||||||
|
this.dataSource.sort
|
||||||
|
);
|
||||||
|
|
||||||
|
return sortedData.slice(
|
||||||
|
this.pageIndex * this.pageSize,
|
||||||
|
(this.pageIndex + 1) * this.pageSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.dataSource.filteredData;
|
||||||
|
}
|
||||||
|
|
||||||
private getSearchableFieldValues(activities: OrderWithAccount[]): Filter[] {
|
private getSearchableFieldValues(activities: OrderWithAccount[]): Filter[] {
|
||||||
const fieldValueMap: { [id: string]: Filter } = {};
|
const fieldValueMap: { [id: string]: Filter } = {};
|
||||||
|
|
||||||
@ -243,8 +271,8 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
|
|
||||||
private getTotalFees() {
|
private getTotalFees() {
|
||||||
let totalFees = new Big(0);
|
let totalFees = new Big(0);
|
||||||
|
const paginatedData = this.getPaginatedData();
|
||||||
for (const activity of this.dataSource.filteredData) {
|
for (const activity of paginatedData) {
|
||||||
if (isNumber(activity.feeInBaseCurrency)) {
|
if (isNumber(activity.feeInBaseCurrency)) {
|
||||||
totalFees = totalFees.plus(activity.feeInBaseCurrency);
|
totalFees = totalFees.plus(activity.feeInBaseCurrency);
|
||||||
} else {
|
} else {
|
||||||
@ -257,8 +285,8 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
|
|||||||
|
|
||||||
private getTotalValue() {
|
private getTotalValue() {
|
||||||
let totalValue = new Big(0);
|
let totalValue = new Big(0);
|
||||||
|
const paginatedData = this.getPaginatedData();
|
||||||
for (const activity of this.dataSource.filteredData) {
|
for (const activity of paginatedData) {
|
||||||
if (isNumber(activity.valueInBaseCurrency)) {
|
if (isNumber(activity.valueInBaseCurrency)) {
|
||||||
if (activity.type === 'BUY' || activity.type === 'ITEM') {
|
if (activity.type === 'BUY' || activity.type === 'ITEM') {
|
||||||
totalValue = totalValue.plus(activity.valueInBaseCurrency);
|
totalValue = totalValue.plus(activity.valueInBaseCurrency);
|
||||||
|
@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||||
import { MatSortModule } from '@angular/material/sort';
|
import { MatSortModule } from '@angular/material/sort';
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
@ -26,6 +27,7 @@ import { ActivitiesTableComponent } from './activities-table.component';
|
|||||||
GfValueModule,
|
GfValueModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
|
MatPaginatorModule,
|
||||||
MatSortModule,
|
MatSortModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
NgxSkeletonLoaderModule,
|
NgxSkeletonLoaderModule,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user