Skip to content

Commit efc0b1b

Browse files
authored
Feature/support filters in AI prompt API (ghostfolio#4431)
* Support filters in AI prompt API * Update changelog
1 parent 235db72 commit efc0b1b

File tree

6 files changed

+51
-5
lines changed

6 files changed

+51
-5
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
### Added
11+
12+
- Added support for filtering in the _Copy AI prompt to clipboard_ actions on the analysis page (experimental)
13+
1014
### Changed
1115

1216
- Improved the symbol validation in the _Yahoo Finance_ service (get asset profiles)

apps/api/src/app/endpoints/ai/ai.controller.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
22
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
3+
import { ApiService } from '@ghostfolio/api/services/api/api.service';
34
import {
45
DEFAULT_CURRENCY,
56
DEFAULT_LANGUAGE_CODE
@@ -8,7 +9,14 @@ import { AiPromptResponse } from '@ghostfolio/common/interfaces';
89
import { permissions } from '@ghostfolio/common/permissions';
910
import type { AiPromptMode, RequestWithUser } from '@ghostfolio/common/types';
1011

11-
import { Controller, Get, Inject, Param, UseGuards } from '@nestjs/common';
12+
import {
13+
Controller,
14+
Get,
15+
Inject,
16+
Param,
17+
Query,
18+
UseGuards
19+
} from '@nestjs/common';
1220
import { REQUEST } from '@nestjs/core';
1321
import { AuthGuard } from '@nestjs/passport';
1422

@@ -18,16 +26,31 @@ import { AiService } from './ai.service';
1826
export class AiController {
1927
public constructor(
2028
private readonly aiService: AiService,
29+
private readonly apiService: ApiService,
2130
@Inject(REQUEST) private readonly request: RequestWithUser
2231
) {}
2332

2433
@Get('prompt/:mode')
2534
@HasPermission(permissions.readAiPrompt)
2635
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
2736
public async getPrompt(
28-
@Param('mode') mode: AiPromptMode
37+
@Param('mode') mode: AiPromptMode,
38+
@Query('accounts') filterByAccounts?: string,
39+
@Query('assetClasses') filterByAssetClasses?: string,
40+
@Query('dataSource') filterByDataSource?: string,
41+
@Query('symbol') filterBySymbol?: string,
42+
@Query('tags') filterByTags?: string
2943
): Promise<AiPromptResponse> {
44+
const filters = this.apiService.buildFiltersFromQueryParams({
45+
filterByAccounts,
46+
filterByAssetClasses,
47+
filterByDataSource,
48+
filterBySymbol,
49+
filterByTags
50+
});
51+
3052
const prompt = await this.aiService.getPrompt({
53+
filters,
3154
mode,
3255
impersonationId: undefined,
3356
languageCode:

apps/api/src/app/endpoints/ai/ai.module.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.servic
77
import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service';
88
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
99
import { UserModule } from '@ghostfolio/api/app/user/user.module';
10+
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
1011
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
1112
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
1213
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module';
@@ -25,6 +26,7 @@ import { AiService } from './ai.service';
2526
@Module({
2627
controllers: [AiController],
2728
imports: [
29+
ApiModule,
2830
ConfigurationModule,
2931
DataProviderModule,
3032
ExchangeRateDataModule,

apps/api/src/app/endpoints/ai/ai.service.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service';
2+
import { Filter } from '@ghostfolio/common/interfaces';
23
import type { AiPromptMode } from '@ghostfolio/common/types';
34

45
import { Injectable } from '@nestjs/common';
@@ -8,19 +9,22 @@ export class AiService {
89
public constructor(private readonly portfolioService: PortfolioService) {}
910

1011
public async getPrompt({
12+
filters,
1113
impersonationId,
1214
languageCode,
1315
mode,
1416
userCurrency,
1517
userId
1618
}: {
19+
filters?: Filter[];
1720
impersonationId: string;
1821
languageCode: string;
1922
mode: AiPromptMode;
2023
userCurrency: string;
2124
userId: string;
2225
}) {
2326
const { holdings } = await this.portfolioService.getDetails({
27+
filters,
2428
impersonationId,
2529
userId
2630
});

apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,10 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
161161
}
162162

163163
this.dataService
164-
.fetchPrompt(mode)
164+
.fetchPrompt({
165+
mode,
166+
filters: this.userService.getFilters()
167+
})
165168
.pipe(takeUntil(this.unsubscribeSubject))
166169
.subscribe(({ prompt }) => {
167170
this.clipboard.copy(prompt);

apps/client/src/app/services/data.service.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -653,8 +653,18 @@ export class DataService {
653653
return this.http.get<PortfolioReportResponse>('/api/v1/portfolio/report');
654654
}
655655

656-
public fetchPrompt(mode: AiPromptMode) {
657-
return this.http.get<AiPromptResponse>(`/api/v1/ai/prompt/${mode}`);
656+
public fetchPrompt({
657+
filters,
658+
mode
659+
}: {
660+
filters?: Filter[];
661+
mode: AiPromptMode;
662+
}) {
663+
const params = this.buildFiltersAsQueryParams({ filters });
664+
665+
return this.http.get<AiPromptResponse>(`/api/v1/ai/prompt/${mode}`, {
666+
params
667+
});
658668
}
659669

660670
public fetchPublicPortfolio(aAccessId: string) {

0 commit comments

Comments
 (0)