Feature/improve activities import by preview step (#1540)

* Improve activities import

* Update changelog
pull/1541/head
Thomas Kaul 2 years ago committed by GitHub
parent 1918dee9c5
commit d545e4877c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Improved the activities import by a preview step
- Improved the labels based on the type in the create or edit activity dialog - Improved the labels based on the type in the create or edit activity dialog
- Refreshed the cryptocurrencies list - Refreshed the cryptocurrencies list
- Removed the data source type `RAKUTEN` - Removed the data source type `RAKUTEN`

@ -120,7 +120,7 @@ export class ImportActivitiesDialog implements OnDestroy {
try { try {
this.activities = await this.importActivitiesService.importJson({ this.activities = await this.importActivitiesService.importJson({
content: content.activities, content: content.activities,
dryRun: true isDryRun: true
}); });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -131,8 +131,8 @@ export class ImportActivitiesDialog implements OnDestroy {
} else if (file.name.endsWith('.csv')) { } else if (file.name.endsWith('.csv')) {
try { try {
this.activities = await this.importActivitiesService.importCsv({ this.activities = await this.importActivitiesService.importCsv({
dryRun: true,
fileContent, fileContent,
isDryRun: true,
userAccounts: this.data.user.accounts userAccounts: this.data.user.accounts
}); });
} catch (error) { } catch (error) {

@ -3,9 +3,9 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
import { MatExpansionModule } from '@angular/material/expansion'; import { MatExpansionModule } from '@angular/material/expansion';
import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module';
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module';
import { ImportActivitiesDialog } from './import-activities-dialog.component'; import { ImportActivitiesDialog } from './import-activities-dialog.component';

@ -1,8 +1,8 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module'; import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { HoldingsPageRoutingModule } from './holdings-page-routing.module'; import { HoldingsPageRoutingModule } from './holdings-page-routing.module';
import { HoldingsPageComponent } from './holdings-page.component'; import { HoldingsPageComponent } from './holdings-page.component';

@ -2,8 +2,8 @@ import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module';
import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module';
import { GfValueModule } from '@ghostfolio/ui/value'; import { GfValueModule } from '@ghostfolio/ui/value';

@ -26,12 +26,12 @@ export class ImportActivitiesService {
public constructor(private http: HttpClient) {} public constructor(private http: HttpClient) {}
public async importCsv({ public async importCsv({
dryRun = false,
fileContent, fileContent,
isDryRun = false,
userAccounts userAccounts
}: { }: {
dryRun?: boolean;
fileContent: string; fileContent: string;
isDryRun?: boolean;
userAccounts: Account[]; userAccounts: Account[];
}): Promise<Activity[]> { }): Promise<Activity[]> {
const content = csvToJson(fileContent, { const content = csvToJson(fileContent, {
@ -55,22 +55,22 @@ export class ImportActivitiesService {
}); });
} }
return await this.importJson({ content: activities, dryRun }); return await this.importJson({ isDryRun, content: activities });
} }
public importJson({ public importJson({
content, content,
dryRun = false isDryRun = false
}: { }: {
content: CreateOrderDto[]; content: CreateOrderDto[];
dryRun?: boolean; isDryRun?: boolean;
}): Promise<Activity[]> { }): Promise<Activity[]> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.postImport( this.postImport(
{ {
activities: content activities: content
}, },
dryRun isDryRun
) )
.pipe( .pipe(
catchError((error) => { catchError((error) => {
@ -96,15 +96,22 @@ export class ImportActivitiesService {
return this.importJson({ content: importData }); return this.importJson({ content: importData });
} }
private convertToCreateOrderDto(aActivity: Activity): CreateOrderDto { private convertToCreateOrderDto({
date,
fee,
quantity,
SymbolProfile,
type,
unitPrice
}: Activity): CreateOrderDto {
return { return {
currency: aActivity.SymbolProfile.currency, fee,
date: aActivity.date.toString(), quantity,
fee: aActivity.fee, type,
quantity: aActivity.quantity, unitPrice,
symbol: aActivity.SymbolProfile.symbol, currency: SymbolProfile.currency,
type: aActivity.type, date: date.toString(),
unitPrice: aActivity.unitPrice symbol: SymbolProfile.symbol
}; };
} }
@ -337,10 +344,10 @@ export class ImportActivitiesService {
private postImport( private postImport(
aImportData: { activities: CreateOrderDto[] }, aImportData: { activities: CreateOrderDto[] },
dryRun = false aIsDryRun = false
) { ) {
return this.http.post<{ activities: Activity[] }>( return this.http.post<{ activities: Activity[] }>(
`/api/v1/import?dryRun=${dryRun}`, `/api/v1/import?dryRun=${aIsDryRun}`,
aImportData aImportData
); );
} }

@ -19,6 +19,7 @@
<th *matHeaderCellDef class="px-1" mat-header-cell> <th *matHeaderCellDef class="px-1" mat-header-cell>
<mat-checkbox <mat-checkbox
class="mt-2" class="mt-2"
color="primary"
[checked]="selectedRows.hasValue() && areAllRowsSelected()" [checked]="selectedRows.hasValue() && areAllRowsSelected()"
[indeterminate]="selectedRows.hasValue() && !areAllRowsSelected()" [indeterminate]="selectedRows.hasValue() && !areAllRowsSelected()"
(change)="$event ? toggleAllRows() : null" (change)="$event ? toggleAllRows() : null"
@ -27,6 +28,7 @@
<td *matCellDef="let element" class="px-1" mat-cell> <td *matCellDef="let element" class="px-1" mat-cell>
<mat-checkbox <mat-checkbox
class="mt-2" class="mt-2"
color="primary"
[checked]="selectedRows.isSelected(element)" [checked]="selectedRows.isSelected(element)"
(change)="$event ? selectedRows.toggle(element) : null" (change)="$event ? selectedRows.toggle(element) : null"
(click)="$event.stopPropagation()" (click)="$event.stopPropagation()"
@ -65,7 +67,7 @@
</th> </th>
<td *matCellDef="let element" class="px-1" mat-cell> <td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex"> <div class="d-flex">
{{ element.date | date: defaultDateFormat }} {{ element.date | date : defaultDateFormat }}
</div> </div>
</td> </td>
<td *matFooterCellDef class="px-1" i18n mat-footer-cell>Total</td> <td *matFooterCellDef class="px-1" i18n mat-footer-cell>Total</td>

@ -1,3 +1,4 @@
import { SelectionModel } from '@angular/cdk/collections';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
@ -8,7 +9,6 @@ import {
Output, Output,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import { SelectionModel } from '@angular/cdk/collections';
import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';

Loading…
Cancel
Save