diff --git a/apps/api/src/app/user/update-user-setting.dto.ts b/apps/api/src/app/user/update-user-setting.dto.ts index e510880ed..f618e42b1 100644 --- a/apps/api/src/app/user/update-user-setting.dto.ts +++ b/apps/api/src/app/user/update-user-setting.dto.ts @@ -4,6 +4,7 @@ import type { ViewMode } from '@ghostfolio/common/types'; import { + IsArray, IsBoolean, IsISO8601, IsIn, @@ -37,6 +38,10 @@ export class UpdateUserSettingDto { @IsOptional() emergencyFund?: number; + @IsArray() + @IsOptional() + 'filters.tags'?: string[]; + @IsBoolean() @IsOptional() isExperimentalFeatures?: boolean; diff --git a/apps/client/src/app/components/header/header.component.html b/apps/client/src/app/components/header/header.component.html index f454ab914..8d08533e4 100644 --- a/apps/client/src/app/components/header/header.component.html +++ b/apps/client/src/app/components/header/header.component.html @@ -141,6 +141,7 @@ [user]="user" (closed)="closeAssistant()" (dateRangeChanged)="onDateRangeChange($event)" + (selectedTagChanged)="onSelectedTagChanged($event)" /> diff --git a/apps/client/src/app/components/header/header.component.ts b/apps/client/src/app/components/header/header.component.ts index 5218e2870..19bd7e8fa 100644 --- a/apps/client/src/app/components/header/header.component.ts +++ b/apps/client/src/app/components/header/header.component.ts @@ -24,6 +24,7 @@ import { InfoItem, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { DateRange } from '@ghostfolio/common/types'; import { AssistantComponent } from '@ghostfolio/ui/assistant/assistant.component'; +import { Tag } from '@prisma/client'; import { EMPTY, Subject } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; @@ -173,6 +174,20 @@ export class HeaderComponent implements OnChanges { this.assistantElement.initialize(); } + public onSelectedTagChanged(tag: Tag) { + this.dataService + .putUserSetting({ 'filters.tags': tag ? [tag.id] : null }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.userService.remove(); + + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(); + }); + } + public onSignOut() { this.signOut.next(); } 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 5d3468319..4beb90df9 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 @@ -15,7 +15,7 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/imperso import { UserService } from '@ghostfolio/client/services/user/user.service'; import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config'; import { downloadAsFile } from '@ghostfolio/common/helper'; -import { User } from '@ghostfolio/common/interfaces'; +import { Filter, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { DataSource, Order as OrderModel } from '@prisma/client'; import { format, parseISO } from 'date-fns'; @@ -111,6 +111,8 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { if (state?.user) { this.updateUser(state.user); + this.fetchActivities(); + this.changeDetectorRef.markForCheck(); } }); @@ -120,8 +122,18 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { public fetchActivities() { if (this.user?.settings?.isExperimentalFeatures === true) { + const filters: Filter[] = []; + + if (this.user?.settings?.['filters.tags']) { + filters.push({ + id: this.user.settings['filters.tags'][0], + type: 'TAG' + }); + } + this.dataService .fetchActivities({ + filters, skip: this.pageIndex * this.pageSize, sortColumn: this.sortColumn, sortDirection: this.sortDirection, diff --git a/libs/common/src/lib/interfaces/user-settings.interface.ts b/libs/common/src/lib/interfaces/user-settings.interface.ts index d3864ab64..4ac7c4726 100644 --- a/libs/common/src/lib/interfaces/user-settings.interface.ts +++ b/libs/common/src/lib/interfaces/user-settings.interface.ts @@ -7,6 +7,7 @@ export interface UserSettings { colorScheme?: ColorScheme; dateRange?: DateRange; emergencyFund?: number; + 'filters.tags'?: string[]; isExperimentalFeatures?: boolean; isRestrictedView?: boolean; language?: string; diff --git a/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts b/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts index 950df149b..0ceb69bef 100644 --- a/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts +++ b/libs/ui/src/lib/activities-table-lazy/activities-table-lazy.component.ts @@ -75,7 +75,6 @@ export class ActivitiesTableLazyComponent public isLoading = true; public isUUID = isUUID; public routeQueryParams: Subscription; - public searchKeywords: string[] = []; public selectedRows = new SelectionModel(true, []); private unsubscribeSubject = new Subject(); @@ -182,15 +181,7 @@ export class ActivitiesTableLazyComponent } public onExport() { - if (this.searchKeywords.length > 0) { - this.export.emit( - this.dataSource.filteredData.map((activity) => { - return activity.id; - }) - ); - } else { - this.export.emit(); - } + this.export.emit(); } public onExportDraft(aActivityId: string) { diff --git a/libs/ui/src/lib/assistant/assistant.component.ts b/libs/ui/src/lib/assistant/assistant.component.ts index c9d39b5f0..46c892860 100644 --- a/libs/ui/src/lib/assistant/assistant.component.ts +++ b/libs/ui/src/lib/assistant/assistant.component.ts @@ -7,6 +7,7 @@ import { EventEmitter, HostListener, Input, + OnChanges, OnDestroy, OnInit, Output, @@ -42,7 +43,7 @@ import { ISearchResultItem, ISearchResults } from './interfaces/interfaces'; styleUrls: ['./assistant.scss'], templateUrl: './assistant.html' }) -export class AssistantComponent implements OnDestroy, OnInit { +export class AssistantComponent implements OnChanges, OnDestroy, OnInit { @HostListener('document:keydown', ['$event']) onKeydown( event: KeyboardEvent ) { @@ -81,6 +82,7 @@ export class AssistantComponent implements OnDestroy, OnInit { @Output() closed = new EventEmitter(); @Output() dateRangeChanged = new EventEmitter(); + @Output() selectedTagChanged = new EventEmitter(); @ViewChild('menuTrigger') menuTriggerElement: MatMenuTrigger; @ViewChild('search', { static: true }) searchElement: ElementRef; @@ -100,6 +102,7 @@ export class AssistantComponent implements OnDestroy, OnInit { holdings: [] }; public tags: Tag[] = []; + public tagsFormControl = new FormControl(undefined); private keyManager: FocusKeyManager; private unsubscribeSubject = new Subject(); @@ -159,6 +162,12 @@ export class AssistantComponent implements OnDestroy, OnInit { }); } + public ngOnChanges() { + this.tagsFormControl.setValue( + this.user?.settings?.['filters.tags']?.[0] ?? null + ); + } + public async initialize() { this.isLoading = true; this.keyManager = new FocusKeyManager(this.assistantListItems).withWrap(); @@ -192,8 +201,12 @@ export class AssistantComponent implements OnDestroy, OnInit { this.closed.emit(); } - public onSelectTag(tag: Tag) { - console.log(tag); + public onTagChange() { + const selectedTag = this.tags.find(({ id }) => { + return id === this.tagsFormControl.value; + }); + + this.selectedTagChanged.emit(selectedTag); this.onCloseAssistant(); } diff --git a/libs/ui/src/lib/assistant/assistant.html b/libs/ui/src/lib/assistant/assistant.html index d4ceb3465..6b58faea2 100644 --- a/libs/ui/src/lib/assistant/assistant.html +++ b/libs/ui/src/lib/assistant/assistant.html @@ -116,13 +116,17 @@ >Tags -
- +
+ + No tag @for (tag of tags; track tag.id) { - {{ tag.name }} }