Browse Source

Limit type filter in activities table component to used types

pull/7602/head
Thomas Kaul 2 weeks ago
parent
commit
a92b0b2f27
  1. 12
      apps/api/src/app/user/user.service.ts
  2. 7
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
  3. 10
      libs/ui/src/lib/activities-table/activities-table.component.html
  4. 23
      libs/ui/src/lib/activities-table/activities-table.component.ts
  5. 5
      prisma/migrations/20260820000000_updated_indexes_of_order/migration.sql
  6. 3
      prisma/schema.prisma

12
apps/api/src/app/user/user.service.ts

@ -61,7 +61,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter'; import { EventEmitter2 } from '@nestjs/event-emitter';
import { InjectThrottlerStorage, ThrottlerStorage } from '@nestjs/throttler'; import { InjectThrottlerStorage, ThrottlerStorage } from '@nestjs/throttler';
import { Prisma, Role, User } from '@prisma/client'; import { Prisma, Role, User } from '@prisma/client';
import { differenceInDays, subDays } from 'date-fns'; import { differenceInDays, min, subDays } from 'date-fns';
import { isNil, without } from 'lodash'; import { isNil, without } from 'lodash';
import { createHmac } from 'node:crypto'; import { createHmac } from 'node:crypto';
@ -171,8 +171,16 @@ export class UserService {
}) })
.sort(); .sort();
const datesOfFirstActivityByType = activitiesGroupedByType.map(
({ _min }) => {
return _min.date;
}
);
const dateOfFirstActivity = const dateOfFirstActivity =
activitiesGroupedByType[0]?._min.date ?? new Date(); datesOfFirstActivityByType.length > 0
? min(datesOfFirstActivityByType)
: new Date();
const resolvedUserSettings = resolveUserSettings({ const resolvedUserSettings = resolveUserSettings({
impersonationUserSettings: impersonationUser?.settings impersonationUserSettings: impersonationUser?.settings

7
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts

@ -647,7 +647,12 @@ export class GfHoldingDetailDialogComponent implements OnInit {
this.dataService this.dataService
.postActivity(activity) .postActivity(activity)
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(
switchMap(() => {
return this.userService.get(true);
}),
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => { .subscribe(() => {
this.router.navigate( this.router.navigate(
internalRoutes.portfolio.subRoutes.activities.routerLink internalRoutes.portfolio.subRoutes.activities.routerLink

10
libs/ui/src/lib/activities-table/activities-table.component.html

@ -2,17 +2,11 @@
class="align-items-center d-flex justify-content-end justify-content-lg-between" class="align-items-center d-flex justify-content-end justify-content-lg-between"
> >
<div class="d-none d-lg-flex"> <div class="d-none d-lg-flex">
@if ( @if (hasPermissionToFilterByType && activityTypeOptions().length > 0) {
hasPermissionToFilterByType && activityTypesTranslationMap().size > 0
) {
<mat-form-field appearance="outline" class="without-hint"> <mat-form-field appearance="outline" class="without-hint">
<mat-label i18n>Type</mat-label> <mat-label i18n>Type</mat-label>
<mat-select multiple [formControl]="typesFilter"> <mat-select multiple [formControl]="typesFilter">
@for ( @for (activityType of activityTypeOptions(); track activityType.key) {
activityType of activityTypesTranslationMap()
| keyvalue: sortByValue;
track activityType.key
) {
<mat-option [value]="activityType.key"> <mat-option [value]="activityType.key">
{{ activityType.value }} {{ activityType.value }}
</mat-option> </mat-option>

23
libs/ui/src/lib/activities-table/activities-table.component.ts

@ -173,14 +173,14 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
return routerLinks; return routerLinks;
}); });
protected readonly activityTypesTranslationMap = computed(() => { protected readonly activityTypeOptions = computed(() => {
const translationMap = new Map<ActivityType, string>(); return (this.activityTypes() ?? [])
.map((activityType) => {
for (const activityType of this.activityTypes() ?? []) { return { key: activityType, value: translate(activityType) };
translationMap.set(activityType, translate(activityType)); })
} .sort((a, b) => {
return a.value.localeCompare(b.value);
return translationMap; });
}); });
protected readonly displayedColumns = computed(() => { protected readonly displayedColumns = computed(() => {
@ -387,13 +387,6 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
}); });
} }
public sortByValue(
a: { key: ActivityType; value: string },
b: { key: ActivityType; value: string }
) {
return a.value.localeCompare(b.value);
}
public toggleAllRows() { public toggleAllRows() {
if (this.areAllRowsSelected()) { if (this.areAllRowsSelected()) {
this.selectedRows.clear(); this.selectedRows.clear();

5
prisma/migrations/20260820000000_updated_indexes_of_order/migration.sql

@ -8,7 +8,10 @@ DROP INDEX "Order_type_idx";
DROP INDEX "Order_userId_idx"; DROP INDEX "Order_userId_idx";
-- CreateIndex -- CreateIndex
CREATE INDEX "Order_symbolProfileId_idx" ON "Order"("symbolProfileId"); CREATE INDEX "Order_symbolProfileId_date_idx" ON "Order"("symbolProfileId", "date");
-- CreateIndex -- CreateIndex
CREATE INDEX "Order_userId_date_type_idx" ON "Order"("userId", "date", "type"); CREATE INDEX "Order_userId_date_type_idx" ON "Order"("userId", "date", "type");
-- CreateIndex
CREATE INDEX "Order_userId_type_idx" ON "Order"("userId", "type");

3
prisma/schema.prisma

@ -197,8 +197,9 @@ model Order {
@@index([accountId]) @@index([accountId])
@@index([date]) @@index([date])
@@index([symbolProfileId]) @@index([symbolProfileId, date])
@@index([userId, date, type]) @@index([userId, date, type])
@@index([userId, type])
} }
model Platform { model Platform {

Loading…
Cancel
Save