Browse Source

Merge branch 'main' into translate-tr

pull/5030/head
Thomas Kaul 6 days ago
committed by GitHub
parent
commit
4933c5bbf2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 5
      CHANGELOG.md
  2. 8
      apps/api/src/app/admin/admin.controller.ts
  3. 8
      apps/api/src/services/data-provider/manual/manual.service.ts
  4. 35
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  5. 18
      apps/client/src/locales/messages.ca.xlf

5
CHANGELOG.md

@ -9,8 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Improved the language localization for Catalan (`ca`)
- Improved the language localization for Turkish (`tr`)
### Fixed
- Fixed an issue with the locale in the scraper configuration
## 2.174.0 - 2025-06-24
### Added

8
apps/api/src/app/admin/admin.controller.ts

@ -17,7 +17,8 @@ import {
AdminData,
AdminMarketData,
AdminUsers,
EnhancedSymbolProfile
EnhancedSymbolProfile,
ScraperConfiguration
} from '@ghostfolio/common/interfaces';
import { permissions } from '@ghostfolio/common/permissions';
import type {
@ -222,13 +223,12 @@ export class AdminController {
@Post('market-data/:dataSource/:symbol/test')
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async testMarketData(
@Body() data: { scraperConfiguration: string },
@Body() data: { scraperConfiguration: ScraperConfiguration },
@Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string
): Promise<{ price: number }> {
try {
const scraperConfiguration = JSON.parse(data.scraperConfiguration);
const price = await this.manualService.test(scraperConfiguration);
const price = await this.manualService.test(data.scraperConfiguration);
if (price) {
return { price };

8
apps/api/src/services/data-provider/manual/manual.service.ts

@ -104,7 +104,7 @@ export class ManualService implements DataProviderInterface {
}
return historical;
} else if (selector === undefined || url === undefined) {
} else if (!selector || !url) {
return {};
}
@ -162,7 +162,11 @@ export class ManualService implements DataProviderInterface {
const symbolProfilesWithScraperConfigurationAndInstantMode =
symbolProfiles.filter(({ scraperConfiguration }) => {
return scraperConfiguration?.mode === 'instant';
return (
scraperConfiguration?.mode === 'instant' &&
scraperConfiguration?.selector &&
scraperConfiguration?.url
);
});
const scraperResultPromises =

35
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -11,6 +11,7 @@ import {
AdminMarketDataDetails,
AssetProfileIdentifier,
LineChartItem,
ScraperConfiguration,
User
} from '@ghostfolio/common/interfaces';
import { translate } from '@ghostfolio/ui/i18n';
@ -41,6 +42,7 @@ import {
AssetClass,
AssetSubClass,
MarketData,
Prisma,
SymbolProfile
} from '@prisma/client';
import { format } from 'date-fns';
@ -343,7 +345,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
public async onSubmitAssetProfileForm() {
let countries = [];
let scraperConfiguration = {};
let scraperConfiguration: ScraperConfiguration = {
selector: '',
url: ''
};
let sectors = [];
let symbolMapping = {};
@ -354,9 +359,9 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
try {
scraperConfiguration = {
defaultMarketPrice:
this.assetProfileForm.controls['scraperConfiguration'].controls[
(this.assetProfileForm.controls['scraperConfiguration'].controls[
'defaultMarketPrice'
].value,
].value as number) || undefined,
headers: JSON.parse(
this.assetProfileForm.controls['scraperConfiguration'].controls[
'headers'
@ -365,10 +370,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
locale:
this.assetProfileForm.controls['scraperConfiguration'].controls[
'locale'
].value,
].value || undefined,
mode: this.assetProfileForm.controls['scraperConfiguration'].controls[
'mode'
].value,
].value as ScraperConfiguration['mode'],
selector:
this.assetProfileForm.controls['scraperConfiguration'].controls[
'selector'
@ -377,6 +382,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
'url'
].value
};
if (!scraperConfiguration.selector || !scraperConfiguration.url) {
scraperConfiguration = undefined;
}
} catch {}
try {
@ -391,7 +400,6 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
const assetProfile: UpdateAssetProfileDto = {
countries,
scraperConfiguration,
sectors,
symbolMapping,
assetClass: this.assetProfileForm.get('assetClass').value,
@ -400,6 +408,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
currency: this.assetProfileForm.get('currency').value,
isActive: this.assetProfileForm.get('isActive').value,
name: this.assetProfileForm.get('name').value,
scraperConfiguration:
scraperConfiguration as unknown as Prisma.InputJsonObject,
url: this.assetProfileForm.get('url').value || null
};
@ -493,11 +503,10 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
this.adminService
.testMarketData({
dataSource: this.data.dataSource,
scraperConfiguration: JSON.stringify({
defaultMarketPrice:
this.assetProfileForm.controls['scraperConfiguration'].controls[
'defaultMarketPrice'
].value,
scraperConfiguration: {
defaultMarketPrice: this.assetProfileForm.controls[
'scraperConfiguration'
].controls['defaultMarketPrice'].value as number,
headers: JSON.parse(
this.assetProfileForm.controls['scraperConfiguration'].controls[
'headers'
@ -506,7 +515,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
locale:
this.assetProfileForm.controls['scraperConfiguration'].controls[
'locale'
].value,
].value || undefined,
mode: this.assetProfileForm.controls['scraperConfiguration'].controls[
'mode'
].value,
@ -517,7 +526,7 @@ export class AssetProfileDialog implements OnDestroy, OnInit {
url: this.assetProfileForm.controls['scraperConfiguration'].controls[
'url'
].value
}),
},
symbol: this.data.symbol
})
.pipe(

18
apps/client/src/locales/messages.ca.xlf

@ -4845,7 +4845,7 @@
</trans-unit>
<trans-unit id="50760c2140335b2324deaee120f40d9aa64b3238" datatype="html">
<source>Currency Cluster Risks</source>
<target state="new">Currency Cluster Risks</target>
<target state="translated">Riscos del clúster de divises</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html</context>
<context context-type="linenumber">93</context>
@ -4853,7 +4853,7 @@
</trans-unit>
<trans-unit id="c7b797e5df289241021db16010efb6ac3c6cfb86" datatype="html">
<source>Account Cluster Risks</source>
<target state="new">Account Cluster Risks</target>
<target state="translated">Riscos del clúster de comptes</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html</context>
<context context-type="linenumber">141</context>
@ -4861,7 +4861,7 @@
</trans-unit>
<trans-unit id="5080775557941296581" datatype="html">
<source>Pricing</source>
<target state="new">Pricing</target>
<target state="translated">Preus</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page-routing.module.ts</context>
<context context-type="linenumber">13</context>
@ -4873,7 +4873,7 @@
</trans-unit>
<trans-unit id="9ba87e803f0b976584dc2a4dd69d32090cdfc229" datatype="html">
<source>Pricing Plans</source>
<target state="new">Pricing Plans</target>
<target state="translated">Plans de preus</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">4</context>
@ -4881,7 +4881,7 @@
</trans-unit>
<trans-unit id="de0d77a5255f97548d2b579f78c20c911a71820f" datatype="html">
<source> Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. </source>
<target state="new"> Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. </target>
<target state="translated"> La nostra oferta oficial al núvol Ghostfolio Premium és la manera més senzilla de començar. A causa del temps que estalvia, aquesta serà la millor opció per a la majoria de la gent. Els ingressos s’utilitzen per cobrir els costos de la infraestructura d’allotjament i per finançar el desenvolupament en curs. </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">6</context>
@ -4897,7 +4897,7 @@
</trans-unit>
<trans-unit id="fd30b4e3189726798f09fa0ce875486cf50dda2d" datatype="html">
<source> For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. </source>
<target state="new"> For tech-savvy investors who prefer to run Ghostfolio on their own infrastructure. </target>
<target state="translated"> Per a inversors experts en tecnologia que prefereixen executar Ghostfolio a la seva pròpia infraestructura. </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">24</context>
@ -4905,7 +4905,7 @@
</trans-unit>
<trans-unit id="435445e728dcf7fdf68fbae0e55e83f61591ac87" datatype="html">
<source>Unlimited Transactions</source>
<target state="new">Unlimited Transactions</target>
<target state="translated">Transaccions il·limitades</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">31</context>
@ -4921,7 +4921,7 @@
</trans-unit>
<trans-unit id="897e322427107efb4a101afcc9641f0e81ce9643" datatype="html">
<source>Unlimited Accounts</source>
<target state="new">Unlimited Accounts</target>
<target state="translated">Comptes il·limitats</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">35</context>
@ -4937,7 +4937,7 @@
</trans-unit>
<trans-unit id="60d7aee1c199a9995a318cfce24cbccbcfb52863" datatype="html">
<source>Portfolio Performance</source>
<target state="new">Portfolio Performance</target>
<target state="translated">Rendiment de la cartera</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">39</context>

Loading…
Cancel
Save