diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/file-drop.directive.ts b/apps/client/src/app/directives/file-drop/file-drop.directive.ts similarity index 100% rename from apps/client/src/app/pages/portfolio/activities/import-activities-dialog/file-drop.directive.ts rename to apps/client/src/app/directives/file-drop/file-drop.directive.ts diff --git a/apps/client/src/app/directives/file-drop/file-drop.module.ts b/apps/client/src/app/directives/file-drop/file-drop.module.ts new file mode 100644 index 000000000..a0148516e --- /dev/null +++ b/apps/client/src/app/directives/file-drop/file-drop.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core'; + +import { FileDropDirective } from './file-drop.directive'; + +@NgModule({ + declarations: [FileDropDirective], + exports: [FileDropDirective] +}) +export class GfFileDropModule {} diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts index 54f23bad4..d11cafdb9 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -137,6 +137,20 @@ export class ImportActivitiesDialog implements OnDestroy { } } + public onFilesDropped({ + files, + stepper + }: { + files: FileList; + stepper: MatStepper; + }): void { + if (files.length === 0) { + return; + } + + this.handleFile({ stepper, file: files[0] }); + } + public onImportStepChange(event: StepperSelectionEvent) { if (event.selectedIndex === ImportStep.UPLOAD_FILE) { this.importStep = ImportStep.UPLOAD_FILE; @@ -175,7 +189,38 @@ export class ImportActivitiesDialog implements OnDestroy { aStepper.reset(); } - private async handleFile(file: File): Promise { + public onSelectFile(stepper: MatStepper) { + const input = document.createElement('input'); + input.accept = 'application/JSON, .csv'; + input.type = 'file'; + + input.onchange = (event) => { + // Getting the file reference + const file = (event.target as HTMLInputElement).files[0]; + this.handleFile({ file, stepper }); + }; + + input.click(); + } + + public updateSelection(activities: Activity[]) { + this.selectedActivities = activities.filter(({ error }) => { + return !error; + }); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } + + private async handleFile({ + file, + stepper + }: { + file: File; + stepper: MatStepper; + }): Promise { this.snackBar.open('⏳ ' + $localize`Validating data...`); // Setting up the reader @@ -186,12 +231,13 @@ export class ImportActivitiesDialog implements OnDestroy { const fileContent = readerEvent.target.result as string; try { - if (file.type === 'application/json' || file.name.endsWith('.json')) { + if (file.name.endsWith('.json')) { const content = JSON.parse(fileContent); + this.accounts = content.accounts; - if (!Array.isArray(content.activities)) { - if (Array.isArray(content.orders)) { + if (!isArray(content.activities)) { + if (isArray(content.orders)) { this.handleImportError({ activities: [], error: { @@ -206,65 +252,57 @@ export class ImportActivitiesDialog implements OnDestroy { } } - const { activities } = await this.importActivitiesService.importJson({ - accounts: content.accounts, - activities: content.activities, - isDryRun: true - }); - this.activities = activities; - } else if (file.type === 'text/csv' || file.name.endsWith('.csv')) { - const data = await this.importActivitiesService.importCsv({ - fileContent, - isDryRun: true, - userAccounts: this.data.user.accounts - }); - this.activities = data.activities; - } else { - throw new Error(); + try { + const { activities } = + await this.importActivitiesService.importJson({ + accounts: content.accounts, + activities: content.activities, + isDryRun: true + }); + this.activities = activities; + } catch (error) { + console.error(error); + this.handleImportError({ error, activities: content.activities }); + } + + return; + } else if (file.name.endsWith('.csv')) { + try { + const data = await this.importActivitiesService.importCsv({ + fileContent, + isDryRun: true, + userAccounts: this.data.user.accounts + }); + this.activities = data.activities; + } catch (error) { + console.error(error); + this.handleImportError({ + activities: error?.activities ?? [], + error: { + error: { message: error?.error?.message ?? [error?.message] } + } + }); + } + + return; } + + throw new Error(); } catch (error) { console.error(error); - this.handleImportError({ error, activities: [] }); + this.handleImportError({ + activities: [], + error: { error: { message: ['Unexpected format'] } } + }); } finally { this.importStep = ImportStep.SELECT_ACTIVITIES; this.snackBar.dismiss(); - this.changeDetectorRef.markForCheck(); - } - }; - } - public onFilesDropped(files: FileList): void { - if (files.length === 0) { - return; - } - - const droppedFile = files[0]; - this.handleFile(droppedFile); - } - - public onSelectFile(aStepper: MatStepper) { - const input = document.createElement('input'); - input.accept = 'application/JSON, .csv'; - input.type = 'file'; + stepper.next(); - input.onchange = (event) => { - // Getting the file reference - const file = (event.target as HTMLInputElement).files[0]; - this.handleFile(file); + this.changeDetectorRef.markForCheck(); + } }; - - input.click(); - } - - public updateSelection(activities: Activity[]) { - this.selectedActivities = activities.filter(({ error }) => { - return !error; - }); - } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); } private handleImportError({ diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html index 3a0194d16..06cadad8e 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -70,13 +70,13 @@
-

- The following file formats are supported: - CSV - or - JSON +

+ + The following file formats are supported: + CSV + or + JSON +

@@ -116,7 +118,7 @@ >
- +