From 68c28b895892fcfd940a223e1714bfcc585a8cd7 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sun, 15 May 2022 11:58:48 +0200 Subject: [PATCH] Add groups to activities filter component --- apps/api/src/app/account/account.service.ts | 2 +- apps/api/src/app/order/order.service.ts | 2 +- .../src/app/portfolio/portfolio.controller.ts | 4 +- .../allocations/allocations-page.component.ts | 4 +- apps/client/src/app/services/data.service.ts | 2 +- .../lib/interfaces/filter-group.interface.ts | 6 ++ .../src/lib/interfaces/filter.interface.ts | 2 +- libs/common/src/lib/interfaces/index.ts | 2 + .../activities-filter.component.html | 14 ++- .../activities-filter.component.ts | 86 ++++++++++++------- .../activities-table.component.ts | 2 +- 11 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 libs/common/src/lib/interfaces/filter-group.interface.ts diff --git a/apps/api/src/app/account/account.service.ts b/apps/api/src/app/account/account.service.ts index 34c2f4a15..240045e8e 100644 --- a/apps/api/src/app/account/account.service.ts +++ b/apps/api/src/app/account/account.service.ts @@ -120,7 +120,7 @@ export class AccountService { where.id = { in: filters .filter(({ type }) => { - return type === 'account'; + return type === 'ACCOUNT'; }) .map(({ id }) => { return id; diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index aceb8de06..3e87c5f5e 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -188,7 +188,7 @@ export class OrderService { }): Promise { const where: Prisma.OrderWhereInput = { userId }; - const { account: filtersByAccount, tag: filtersByTag } = groupBy( + const { ACCOUNT: filtersByAccount, TAG: filtersByTag } = groupBy( filters, (filter) => { return filter.type; diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 68cd03c0a..5c648378d 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -119,13 +119,13 @@ export class PortfolioController { ...accountIds.map((accountId) => { return { id: accountId, - type: 'account' + type: 'ACCOUNT' }; }), ...tagIds.map((tagId) => { return { id: tagId, - type: 'tag' + type: 'TAG' }; }) ]; diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index 7b4f04e0a..a072319f0 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -165,7 +165,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { return { id, label: name, - type: 'account' + type: 'ACCOUNT' }; }); @@ -173,7 +173,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { return { id, label: name, - type: 'tag' + type: 'TAG' }; }); diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 7679c154f..3edde74e4 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -187,7 +187,7 @@ export class DataService { let params = new HttpParams(); if (filters?.length > 0) { - const { account: filtersByAccount, tag: filtersByTag } = groupBy( + const { ACCOUNT: filtersByAccount, TAG: filtersByTag } = groupBy( filters, (filter) => { return filter.type; diff --git a/libs/common/src/lib/interfaces/filter-group.interface.ts b/libs/common/src/lib/interfaces/filter-group.interface.ts new file mode 100644 index 000000000..7087b99fa --- /dev/null +++ b/libs/common/src/lib/interfaces/filter-group.interface.ts @@ -0,0 +1,6 @@ +import { Filter } from './filter.interface'; + +export interface FilterGroup { + filters: Filter[]; + name: Filter['type']; +} diff --git a/libs/common/src/lib/interfaces/filter.interface.ts b/libs/common/src/lib/interfaces/filter.interface.ts index e6d5bb108..7a7e79988 100644 --- a/libs/common/src/lib/interfaces/filter.interface.ts +++ b/libs/common/src/lib/interfaces/filter.interface.ts @@ -1,5 +1,5 @@ export interface Filter { id: string; label?: string; - type: 'account' | 'tag'; + type: 'ACCOUNT' | 'TAG'; } diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index 0f483c100..96275e4d3 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -8,6 +8,7 @@ import { } from './admin-market-data.interface'; import { Coupon } from './coupon.interface'; import { Export } from './export.interface'; +import { FilterGroup } from './filter-group.interface'; import { Filter } from './filter.interface'; import { HistoricalDataItem } from './historical-data-item.interface'; import { InfoItem } from './info-item.interface'; @@ -41,6 +42,7 @@ export { Coupon, Export, Filter, + FilterGroup, HistoricalDataItem, InfoItem, PortfolioChart, diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.html b/libs/ui/src/lib/activities-filter/activities-filter.component.html index e0eb5da87..1ade36db5 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.html +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.html @@ -26,9 +26,17 @@ #autocomplete="matAutocomplete" (optionSelected)="onSelectFilter($event)" > - - {{ filter.label | gfSymbol }} - + + + {{ filter.label | gfSymbol }} + + ; + public filterGroups$: Subject = new BehaviorSubject([]); public filters$: Subject = new BehaviorSubject([]); public filters: Observable = this.filters$.asObservable(); public searchControl = new FormControl(); @@ -50,40 +52,27 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((filterOrSearchTerm: Filter | string) => { if (filterOrSearchTerm) { - this.filters$.next( - this.allFilters - .filter((filter) => { - // Filter selected filters - return !this.selectedFilters.some((selectedFilter) => { - return selectedFilter.id === filter.id; - }); - }) - .filter((filter) => { - if (typeof filterOrSearchTerm === 'string') { - return filter.label - .toLowerCase() - .startsWith(filterOrSearchTerm.toLowerCase()); - } - - return filter.label - .toLowerCase() - .startsWith(filterOrSearchTerm?.label?.toLowerCase()); - }) - .sort((a, b) => a.label.localeCompare(b.label)) - ); + const searchTerm = + typeof filterOrSearchTerm === 'string' + ? filterOrSearchTerm + : filterOrSearchTerm?.label; + + this.filterGroups$.next(this.getGroupedFilters(searchTerm)); + } else { + this.filterGroups$.next(this.getGroupedFilters()); } }); } public ngOnChanges(changes: SimpleChanges) { if (changes.allFilters?.currentValue) { - this.updateFilter(); + this.updateFilters(); } } public onAddFilter({ input, value }: MatChipInputEvent): void { if (value?.trim()) { - this.updateFilter(); + this.updateFilters(); } // Reset the input value @@ -99,12 +88,16 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy { return filter.id !== aFilter.id; }); - this.updateFilter(); + this.updateFilters(); } public onSelectFilter(event: MatAutocompleteSelectedEvent): void { - this.selectedFilters.push(event.option.value); - this.updateFilter(); + this.selectedFilters.push( + this.allFilters.find((filter) => { + return filter.id === event.option.value; + }) + ); + this.updateFilters(); this.searchInput.nativeElement.value = ''; this.searchControl.setValue(null); } @@ -114,8 +107,8 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy { this.unsubscribeSubject.complete(); } - private updateFilter() { - this.filters$.next( + private getGroupedFilters(searchTerm?: string) { + const filterGroupsMap = groupBy( this.allFilters .filter((filter) => { // Filter selected filters @@ -123,9 +116,42 @@ export class ActivitiesFilterComponent implements OnChanges, OnDestroy { return selectedFilter.id === filter.id; }); }) - .sort((a, b) => a.label.localeCompare(b.label)) + .filter((filter) => { + if (searchTerm) { + // Filter by search term + return filter.label + .toLowerCase() + .includes(searchTerm.toLowerCase()); + } + + return filter; + }) + .sort((a, b) => a.label.localeCompare(b.label)), + (filter) => { + return filter.type; + } ); + const filterGroups: FilterGroup[] = []; + + for (const type of Object.keys(filterGroupsMap)) { + filterGroups.push({ + name: type, + filters: filterGroupsMap[type] + }); + } + + return filterGroups.map((filterGroup) => { + return { + ...filterGroup, + filters: filterGroup.filters + }; + }); + } + + private updateFilters() { + this.filterGroups$.next(this.getGroupedFilters()); + // Emit an array with a new reference this.valueChanged.emit([...this.selectedFilters]); } 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 959a4e867..724537c4f 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -107,7 +107,7 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy { if (this.activities) { this.allFilters = this.getSearchableFieldValues(this.activities).map( (label) => { - return { label, id: label, type: 'tag' }; + return { label, id: label, type: 'TAG' }; } );