Feature/improve activities import by preview step (#1540)
* Improve activities import * Update changelog
This commit is contained in:
parent
1918dee9c5
commit
d545e4877c
@ -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…
x
Reference in New Issue
Block a user