Browse Source

Refactoring

pull/2002/head
Thomas 2 years ago
parent
commit
95d0f5d16f
  1. 18
      apps/api/src/app/benchmark/benchmark.controller.ts
  2. 11
      apps/api/src/app/benchmark/benchmark.service.ts
  3. 28
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  4. 19
      apps/client/src/app/components/admin-market-data/admin-market-data.html
  5. 23
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  6. 7
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  7. 3
      libs/common/src/lib/exceptions/index.ts
  8. 6
      libs/common/src/lib/exceptions/not-found-error.ts

18
apps/api/src/app/benchmark/benchmark.controller.ts

@ -23,7 +23,6 @@ import { BenchmarkService } from './benchmark.service';
import { REQUEST } from '@nestjs/core'; import { REQUEST } from '@nestjs/core';
import { RequestWithUser } from '@ghostfolio/common/types'; import { RequestWithUser } from '@ghostfolio/common/types';
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { NotFoundError } from '@ghostfolio/common/exceptions';
@Controller('benchmark') @Controller('benchmark')
export class BenchmarkController { export class BenchmarkController {
@ -60,7 +59,7 @@ export class BenchmarkController {
@Post() @Post()
@UseGuards(AuthGuard('jwt')) @UseGuards(AuthGuard('jwt'))
public async addBenchmark(@Body() benchmark: UniqueAsset) { public async addBenchmark(@Body() { dataSource, symbol }: UniqueAsset) {
if ( if (
!hasPermission( !hasPermission(
this.request.user.permissions, this.request.user.permissions,
@ -74,19 +73,24 @@ export class BenchmarkController {
} }
try { try {
return await this.benchmarkService.addBenchmark(benchmark); const benchmark = await this.benchmarkService.addBenchmark({
} catch (error) { dataSource,
if (error instanceof NotFoundError) { symbol
});
if (!benchmark) {
throw new HttpException( throw new HttpException(
getReasonPhrase(StatusCodes.NOT_FOUND), getReasonPhrase(StatusCodes.NOT_FOUND),
StatusCodes.NOT_FOUND StatusCodes.NOT_FOUND
); );
} else { }
return benchmark;
} catch {
throw new HttpException( throw new HttpException(
getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR), getReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR),
StatusCodes.INTERNAL_SERVER_ERROR StatusCodes.INTERNAL_SERVER_ERROR
); );
} }
} }
}
} }

11
apps/api/src/app/benchmark/benchmark.service.ts

@ -2,6 +2,7 @@ import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.s
import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service'; import { SymbolService } from '@ghostfolio/api/app/symbol/symbol.service';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import { import {
@ -21,8 +22,6 @@ import Big from 'big.js';
import { format } from 'date-fns'; import { format } from 'date-fns';
import ms from 'ms'; import ms from 'ms';
import { uniqBy } from 'lodash'; import { uniqBy } from 'lodash';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { NotFoundError } from '@ghostfolio/common/exceptions';
@Injectable() @Injectable()
export class BenchmarkService { export class BenchmarkService {
@ -221,21 +220,21 @@ export class BenchmarkService {
}); });
if (!symbolProfile) { if (!symbolProfile) {
throw new NotFoundError('Symbol profile not found'); return;
} }
const benchmarks = let benchmarks =
((await this.propertyService.getByKey( ((await this.propertyService.getByKey(
PROPERTY_BENCHMARKS PROPERTY_BENCHMARKS
)) as BenchmarkProperty[]) ?? []; )) as BenchmarkProperty[]) ?? [];
benchmarks.push({ symbolProfileId: symbolProfile.id } as BenchmarkProperty); benchmarks.push({ symbolProfileId: symbolProfile.id } as BenchmarkProperty);
const newBenchmarks = uniqBy(benchmarks, 'symbolProfileId'); benchmarks = uniqBy(benchmarks, 'symbolProfileId');
await this.propertyService.put({ await this.propertyService.put({
key: PROPERTY_BENCHMARKS, key: PROPERTY_BENCHMARKS,
value: JSON.stringify(newBenchmarks) value: JSON.stringify(benchmarks)
}); });
return { return {

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

@ -14,23 +14,13 @@ import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
import { getDateFormatString } from '@ghostfolio/common/helper'; import { getDateFormatString } from '@ghostfolio/common/helper';
import { import { Filter, UniqueAsset, User } from '@ghostfolio/common/interfaces';
Filter,
InfoItem,
UniqueAsset,
User
} from '@ghostfolio/common/interfaces';
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface'; import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
import { AssetSubClass, DataSource, SymbolProfile } from '@prisma/client'; import { AssetSubClass, DataSource, SymbolProfile } from '@prisma/client';
import { DeviceDetectorService } from 'ngx-device-detector'; import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
distinctUntilChanged,
switchMap,
take,
takeUntil
} from 'rxjs/operators';
import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component'; import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component';
import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces'; import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces';
@ -155,13 +145,6 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
}); });
} }
public isBenchmark({ dataSource, symbol }: UniqueAsset) {
return this.benchmarks.some(
(benchmark) =>
benchmark.dataSource === dataSource && benchmark.symbol === symbol
);
}
public onDeleteProfileData({ dataSource, symbol }: UniqueAsset) { public onDeleteProfileData({ dataSource, symbol }: UniqueAsset) {
this.adminService this.adminService
.deleteProfileData({ dataSource, symbol }) .deleteProfileData({ dataSource, symbol })
@ -205,13 +188,6 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
.subscribe(() => {}); .subscribe(() => {});
} }
public onSetBenchmark(benchmark: UniqueAsset) {
this.dataService
.postBenchmark(benchmark)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {});
}
public onGatherSymbol({ dataSource, symbol }: UniqueAsset) { public onGatherSymbol({ dataSource, symbol }: UniqueAsset) {
this.adminService this.adminService
.gatherSymbol({ dataSource, symbol }) .gatherSymbol({ dataSource, symbol })

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

@ -143,25 +143,6 @@
<ion-icon name="ellipsis-vertical"></ion-icon> <ion-icon name="ellipsis-vertical"></ion-icon>
</button> </button>
<mat-menu #assetProfileActionsMenu="matMenu" xPosition="before"> <mat-menu #assetProfileActionsMenu="matMenu" xPosition="before">
<button
mat-menu-item
(click)="onGatherSymbol({dataSource: element.dataSource, symbol: element.symbol})"
>
<ng-container i18n>Gather Historical Data</ng-container>
</button>
<button
mat-menu-item
(click)="onGatherProfileDataBySymbol({dataSource: element.dataSource, symbol: element.symbol})"
>
<ng-container i18n>Gather Profile Data</ng-container>
</button>
<button
mat-menu-item
[disabled]="isBenchmark({dataSource: element.dataSource, symbol: element.symbol})"
(click)="onSetBenchmark({dataSource: element.dataSource, symbol: element.symbol})"
>
<ng-container i18n>Set as Benchmark</ng-container>
</button>
<button <button
mat-menu-item mat-menu-item
[disabled]="element.activitiesCount !== 0" [disabled]="element.activitiesCount !== 0"

23
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -10,13 +10,13 @@ import { FormBuilder } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UpdateAssetProfileDto } from '@ghostfolio/api/app/admin/update-asset-profile.dto'; import { UpdateAssetProfileDto } from '@ghostfolio/api/app/admin/update-asset-profile.dto';
import { AdminService } from '@ghostfolio/client/services/admin.service'; import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service';
import { import {
AdminMarketDataDetails, AdminMarketDataDetails,
EnhancedSymbolProfile,
UniqueAsset UniqueAsset
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
import { MarketData } from '@prisma/client'; import { MarketData, SymbolProfile } from '@prisma/client';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
@ -37,9 +37,11 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
symbolMapping: '' symbolMapping: ''
}); });
public assetSubClass: string; public assetSubClass: string;
public benchmarks: Partial<SymbolProfile>[];
public countries: { public countries: {
[code: string]: { name: string; value: number }; [code: string]: { name: string; value: number };
}; };
public isBenchmark = false;
public marketDataDetails: MarketData[] = []; public marketDataDetails: MarketData[] = [];
public sectors: { public sectors: {
[name: string]: { name: string; value: number }; [name: string]: { name: string; value: number };
@ -51,11 +53,14 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
private adminService: AdminService, private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
@Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogParams, @Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogParams,
private dataService: DataService,
public dialogRef: MatDialogRef<AssetProfileDialog>, public dialogRef: MatDialogRef<AssetProfileDialog>,
private formBuilder: FormBuilder private formBuilder: FormBuilder
) {} ) {}
public ngOnInit(): void { public ngOnInit(): void {
this.benchmarks = this.dataService.fetchInfo().benchmarks;
this.initialize(); this.initialize();
} }
@ -72,6 +77,9 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
this.assetClass = translate(this.assetProfile?.assetClass); this.assetClass = translate(this.assetProfile?.assetClass);
this.assetSubClass = translate(this.assetProfile?.assetSubClass); this.assetSubClass = translate(this.assetProfile?.assetSubClass);
this.countries = {}; this.countries = {};
this.isBenchmark = this.benchmarks.some(({ id }) => {
return id === this.assetProfile.id;
});
this.marketDataDetails = marketData; this.marketDataDetails = marketData;
this.sectors = {}; this.sectors = {};
@ -128,6 +136,17 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
} }
} }
public onSetBenchmark({ dataSource, symbol }: UniqueAsset) {
this.dataService
.postBenchmark({ dataSource, symbol })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
setTimeout(() => {
window.location.reload();
}, 300);
});
}
public onSubmit() { public onSubmit() {
let symbolMapping = {}; let symbolMapping = {};

7
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -37,6 +37,13 @@
> >
<ng-container i18n>Gather Profile Data</ng-container> <ng-container i18n>Gather Profile Data</ng-container>
</button> </button>
<button
mat-menu-item
[disabled]="isBenchmark"
(click)="onSetBenchmark({dataSource: data.dataSource, symbol: data.symbol})"
>
<ng-container i18n>Set as Benchmark</ng-container>
</button>
</mat-menu> </mat-menu>
</div> </div>

3
libs/common/src/lib/exceptions/index.ts

@ -1,3 +0,0 @@
import { NotFoundError } from './not-found-error';
export { NotFoundError };

6
libs/common/src/lib/exceptions/not-found-error.ts

@ -1,6 +0,0 @@
export class NotFoundError extends Error {
constructor(message: string) {
super(message);
this.name = 'NotFoundError';
}
}
Loading…
Cancel
Save