Browse Source

Limit type filter in activities table component to used types

pull/7602/head
Thomas Kaul 3 weeks ago
parent
commit
65f750f794
  1. 19
      apps/api/src/app/user/user.service.ts
  2. 1
      apps/client/src/app/pages/portfolio/activities/activities-page.html
  3. 3
      libs/common/src/lib/interfaces/user.interface.ts
  4. 3
      libs/ui/src/lib/activities-table/activities-table.component.html
  5. 1
      libs/ui/src/lib/activities-table/activities-table.component.stories.ts
  6. 19
      libs/ui/src/lib/activities-table/activities-table.component.ts
  7. 11
      prisma/migrations/20260820000000_updated_indexes_of_order/migration.sql
  8. 3
      prisma/schema.prisma

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

@ -129,7 +129,7 @@ export class UserService {
const [ const [
access, access,
accounts, accounts,
activitiesCount, activitiesGroupedByType,
firstActivity, firstActivity,
impersonationUser, impersonationUser,
tagsForUser tagsForUser
@ -150,7 +150,10 @@ export class UserService {
userId: impersonationUserId || user.id userId: impersonationUserId || user.id
} }
}), }),
this.prismaService.order.count({ this.prismaService.order.groupBy({
_count: { _all: true },
by: ['type'],
orderBy: { type: 'asc' },
where: { userId: impersonationUserId || user.id } where: { userId: impersonationUserId || user.id }
}), }),
this.prismaService.order.findFirst({ this.prismaService.order.findFirst({
@ -165,6 +168,17 @@ export class UserService {
this.tagService.getTagsForUser(impersonationUserId || user.id) this.tagService.getTagsForUser(impersonationUserId || user.id)
]); ]);
const activitiesCount = activitiesGroupedByType.reduce(
(count, { _count }) => {
return count + _count._all;
},
0
);
const activityTypes = activitiesGroupedByType.map(({ type }) => {
return type;
});
const resolvedUserSettings = resolveUserSettings({ const resolvedUserSettings = resolveUserSettings({
impersonationUserSettings: impersonationUser?.settings impersonationUserSettings: impersonationUser?.settings
?.settings as UserSettings, ?.settings as UserSettings,
@ -209,6 +223,7 @@ export class UserService {
return { return {
activitiesCount, activitiesCount,
activityTypes,
id, id,
permissions, permissions,
referralPartners, referralPartners,

1
apps/client/src/app/pages/portfolio/activities/activities-page.html

@ -3,6 +3,7 @@
<div class="col"> <div class="col">
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Activities</h1> <h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Activities</h1>
<gf-activities-table <gf-activities-table
[activityTypes]="user?.activityTypes"
[baseCurrency]="user?.settings?.baseCurrency" [baseCurrency]="user?.settings?.baseCurrency"
[dataSource]="dataSource" [dataSource]="dataSource"
[deviceType]="deviceType" [deviceType]="deviceType"

3
libs/common/src/lib/interfaces/user.interface.ts

@ -1,7 +1,7 @@
import { SubscriptionType } from '@ghostfolio/common/enums'; import { SubscriptionType } from '@ghostfolio/common/enums';
import { AccountWithPlatform } from '@ghostfolio/common/types'; import { AccountWithPlatform } from '@ghostfolio/common/types';
import { Access, Tag } from '@prisma/client'; import { Access, Tag, Type as ActivityType } from '@prisma/client';
import { ReferralPartner } from './referral-partner.interface'; import { ReferralPartner } from './referral-partner.interface';
import { SubscriptionOffer } from './subscription-offer.interface'; import { SubscriptionOffer } from './subscription-offer.interface';
@ -13,6 +13,7 @@ export interface User {
access: Pick<Access, 'alias' | 'id' | 'permissions' | 'scopes'>[]; access: Pick<Access, 'alias' | 'id' | 'permissions' | 'scopes'>[];
accounts: AccountWithPlatform[]; accounts: AccountWithPlatform[];
activitiesCount: number; activitiesCount: number;
activityTypes: ActivityType[];
dateOfFirstActivity: Date; dateOfFirstActivity: Date;
id: string; id: string;
permissions: string[]; permissions: string[];

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

@ -7,7 +7,8 @@
<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 activityTypesTranslationMap | keyvalue: sortByValue; activityType of activityTypesTranslationMap()
| keyvalue: sortByValue;
track activityType.key track activityType.key
) { ) {
<mat-option [value]="activityType.key"> <mat-option [value]="activityType.key">

1
libs/ui/src/lib/activities-table/activities-table.component.stories.ts

@ -483,6 +483,7 @@ export const Actions: Story = {
export const Toolbar: Story = { export const Toolbar: Story = {
args: { args: {
dataSource, dataSource,
activityTypes: ['BUY', 'DIVIDEND', 'SELL'],
baseCurrency: 'USD', baseCurrency: 'USD',
deviceType: 'desktop', deviceType: 'desktop',
hasActivities: true, hasActivities: true,

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

@ -139,7 +139,6 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
@ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort; @ViewChild(MatSort) sort: MatSort;
public activityTypesTranslationMap = new Map<ActivityType, string>();
public hasDrafts = false; public hasDrafts = false;
public hasErrors = false; public hasErrors = false;
public isDraftActivity = isDraftActivity; public isDraftActivity = isDraftActivity;
@ -147,6 +146,7 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
public selectedRows = new SelectionModel<Activity>(true, []); public selectedRows = new SelectionModel<Activity>(true, []);
public typesFilter = new FormControl<string[]>([]); public typesFilter = new FormControl<string[]>([]);
public readonly activityTypes = input<ActivityType[]>([]);
public readonly dataSource = input.required< public readonly dataSource = input.required<
MatTableDataSource<Activity> | undefined MatTableDataSource<Activity> | undefined
>(); >();
@ -173,6 +173,16 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
return routerLinks; return routerLinks;
}); });
protected readonly activityTypesTranslationMap = computed(() => {
const translationMap = new Map<ActivityType, string>();
for (const activityType of this.activityTypes()) {
translationMap.set(activityType, translate(activityType));
}
return translationMap;
});
protected readonly displayedColumns = computed(() => { protected readonly displayedColumns = computed(() => {
let columns = [ let columns = [
'select', 'select',
@ -220,13 +230,6 @@ export class GfActivitiesTableComponent implements AfterViewInit, OnInit {
private readonly notificationService = inject(NotificationService); private readonly notificationService = inject(NotificationService);
public constructor(private destroyRef: DestroyRef) { public constructor(private destroyRef: DestroyRef) {
for (const type of Object.keys(ActivityType) as ActivityType[]) {
this.activityTypesTranslationMap.set(
ActivityType[type],
translate(ActivityType[type])
);
}
addIcons({ addIcons({
alertCircleOutline, alertCircleOutline,
calendarClearOutline, calendarClearOutline,

11
prisma/migrations/20260820000000_updated_indexes_of_order/migration.sql

@ -0,0 +1,11 @@
-- DropIndex
DROP INDEX "Order_symbolProfileId_idx";
-- DropIndex
DROP INDEX "Order_type_idx";
-- DropIndex
DROP INDEX "Order_userId_idx";
-- CreateIndex
CREATE INDEX "Order_userId_type_idx" ON "Order"("userId", "type");

3
prisma/schema.prisma

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

Loading…
Cancel
Save