Browse Source

Feature/assistant accounts Feature/extend search in assistant by accounts

pull/5356/head
David Requeno 1 week ago
committed by Thomas Kaul
parent
commit
e928141663
  1. 16
      libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts
  2. 120
      libs/ui/src/lib/assistant/assistant.component.ts
  3. 4
      libs/ui/src/lib/assistant/assistant.html
  4. 15
      libs/ui/src/lib/assistant/interfaces/interfaces.ts

16
libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts

@ -50,7 +50,14 @@ export class GfAssistantListItemComponent
public constructor(private changeDetectorRef: ChangeDetectorRef) {}
public ngOnChanges() {
if (this.item?.mode === SearchMode.ASSET_PROFILE) {
if (this.item?.mode === SearchMode.ACCOUNT) {
this.queryParams = {
accountDetailDialog: true,
accountId: this.item.id
};
this.routerLink = internalRoutes.accounts.routerLink;
} else if (this.item?.mode === SearchMode.ASSET_PROFILE) {
this.queryParams = {
assetProfileDialog: true,
dataSource: this.item?.dataSource,
@ -67,13 +74,6 @@ export class GfAssistantListItemComponent
};
this.routerLink = [];
} else if (this.item?.mode === SearchMode.ACCOUNT) {
this.queryParams = {
accountDetailDialog: true,
accountId: (this.item as any).id
};
this.routerLink = internalRoutes.accounts.routerLink;
} else if (this.item?.mode === SearchMode.QUICK_LINK) {
this.queryParams = {};
this.routerLink = this.item.routerLink;

120
libs/ui/src/lib/assistant/assistant.component.ts

@ -153,8 +153,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
});
public holdings: PortfolioPosition[] = [];
public isLoading = {
assetProfiles: false,
accounts: false,
assetProfiles: false,
holdings: false,
quickLinks: false
};
@ -162,8 +162,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
public placeholder = $localize`Find account, holding or page...`;
public searchFormControl = new FormControl('');
public searchResults: ISearchResults = {
assetProfiles: [],
accounts: [],
assetProfiles: [],
holdings: [],
quickLinks: []
};
@ -201,14 +201,14 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
.pipe(
map((searchTerm) => {
this.isLoading = {
assetProfiles: true,
accounts: true,
assetProfiles: true,
holdings: true,
quickLinks: true
};
this.searchResults = {
assetProfiles: [],
accounts: [],
assetProfiles: [],
holdings: [],
quickLinks: []
};
@ -221,8 +221,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
distinctUntilChanged(),
switchMap((searchTerm) => {
const results = {
assetProfiles: [],
accounts: [],
assetProfiles: [],
holdings: [],
quickLinks: []
} as ISearchResults;
@ -231,8 +231,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
return of(results).pipe(
tap(() => {
this.isLoading = {
assetProfiles: false,
accounts: false,
assetProfiles: false,
holdings: false,
quickLinks: false
};
@ -240,6 +240,25 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
);
}
// Accounts
const accounts$: Observable<Partial<ISearchResults>> =
this.searchAccounts(searchTerm).pipe(
map((accounts) => ({
accounts: accounts.slice(
0,
GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT
)
})),
catchError((error) => {
console.error('Error fetching accounts for assistant:', error);
return of({ accounts: [] as ISearchResultItem[] });
}),
tap(() => {
this.isLoading.accounts = false;
this.changeDetectorRef.markForCheck();
})
);
// Asset profiles
const assetProfiles$: Observable<Partial<ISearchResults>> = this
.hasPermissionToAccessAdminControl
@ -269,25 +288,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
})
);
// Accounts
const accounts$: Observable<Partial<ISearchResults>> =
this.searchAccounts(searchTerm).pipe(
map((accounts) => ({
accounts: accounts.slice(
0,
GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT
)
})),
catchError((error) => {
console.error('Error fetching accounts for assistant:', error);
return of({ accounts: [] as ISearchResultItem[] });
}),
tap(() => {
this.isLoading.accounts = false;
this.changeDetectorRef.markForCheck();
})
);
// Holdings
const holdings$: Observable<Partial<ISearchResults>> =
this.searchHoldings(searchTerm).pipe(
@ -324,15 +324,15 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
);
// Merge all results
return merge(quickLinks$, assetProfiles$, accounts$, holdings$).pipe(
return merge(accounts$, assetProfiles$, holdings$, quickLinks$).pipe(
scan(
(acc: ISearchResults, curr: Partial<ISearchResults>) => ({
...acc,
...curr
}),
{
assetProfiles: [],
accounts: [],
assetProfiles: [],
holdings: [],
quickLinks: []
} as ISearchResults
@ -349,8 +349,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
error: (error) => {
console.error('Assistant search stream error:', error);
this.searchResults = {
assetProfiles: [],
accounts: [],
assetProfiles: [],
holdings: [],
quickLinks: []
};
@ -358,8 +358,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
},
complete: () => {
this.isLoading = {
assetProfiles: false,
accounts: false,
assetProfiles: false,
holdings: false,
quickLinks: false
};
@ -479,15 +479,15 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
public initialize() {
this.isLoading = {
assetProfiles: true,
accounts: true,
assetProfiles: true,
holdings: true,
quickLinks: true
};
this.keyManager = new FocusKeyManager(this.assistantListItems).withWrap();
this.searchResults = {
assetProfiles: [],
accounts: [],
assetProfiles: [],
holdings: [],
quickLinks: []
};
@ -502,8 +502,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
});
this.isLoading = {
assetProfiles: false,
accounts: false,
assetProfiles: false,
holdings: false,
quickLinks: false
};
@ -595,6 +595,34 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
});
}
private searchAccounts(aSearchTerm: string): Observable<ISearchResultItem[]> {
return this.dataService
.fetchAccounts({
filters: [
{
id: aSearchTerm,
type: 'SEARCH_QUERY'
}
]
})
.pipe(
catchError(() => {
return EMPTY;
}),
map(({ accounts }) => {
return accounts.map(({ id, name }) => {
return {
id,
name,
routerLink: internalRoutes.accounts.routerLink,
mode: SearchMode.ACCOUNT as const
};
});
}),
takeUntil(this.unsubscribeSubject)
);
}
private searchAssetProfiles(
aSearchTerm: string
): Observable<ISearchResultItem[]> {
@ -662,34 +690,6 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit {
);
}
private searchAccounts(aSearchTerm: string): Observable<ISearchResultItem[]> {
return this.dataService
.fetchAccounts({
filters: [
{
id: aSearchTerm,
type: 'SEARCH_QUERY'
}
]
})
.pipe(
catchError(() => {
return EMPTY;
}),
map(({ accounts }) => {
return accounts.map(({ id, name, platform }) => {
return {
id,
name,
platform,
mode: SearchMode.ACCOUNT as const
};
});
}),
takeUntil(this.unsubscribeSubject)
);
}
private searchQuickLinks(aSearchTerm: string): ISearchResultItem[] {
const searchTerm = aSearchTerm.toLowerCase();

4
libs/ui/src/lib/assistant/assistant.html

@ -39,12 +39,12 @@
@if (searchFormControl.value) {
<div class="overflow-auto py-2 result-container">
@if (
!isLoading.assetProfiles &&
!isLoading.accounts &&
!isLoading.assetProfiles &&
!isLoading.holdings &&
!isLoading.quickLinks &&
searchResults.assetProfiles?.length === 0 &&
searchResults.accounts?.length === 0 &&
searchResults.assetProfiles?.length === 0 &&
searchResults.holdings?.length === 0 &&
searchResults.quickLinks?.length === 0
) {

15
libs/ui/src/lib/assistant/interfaces/interfaces.ts

@ -3,6 +3,12 @@ import { AccountWithValue, DateRange } from '@ghostfolio/common/types';
import { SearchMode } from '../enums/search-mode';
export interface IAccountSearchResultItem
extends Pick<AccountWithValue, 'id' | 'name'> {
mode: SearchMode.ACCOUNT;
routerLink: string[];
}
export interface IAssetSearchResultItem extends AssetProfileIdentifier {
assetSubClassString: string;
currency: string;
@ -21,19 +27,14 @@ export interface IQuickLinkSearchResultItem {
routerLink: string[];
}
export interface IAccountSearchResultItem
extends Pick<AccountWithValue, 'id' | 'name' | 'platform'> {
mode: SearchMode.ACCOUNT;
}
export type ISearchResultItem =
| IAssetSearchResultItem
| IAccountSearchResultItem
| IAssetSearchResultItem
| IQuickLinkSearchResultItem;
export interface ISearchResults {
assetProfiles: ISearchResultItem[];
accounts: ISearchResultItem[];
assetProfiles: ISearchResultItem[];
holdings: ISearchResultItem[];
quickLinks: ISearchResultItem[];
}

Loading…
Cancel
Save