Browse Source

Support sorting

pull/2108/head
Thomas 2 years ago
parent
commit
2f16f9255f
  1. 6
      apps/api/src/app/admin/admin.controller.ts
  2. 12
      apps/api/src/app/admin/admin.service.ts
  3. 47
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  4. 6
      apps/client/src/app/components/admin-market-data/admin-market-data.html
  5. 14
      apps/client/src/app/services/admin.service.ts

6
apps/api/src/app/admin/admin.controller.ts

@ -33,7 +33,7 @@ import {
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { DataSource, MarketData, SymbolProfile } from '@prisma/client';
import { DataSource, MarketData, Prisma, SymbolProfile } from '@prisma/client';
import { isDate } from 'date-fns';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
@ -250,6 +250,8 @@ export class AdminController {
public async getMarketData(
@Query('assetSubClasses') filterByAssetSubClasses?: string,
@Query('skip') skip?: number,
@Query('sortColumn') sortColumn?: string,
@Query('sortDirection') sortDirection?: Prisma.SortOrder,
@Query('take') take?: number
): Promise<AdminMarketData> {
if (
@ -277,6 +279,8 @@ export class AdminController {
return this.adminService.getMarketData({
filters,
sortColumn,
sortDirection,
skip: isNaN(skip) ? undefined : skip,
take: isNaN(take) ? undefined : take
});

12
apps/api/src/app/admin/admin.service.ts

@ -103,13 +103,19 @@ export class AdminService {
public async getMarketData({
filters,
sortColumn,
sortDirection,
skip,
take = DEFAULT_PAGE_SIZE
}: {
filters?: Filter[];
skip?: number;
sortColumn?: string;
sortDirection?: Prisma.SortOrder;
take?: number;
}): Promise<AdminMarketData> {
let orderBy: Prisma.Enumerable<Prisma.SymbolProfileOrderByWithRelationInput> =
[{ symbol: 'asc' }];
const where: Prisma.SymbolProfileWhereInput = {};
const { ASSET_SUB_CLASS: filtersByAssetSubClass } = groupBy(
@ -128,12 +134,16 @@ export class AdminService {
where.assetSubClass = AssetSubClass[filtersByAssetSubClass[0].id];
}
if (sortColumn) {
orderBy = [{ [sortColumn]: sortDirection }];
}
const [assetProfiles, count] = await Promise.all([
this.prismaService.symbolProfile.findMany({
orderBy,
skip,
take,
where,
orderBy: [{ symbol: 'asc' }],
select: {
_count: {
select: { Order: true }

47
apps/client/src/app/components/admin-market-data/admin-market-data.component.ts

@ -1,4 +1,5 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
@ -7,7 +8,7 @@ import {
ViewChild
} from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort';
import { MatSort, Sort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router';
import { AdminService } from '@ghostfolio/client/services/admin.service';
@ -16,7 +17,7 @@ import { getDateFormatString } from '@ghostfolio/common/helper';
import { Filter, UniqueAsset, User } from '@ghostfolio/common/interfaces';
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
import { translate } from '@ghostfolio/ui/i18n';
import { AssetSubClass, DataSource } from '@prisma/client';
import { AssetSubClass, DataSource, Prisma } from '@prisma/client';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
@ -34,7 +35,9 @@ import { MatPaginator, PageEvent } from '@angular/material/paginator';
styleUrls: ['./admin-market-data.scss'],
templateUrl: './admin-market-data.html'
})
export class AdminMarketDataComponent implements OnDestroy, OnInit {
export class AdminMarketDataComponent
implements AfterViewInit, OnDestroy, OnInit
{
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ -130,12 +133,30 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
});
}
public ngAfterViewInit() {
this.sort.sortChange.subscribe(
({ active: sortColumn, direction }: Sort) => {
this.paginator.pageIndex = 0;
this.loadData({
sortColumn,
sortDirection: <Prisma.SortOrder>direction,
pageIndex: this.paginator.pageIndex
});
}
);
}
public ngOnInit() {
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
}
public onChangePage(page: PageEvent) {
this.loadData(page.pageIndex);
this.loadData({
pageIndex: page.pageIndex,
sortColumn: this.sort.active,
sortDirection: <Prisma.SortOrder>this.sort.direction
});
}
public onDeleteProfileData({ dataSource, symbol }: UniqueAsset) {
@ -203,10 +224,20 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
this.unsubscribeSubject.complete();
}
private loadData(aPageIndex = 0) {
private loadData(
{
pageIndex,
sortColumn,
sortDirection
}: {
pageIndex: number;
sortColumn?: string;
sortDirection?: Prisma.SortOrder;
} = { pageIndex: 0 }
) {
this.isLoading = true;
if (aPageIndex === 0 && this.paginator) {
if (pageIndex === 0 && this.paginator) {
this.paginator.pageIndex = 0;
}
@ -215,8 +246,10 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
this.adminService
.fetchAdminMarketData({
sortColumn,
sortDirection,
filters: this.activeFilters,
skip: aPageIndex * this.pageSize,
skip: pageIndex * this.pageSize,
take: this.pageSize
})
.pipe(takeUntil(this.unsubscribeSubject))

6
apps/client/src/app/components/admin-market-data/admin-market-data.html

@ -29,7 +29,7 @@
</ng-container>
<ng-container matColumnDef="dataSource">
<th *matHeaderCellDef class="px-1" mat-header-cell>
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Data Source</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
@ -38,7 +38,7 @@
</ng-container>
<ng-container matColumnDef="assetClass">
<th *matHeaderCellDef class="px-1" mat-header-cell>
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Asset Class</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
@ -47,7 +47,7 @@
</ng-container>
<ng-container matColumnDef="assetSubClass">
<th *matHeaderCellDef class="px-1" mat-header-cell>
<th *matHeaderCellDef class="px-1" mat-header-cell mat-sort-header>
<ng-container i18n>Asset Sub Class</ng-container>
</th>
<td *matCellDef="let element" class="px-1" mat-cell>

14
apps/client/src/app/services/admin.service.ts

@ -15,7 +15,7 @@ import {
Filter,
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { DataSource, MarketData, Platform } from '@prisma/client';
import { DataSource, MarketData, Platform, Prisma } from '@prisma/client';
import { JobStatus } from 'bull';
import { format, parseISO } from 'date-fns';
import { Observable, map } from 'rxjs';
@ -70,10 +70,14 @@ export class AdminService {
public fetchAdminMarketData({
filters,
skip,
sortColumn,
sortDirection,
take
}: {
filters?: Filter[];
skip?: number;
sortColumn?: string;
sortDirection?: Prisma.SortOrder;
take: number;
}) {
let params = this.dataService.buildFiltersAsQueryParams({ filters });
@ -82,6 +86,14 @@ export class AdminService {
params = params.append('skip', skip);
}
if (sortColumn) {
params = params.append('sortColumn', sortColumn);
}
if (sortDirection) {
params = params.append('sortDirection', sortDirection);
}
params = params.append('take', take);
return this.http.get<AdminMarketData>('/api/v1/admin/market-data', {

Loading…
Cancel
Save