Browse Source

Add actions

pull/1474/head
Thomas 3 years ago
parent
commit
b08da57404
  1. 4
      apps/api/src/app/admin/admin.controller.ts
  2. 2
      apps/api/src/app/admin/admin.service.ts
  3. 4
      apps/api/src/app/admin/update-asset-profile.dto.ts
  4. 101
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  5. 37
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html
  6. 2
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/assset-profile-dialog.module.ts

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

@ -337,7 +337,7 @@ export class AdminController {
@Patch('profile-data/:dataSource/:symbol')
@UseGuards(AuthGuard('jwt'))
public async patchProfileData(
public async patchAssetProfileData(
@Body() assetProfileData: UpdateAssetProfileDto,
@Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string
@ -354,7 +354,7 @@ export class AdminController {
);
}
return this.adminService.patchProfileData({
return this.adminService.patchAssetProfileData({
...assetProfileData,
dataSource,
symbol

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

@ -189,7 +189,7 @@ export class AdminService {
};
}
public async patchProfileData({
public async patchAssetProfileData({
dataSource,
symbol,
symbolMapping

4
apps/api/src/app/admin/update-asset-profile.dto.ts

@ -3,5 +3,7 @@ import { IsObject, IsOptional } from 'class-validator';
export class UpdateAssetProfileDto {
@IsObject()
@IsOptional()
symbolMapping?: object;
symbolMapping?: {
[dataProvider: string]: string;
};
}

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

@ -10,7 +10,10 @@ import { FormBuilder } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UpdateAssetProfileDto } from '@ghostfolio/api/app/admin/update-asset-profile.dto';
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { EnhancedSymbolProfile } from '@ghostfolio/common/interfaces';
import {
EnhancedSymbolProfile,
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { MarketData } from '@prisma/client';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -42,8 +45,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
public constructor(
private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef,
public dialogRef: MatDialogRef<AssetProfileDialog>,
@Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogParams,
public dialogRef: MatDialogRef<AssetProfileDialog>,
private formBuilder: FormBuilder
) {}
@ -51,10 +54,65 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
this.initialize();
}
public initialize() {
this.adminService
.fetchAdminMarketDataBySymbol({
dataSource: this.data.dataSource,
symbol: this.data.symbol
})
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ assetProfile, marketData }) => {
this.assetProfile = assetProfile;
this.countries = {};
this.marketDataDetails = marketData;
this.sectors = {};
if (assetProfile?.countries?.length > 0) {
for (const country of assetProfile.countries) {
this.countries[country.code] = {
name: country.name,
value: country.weight
};
}
}
if (assetProfile?.sectors?.length > 0) {
for (const sector of assetProfile.sectors) {
this.sectors[sector.name] = {
name: sector.name,
value: sector.weight
};
}
}
this.assetProfileForm.setValue({
symbolMapping: JSON.stringify(this.assetProfile?.symbolMapping)
});
this.assetProfileForm.markAsPristine();
this.changeDetectorRef.markForCheck();
});
}
public onClose(): void {
this.dialogRef.close();
}
public onGatherProfileDataBySymbol({ dataSource, symbol }: UniqueAsset) {
this.adminService
.gatherProfileDataBySymbol({ dataSource, symbol })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {});
}
public onGatherSymbol({ dataSource, symbol }: UniqueAsset) {
this.adminService
.gatherSymbol({ dataSource, symbol })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {});
}
public onMarketDataChanged(withRefresh: boolean = false) {
if (withRefresh) {
this.initialize();
@ -89,43 +147,4 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private initialize() {
this.adminService
.fetchAdminMarketDataBySymbol({
dataSource: this.data.dataSource,
symbol: this.data.symbol
})
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ assetProfile, marketData }) => {
this.assetProfile = assetProfile;
this.countries = {};
this.marketDataDetails = marketData;
this.sectors = {};
if (assetProfile?.countries?.length > 0) {
for (const country of assetProfile.countries) {
this.countries[country.code] = {
name: country.name,
value: country.weight
};
}
}
if (assetProfile?.sectors?.length > 0) {
for (const sector of assetProfile.sectors) {
this.sectors[sector.name] = {
name: sector.name,
value: sector.weight
};
}
}
this.assetProfileForm.setValue({
symbolMapping: JSON.stringify(this.assetProfile?.symbolMapping)
});
this.changeDetectorRef.markForCheck();
});
}
}

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

@ -4,7 +4,42 @@
(keyup.enter)="assetProfileForm.valid && onSubmit()"
(ngSubmit)="onSubmit()"
>
<h1 mat-dialog-title>{{ assetProfile?.name ?? data.symbol }}</h1>
<div class="d-flex mb-3">
<h1 class="flex-grow-1 m-0" mat-dialog-title>
{{ assetProfile?.name ?? data.symbol }}
</h1>
<button
class="mx-1 no-min-width px-2"
mat-button
type="button"
[matMenuTriggerFor]="assetProfileActionsMenu"
(click)="$event.stopPropagation()"
>
<ion-icon name="ellipsis-vertical"></ion-icon>
</button>
<mat-menu #assetProfileActionsMenu="matMenu" xPosition="before">
<button mat-menu-item type="button" (click)="initialize()">
<ng-container i18n>Refresh</ng-container>
</button>
<button
mat-menu-item
type="button"
[disabled]="assetProfileForm.dirty"
(click)="onGatherSymbol({dataSource: data.dataSource, symbol: data.symbol})"
>
<ng-container i18n>Gather Data</ng-container>
</button>
<button
mat-menu-item
type="button"
[disabled]="assetProfileForm.dirty"
(click)="onGatherProfileDataBySymbol({dataSource: data.dataSource, symbol: data.symbol})"
>
<ng-container i18n>Gather Profile Data</ng-container>
</button>
</mat-menu>
</div>
<div class="flex-grow-1" mat-dialog-content>
<gf-admin-market-data-detail
class="mb-3"

2
apps/client/src/app/components/admin-market-data/asset-profile-dialog/assset-profile-dialog.module.ts

@ -5,6 +5,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { GfAdminMarketDataDetailModule } from '@ghostfolio/client/components/admin-market-data-detail/admin-market-data-detail.module';
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
import { GfValueModule } from '@ghostfolio/ui/value';
@ -22,6 +23,7 @@ import { AssetProfileDialog } from './asset-profile-dialog.component';
MatButtonModule,
MatDialogModule,
MatInputModule,
MatMenuModule,
ReactiveFormsModule,
TextFieldModule
],

Loading…
Cancel
Save