Browse Source

Support migrating asset profile to MANUAL data source

pull/7376/head
Thomas Kaul 1 month ago
parent
commit
4f57225748
  1. 4
      apps/api/src/app/admin/admin.service.ts
  2. 9
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  3. 52
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

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

@ -242,9 +242,9 @@ export class AdminService {
}: Prisma.SymbolProfileUpdateInput }: Prisma.SymbolProfileUpdateInput
) { ) {
if ( if (
newSymbol &&
newDataSource && newDataSource &&
(newSymbol !== symbol || newDataSource !== dataSource) newSymbol &&
(newDataSource !== dataSource || newSymbol !== symbol)
) { ) {
const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([ const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([
{ {

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

@ -410,7 +410,8 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit {
const dialogRef = this.dialog.open< const dialogRef = this.dialog.open<
GfAssetProfileDialogComponent, GfAssetProfileDialogComponent,
AssetProfileDialogParams AssetProfileDialogParams,
AssetProfileIdentifier
>(GfAssetProfileDialogComponent, { >(GfAssetProfileDialogComponent, {
autoFocus: false, autoFocus: false,
data: { data: {
@ -428,15 +429,13 @@ export class GfAdminMarketDataComponent implements AfterViewInit, OnInit {
dialogRef dialogRef
.afterClosed() .afterClosed()
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe( .subscribe((newAssetProfileIdentifier) => {
(newAssetProfileIdentifier: AssetProfileIdentifier | undefined) => {
if (newAssetProfileIdentifier) { if (newAssetProfileIdentifier) {
this.onOpenAssetProfileDialog(newAssetProfileIdentifier); this.onOpenAssetProfileDialog(newAssetProfileIdentifier);
} else { } else {
this.router.navigate(['.'], { relativeTo: this.route }); this.router.navigate(['.'], { relativeTo: this.route });
} }
} });
);
}); });
} }

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

@ -5,6 +5,7 @@ import {
PROPERTY_IS_DATA_GATHERING_ENABLED PROPERTY_IS_DATA_GATHERING_ENABLED
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { UpdateAssetProfileDto } from '@ghostfolio/common/dtos'; import { UpdateAssetProfileDto } from '@ghostfolio/common/dtos';
import { ConfirmationDialogType } from '@ghostfolio/common/enums';
import { import {
canDeleteAssetProfile, canDeleteAssetProfile,
DATE_FORMAT, DATE_FORMAT,
@ -278,7 +279,10 @@ export class GfAssetProfileDialogComponent implements OnInit {
@Inject(MAT_DIALOG_DATA) protected data: AssetProfileDialogParams, @Inject(MAT_DIALOG_DATA) protected data: AssetProfileDialogParams,
private dataService: DataService, private dataService: DataService,
private destroyRef: DestroyRef, private destroyRef: DestroyRef,
private dialogRef: MatDialogRef<GfAssetProfileDialogComponent>, private dialogRef: MatDialogRef<
GfAssetProfileDialogComponent,
AssetProfileIdentifier
>,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private notificationService: NotificationService, private notificationService: NotificationService,
private snackBar: MatSnackBar, private snackBar: MatSnackBar,
@ -469,13 +473,20 @@ export class GfAssetProfileDialogComponent implements OnInit {
} }
protected onConvertToManualDataSource() { protected onConvertToManualDataSource() {
this.notificationService.confirm({
confirmFn: () => {
const newAssetProfileIdentifier: AssetProfileIdentifier = {
dataSource: DataSource.MANUAL,
symbol: crypto.randomUUID()
};
const convertedAssetProfile: UpdateAssetProfileDto = { const convertedAssetProfile: UpdateAssetProfileDto = {
assetClass: this.assetProfile?.assetClass ?? undefined, assetClass: this.assetProfile?.assetClass ?? undefined,
assetSubClass: this.assetProfile?.assetSubClass ?? undefined, assetSubClass: this.assetProfile?.assetSubClass ?? undefined,
countries: this.assetProfile?.countries?.map(({ code, weight }) => { countries: this.assetProfile?.countries?.map(({ code, weight }) => {
return { code, weight }; return { code, weight };
}), }),
dataSource: DataSource.MANUAL, dataSource: newAssetProfileIdentifier.dataSource,
holdings: this.assetProfile?.holdings?.map( holdings: this.assetProfile?.holdings?.map(
({ allocationInPercentage, name }) => { ({ allocationInPercentage, name }) => {
return { allocationInPercentage, name }; return { allocationInPercentage, name };
@ -485,7 +496,7 @@ export class GfAssetProfileDialogComponent implements OnInit {
sectors: this.assetProfile?.sectors?.map(({ name, weight }) => { sectors: this.assetProfile?.sectors?.map(({ name, weight }) => {
return { name, weight }; return { name, weight };
}), }),
symbol: crypto.randomUUID(), symbol: newAssetProfileIdentifier.symbol,
url: this.assetProfile?.url ?? undefined url: this.assetProfile?.url ?? undefined
}; };
@ -513,13 +524,12 @@ export class GfAssetProfileDialogComponent implements OnInit {
takeUntilDestroyed(this.destroyRef) takeUntilDestroyed(this.destroyRef)
) )
.subscribe(() => { .subscribe(() => {
const newAssetProfileIdentifier = {
dataSource: convertedAssetProfile.dataSource,
symbol: convertedAssetProfile.symbol
};
this.dialogRef.close(newAssetProfileIdentifier); this.dialogRef.close(newAssetProfileIdentifier);
}); });
},
confirmType: ConfirmationDialogType.Primary,
title: $localize`Do you really want to convert this asset profile to ${DataSource.MANUAL}?`
});
} }
protected onDeleteProfileData({ protected onDeleteProfileData({
@ -721,13 +731,16 @@ export class GfAssetProfileDialogComponent implements OnInit {
} }
protected async onSubmitAssetProfileIdentifierForm() { protected async onSubmitAssetProfileIdentifierForm() {
const newAssetProfileIdentifier =
this.assetProfileIdentifierForm.controls.assetProfileIdentifier.value;
if (!newAssetProfileIdentifier?.dataSource) {
return;
}
const assetProfileIdentifier: UpdateAssetProfileDto = { const assetProfileIdentifier: UpdateAssetProfileDto = {
dataSource: dataSource: newAssetProfileIdentifier.dataSource,
this.assetProfileIdentifierForm.controls.assetProfileIdentifier.value symbol: newAssetProfileIdentifier.symbol
?.dataSource ?? undefined,
symbol:
this.assetProfileIdentifierForm.controls.assetProfileIdentifier.value
?.symbol ?? undefined
}; };
try { try {
@ -742,6 +755,8 @@ export class GfAssetProfileDialogComponent implements OnInit {
return; return;
} }
this.notificationService.confirm({
confirmFn: () => {
this.adminService this.adminService
.patchAssetProfile( .patchAssetProfile(
{ {
@ -775,13 +790,12 @@ export class GfAssetProfileDialogComponent implements OnInit {
takeUntilDestroyed(this.destroyRef) takeUntilDestroyed(this.destroyRef)
) )
.subscribe(() => { .subscribe(() => {
const newAssetProfileIdentifier = {
dataSource: assetProfileIdentifier.dataSource,
symbol: assetProfileIdentifier.symbol
};
this.dialogRef.close(newAssetProfileIdentifier); this.dialogRef.close(newAssetProfileIdentifier);
}); });
},
confirmType: ConfirmationDialogType.Primary,
title: $localize`Do you really want to convert this asset profile to ${newAssetProfileIdentifier.symbol} (${newAssetProfileIdentifier.dataSource})?`
});
} }
protected onTestMarketData() { protected onTestMarketData() {

Loading…
Cancel
Save