Feature/support delete activities with filtering (#3394)
* Support delete activities with filtering * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
This commit is contained in:
parent
782d131b0d
commit
8319b216bb
@ -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
|
||||
|
@ -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<number> {
|
||||
public async deleteOrders(
|
||||
@Query('accounts') filterByAccounts?: string,
|
||||
@Query('assetClasses') filterByAssetClasses?: string,
|
||||
@Query('tags') filterByTags?: string
|
||||
): Promise<number> {
|
||||
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
|
||||
});
|
||||
}
|
||||
|
@ -194,16 +194,36 @@ export class OrderService {
|
||||
return order;
|
||||
}
|
||||
|
||||
public async deleteOrders(where: Prisma.OrderWhereInput): Promise<number> {
|
||||
public async deleteOrders({
|
||||
filters,
|
||||
userCurrency,
|
||||
userId
|
||||
}: {
|
||||
filters?: Filter[];
|
||||
userCurrency: string;
|
||||
userId: string;
|
||||
}): Promise<number> {
|
||||
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: <string>where.userId
|
||||
})
|
||||
new PortfolioChangedEvent({ userId })
|
||||
);
|
||||
|
||||
return count;
|
||||
|
@ -142,34 +142,26 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
|
||||
this.openCreateActivityDialog(aActivity);
|
||||
}
|
||||
|
||||
public onDeleteActivities() {
|
||||
this.dataService
|
||||
.deleteActivities({
|
||||
filters: this.userService.getFilters()
|
||||
})
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(() => {
|
||||
this.fetchActivities();
|
||||
});
|
||||
}
|
||||
|
||||
public onDeleteActivity(aId: string) {
|
||||
this.dataService
|
||||
.deleteActivity(aId)
|
||||
.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 onExport(activityIds?: string[]) {
|
||||
let fetchExportParams: any = { activityIds };
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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()"
|
||||
|
@ -256,12 +256,14 @@ export class DataService {
|
||||
return this.http.delete<any>(`/api/v1/account-balance/${aId}`);
|
||||
}
|
||||
|
||||
public deleteActivity(aId: string) {
|
||||
return this.http.delete<any>(`/api/v1/order/${aId}`);
|
||||
public deleteActivities({ filters }) {
|
||||
let params = this.buildFiltersAsQueryParams({ filters });
|
||||
|
||||
return this.http.delete<any>(`/api/v1/order`, { params });
|
||||
}
|
||||
|
||||
public deleteAllActivities() {
|
||||
return this.http.delete<any>(`/api/v1/order`);
|
||||
public deleteActivity(aId: string) {
|
||||
return this.http.delete<any>(`/api/v1/order/${aId}`);
|
||||
}
|
||||
|
||||
public deleteBenchmark({ dataSource, symbol }: UniqueAsset) {
|
||||
|
@ -59,11 +59,11 @@
|
||||
class="align-items-center d-flex"
|
||||
mat-menu-item
|
||||
[disabled]="!hasPermissionToDeleteActivity"
|
||||
(click)="onDeleteAllActivities()"
|
||||
(click)="onDeleteActivities()"
|
||||
>
|
||||
<span class="align-items-center d-flex">
|
||||
<ion-icon class="mr-2" name="trash-outline" />
|
||||
<span i18n>Delete all Activities</span>
|
||||
<span i18n>Delete Activities</span>
|
||||
</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
@ -92,10 +92,10 @@ export class GfActivitiesTableComponent
|
||||
@Input() sortDisabled = false;
|
||||
@Input() totalItems = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
@Output() activitiesDeleted = new EventEmitter<void>();
|
||||
@Output() activityDeleted = new EventEmitter<string>();
|
||||
@Output() activityToClone = new EventEmitter<OrderWithAccount>();
|
||||
@Output() activityToUpdate = new EventEmitter<OrderWithAccount>();
|
||||
@Output() deleteAllActivities = new EventEmitter<void>();
|
||||
@Output() export = new EventEmitter<void>();
|
||||
@Output() exportDrafts = new EventEmitter<string[]>();
|
||||
@Output() import = new EventEmitter<void>();
|
||||
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user