diff --git a/CHANGELOG.md b/CHANGELOG.md index ec4cc6769..eeba19537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Disabled the button to delete all activities on the portfolio activities page if there are active filters +- Improved the delete all activities functionality on the portfolio activities page to work with the filters of the assistant - Upgraded `Nx` from version `18.3.3` to `19.0.2` ### Fixed diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index bf4920463..e97fb1c11 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -11,7 +11,7 @@ import { DATA_GATHERING_QUEUE_PRIORITY_HIGH, HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; -import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { permissions } from '@ghostfolio/common/permissions'; import type { DateRange, RequestWithUser } from '@ghostfolio/common/types'; import { @@ -53,8 +53,20 @@ export class OrderController { @Delete() @HasPermission(permissions.deleteOrder) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async deleteOrders(): Promise { + public async deleteOrders( + @Query('accounts') filterByAccounts?: string, + @Query('assetClasses') filterByAssetClasses?: string, + @Query('tags') filterByTags?: string + ): Promise { + const filters = this.apiService.buildFiltersFromQueryParams({ + filterByAccounts, + filterByAssetClasses, + filterByTags + }); + return this.orderService.deleteOrders({ + filters, + userCurrency: this.request.user.Settings.settings.baseCurrency, userId: this.request.user.id }); } diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index e976fc80d..4174a9f8d 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -194,16 +194,36 @@ export class OrderService { return order; } - public async deleteOrders(where: Prisma.OrderWhereInput): Promise { + public async deleteOrders({ + filters, + userCurrency, + userId + }: { + filters?: Filter[]; + userCurrency: string; + userId: string; + }): Promise { + const { activities } = await this.getOrders({ + filters, + userId, + userCurrency, + includeDrafts: true, + withExcludedAccounts: true + }); + const { count } = await this.prismaService.order.deleteMany({ - where + where: { + id: { + in: activities.map(({ id }) => { + return id; + }) + } + } }); this.eventEmitter.emit( PortfolioChangedEvent.getName(), - new PortfolioChangedEvent({ - userId: where.userId - }) + new PortfolioChangedEvent({ userId }) ); return count; diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index b4a6aa6a0..c96921c30 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -142,32 +142,24 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { this.openCreateActivityDialog(aActivity); } - public onDeleteActivity(aId: string) { + public onDeleteActivities() { this.dataService - .deleteActivity(aId) + .deleteActivities({ + filters: this.userService.getFilters() + }) .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe({ - next: () => { - this.fetchActivities(); - } + .subscribe(() => { + this.fetchActivities(); }); } - public onDeleteAllActivities() { - const confirmation = confirm( - $localize`Do you really want to delete all your activities?` - ); - - if (confirmation) { - this.dataService - .deleteAllActivities() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe({ - next: () => { - this.fetchActivities(); - } - }); - } + public onDeleteActivity(aId: string) { + this.dataService + .deleteActivity(aId) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.fetchActivities(); + }); } public onExport(activityIds?: string[]) { @@ -348,7 +340,6 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { hasPermission(this.user.permissions, permissions.createOrder); this.hasPermissionToDeleteActivity = !this.hasImpersonationId && - hasPermission(this.user.permissions, permissions.deleteOrder) && - !this.userService.hasFilters(); + hasPermission(this.user.permissions, permissions.deleteOrder); } } diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.html b/apps/client/src/app/pages/portfolio/activities/activities-page.html index c16d8a689..9edb400ab 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.html +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -20,10 +20,10 @@ [sortColumn]="sortColumn" [sortDirection]="sortDirection" [totalItems]="totalItems" + (activitiesDeleted)="onDeleteActivities()" (activityDeleted)="onDeleteActivity($event)" (activityToClone)="onCloneActivity($event)" (activityToUpdate)="onUpdateActivity($event)" - (deleteAllActivities)="onDeleteAllActivities()" (export)="onExport()" (exportDrafts)="onExportDrafts($event)" (import)="onImport()" diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index bfa4cb71e..b6f438ad5 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -256,12 +256,14 @@ export class DataService { return this.http.delete(`/api/v1/account-balance/${aId}`); } - public deleteActivity(aId: string) { - return this.http.delete(`/api/v1/order/${aId}`); + public deleteActivities({ filters }) { + let params = this.buildFiltersAsQueryParams({ filters }); + + return this.http.delete(`/api/v1/order`, { params }); } - public deleteAllActivities() { - return this.http.delete(`/api/v1/order`); + public deleteActivity(aId: string) { + return this.http.delete(`/api/v1/order/${aId}`); } public deleteBenchmark({ dataSource, symbol }: UniqueAsset) { diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html index 7aa5d0ee1..68950a0c0 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -59,11 +59,11 @@ class="align-items-center d-flex" mat-menu-item [disabled]="!hasPermissionToDeleteActivity" - (click)="onDeleteAllActivities()" + (click)="onDeleteActivities()" > - Delete all Activities + Delete Activities diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts index f63cec111..204cba0c2 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -92,10 +92,10 @@ export class GfActivitiesTableComponent @Input() sortDisabled = false; @Input() totalItems = Number.MAX_SAFE_INTEGER; + @Output() activitiesDeleted = new EventEmitter(); @Output() activityDeleted = new EventEmitter(); @Output() activityToClone = new EventEmitter(); @Output() activityToUpdate = new EventEmitter(); - @Output() deleteAllActivities = new EventEmitter(); @Output() export = new EventEmitter(); @Output() exportDrafts = new EventEmitter(); @Output() import = new EventEmitter(); @@ -211,6 +211,16 @@ export class GfActivitiesTableComponent this.activityToClone.emit(aActivity); } + public onDeleteActivities() { + const confirmation = confirm( + $localize`Do you really want to delete these activities?` + ); + + if (confirmation) { + this.activitiesDeleted.emit(); + } + } + public onDeleteActivity(aId: string) { const confirmation = confirm( $localize`Do you really want to delete this activity?` @@ -241,10 +251,6 @@ export class GfActivitiesTableComponent ); } - public onDeleteAllActivities() { - this.deleteAllActivities.emit(); - } - public onImport() { this.import.emit(); }