From 7999ff973b8aab86f1f6b064ec3424fa8a34207f Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 2 Jan 2026 10:43:39 +0100 Subject: [PATCH 1/8] Bugfix/jsonpath import in manual service (#6129) * Fix jsonpath import * Update changelog --- CHANGELOG.md | 6 +++++ apps/api/src/helper/object.helper.spec.ts | 22 ++++++++++++++++++- apps/api/src/helper/object.helper.ts | 11 ++++++++++ .../data-provider/manual/manual.service.ts | 11 +++++++--- package-lock.json | 8 +++++++ package.json | 1 + 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 088dd774b..2ee1be4c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Fixed the import of `jsonpath` to support REST APIs (`JSON`) via the scraper configuration + ## 2.226.0 - 2026-01-01 ### Added diff --git a/apps/api/src/helper/object.helper.spec.ts b/apps/api/src/helper/object.helper.spec.ts index 433490325..e1ec81b8f 100644 --- a/apps/api/src/helper/object.helper.spec.ts +++ b/apps/api/src/helper/object.helper.spec.ts @@ -1,4 +1,24 @@ -import { redactAttributes } from './object.helper'; +import { query, redactAttributes } from './object.helper'; + +describe('query', () => { + it('should get market price from stock API response', () => { + const object = { + currency: 'USD', + market: { + previousClose: 273.04, + price: 271.86 + }, + symbol: 'AAPL' + }; + + const result = query({ + object, + pathExpression: '$.market.price' + })[0]; + + expect(result).toBe(271.86); + }); +}); describe('redactAttributes', () => { it('should redact provided attributes', () => { diff --git a/apps/api/src/helper/object.helper.ts b/apps/api/src/helper/object.helper.ts index a5854e9d9..6bb6579d2 100644 --- a/apps/api/src/helper/object.helper.ts +++ b/apps/api/src/helper/object.helper.ts @@ -1,4 +1,5 @@ import { Big } from 'big.js'; +import jsonpath from 'jsonpath'; import { cloneDeep, isArray, isObject } from 'lodash'; export function hasNotDefinedValuesInObject(aObject: Object): boolean { @@ -31,6 +32,16 @@ export function nullifyValuesInObjects(aObjects: T[], keys: string[]): T[] { }); } +export function query({ + object, + pathExpression +}: { + object: object; + pathExpression: string; +}) { + return jsonpath.query(object, pathExpression); +} + export function redactAttributes({ isFirstRun = true, object, diff --git a/apps/api/src/services/data-provider/manual/manual.service.ts b/apps/api/src/services/data-provider/manual/manual.service.ts index f18da49ab..7392f0914 100644 --- a/apps/api/src/services/data-provider/manual/manual.service.ts +++ b/apps/api/src/services/data-provider/manual/manual.service.ts @@ -1,3 +1,4 @@ +import { query } from '@ghostfolio/api/helper/object.helper'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderInterface, @@ -26,7 +27,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { DataSource, SymbolProfile } from '@prisma/client'; import * as cheerio from 'cheerio'; import { addDays, format, isBefore } from 'date-fns'; -import * as jsonpath from 'jsonpath'; @Injectable() export class ManualService implements DataProviderInterface { @@ -286,9 +286,14 @@ export class ManualService implements DataProviderInterface { let value: string; if (response.headers.get('content-type')?.includes('application/json')) { - const data = await response.json(); + const object = await response.json(); - value = String(jsonpath.query(data, scraperConfiguration.selector)[0]); + value = String( + query({ + object, + pathExpression: scraperConfiguration.selector + })[0] + ); } else { const $ = cheerio.load(await response.text()); diff --git a/package-lock.json b/package-lock.json index 9e897adc4..6512d2162 100644 --- a/package-lock.json +++ b/package-lock.json @@ -124,6 +124,7 @@ "@types/big.js": "6.2.2", "@types/google-spreadsheet": "3.1.5", "@types/jest": "30.0.0", + "@types/jsonpath": "0.2.4", "@types/lodash": "4.17.20", "@types/node": "22.15.17", "@types/papaparse": "5.3.7", @@ -12436,6 +12437,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/jsonpath": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@types/jsonpath/-/jsonpath-0.2.4.tgz", + "integrity": "sha512-K3hxB8Blw0qgW6ExKgMbXQv2UPZBoE2GqLpVY+yr7nMD2Pq86lsuIzyAaiQ7eMqFL5B6di6pxSkogLJEyEHoGA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/jsonwebtoken": { "version": "9.0.10", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", diff --git a/package.json b/package.json index 464a9a7cd..59a455ae1 100644 --- a/package.json +++ b/package.json @@ -168,6 +168,7 @@ "@types/big.js": "6.2.2", "@types/google-spreadsheet": "3.1.5", "@types/jest": "30.0.0", + "@types/jsonpath": "0.2.4", "@types/lodash": "4.17.20", "@types/node": "22.15.17", "@types/papaparse": "5.3.7", From 6d3e16a6fb931404d39c9c4919e70fcd184d77e6 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:15:17 +0100 Subject: [PATCH 2/8] Bugfix/initialize input properties in fire calculator (#6122) * Initialize input properties * Update changelog --- CHANGELOG.md | 4 ++++ .../fire-calculator/fire-calculator.component.stories.ts | 4 +++- .../src/lib/fire-calculator/fire-calculator.component.ts | 8 ++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ee1be4c1..d9028e21c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- Initialized the input properties in the _FIRE_ calculator + ### Fixed - Fixed the import of `jsonpath` to support REST APIs (`JSON`) via the scraper configuration diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.stories.ts b/libs/ui/src/lib/fire-calculator/fire-calculator.component.stories.ts index e4cfa18ea..0872c2aac 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.stories.ts +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.stories.ts @@ -44,8 +44,10 @@ type Story = StoryObj; export const Simple: Story = { args: { + annualInterestRate: 5, currency: 'USD', fireWealth: 50000, - locale: locale + locale: locale, + savingsRate: 1000 } }; diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts index 655798b3d..6b0bc8dcb 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts @@ -77,16 +77,16 @@ import { FireCalculatorService } from './fire-calculator.service'; templateUrl: './fire-calculator.component.html' }) export class GfFireCalculatorComponent implements OnChanges, OnDestroy { - @Input() annualInterestRate: number; + @Input() annualInterestRate = 0; @Input() colorScheme: ColorScheme; @Input() currency: string; @Input() deviceType: string; - @Input() fireWealth: number; + @Input() fireWealth = 0; @Input() hasPermissionToUpdateUserSettings: boolean; @Input() locale = getLocale(); - @Input() projectedTotalAmount: number; + @Input() projectedTotalAmount = 0; @Input() retirementDate: Date; - @Input() savingsRate: number; + @Input() savingsRate = 0; @Output() annualInterestRateChanged = new EventEmitter(); @Output() calculationCompleted = From a1fab9fdf36f415bac5fbf5a83257582f6cdac24 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:28:04 +0100 Subject: [PATCH 3/8] Task/upgrade stripe to version 20.1.0 (#6132) * Upgrade stripe to version 20.1.0 * Update changelog --- CHANGELOG.md | 1 + .../api/src/app/subscription/subscription.service.ts | 2 +- package-lock.json | 12 ++++++------ package.json | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9028e21c..d438e0610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Initialized the input properties in the _FIRE_ calculator +- Upgraded `stripe` from version `18.5.0` to `20.1.0` ### Fixed diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index 8dc7d27f1..b38b07bb4 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -35,7 +35,7 @@ export class SubscriptionService { this.stripe = new Stripe( this.configurationService.get('STRIPE_SECRET_KEY'), { - apiVersion: '2025-08-27.basil' + apiVersion: '2025-12-15.clover' } ); } diff --git a/package-lock.json b/package-lock.json index 6512d2162..d1a228ade 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,7 +84,7 @@ "passport-openidconnect": "0.1.2", "reflect-metadata": "0.2.2", "rxjs": "7.8.1", - "stripe": "18.5.0", + "stripe": "20.1.0", "svgmap": "2.14.0", "tablemark": "4.1.0", "twitter-api-v2": "1.27.0", @@ -31464,18 +31464,18 @@ } }, "node_modules/stripe": { - "version": "18.5.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-18.5.0.tgz", - "integrity": "sha512-Hp+wFiEQtCB0LlNgcFh5uVyKznpDjzyUZ+CNVEf+I3fhlYvh7rZruIg+jOwzJRCpy0ZTPMjlzm7J2/M2N6d+DA==", + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-20.1.0.tgz", + "integrity": "sha512-o1VNRuMkY76ZCq92U3EH3/XHm/WHp7AerpzDs4Zyo8uE5mFL4QUcv/2SudWsSnhBSp4moO2+ZoGCZ7mT8crPmQ==", "license": "MIT", "dependencies": { "qs": "^6.11.0" }, "engines": { - "node": ">=12.*" + "node": ">=16" }, "peerDependencies": { - "@types/node": ">=12.x.x" + "@types/node": ">=16" }, "peerDependenciesMeta": { "@types/node": { diff --git a/package.json b/package.json index 59a455ae1..b887010cd 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "passport-openidconnect": "0.1.2", "reflect-metadata": "0.2.2", "rxjs": "7.8.1", - "stripe": "18.5.0", + "stripe": "20.1.0", "svgmap": "2.14.0", "tablemark": "4.1.0", "twitter-api-v2": "1.27.0", From a6011f2c47532195a044abdc337b8f2adbe49e1f Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 2 Jan 2026 12:16:20 +0100 Subject: [PATCH 4/8] Task/remove deprecated public Stripe key (#6124) * Remove deprecated public Stripe key * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/info/info.service.ts | 1 - apps/api/src/services/configuration/configuration.service.ts | 1 - apps/api/src/services/interfaces/environment.interface.ts | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d438e0610..22acc4090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Initialized the input properties in the _FIRE_ calculator +- Removed the deprecated public _Stripe_ key - Upgraded `stripe` from version `18.5.0` to `20.1.0` ### Fixed diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index 3802e3ef4..c5152c1a2 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -93,7 +93,6 @@ export class InfoService { (await this.propertyService.getByKey( PROPERTY_COUNTRIES_OF_SUBSCRIBERS )) ?? []; - info.stripePublicKey = this.configurationService.get('STRIPE_PUBLIC_KEY'); } if (this.configurationService.get('ENABLE_FEATURE_SYSTEM_MESSAGE')) { diff --git a/apps/api/src/services/configuration/configuration.service.ts b/apps/api/src/services/configuration/configuration.service.ts index a91aa6e69..5f9d1055d 100644 --- a/apps/api/src/services/configuration/configuration.service.ts +++ b/apps/api/src/services/configuration/configuration.service.ts @@ -102,7 +102,6 @@ export class ConfigurationService { ROOT_URL: url({ default: environment.rootUrl }), - STRIPE_PUBLIC_KEY: str({ default: '' }), STRIPE_SECRET_KEY: str({ default: '' }), TWITTER_ACCESS_TOKEN: str({ default: 'dummyAccessToken' }), TWITTER_ACCESS_TOKEN_SECRET: str({ default: 'dummyAccessTokenSecret' }), diff --git a/apps/api/src/services/interfaces/environment.interface.ts b/apps/api/src/services/interfaces/environment.interface.ts index 3c03744f1..57c58898e 100644 --- a/apps/api/src/services/interfaces/environment.interface.ts +++ b/apps/api/src/services/interfaces/environment.interface.ts @@ -52,7 +52,6 @@ export interface Environment extends CleanedEnvAccessors { REDIS_PORT: number; REQUEST_TIMEOUT: number; ROOT_URL: string; - STRIPE_PUBLIC_KEY: string; STRIPE_SECRET_KEY: string; TWITTER_ACCESS_TOKEN: string; TWITTER_ACCESS_TOKEN_SECRET: string; From 6c5883349ca7815d33722d70b9e277464ee835bb Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 2 Jan 2026 14:38:42 +0100 Subject: [PATCH 5/8] Release 2.227.0 (#6134) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22acc4090..36b516c8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.227.0 - 2026-01-02 ### Changed diff --git a/package-lock.json b/package-lock.json index d1a228ade..05e735609 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.226.0", + "version": "2.227.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.226.0", + "version": "2.227.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index b887010cd..1e82ec439 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.226.0", + "version": "2.227.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From c52d7f46c26f7bb1caba524e2e64db869118680b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20G=C3=BCnther?= Date: Fri, 2 Jan 2026 19:27:03 +0100 Subject: [PATCH 6/8] Task/move scraper configuration to tab in asset profile dialog (#6094) * Move scraper configuration to tab in asset profile dialog * Update changelog --- CHANGELOG.md | 6 + .../asset-profile-dialog.component.scss | 16 -- .../asset-profile-dialog.component.ts | 70 +++++- .../asset-profile-dialog.html | 233 ++++++++---------- 4 files changed, 172 insertions(+), 153 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36b516c8c..8cabbc605 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Extracted the scraper configuration to a dedicated tab in the asset profile details dialog of the admin control panel + ## 2.227.0 - 2026-01-02 ### Changed diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.scss b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.scss index 5e469970e..73c0c0d74 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.scss +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.scss @@ -13,21 +13,5 @@ right: 1rem; top: 0; } - - .mat-expansion-panel { - --mat-expansion-container-background-color: transparent; - - ::ng-deep { - .mat-expansion-panel-body { - padding: 0; - } - } - - .mat-expansion-panel-header { - &:hover { - --mat-expansion-header-hover-state-layer-color: transparent; - } - } - } } } diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index abea236b8..07e060764 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -38,8 +38,7 @@ import { Inject, OnDestroy, OnInit, - ViewChild, - signal + ViewChild } from '@angular/core'; import { AbstractControl, @@ -60,7 +59,6 @@ import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; -import { MatExpansionModule } from '@angular/material/expansion'; import { MatInputModule } from '@angular/material/input'; import { MatMenuModule } from '@angular/material/menu'; import { MatSelectModule } from '@angular/material/select'; @@ -79,6 +77,7 @@ import { format } from 'date-fns'; import { StatusCodes } from 'http-status-codes'; import { addIcons } from 'ionicons'; import { + codeSlashOutline, createOutline, ellipsisVertical, readerOutline, @@ -106,7 +105,6 @@ import { AssetProfileDialogParams } from './interfaces/interfaces'; MatButtonModule, MatCheckboxModule, MatDialogModule, - MatExpansionModule, MatInputModule, MatMenuModule, MatSelectModule, @@ -233,8 +231,6 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit { } ]; - public scraperConfiguationIsExpanded = signal(false); - public sectors: { [name: string]: { name: string; value: number }; }; @@ -255,7 +251,13 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit { private snackBar: MatSnackBar, private userService: UserService ) { - addIcons({ createOutline, ellipsisVertical, readerOutline, serverOutline }); + addIcons({ + codeSlashOutline, + createOutline, + ellipsisVertical, + readerOutline, + serverOutline + }); } public get canSaveAssetProfileIdentifier() { @@ -504,7 +506,19 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit { if (!scraperConfiguration.selector || !scraperConfiguration.url) { scraperConfiguration = undefined; } - } catch {} + } catch (error) { + console.error($localize`Could not parse scraper configuration`, error); + + this.snackBar.open( + '😞 ' + $localize`Could not parse scraper configuration`, + undefined, + { + duration: ms('3 seconds') + } + ); + + return; + } try { sectors = JSON.parse(this.assetProfileForm.get('sectors').value); @@ -538,7 +552,16 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit { object: assetProfile }); } catch (error) { - console.error(error); + console.error($localize`Could not validate form`, error); + + this.snackBar.open( + '😞 ' + $localize`Could not validate form`, + undefined, + { + duration: ms('3 seconds') + } + ); + return; } @@ -550,8 +573,29 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit { }, assetProfile ) - .subscribe(() => { - this.initialize(); + .subscribe({ + next: () => { + this.snackBar.open( + '✅ ' + $localize`Asset profile has been saved`, + undefined, + { + duration: ms('3 seconds') + } + ); + + this.initialize(); + }, + error: (error) => { + console.error($localize`Could not save asset profile`, error); + + this.snackBar.open( + '😞 ' + $localize`Could not save asset profile`, + undefined, + { + duration: ms('3 seconds') + } + ); + } }); } @@ -702,8 +746,8 @@ export class GfAssetProfileDialogComponent implements OnDestroy, OnInit { } public onTriggerSubmitAssetProfileForm() { - if (this.assetProfileForm) { - this.assetProfileFormElement.nativeElement.requestSubmit(); + if (this.assetProfileForm.valid) { + this.onSubmitAssetProfileForm(); } } diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html index ce0cafbc1..a60e10edc 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -390,130 +390,6 @@ > - @if (assetProfile?.dataSource === 'MANUAL') { -
- - - - Scraper Configuration - -
-
- - Default Market Price - - -
-
- - HTTP Request Headers - - -
-
- - Locale - - -
-
- - Mode - - @for (modeValue of modeValues; track modeValue) { - {{ - modeValue.viewValue - }} - } - - -
-
- - - Selector* - - - -
-
- - - Url* - - - -
-
- -
-
-
-
-
- } @if (assetProfile?.dataSource === 'MANUAL') {
@@ -588,6 +464,115 @@
+ @if (assetProfile?.dataSource === 'MANUAL') { + + + +
Scraper Configuration
+
+
+
+
+
+ + Default Market Price + + +
+
+ + HTTP Request Headers + + +
+
+ + Locale + + +
+
+ + Mode + + @for (modeValue of modeValues; track modeValue) { + {{ + modeValue.viewValue + }} + } + + +
+
+ + + Selector* + + + +
+
+ + + Url* + + + +
+
+ +
+
+
+
+
+ } From 95cbd01a4c5becac550c69a69f74fa35fcf5502d Mon Sep 17 00:00:00 2001 From: Omkar Gujja <67428719+omkarg01@users.noreply.github.com> Date: Sat, 3 Jan 2026 00:09:18 +0530 Subject: [PATCH 7/8] Task/lazy load platforms via API in create or update account dialog (#6130) * Lazy load platforms via API * Update changelog --- CHANGELOG.md | 1 + ...eate-or-update-account-dialog.component.ts | 44 +++++++++++-------- apps/client/src/app/services/data.service.ts | 5 +++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cabbc605..91fc2bc39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Integrated the endpoint to get all platforms (`GET api/v1/platforms`) into the create or update account dialog - Extracted the scraper configuration to a dedicated tab in the asset profile details dialog of the admin control panel ## 2.227.0 - 2026-01-02 diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts index 5e18f25cf..ceb11a011 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts @@ -59,7 +59,7 @@ export class GfCreateOrUpdateAccountDialogComponent implements OnDestroy { public accountForm: FormGroup; public currencies: string[] = []; public filteredPlatforms: Observable; - public platforms: Platform[]; + public platforms: Platform[] = []; private unsubscribeSubject = new Subject(); @@ -71,10 +71,8 @@ export class GfCreateOrUpdateAccountDialogComponent implements OnDestroy { ) {} public ngOnInit() { - const { currencies, platforms } = this.dataService.fetchInfo(); - + const { currencies } = this.dataService.fetchInfo(); this.currencies = currencies; - this.platforms = platforms; this.accountForm = this.formBuilder.group({ accountId: [{ disabled: true, value: this.data.account.id }], @@ -83,23 +81,33 @@ export class GfCreateOrUpdateAccountDialogComponent implements OnDestroy { currency: [this.data.account.currency, Validators.required], isExcluded: [this.data.account.isExcluded], name: [this.data.account.name, Validators.required], - platformId: [ - this.platforms.find(({ id }) => { - return id === this.data.account.platformId; - }), - this.autocompleteObjectValidator() - ] + platformId: [null, this.autocompleteObjectValidator()] }); - this.filteredPlatforms = this.accountForm - .get('platformId') - .valueChanges.pipe( - startWith(''), - map((value) => { - const name = typeof value === 'string' ? value : value?.name; - return name ? this.filter(name as string) : this.platforms.slice(); - }) + this.dataService.fetchPlatforms().subscribe(({ platforms }) => { + this.platforms = platforms; + + const selectedPlatform = this.platforms.find(({ id }) => { + return id === this.data.account.platformId; + }); + + this.accountForm.patchValue( + { + platformId: selectedPlatform + }, + { emitEvent: false } ); + + this.filteredPlatforms = this.accountForm + .get('platformId') + .valueChanges.pipe( + startWith(''), + map((value) => { + const name = typeof value === 'string' ? value : value?.name; + return name ? this.filter(name as string) : this.platforms.slice(); + }) + ); + }); } public autoCompleteCheck() { diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 31b0fef73..21eec06c3 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -42,6 +42,7 @@ import { MarketDataDetailsResponse, MarketDataOfMarketsResponse, OAuthResponse, + PlatformsResponse, PortfolioDetails, PortfolioDividendsResponse, PortfolioHoldingResponse, @@ -521,6 +522,10 @@ export class DataService { ); } + public fetchPlatforms() { + return this.http.get('/api/v1/platforms'); + } + public fetchPortfolioDetails({ filters, withMarkets = false From 113238f86ee73491ea961672c7c9f4885463ecab Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 3 Jan 2026 08:48:20 +0100 Subject: [PATCH 8/8] Task/remove deprecated public Stripe key (part 2) (#6138) * Remove deprecated public Stripe key --- libs/common/src/lib/interfaces/info-item.interface.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/common/src/lib/interfaces/info-item.interface.ts b/libs/common/src/lib/interfaces/info-item.interface.ts index c2ee54526..119a94a7c 100644 --- a/libs/common/src/lib/interfaces/info-item.interface.ts +++ b/libs/common/src/lib/interfaces/info-item.interface.ts @@ -18,9 +18,5 @@ export interface InfoItem { platforms: Platform[]; statistics: Statistics; - - /** @deprecated */ - stripePublicKey?: string; - subscriptionOffer?: SubscriptionOffer; }