|
|
@ -22,11 +22,11 @@ import { |
|
|
ChangeDetectorRef, |
|
|
ChangeDetectorRef, |
|
|
Component, |
|
|
Component, |
|
|
DestroyRef, |
|
|
DestroyRef, |
|
|
Inject |
|
|
inject |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { |
|
|
import { |
|
|
FormBuilder, |
|
|
FormControl, |
|
|
FormGroup, |
|
|
FormGroup, |
|
|
ReactiveFormsModule, |
|
|
ReactiveFormsModule, |
|
|
Validators |
|
|
Validators |
|
|
@ -52,7 +52,6 @@ import { addIcons } from 'ionicons'; |
|
|
import { cloudUploadOutline, warningOutline } from 'ionicons/icons'; |
|
|
import { cloudUploadOutline, warningOutline } from 'ionicons/icons'; |
|
|
import { isArray, sortBy } from 'lodash'; |
|
|
import { isArray, sortBy } from 'lodash'; |
|
|
import ms from 'ms'; |
|
|
import ms from 'ms'; |
|
|
import { DeviceDetectorService } from 'ngx-device-detector'; |
|
|
|
|
|
|
|
|
|
|
|
import { ImportStep } from './enums/import-step'; |
|
|
import { ImportStep } from './enums/import-step'; |
|
|
import { ImportActivitiesDialogParams } from './interfaces/interfaces'; |
|
|
import { ImportActivitiesDialogParams } from './interfaces/interfaces'; |
|
|
@ -82,51 +81,48 @@ import { ImportActivitiesDialogParams } from './interfaces/interfaces'; |
|
|
templateUrl: 'import-activities-dialog.html' |
|
|
templateUrl: 'import-activities-dialog.html' |
|
|
}) |
|
|
}) |
|
|
export class GfImportActivitiesDialogComponent { |
|
|
export class GfImportActivitiesDialogComponent { |
|
|
public accounts: CreateAccountWithBalancesDto[] = []; |
|
|
protected readonly assetProfileForm = new FormGroup({ |
|
|
public activities: Activity[] = []; |
|
|
assetProfileIdentifier: new FormControl<PortfolioPosition | null>(null, { |
|
|
public assetProfileForm: FormGroup; |
|
|
validators: [Validators.required] |
|
|
public assetProfiles: CreateAssetProfileWithMarketDataDto[] = []; |
|
|
}) |
|
|
public dataSource: MatTableDataSource<Activity>; |
|
|
}); |
|
|
public details: any[] = []; |
|
|
protected readonly data = |
|
|
public deviceType: string; |
|
|
inject<ImportActivitiesDialogParams>(MAT_DIALOG_DATA); |
|
|
public dialogTitle = $localize`Import Activities`; |
|
|
protected dataSource: MatTableDataSource<Activity>; |
|
|
public errorMessages: string[] = []; |
|
|
protected details: any[] = []; |
|
|
public holdings: PortfolioPosition[] = []; |
|
|
protected dialogTitle = $localize`Import Activities`; |
|
|
public importStep: ImportStep = ImportStep.UPLOAD_FILE; |
|
|
protected errorMessages: string[] = []; |
|
|
public isLoading = false; |
|
|
protected holdings: PortfolioPosition[] = []; |
|
|
public mode: 'DIVIDEND'; |
|
|
protected importStep: ImportStep = ImportStep.UPLOAD_FILE; |
|
|
public pageIndex = 0; |
|
|
protected isLoading = false; |
|
|
public pageSize = 8; |
|
|
protected mode: 'DIVIDEND'; |
|
|
public selectedActivities: Activity[] = []; |
|
|
protected pageIndex = 0; |
|
|
public sortColumn = 'date'; |
|
|
protected readonly pageSize = 8; |
|
|
public sortDirection: SortDirection = 'desc'; |
|
|
protected selectedActivities: Activity[] = []; |
|
|
public stepperOrientation: StepperOrientation; |
|
|
protected readonly sortColumn = 'date'; |
|
|
public tags: CreateTagDto[] = []; |
|
|
protected readonly sortDirection: SortDirection = 'desc'; |
|
|
public totalItems: number; |
|
|
protected readonly stepperOrientation: StepperOrientation = |
|
|
|
|
|
this.data.deviceType === 'mobile' ? 'vertical' : 'horizontal'; |
|
|
public constructor( |
|
|
protected totalItems: number; |
|
|
private changeDetectorRef: ChangeDetectorRef, |
|
|
|
|
|
@Inject(MAT_DIALOG_DATA) public data: ImportActivitiesDialogParams, |
|
|
private accounts: CreateAccountWithBalancesDto[] = []; |
|
|
private dataService: DataService, |
|
|
private activities: Activity[] = []; |
|
|
private destroyRef: DestroyRef, |
|
|
private assetProfiles: CreateAssetProfileWithMarketDataDto[] = []; |
|
|
private deviceDetectorService: DeviceDetectorService, |
|
|
private tags: CreateTagDto[] = []; |
|
|
private formBuilder: FormBuilder, |
|
|
|
|
|
public dialogRef: MatDialogRef<GfImportActivitiesDialogComponent>, |
|
|
private readonly changeDetectorRef = inject(ChangeDetectorRef); |
|
|
private importActivitiesService: ImportActivitiesService, |
|
|
private readonly dataService = inject(DataService); |
|
|
private snackBar: MatSnackBar |
|
|
private readonly destroyRef = inject(DestroyRef); |
|
|
) { |
|
|
private readonly dialogRef = |
|
|
|
|
|
inject<MatDialogRef<GfImportActivitiesDialogComponent>>(MatDialogRef); |
|
|
|
|
|
private readonly importActivitiesService = inject(ImportActivitiesService); |
|
|
|
|
|
private readonly snackBar = inject(MatSnackBar); |
|
|
|
|
|
|
|
|
|
|
|
public constructor() { |
|
|
addIcons({ cloudUploadOutline, warningOutline }); |
|
|
addIcons({ cloudUploadOutline, warningOutline }); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public ngOnInit() { |
|
|
public ngOnInit() { |
|
|
this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType; |
|
|
|
|
|
this.stepperOrientation = |
|
|
|
|
|
this.deviceType === 'mobile' ? 'vertical' : 'horizontal'; |
|
|
|
|
|
|
|
|
|
|
|
this.assetProfileForm = this.formBuilder.group({ |
|
|
|
|
|
assetProfileIdentifier: [undefined, Validators.required] |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
if ( |
|
|
this.data?.activityTypes?.length === 1 && |
|
|
this.data?.activityTypes?.length === 1 && |
|
|
this.data?.activityTypes?.[0] === 'DIVIDEND' |
|
|
this.data?.activityTypes?.[0] === 'DIVIDEND' |
|
|
@ -135,7 +131,7 @@ export class GfImportActivitiesDialogComponent { |
|
|
|
|
|
|
|
|
this.dialogTitle = $localize`Import Dividends`; |
|
|
this.dialogTitle = $localize`Import Dividends`; |
|
|
this.mode = 'DIVIDEND'; |
|
|
this.mode = 'DIVIDEND'; |
|
|
this.assetProfileForm.get('assetProfileIdentifier').disable(); |
|
|
this.assetProfileForm.controls.assetProfileIdentifier.disable(); |
|
|
|
|
|
|
|
|
this.dataService |
|
|
this.dataService |
|
|
.fetchPortfolioHoldings({ |
|
|
.fetchPortfolioHoldings({ |
|
|
@ -156,7 +152,7 @@ export class GfImportActivitiesDialogComponent { |
|
|
this.holdings = sortBy(holdings, ({ name }) => { |
|
|
this.holdings = sortBy(holdings, ({ name }) => { |
|
|
return name.toLowerCase(); |
|
|
return name.toLowerCase(); |
|
|
}); |
|
|
}); |
|
|
this.assetProfileForm.get('assetProfileIdentifier').enable(); |
|
|
this.assetProfileForm.controls.assetProfileIdentifier.enable(); |
|
|
|
|
|
|
|
|
this.isLoading = false; |
|
|
this.isLoading = false; |
|
|
|
|
|
|
|
|
@ -165,11 +161,11 @@ export class GfImportActivitiesDialogComponent { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onCancel() { |
|
|
protected onCancel() { |
|
|
this.dialogRef.close(); |
|
|
this.dialogRef.close(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async onImportActivities() { |
|
|
protected async onImportActivities() { |
|
|
try { |
|
|
try { |
|
|
this.snackBar.open('⏳ ' + $localize`Importing data...`); |
|
|
this.snackBar.open('⏳ ' + $localize`Importing data...`); |
|
|
|
|
|
|
|
|
@ -202,7 +198,7 @@ export class GfImportActivitiesDialogComponent { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onFilesDropped({ |
|
|
protected onFilesDropped({ |
|
|
files, |
|
|
files, |
|
|
stepper |
|
|
stepper |
|
|
}: { |
|
|
}: { |
|
|
@ -216,7 +212,7 @@ export class GfImportActivitiesDialogComponent { |
|
|
this.handleFile({ stepper, file: files[0] }); |
|
|
this.handleFile({ stepper, file: files[0] }); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onImportStepChange(event: StepperSelectionEvent) { |
|
|
protected onImportStepChange(event: StepperSelectionEvent) { |
|
|
if (event.selectedIndex === ImportStep.UPLOAD_FILE) { |
|
|
if (event.selectedIndex === ImportStep.UPLOAD_FILE) { |
|
|
this.importStep = ImportStep.UPLOAD_FILE; |
|
|
this.importStep = ImportStep.UPLOAD_FILE; |
|
|
} else if (event.selectedIndex === ImportStep.SELECT_ACTIVITIES) { |
|
|
} else if (event.selectedIndex === ImportStep.SELECT_ACTIVITIES) { |
|
|
@ -224,12 +220,15 @@ export class GfImportActivitiesDialogComponent { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onLoadDividends(aStepper: MatStepper) { |
|
|
protected onLoadDividends(aStepper: MatStepper) { |
|
|
this.assetProfileForm.get('assetProfileIdentifier').disable(); |
|
|
this.assetProfileForm.controls.assetProfileIdentifier.disable(); |
|
|
|
|
|
|
|
|
const { dataSource, symbol } = this.assetProfileForm.get( |
|
|
const { dataSource, symbol } = |
|
|
'assetProfileIdentifier' |
|
|
this.assetProfileForm.controls.assetProfileIdentifier.value ?? {}; |
|
|
).value; |
|
|
|
|
|
|
|
|
if (!dataSource || !symbol) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.dataService |
|
|
this.dataService |
|
|
.fetchDividendsImport({ |
|
|
.fetchDividendsImport({ |
|
|
@ -249,47 +248,43 @@ export class GfImportActivitiesDialogComponent { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onPageChanged({ pageIndex }: PageEvent) { |
|
|
protected onPageChanged({ pageIndex }: PageEvent) { |
|
|
this.pageIndex = pageIndex; |
|
|
this.pageIndex = pageIndex; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onReset(aStepper: MatStepper) { |
|
|
protected onReset(aStepper: MatStepper) { |
|
|
this.details = []; |
|
|
this.details = []; |
|
|
this.errorMessages = []; |
|
|
this.errorMessages = []; |
|
|
this.importStep = ImportStep.SELECT_ACTIVITIES; |
|
|
this.importStep = ImportStep.SELECT_ACTIVITIES; |
|
|
this.pageIndex = 0; |
|
|
this.pageIndex = 0; |
|
|
this.assetProfileForm.get('assetProfileIdentifier').enable(); |
|
|
this.assetProfileForm.controls.assetProfileIdentifier.enable(); |
|
|
|
|
|
|
|
|
aStepper.reset(); |
|
|
aStepper.reset(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onSelectFile(stepper: MatStepper) { |
|
|
protected onSelectFile(stepper: MatStepper) { |
|
|
const input = document.createElement('input'); |
|
|
const input = document.createElement('input'); |
|
|
input.accept = 'application/JSON, .csv'; |
|
|
input.accept = 'application/JSON, .csv'; |
|
|
input.type = 'file'; |
|
|
input.type = 'file'; |
|
|
|
|
|
|
|
|
input.onchange = (event) => { |
|
|
input.onchange = (event) => { |
|
|
// Getting the file reference
|
|
|
// Getting the file reference
|
|
|
const file = (event.target as HTMLInputElement).files[0]; |
|
|
const file = (event.target as HTMLInputElement).files?.[0]; |
|
|
this.handleFile({ file, stepper }); |
|
|
if (file) { |
|
|
|
|
|
this.handleFile({ file, stepper }); |
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
input.click(); |
|
|
input.click(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public updateSelection(activities: Activity[]) { |
|
|
protected updateSelection(activities: Activity[]) { |
|
|
this.selectedActivities = activities.filter(({ error }) => { |
|
|
this.selectedActivities = activities.filter(({ error }) => { |
|
|
return !error; |
|
|
return !error; |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private async handleFile({ |
|
|
private handleFile({ file, stepper }: { file: File; stepper: MatStepper }) { |
|
|
file, |
|
|
|
|
|
stepper |
|
|
|
|
|
}: { |
|
|
|
|
|
file: File; |
|
|
|
|
|
stepper: MatStepper; |
|
|
|
|
|
}): Promise<void> { |
|
|
|
|
|
this.snackBar.open('⏳ ' + $localize`Validating data...`); |
|
|
this.snackBar.open('⏳ ' + $localize`Validating data...`); |
|
|
|
|
|
|
|
|
// Setting up the reader
|
|
|
// Setting up the reader
|
|
|
@ -297,7 +292,7 @@ export class GfImportActivitiesDialogComponent { |
|
|
reader.readAsText(file, 'UTF-8'); |
|
|
reader.readAsText(file, 'UTF-8'); |
|
|
|
|
|
|
|
|
reader.onload = async (readerEvent) => { |
|
|
reader.onload = async (readerEvent) => { |
|
|
const fileContent = readerEvent.target.result as string; |
|
|
const fileContent = readerEvent.target?.result as string; |
|
|
const fileExtension = file.name.split('.').pop()?.toLowerCase(); |
|
|
const fileExtension = file.name.split('.').pop()?.toLowerCase(); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
|