diff --git a/CHANGELOG.md b/CHANGELOG.md index 863df020b..d0b160b19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added a stepper to the activities import dialog - Added a link to manage the benchmarks to the benchmark comparator - Added support for localized routes diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/enums/import-step.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/enums/import-step.ts new file mode 100644 index 000000000..35f2276c8 --- /dev/null +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/enums/import-step.ts @@ -0,0 +1,4 @@ +export enum ImportStep { + UPLOAD_FILE = 0, + SELECT_ACTIVITIES = 1 +} 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 afdf11a9a..4bd636b0d 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 @@ -1,3 +1,7 @@ +import { + StepperOrientation, + StepperSelectionEvent +} from '@angular/cdk/stepper'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -8,6 +12,7 @@ import { import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { MatStepper } from '@angular/material/stepper'; import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { DataService } from '@ghostfolio/client/services/data.service'; @@ -15,8 +20,10 @@ import { ImportActivitiesService } from '@ghostfolio/client/services/import-acti import { Position } from '@ghostfolio/common/interfaces'; import { AssetClass } from '@prisma/client'; import { isArray, sortBy } from 'lodash'; +import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; +import { ImportStep } from './enums/import-step'; import { ImportActivitiesDialogParams } from './interfaces/interfaces'; @Component({ @@ -29,12 +36,14 @@ export class ImportActivitiesDialog implements OnDestroy { public accounts: CreateAccountDto[] = []; public activities: Activity[] = []; public details: any[] = []; + public deviceType: string; public errorMessages: string[] = []; public holdings: Position[] = []; - public isFileSelected = false; + public importStep: ImportStep = ImportStep.UPLOAD_FILE; public maxSafeInteger = Number.MAX_SAFE_INTEGER; public mode: 'DIVIDEND'; public selectedActivities: Activity[] = []; + public stepperOrientation: StepperOrientation; public uniqueAssetForm: FormGroup; private unsubscribeSubject = new Subject(); @@ -43,6 +52,7 @@ export class ImportActivitiesDialog implements OnDestroy { private changeDetectorRef: ChangeDetectorRef, @Inject(MAT_DIALOG_DATA) public data: ImportActivitiesDialogParams, private dataService: DataService, + private deviceService: DeviceDetectorService, private formBuilder: FormBuilder, public dialogRef: MatDialogRef, private importActivitiesService: ImportActivitiesService, @@ -50,6 +60,10 @@ export class ImportActivitiesDialog implements OnDestroy { ) {} public ngOnInit() { + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + this.stepperOrientation = + this.deviceType === 'mobile' ? 'vertical' : 'horizontal'; + this.uniqueAssetForm = this.formBuilder.group({ uniqueAsset: [undefined, Validators.required] }); @@ -116,7 +130,15 @@ export class ImportActivitiesDialog implements OnDestroy { } } - public onLoadDividends() { + public onImportStepChange(event: StepperSelectionEvent) { + if (event.selectedIndex === ImportStep.UPLOAD_FILE) { + this.importStep = ImportStep.UPLOAD_FILE; + } else if (event.selectedIndex === ImportStep.SELECT_ACTIVITIES) { + this.importStep = ImportStep.SELECT_ACTIVITIES; + } + } + + public onLoadDividends(aStepper: MatStepper) { this.uniqueAssetForm.controls['uniqueAsset'].disable(); const { dataSource, symbol } = @@ -130,19 +152,23 @@ export class ImportActivitiesDialog implements OnDestroy { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(({ activities }) => { this.activities = activities; - this.isFileSelected = true; + + aStepper.next(); this.changeDetectorRef.markForCheck(); }); } - public onReset() { + public onReset(aStepper: MatStepper) { this.details = []; this.errorMessages = []; - this.isFileSelected = false; + this.importStep = ImportStep.SELECT_ACTIVITIES; + this.uniqueAssetForm.controls['uniqueAsset'].enable(); + + aStepper.reset(); } - public onSelectFile() { + public onSelectFile(aStepper: MatStepper) { const input = document.createElement('input'); input.accept = 'application/JSON, .csv'; input.type = 'file'; @@ -225,8 +251,11 @@ export class ImportActivitiesDialog implements OnDestroy { error: { error: { message: ['Unexpected format'] } } }); } finally { - this.isFileSelected = true; + this.importStep = ImportStep.SELECT_ACTIVITIES; this.snackBar.dismiss(); + + aStepper.next(); + this.changeDetectorRef.markForCheck(); } }; 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 3e47b966f..179003e23 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 @@ -5,123 +5,152 @@ (closeButtonClicked)="onCancel()" > -
- - -
- - Holding - - {{ holding.name }} - - -
- -
-
-
- -
- -

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

+ +
-

-
- - - - - - - - - - - -
-
- -
-
{{ message }}
-
-
-
-
{{ details[i] | json }}
-
-
-
- + + Holding + + {{ holding.name }} + + +
+ +
+ + + +
+ +

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

+
+
-
-
-
+ -
- - + + Select Activities +
+ + +
+ + +
+
+ + + + + +
+
+ +
+
{{ message }}
+
+
+
+
{{ details[i] | json }}
+
+
+
+ + +
+
+
+
+