diff --git a/CHANGELOG.md b/CHANGELOG.md index de1ef0182..dbb9efe79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,6 +96,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Extended the tags selector component by a `readonly` attribute +- Extended the tags selector component to support creating custom tags +- Added global styles to the _Storybook_ setup + +### Changed + +- Improved the language localization for German (`de`) + +## 2.138.0 - 2025-02-08 + +### Added + +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Emerging Markets) +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Europe) +- Added a link to _Duck.ai_ to the _Copy AI prompt to clipboard_ action on the analysis page (experimental) +- Extracted the tags selector to a reusable component used in the create or update activity dialog and holding detail dialog +- Added stories for the tags selector component + +### Changed + +- Improved the caching of the portfolio snapshot in the portfolio calculator by expiring cache entries when a user changes tags in the holding detail dialog +- Improved the error handling in the _CoinGecko_ service +- Improved the language localization for German (`de`) +- Upgraded `svgmap` from version `2.6.0` to `2.12.2` + +## 2.137.1 - 2025-02-01 + +### Added + +- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (North America) +- Added support for ETF sector data in the _Yahoo Finance_ data enhancer + +### Changed + +- Extracted the scraper configuration to a sub form in the asset profile details dialog of the admin control +- Migrated the database seeding to _TypeScript_ +- Improved the language localization for German (`de`) +- Upgraded `@trivago/prettier-plugin-sort-imports` from version `4.3.0` to `5.2.1` +- Upgraded `bull` from version `4.16.4` to `4.16.5` +- Upgraded `ng-extract-i18n-merge` from version `2.13.1` to `2.14.1` +- Upgraded `prisma` from version `6.2.1` to `6.3.0` + +### Fixed + +- Fixed the dynamic numerical precision for cryptocurrencies in the holding detail dialog + +## 2.136.0 - 2025-01-24 + +### Added + - Set up a _GitHub Action_ to automatically extract locales when the `main` branch changes ### Changed @@ -108,6 +158,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed an issue with the detection of the thousand separator by locale +- Fixed an issue with holdings and sectors while using symbol profile overrides - Fixed an issue with the MIME type detection in the scraper configuration ## 2.135.0 - 2025-01-19 @@ -117,6 +169,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Moved the language localization for Polski (`pl`) from experimental to general availability - Extended the _Financial Modeling Prep_ service - Switched to _ESLint_’s flat config format +- Upgraded `bull` from version `4.16.2` to `4.16.4` - Upgraded `chart.js` from version `4.2.0` to `4.4.7` - Upgraded `chartjs-chart-treemap` from version `2.3.1` to `3.1.0` - Upgraded `chartjs-plugin-annotation` from version `2.1.2` to `3.1.0` diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index dbe30c914..6876eea50 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -51,6 +51,7 @@ export class OrderService { public async assignTags({ dataSource, symbol, + userId, tags }: { tags: Tag[]; userId: string } & AssetProfileIdentifier) { const symbolProfile: SymbolProfile = @@ -60,7 +61,7 @@ export class OrderService { symbol } ])[0]; - return await this.symbolProfileService.updateSymbolProfile({ + var result = await this.symbolProfileService.updateSymbolProfile({ assetClass: symbolProfile.assetClass, assetSubClass: symbolProfile.assetSubClass, countries: symbolProfile.countries, @@ -85,6 +86,15 @@ export class OrderService { }, url: symbolProfile.url }); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId + }) + ); + + return result; } public async createOrder( diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 4e8f4de60..c2c1b4c5a 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -16,6 +16,9 @@ import { EconomicMarketClusterRiskDevelopedMarkets } from '@ghostfolio/api/model import { EconomicMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/economic-market-cluster-risk/emerging-markets'; import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup'; import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment'; +import { RegionalMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/emerging-markets'; +import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe'; +import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; @@ -1196,12 +1199,19 @@ export class PortfolioService { const userId = await this.getUserId(impersonationId, this.request.user.id); const userSettings = this.request.user.Settings.settings as UserSettings; - const { accounts, holdings, markets, summary } = await this.getDetails({ - impersonationId, - userId, - withMarkets: true, - withSummary: true - }); + const { accounts, holdings, markets, marketsAdvanced, summary } = + await this.getDetails({ + impersonationId, + userId, + withMarkets: true, + withSummary: true + }); + + const marketsAdvancedTotalInBaseCurrency = getSum( + Object.values(marketsAdvanced).map(({ valueInBaseCurrency }) => { + return new Big(valueInBaseCurrency); + }) + ).toNumber(); const marketsTotalInBaseCurrency = getSum( Object.values(markets).map(({ valueInBaseCurrency }) => { @@ -1294,7 +1304,30 @@ export class PortfolioService { ) ], userSettings - ) + ), + regionalMarketClusterRisk: + summary.ordersCount > 0 + ? await this.rulesService.evaluate( + [ + new RegionalMarketClusterRiskEmergingMarkets( + this.exchangeRateDataService, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.emergingMarkets.valueInBaseCurrency + ), + new RegionalMarketClusterRiskEurope( + this.exchangeRateDataService, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.europe.valueInBaseCurrency + ), + new RegionalMarketClusterRiskNorthAmerica( + this.exchangeRateDataService, + marketsAdvancedTotalInBaseCurrency, + marketsAdvanced.northAmerica.valueInBaseCurrency + ) + ], + userSettings + ) + : undefined }; return { rules, statistics: this.getReportStatistics(rules) }; diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index b5c71179f..1dae9d45b 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -13,6 +13,9 @@ import { EconomicMarketClusterRiskDevelopedMarkets } from '@ghostfolio/api/model import { EconomicMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/economic-market-cluster-risk/emerging-markets'; import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup'; import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment'; +import { RegionalMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/emerging-markets'; +import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe'; +import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; @@ -268,7 +271,24 @@ export class UserService { undefined, undefined, undefined - ).getSettings(user.Settings.settings) + ).getSettings(user.Settings.settings), + RegionalMarketClusterRiskEmergingMarkets: + new RegionalMarketClusterRiskEmergingMarkets( + undefined, + undefined, + undefined + ).getSettings(user.Settings.settings), + RegionalMarketClusterRiskEurope: new RegionalMarketClusterRiskEurope( + undefined, + undefined, + undefined + ).getSettings(user.Settings.settings), + RegionalMarketClusterRiskNorthAmerica: + new RegionalMarketClusterRiskNorthAmerica( + undefined, + undefined, + undefined + ).getSettings(user.Settings.settings) }; let currentPermissions = getPermissions(user.role); diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts b/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts new file mode 100644 index 000000000..2d9a3b394 --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/emerging-markets.ts @@ -0,0 +1,79 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskEmergingMarkets extends Rule { + private currentValueInBaseCurrency: number; + private emergingMarketsValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + currentValueInBaseCurrency: number, + emergingMarketsValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + key: RegionalMarketClusterRiskEmergingMarkets.name, + name: 'Emerging Markets' + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.emergingMarketsValueInBaseCurrency = + emergingMarketsValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const emergingMarketsValueRatio = this.currentValueInBaseCurrency + ? this.emergingMarketsValueInBaseCurrency / + this.currentValueInBaseCurrency + : 0; + + if (emergingMarketsValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: `The Emerging Markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) exceeds ${( + ruleSettings.thresholdMax * 100 + ).toPrecision(3)}%`, + value: false + }; + } else if (emergingMarketsValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: `The Emerging Markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) is below ${( + ruleSettings.thresholdMin * 100 + ).toPrecision(3)}%`, + value: false + }; + } + + return { + evaluation: `The Emerging Markets contribution of your current investment (${(emergingMarketsValueRatio * 100).toPrecision(3)}%) is within the range of ${( + ruleSettings.thresholdMin * 100 + ).toPrecision( + 3 + )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + value: true + }; + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.12, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.08 + }; + } +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts b/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts new file mode 100644 index 000000000..d33190ceb --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/europe.ts @@ -0,0 +1,77 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskEurope extends Rule { + private currentValueInBaseCurrency: number; + private europeValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + currentValueInBaseCurrency: number, + europeValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + key: RegionalMarketClusterRiskEurope.name, + name: 'Europe' + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.europeValueInBaseCurrency = europeValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const europeMarketValueRatio = this.currentValueInBaseCurrency + ? this.europeValueInBaseCurrency / this.currentValueInBaseCurrency + : 0; + + if (europeMarketValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) exceeds ${( + ruleSettings.thresholdMax * 100 + ).toPrecision(3)}%`, + value: false + }; + } else if (europeMarketValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) is below ${( + ruleSettings.thresholdMin * 100 + ).toPrecision(3)}%`, + value: false + }; + } + + return { + evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) is within the range of ${( + ruleSettings.thresholdMin * 100 + ).toPrecision( + 3 + )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + value: true + }; + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.15, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.11 + }; + } +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts b/apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts new file mode 100644 index 000000000..8b9fddf3a --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts @@ -0,0 +1,7 @@ +import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; + +export interface Settings extends RuleSettings { + baseCurrency: string; + thresholdMin: number; + thresholdMax: number; +} diff --git a/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts b/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts new file mode 100644 index 000000000..4563b7c54 --- /dev/null +++ b/apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts @@ -0,0 +1,77 @@ +import { Rule } from '@ghostfolio/api/models/rule'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; + +import { Settings } from './interfaces/rule-settings.interface'; + +export class RegionalMarketClusterRiskNorthAmerica extends Rule { + private currentValueInBaseCurrency: number; + private northAmericaValueInBaseCurrency: number; + + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + currentValueInBaseCurrency: number, + northAmericaValueInBaseCurrency: number + ) { + super(exchangeRateDataService, { + key: RegionalMarketClusterRiskNorthAmerica.name, + name: 'North America' + }); + + this.currentValueInBaseCurrency = currentValueInBaseCurrency; + this.northAmericaValueInBaseCurrency = northAmericaValueInBaseCurrency; + } + + public evaluate(ruleSettings: Settings) { + const northAmericaMarketValueRatio = this.currentValueInBaseCurrency + ? this.northAmericaValueInBaseCurrency / this.currentValueInBaseCurrency + : 0; + + if (northAmericaMarketValueRatio > ruleSettings.thresholdMax) { + return { + evaluation: `The North America market contribution of your current investment (${(northAmericaMarketValueRatio * 100).toPrecision(3)}%) exceeds ${( + ruleSettings.thresholdMax * 100 + ).toPrecision(3)}%`, + value: false + }; + } else if (northAmericaMarketValueRatio < ruleSettings.thresholdMin) { + return { + evaluation: `The North America market contribution of your current investment (${(northAmericaMarketValueRatio * 100).toPrecision(3)}%) is below ${( + ruleSettings.thresholdMin * 100 + ).toPrecision(3)}%`, + value: false + }; + } + + return { + evaluation: `The North America market contribution of your current investment (${(northAmericaMarketValueRatio * 100).toPrecision(3)}%) is within the range of ${( + ruleSettings.thresholdMin * 100 + ).toPrecision( + 3 + )}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`, + value: true + }; + } + + public getConfiguration() { + return { + threshold: { + max: 1, + min: 0, + step: 0.01, + unit: '%' + }, + thresholdMax: true, + thresholdMin: true + }; + } + + public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings { + return { + baseCurrency, + isActive: xRayRules?.[this.getKey()]?.isActive ?? true, + thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.69, + thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.65 + }; + } +} diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts index 30dbe0ae1..fb1fa9b63 100644 --- a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -112,7 +112,7 @@ export class CoinGeckoService implements DataProviderInterface { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { try { - const { prices } = await fetch( + const { error, prices, status } = await fetch( `${ this.apiUrl }/coins/${symbol}/market_chart/range?vs_currency=${DEFAULT_CURRENCY.toLowerCase()}&from=${getUnixTime( @@ -124,6 +124,14 @@ export class CoinGeckoService implements DataProviderInterface { } ).then((res) => res.json()); + if (error?.status) { + throw new Error(error.status.error_message); + } + + if (status) { + throw new Error(status.error_message); + } + const result: { [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; } = { diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index b71e3e316..18d624098 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -197,7 +197,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { assetProfile.price.symbol ); - if (assetSubClass === AssetSubClass.MUTUALFUND) { + if (['ETF', 'MUTUALFUND'].includes(assetSubClass)) { response.sectors = []; for (const sectorWeighting of assetProfile.topHoldings @@ -207,7 +207,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { } } } else if ( - assetSubClass === AssetSubClass.STOCK && + assetSubClass === 'STOCK' && assetProfile.summaryProfile?.country ) { // Add country if asset is stock and country available diff --git a/apps/api/src/services/symbol-profile/symbol-profile.service.ts b/apps/api/src/services/symbol-profile/symbol-profile.service.ts index 0ea5dcff5..62fac27d4 100644 --- a/apps/api/src/services/symbol-profile/symbol-profile.service.ts +++ b/apps/api/src/services/symbol-profile/symbol-profile.service.ts @@ -189,9 +189,13 @@ export class SymbolProfileService { symbolProfile?.countries as unknown as Prisma.JsonArray ), dateOfFirstActivity: undefined as Date, - holdings: this.getHoldings(symbolProfile), + holdings: this.getHoldings( + symbolProfile?.holdings as unknown as Prisma.JsonArray + ), scraperConfiguration: this.getScraperConfiguration(symbolProfile), - sectors: this.getSectors(symbolProfile), + sectors: this.getSectors( + symbolProfile?.sectors as unknown as Prisma.JsonArray + ), symbolMapping: this.getSymbolMapping(symbolProfile), tags: symbolProfile?.tags }; @@ -222,8 +226,9 @@ export class SymbolProfileService { (item.SymbolProfileOverrides.holdings as unknown as Holding[]) ?.length > 0 ) { - item.holdings = item.SymbolProfileOverrides - .holdings as unknown as Holding[]; + item.holdings = this.getHoldings( + item.SymbolProfileOverrides?.holdings as unknown as Prisma.JsonArray + ); } item.name = item.SymbolProfileOverrides?.name ?? item.name; @@ -232,8 +237,9 @@ export class SymbolProfileService { (item.SymbolProfileOverrides.sectors as unknown as Sector[])?.length > 0 ) { - item.sectors = item.SymbolProfileOverrides - .sectors as unknown as Sector[]; + item.sectors = this.getSectors( + item.SymbolProfileOverrides?.sectors as unknown as Prisma.JsonArray + ); } item.url = item.SymbolProfileOverrides?.url ?? item.url; @@ -262,18 +268,20 @@ export class SymbolProfileService { }); } - private getHoldings(symbolProfile: SymbolProfile): Holding[] { - return ((symbolProfile?.holdings as Prisma.JsonArray) ?? []).map( - (holding) => { - const { name, weight } = holding as Prisma.JsonObject; + private getHoldings(aHoldings: Prisma.JsonArray = []): Holding[] { + if (aHoldings === null) { + return []; + } + + return aHoldings.map((holding) => { + const { name, weight } = holding as Prisma.JsonObject; - return { - allocationInPercentage: weight as number, - name: (name as string) ?? UNKNOWN_KEY, - valueInBaseCurrency: undefined - }; - } - ); + return { + allocationInPercentage: weight as number, + name: (name as string) ?? UNKNOWN_KEY, + valueInBaseCurrency: undefined + }; + }); } private getScraperConfiguration( @@ -298,17 +306,19 @@ export class SymbolProfileService { return null; } - private getSectors(symbolProfile: SymbolProfile): Sector[] { - return ((symbolProfile?.sectors as Prisma.JsonArray) ?? []).map( - (sector) => { - const { name, weight } = sector as Prisma.JsonObject; + private getSectors(aSectors: Prisma.JsonArray = []): Sector[] { + if (aSectors === null) { + return []; + } - return { - name: (name as string) ?? UNKNOWN_KEY, - weight: weight as number - }; - } - ); + return aSectors.map((sector) => { + const { name, weight } = sector as Prisma.JsonObject; + + return { + name: (name as string) ?? UNKNOWN_KEY, + weight: weight as number + }; + }); } private getSymbolMapping(symbolProfile: SymbolProfile) { diff --git a/apps/client/src/app/components/access-table/access-table.component.ts b/apps/client/src/app/components/access-table/access-table.component.ts index 32ae7bfef..34c5fbda2 100644 --- a/apps/client/src/app/components/access-table/access-table.component.ts +++ b/apps/client/src/app/components/access-table/access-table.component.ts @@ -14,6 +14,7 @@ import { } from '@angular/core'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableDataSource } from '@angular/material/table'; +import ms from 'ms'; @Component({ selector: 'gf-access-table', @@ -64,7 +65,7 @@ export class AccessTableComponent implements OnChanges { '✅ ' + $localize`Link has been copied to the clipboard`, undefined, { - duration: 3000 + duration: ms('3 seconds') } ); } 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 7057aad83..a9e135783 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 @@ -7,5 +7,21 @@ gf-line-chart { aspect-ratio: 16/9; } + + .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 96d563047..f43b4596a 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 @@ -24,7 +24,8 @@ import { Inject, OnDestroy, OnInit, - ViewChild + ViewChild, + signal } from '@angular/core'; import { FormBuilder, FormControl, Validators } from '@angular/forms'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; @@ -73,7 +74,14 @@ export class AssetProfileDialog implements OnDestroy, OnInit { name: ['', Validators.required], tags: new FormControl(undefined), tagsDisconnected: new FormControl(undefined), - scraperConfiguration: '', + scraperConfiguration: this.formBuilder.group({ + defaultMarketPrice: null, + headers: JSON.stringify({}), + locale: '', + mode: '', + selector: '', + url: '' + }), sectors: '', symbolMapping: '', url: '' @@ -88,6 +96,17 @@ export class AssetProfileDialog implements OnDestroy, OnInit { public historicalDataItems: LineChartItem[]; public isBenchmark = false; public marketDataItems: MarketData[] = []; + public modeValues = [ + { + value: 'lazy', + viewValue: $localize`Lazy` + ' (' + $localize`end of day` + ')' + }, + { + value: 'instant', + viewValue: $localize`Instant` + ' (' + $localize`real-time` + ')' + } + ]; + public scraperConfiguationIsExpanded = signal(false); public sectors: { [name: string]: { name: string; value: number }; }; @@ -206,9 +225,18 @@ export class AssetProfileDialog implements OnDestroy, OnInit { csvString: AssetProfileDialog.HISTORICAL_DATA_TEMPLATE }, name: this.assetProfile.name ?? this.assetProfile.symbol, - scraperConfiguration: JSON.stringify( - this.assetProfile?.scraperConfiguration ?? {} - ), + scraperConfiguration: { + defaultMarketPrice: + this.assetProfile?.scraperConfiguration?.defaultMarketPrice ?? + null, + headers: JSON.stringify( + this.assetProfile?.scraperConfiguration?.headers ?? {} + ), + locale: this.assetProfile?.scraperConfiguration?.locale ?? '', + mode: this.assetProfile?.scraperConfiguration?.mode ?? 'lazy', + selector: this.assetProfile?.scraperConfiguration?.selector ?? '', + url: this.assetProfile?.scraperConfiguration?.url ?? '' + }, sectors: JSON.stringify(this.assetProfile?.sectors ?? []), symbolMapping: JSON.stringify(this.assetProfile?.symbolMapping ?? {}), url: this.assetProfile?.url @@ -287,9 +315,31 @@ export class AssetProfileDialog implements OnDestroy, OnInit { } catch {} try { - scraperConfiguration = JSON.parse( - this.assetProfileForm.get('scraperConfiguration').value - ); + scraperConfiguration = { + defaultMarketPrice: + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'defaultMarketPrice' + ].value, + headers: JSON.parse( + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'headers' + ].value + ), + locale: + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'locale' + ].value, + mode: this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'mode' + ].value, + selector: + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'selector' + ].value, + url: this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'url' + ].value + }; } catch {} try { @@ -343,8 +393,31 @@ export class AssetProfileDialog implements OnDestroy, OnInit { this.adminService .testMarketData({ dataSource: this.data.dataSource, - scraperConfiguration: this.assetProfileForm.get('scraperConfiguration') - .value, + scraperConfiguration: JSON.stringify({ + defaultMarketPrice: + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'defaultMarketPrice' + ].value, + headers: JSON.parse( + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'headers' + ].value + ), + locale: + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'locale' + ].value, + mode: this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'mode' + ].value, + selector: + this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'selector' + ].value, + url: this.assetProfileForm.controls['scraperConfiguration'].controls[ + 'url' + ].value + }), symbol: this.data.symbol }) .pipe( 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 8ec5b8250..5a66b94d7 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 @@ -322,31 +322,106 @@ @if (assetProfile?.dataSource === 'MANUAL') { -
- - Scraper Configuration -
- - -
-
+
+ + + + Scraper Configuration + +
+
+ + Default Market Price + + +
+
+ + HTTP Request Headers + + +
+
+ + Locale + + +
+
+ + Mode + + @for (modeValue of modeValues; track modeValue) { + {{ + modeValue.viewValue + }} + } + + +
+
+ + + Selector* + + + +
+
+ + + Url* + + + +
+
+ +
+
+
+
+ } + @if (assetProfile?.dataSource === 'MANUAL') {
Sectors diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts index 3fa8e10e3..345bc4a2a 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts @@ -15,6 +15,7 @@ import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatChipsModule } from '@angular/material/chips'; import { MatDialogModule } 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'; @@ -38,6 +39,7 @@ import { AssetProfileDialog } from './asset-profile-dialog.component'; MatButtonModule, MatCheckboxModule, MatDialogModule, + MatExpansionModule, MatInputModule, MatMenuModule, MatSelectModule, diff --git a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html index ac777ffda..d3b0985fa 100644 --- a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html +++ b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.html @@ -17,8 +17,8 @@ data provider for self-hosters, offering - 100’000+ tickers from over 50 exchanges, - is coming soon! + 80’000+ tickers from over 50 exchanges, is + coming soon!

Want to stay updated? Click below to get notified as soon as it’s available. diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts index 6c5080c1d..e39be083b 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts @@ -18,26 +18,20 @@ import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-cre import { translate } from '@ghostfolio/ui/i18n'; import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; +import { GfTagsSelectorComponent } from '@ghostfolio/ui/tags-selector'; import { GfValueComponent } from '@ghostfolio/ui/value'; -import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, - ElementRef, Inject, OnDestroy, - OnInit, - ViewChild + OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { - MatAutocompleteModule, - MatAutocompleteSelectedEvent -} from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatChipsModule } from '@angular/material/chips'; import { @@ -53,8 +47,8 @@ import { Router } from '@angular/router'; import { Account, Tag } from '@prisma/client'; import { format, isSameMonth, isToday, parseISO } from 'date-fns'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Observable, of, Subject } from 'rxjs'; -import { map, startWith, takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; import { HoldingDetailDialogParams } from './interfaces/interfaces'; @@ -70,8 +64,8 @@ import { HoldingDetailDialogParams } from './interfaces/interfaces'; GfDialogHeaderModule, GfLineChartComponent, GfPortfolioProportionChartComponent, + GfTagsSelectorComponent, GfValueComponent, - MatAutocompleteModule, MatButtonModule, MatChipsModule, MatDialogModule, @@ -85,8 +79,6 @@ import { HoldingDetailDialogParams } from './interfaces/interfaces'; templateUrl: 'holding-detail-dialog.html' }) export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { - @ViewChild('tagInput') tagInput: ElementRef; - public activityForm: FormGroup; public accounts: Account[]; public assetClass: string; @@ -103,7 +95,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public dividendInBaseCurrencyPrecision = 2; public dividendYieldPercentWithCurrencyEffect: number; public feeInBaseCurrency: number; - public filteredTagsObservable: Observable = of([]); public firstBuyDate: string; public historicalDataItems: LineChartItem[]; public investment: number; @@ -124,7 +115,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public sectors: { [name: string]: { name: string; value: number }; }; - public separatorKeysCodes: number[] = [COMMA, ENTER]; public sortColumn = 'date'; public sortDirection: SortDirection = 'desc'; public SymbolProfile: EnhancedSymbolProfile; @@ -300,7 +290,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { if (Number.isInteger(this.quantity)) { this.quantityPrecision = 0; - } else if (this.SymbolProfile?.assetSubClass === 'CRYPTOCURRENCY') { + } else if (SymbolProfile?.assetSubClass === 'CRYPTOCURRENCY') { if (this.quantity < 1) { this.quantityPrecision = 7; } else if (this.quantity < 1000) { @@ -323,17 +313,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.activityForm.setValue({ tags: this.tags }, { emitEvent: false }); - this.filteredTagsObservable = this.activityForm.controls[ - 'tags' - ].valueChanges.pipe( - startWith(this.activityForm.get('tags').value), - map((aTags: Tag[] | null) => { - return aTags - ? this.filterTags(aTags) - : this.tagsAvailable.slice(); - }) - ); - this.transactionCount = transactionCount; this.totalItems = transactionCount; this.value = value; @@ -455,17 +434,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { }); } - public onAddTag(event: MatAutocompleteSelectedEvent) { - this.activityForm.get('tags').setValue([ - ...(this.activityForm.get('tags').value ?? []), - this.tagsAvailable.find(({ id }) => { - return id === event.option.value; - }) - ]); - - this.tagInput.nativeElement.value = ''; - } - public onCloneActivity(aActivity: Activity) { this.router.navigate(['/portfolio', 'activities'], { queryParams: { activityId: aActivity.id, createDialog: true } @@ -498,12 +466,8 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { }); } - public onRemoveTag(aTag: Tag) { - this.activityForm.get('tags').setValue( - this.activityForm.get('tags').value.filter(({ id }) => { - return id !== aTag.id; - }) - ); + public onTagsChanged(tags: Tag[]) { + this.activityForm.get('tags').setValue(tags); } public onUpdateActivity(aActivity: Activity) { @@ -518,14 +482,4 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } - - private filterTags(aTags: Tag[]) { - const tagIds = aTags.map(({ id }) => { - return id; - }); - - return this.tagsAvailable.filter(({ id }) => { - return !tagIds.includes(id); - }); - } } diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index ff4c0fc0b..871c9f635 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -370,60 +370,12 @@ -

-
- - Tags - - @for (tag of activityForm.get('tags')?.value; track tag.id) { - - {{ tag.name }} - - - } - - - - @for (tag of filteredTagsObservable | async; track tag.id) { - - {{ tag.name }} - - } - - -
-
- - @if (!data.hasPermissionToUpdateOrder && tagsAvailable?.length > 0) { -
-
-
Tags
- - @for (tag of tags; track tag) { - {{ tag.name }} - } - -
-
- } + @if ( dataSource?.data.length > 0 && diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts index 6139d173e..2214d91f9 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts @@ -12,11 +12,7 @@ import { Component, OnDestroy } from '@angular/core'; -import { - MatSnackBar, - MatSnackBarRef, - TextOnlySnackBar -} from '@angular/material/snack-bar'; +import { MatSnackBar } from '@angular/material/snack-bar'; import ms, { StringValue } from 'ms'; import { StripeService } from 'ngx-stripe'; import { EMPTY, Subject } from 'rxjs'; @@ -41,7 +37,6 @@ export class UserAccountMembershipComponent implements OnDestroy { public price: number; public priceId: string; public routerLinkPricing = ['/' + $localize`:snake-case:pricing`]; - public snackBarRef: MatSnackBarRef; public trySubscriptionMail = 'mailto:hi@ghostfol.io?Subject=Ghostfolio Premium Trial&body=Hello%0D%0DI am interested in Ghostfolio Premium. Can you please send me a coupon code to try it for some time?%0D%0DKind regards'; public user: User; @@ -186,22 +181,22 @@ export class UserAccountMembershipComponent implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(() => { - this.snackBarRef = this.snackBar.open( + const snackBarRef = this.snackBar.open( '✅ ' + $localize`Coupon code has been redeemed`, $localize`Reload`, { - duration: 3000 + duration: ms('3 seconds') } ); - this.snackBarRef + snackBarRef .afterDismissed() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { window.location.reload(); }); - this.snackBarRef + snackBarRef .onAction() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts index c1472515f..ced617117 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -25,6 +25,7 @@ import { MatSlideToggleChange } from '@angular/material/slide-toggle'; import { MatSnackBar } from '@angular/material/snack-bar'; import { format, parseISO } from 'date-fns'; import { uniq } from 'lodash'; +import ms from 'ms'; import { EMPTY, Subject, throwError } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; @@ -301,7 +302,9 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit { this.snackBar.open( $localize`Oops! There was an error setting up biometric authentication.`, undefined, - { duration: 3000 } + { + duration: ms('3 seconds') + } ); return throwError(() => { diff --git a/apps/client/src/app/components/world-map-chart/world-map-chart.component.html b/apps/client/src/app/components/world-map-chart/world-map-chart.component.html index 5de7ea9d0..87bc08672 100644 --- a/apps/client/src/app/components/world-map-chart/world-map-chart.component.html +++ b/apps/client/src/app/components/world-map-chart/world-map-chart.component.html @@ -8,4 +8,4 @@ /> } -
+
diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index 203d3adf5..018e441fc 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -19,6 +19,7 @@ import { } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { StatusCodes } from 'http-status-codes'; +import ms from 'ms'; import { Observable, throwError } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; @@ -54,13 +55,17 @@ export class HttpResponseInterceptor implements HttpInterceptor { ' ' + $localize`Please try again later.`, undefined, - { duration: 6000 } + { + duration: ms('6 seconds') + } ); } else if (!error.url.includes('/auth')) { this.snackBarRef = this.snackBar.open( $localize`This action is not allowed.`, undefined, - { duration: 6000 } + { + duration: ms('6 seconds') + } ); } @@ -79,7 +84,9 @@ export class HttpResponseInterceptor implements HttpInterceptor { ' ' + $localize`Please try again later.`, $localize`Okay`, - { duration: 6000 } + { + duration: ms('6 seconds') + } ); this.snackBarRef.afterDismissed().subscribe(() => { diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts index fe3c7b278..a0aca4605 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts @@ -3,24 +3,20 @@ import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto'; import { getDateFormatString } from '@ghostfolio/common/helper'; import { translate } from '@ghostfolio/ui/i18n'; -import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, - ElementRef, Inject, - OnDestroy, - ViewChild + OnDestroy } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { AssetClass, AssetSubClass, Tag, Type } from '@prisma/client'; import { isAfter, isToday } from 'date-fns'; -import { EMPTY, Observable, Subject, lastValueFrom, of } from 'rxjs'; -import { catchError, delay, map, startWith, takeUntil } from 'rxjs/operators'; +import { EMPTY, Subject, lastValueFrom } from 'rxjs'; +import { catchError, delay, takeUntil } from 'rxjs/operators'; import { DataService } from '../../../../services/data.service'; import { validateObjectForForm } from '../../../../util/form.util'; @@ -35,9 +31,6 @@ import { CreateOrUpdateActivityDialogParams } from './interfaces/interfaces'; standalone: false }) export class CreateOrUpdateActivityDialog implements OnDestroy { - @ViewChild('symbolAutocomplete') symbolAutocomplete; - @ViewChild('tagInput') tagInput: ElementRef; - public activityForm: FormGroup; public assetClasses = Object.keys(AssetClass).map((assetClass) => { return { id: assetClass, label: translate(assetClass) }; @@ -48,12 +41,10 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { public currencies: string[] = []; public currentMarketPrice = null; public defaultDateFormat: string; - public filteredTagsObservable: Observable = of([]); public isLoading = false; public isToday = isToday; public mode: 'create' | 'update'; public platforms: { id: string; name: string }[]; - public separatorKeysCodes: number[] = [COMMA, ENTER]; public tagsAvailable: Tag[] = []; public total = 0; public typesTranslationMap = new Map(); @@ -288,15 +279,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.changeDetectorRef.markForCheck(); }); - this.filteredTagsObservable = this.activityForm.controls[ - 'tags' - ].valueChanges.pipe( - startWith(this.activityForm.get('tags').value), - map((aTags: Tag[] | null) => { - return aTags ? this.filterTags(aTags) : this.tagsAvailable.slice(); - }) - ); - this.activityForm .get('type') .valueChanges.pipe(takeUntil(this.unsubscribeSubject)) @@ -444,29 +426,10 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { return isAfter(aDate, new Date(0)); } - public onAddTag(event: MatAutocompleteSelectedEvent) { - this.activityForm.get('tags').setValue([ - ...(this.activityForm.get('tags').value ?? []), - this.tagsAvailable.find(({ id }) => { - return id === event.option.value; - }) - ]); - - this.tagInput.nativeElement.value = ''; - } - public onCancel() { this.dialogRef.close(); } - public onRemoveTag(aTag: Tag) { - this.activityForm.get('tags').setValue( - this.activityForm.get('tags').value.filter(({ id }) => { - return id !== aTag.id; - }) - ); - } - public async onSubmit() { const activity: CreateOrderDto | UpdateOrderDto = { accountId: this.activityForm.get('accountId').value, @@ -522,21 +485,15 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { } } + public onTagsChanged(tags: Tag[]) { + this.activityForm.get('tags').setValue(tags); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } - private filterTags(aTags: Tag[]) { - const tagIds = aTags.map(({ id }) => { - return id; - }); - - return this.tagsAvailable.filter(({ id }) => { - return !tagIds.includes(id); - }); - } - private updateSymbol() { this.isLoading = true; this.changeDetectorRef.markForCheck(); diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html index a838eefe0..ec6c66358 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -390,38 +390,11 @@
- - Tags - - @for (tag of activityForm.get('tags')?.value; track tag.id) { - - {{ tag.name }} - - - } - - - - @for (tag of filteredTagsObservable | async; track tag.id) { - - {{ tag.name }} - - } - - +
diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts index a4d28d0e0..8fb2c1bed 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts @@ -1,14 +1,13 @@ import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; +import { GfTagsSelectorComponent } from '@ghostfolio/ui/tags-selector'; import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatChipsModule } from '@angular/material/chips'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -24,11 +23,10 @@ import { CreateOrUpdateActivityDialog } from './create-or-update-activity-dialog FormsModule, GfAssetProfileIconComponent, GfSymbolAutocompleteComponent, + GfTagsSelectorComponent, GfValueComponent, - MatAutocompleteModule, MatButtonModule, MatCheckboxModule, - MatChipsModule, MatDatepickerModule, MatDialogModule, MatFormFieldModule, diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts index 2f5ead47a..82e78a180 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -23,6 +23,7 @@ import { MatStepper } from '@angular/material/stepper'; import { MatTableDataSource } from '@angular/material/table'; import { AssetClass } from '@prisma/client'; import { isArray, sortBy } from 'lodash'; +import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; @@ -133,7 +134,7 @@ export class ImportActivitiesDialog implements OnDestroy { '✅ ' + $localize`Import has been completed`, undefined, { - duration: 3000 + duration: ms('3 seconds') } ); } catch (error) { @@ -142,7 +143,9 @@ export class ImportActivitiesDialog implements OnDestroy { ' ' + $localize`Please try again later.`, $localize`Okay`, - { duration: 3000 } + { + duration: ms('3 seconds') + } ); } finally { this.dialogRef.close(); diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index f52e7d558..4aee9965a 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -20,6 +20,7 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { MatSnackBar } from '@angular/material/snack-bar'; import { SymbolProfile } from '@prisma/client'; import { isNumber, sortBy } from 'lodash'; +import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -176,17 +177,27 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { } public onCopyPromptToClipboard() { - this.dataService.fetchPrompt().subscribe(({ prompt }) => { - this.clipboard.copy(prompt); - - this.snackBar.open( - '✅ ' + $localize`AI prompt has been copied to the clipboard`, - undefined, - { - duration: 3000 - } - ); - }); + this.dataService + .fetchPrompt() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ prompt }) => { + this.clipboard.copy(prompt); + + const snackBarRef = this.snackBar.open( + '✅ ' + $localize`AI prompt has been copied to the clipboard`, + $localize`Open Duck.ai` + ' →', + { + duration: ms('7 seconds') + } + ); + + snackBarRef + .onAction() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + window.open('https://duck.ai', '_blank'); + }); + }); } public ngOnDestroy() { diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html index ceba5f52c..6ec5722b7 100644 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html +++ b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html @@ -144,6 +144,30 @@ (rulesUpdated)="onRulesUpdated($event)" />
+
+

+ Regional Market Cluster Risks + @if (user?.subscription?.type === 'Basic') { + + } +

+ +
apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -883,7 +883,7 @@ Realment vol revocar aquest accés? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -1455,7 +1455,7 @@ Cancel·lar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1483,7 +1483,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1499,7 +1499,7 @@ Guardar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1527,7 +1527,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1755,7 +1755,7 @@ El preu de mercat actual és apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -1827,7 +1827,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1847,7 +1847,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1875,7 +1875,7 @@ Configuració del Proveïdor de Dades apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -1883,7 +1883,7 @@ Prova apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -1891,7 +1891,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1907,7 +1911,7 @@ Notes apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2214,16 +2218,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -2515,7 +2515,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -2623,7 +2623,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -2639,7 +2639,7 @@ Informar d’un Problema amb les Dades apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -3319,7 +3319,7 @@ Please enter your coupon code. apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -3327,7 +3327,7 @@ Could not redeem coupon code apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -3335,7 +3335,7 @@ Coupon code has been redeemed apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -3343,7 +3343,7 @@ Reload apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -3379,7 +3379,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3387,7 +3387,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -3395,7 +3395,7 @@ Do you really want to remove this sign in method? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -3403,7 +3403,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -3457,6 +3457,10 @@ Locale Locale + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -3583,7 +3587,7 @@ This feature is currently unavailable. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -3591,15 +3595,15 @@ Please try again later. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -3607,7 +3611,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -3615,11 +3619,11 @@ Oops! Something went wrong. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -3627,15 +3631,15 @@ Okay apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -3643,7 +3647,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -4747,7 +4751,7 @@ Import Activities apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -4755,7 +4759,7 @@ Import Dividends apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -4763,7 +4767,7 @@ Importing data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -4771,7 +4775,7 @@ Import has been completed apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -4779,7 +4783,7 @@ Validating data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -5071,7 +5075,7 @@ Dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -5083,11 +5087,11 @@ Investment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5099,7 +5103,7 @@ Monthly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -5107,7 +5111,7 @@ Yearly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -7027,7 +7031,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,16 +7099,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,7 +7657,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 343ae2f53..0040f8cb6 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -74,7 +74,7 @@ Möchtest du diese Zugangsberechtigung wirklich widerrufen? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -498,7 +498,7 @@ Abbrechen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -526,7 +526,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -542,7 +542,7 @@ Speichern apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -570,7 +570,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1054,7 +1054,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -1322,7 +1322,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1342,7 +1342,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1357,16 +1357,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1374,7 +1370,7 @@ Datenfehler melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -1478,15 +1474,15 @@ Okay apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -1662,7 +1658,7 @@ Bitte gebe deinen Gutscheincode ein. apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -1670,7 +1666,7 @@ Gutscheincode konnte nicht eingelöst werden apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -1678,7 +1674,7 @@ Gutscheincode wurde eingelöst apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -1686,7 +1682,7 @@ Neu laden apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -1694,7 +1690,7 @@ Möchtest du diese Anmeldemethode wirklich löschen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -1768,6 +1764,10 @@ Locale Lokalität + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -2322,7 +2322,7 @@ Kommentar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2378,7 +2378,7 @@ Daten importieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -2386,7 +2386,7 @@ Der Import wurde abgeschlossen apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -2530,7 +2530,7 @@ Aktivitäten importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -2642,7 +2642,7 @@ Diese Funktion ist derzeit nicht verfügbar. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -2650,15 +2650,15 @@ Bitte versuche es später noch einmal. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -2666,11 +2666,11 @@ Ups! Es ist etwas schief gelaufen. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -2806,7 +2806,7 @@ Monatlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -2950,7 +2950,7 @@ Automatisch apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3326,7 +3326,7 @@ Dividenden apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -3354,7 +3354,7 @@ Daten validieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -3434,7 +3434,7 @@ Jährlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -3442,7 +3442,7 @@ Dividenden importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3770,7 +3770,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -3986,7 +3986,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -4374,7 +4378,7 @@ Scraper Konfiguration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -5505,11 +5509,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -6231,7 +6235,7 @@ Der aktuelle Marktpreis ist apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6239,7 +6243,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6315,11 +6319,11 @@ Einlage apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6539,7 +6543,7 @@ Ups! Es sieht so aus, als würdest du zu viele Anfragen senden. Bitte geh es ein bisschen langsamer an. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6603,7 +6607,7 @@ Diese Aktion ist nicht zulässig. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6651,7 +6655,7 @@ Möchtest du dieses Ghostfolio Konto wirklich schliessen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6699,7 +6703,7 @@ Ups! Beim Einrichten der biometrischen Authentifizierung ist ein Fehler aufgetreten. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7027,7 +7031,7 @@ Fehler apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Inaktiv apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,7 +7099,7 @@ - Change with currency effect Change + Change with currency effect Change Änderung mit Währungseffekt Änderung apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -7103,7 +7107,7 @@ - Performance with currency effect Performance + Performance with currency effect Performance Performance mit Währungseffekt Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Erhalte Zugang zu 100’000+ Tickern von über 50 Handelsplätzen + + Get access to 80’000+ tickers from over 50 exchanges + Erhalte Zugang zu 80’000+ Tickern von über 50 Handelsplätzen libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ API-Schlüssel konnte nicht erstellt werden apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Setze diesen API-Schlüssel in deiner selbst gehosteten Umgebung: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ API-Schlüssel für den Ghostfolio Premium Datenanbieter apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Möchtest du wirklich einen neuen API-Schlüssel erstellen? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ KI-Anweisung wurde in die Zwischenablage kopiert apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,17 +7657,105 @@ Link wurde in die Zwischenablage kopiert apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 Early Access - Early Access + Early Access apps/client/src/app/components/admin-settings/admin-settings.component.html 16 + + Regional Market Cluster Risks + Regionale Marktklumpenrisiken + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Verzögert + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Sofort + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Standardmarktpreis + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Modus + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selektor + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request-Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + Tagesende + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + in Echtzeit + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Öffne Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Erstelle + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index f3ea374e3..bc6a62411 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -75,7 +75,7 @@ ¿Quieres revocar el acceso concedido? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -499,7 +499,7 @@ Cancela apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -527,7 +527,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -543,7 +543,7 @@ Guarda apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -571,7 +571,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1055,7 +1055,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -1323,7 +1323,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1343,7 +1343,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1358,16 +1358,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1375,7 +1371,7 @@ Reporta un anomalía de los datos apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -1479,15 +1475,15 @@ De acuerdo apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -1663,7 +1659,7 @@ Por favor, ingresa tu código de cupón: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -1671,7 +1667,7 @@ No se puede canjear este código de cupón apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -1679,7 +1675,7 @@ El codigo de cupón ha sido canjeado apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -1687,7 +1683,7 @@ Refrescar apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -1695,7 +1691,7 @@ ¿Estás seguro de eliminar este método de acceso? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -1769,6 +1765,10 @@ Locale Ubicación + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -2323,7 +2323,7 @@ Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2379,7 +2379,7 @@ Importando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -2387,7 +2387,7 @@ La importación se ha completado apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -2531,7 +2531,7 @@ Importar operaciones apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -2643,7 +2643,7 @@ Esta funcionalidad no está disponible actualmente. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -2651,11 +2651,11 @@ Vaya! Algo no funcionó bien. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -2663,15 +2663,15 @@ Por favor, prueba más tarde. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -2835,7 +2835,7 @@ Mensual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -2951,7 +2951,7 @@ Automático apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3319,7 +3319,7 @@ Dividendo apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -3355,7 +3355,7 @@ Validando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -3435,7 +3435,7 @@ Anual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -3443,7 +3443,7 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3771,7 +3771,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -3987,7 +3987,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -4375,7 +4379,7 @@ Scraper Configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -5506,11 +5510,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -6232,7 +6236,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6240,7 +6244,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6316,11 +6320,11 @@ Inversión apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6540,7 +6544,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6604,7 +6608,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6652,7 +6656,7 @@ ¿Estás seguro de querer borrar tu cuenta de Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6700,7 +6704,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7028,7 +7032,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7052,7 +7056,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7096,16 +7100,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7351,9 +7355,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7526,7 +7530,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7534,7 +7538,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7542,7 +7546,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7550,7 +7554,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7638,7 +7642,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7654,7 +7658,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7665,6 +7669,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index c2ea4d6f7..353a2a3f6 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -70,7 +70,7 @@ Voulez-vous vraiment révoquer cet accès ? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -558,7 +558,7 @@ Annuler apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -586,7 +586,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -602,7 +602,7 @@ Sauvegarder apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -630,7 +630,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -826,7 +826,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -846,7 +846,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -866,7 +866,7 @@ Note apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -969,16 +969,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1374,7 +1370,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -1722,7 +1718,7 @@ Signaler une Erreur de Données apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -1790,7 +1786,7 @@ Cette fonctionnalité est momentanément indisponible. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -1798,15 +1794,15 @@ Veuillez réessayer plus tard. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -1814,11 +1810,11 @@ Oups! Quelque chose s’est mal passé. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -1826,15 +1822,15 @@ D’accord apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -1914,7 +1910,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -1922,7 +1918,7 @@ Veuillez entrer votre code promotionnel : apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -1930,7 +1926,7 @@ Le code promotionnel n’a pas pu être appliqué apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -1938,7 +1934,7 @@ Le code promotionnel a été appliqué apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -1946,7 +1942,7 @@ Rafraîchir apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -1954,7 +1950,7 @@ Voulez-vous vraiment supprimer cette méthode de connexion ? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -2088,6 +2084,10 @@ Locale Paramètres régionaux + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -2546,7 +2546,7 @@ Import des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -2554,7 +2554,7 @@ L’import est terminé apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -2562,7 +2562,7 @@ Validation des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -2750,7 +2750,7 @@ Dividende apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -2770,7 +2770,7 @@ Mensuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -3050,7 +3050,7 @@ Importer Activités apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -3434,7 +3434,7 @@ Annuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -3442,7 +3442,7 @@ Importer Dividendes apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3770,7 +3770,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -3986,7 +3986,11 @@ Lien apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -4374,7 +4378,7 @@ Configuration du Scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -5505,11 +5509,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -6231,7 +6235,7 @@ Le prix actuel du marché est apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6239,7 +6243,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6315,11 +6319,11 @@ Investissement apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6539,7 +6543,7 @@ Oops! Il semble que vous fassiez trop de requêtes. Veuillez ralentir un peu. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6603,7 +6607,7 @@ Cette action n'est pas autorisée. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6651,7 +6655,7 @@ Confirmer la suppresion de votre compte Ghostfolio ? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6699,7 +6703,7 @@ Oops! Une erreur s'est produite lors de la configuration de l'authentification biométrique. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7027,7 +7031,7 @@ Erreur apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Inactif apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,16 +7099,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,7 +7657,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 3000c791a..b31996ab7 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -75,7 +75,7 @@ Vuoi davvero revocare l’accesso concesso? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -499,7 +499,7 @@ Annulla apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -527,7 +527,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -543,7 +543,7 @@ Salva apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -571,7 +571,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1055,7 +1055,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -1323,7 +1323,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1343,7 +1343,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1358,16 +1358,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1375,7 +1371,7 @@ Segnala un’anomalia dei dati apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -1479,15 +1475,15 @@ Bene apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -1663,7 +1659,7 @@ Inserisci il tuo codice del buono: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -1671,7 +1667,7 @@ Impossibile riscattare il codice del buono apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -1679,7 +1675,7 @@ Il codice del buono è stato riscattato apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -1687,7 +1683,7 @@ Ricarica apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -1695,7 +1691,7 @@ Vuoi davvero rimuovere questo metodo di accesso? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -1769,6 +1765,10 @@ Locale Locale + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -2323,7 +2323,7 @@ Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2379,7 +2379,7 @@ Importazione dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -2387,7 +2387,7 @@ L’importazione è stata completata apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -2531,7 +2531,7 @@ Importa le attività apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -2643,7 +2643,7 @@ Questa funzionalità non è attualmente disponibile. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -2651,11 +2651,11 @@ Ops! Qualcosa è andato storto. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -2663,15 +2663,15 @@ Riprova più tardi. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -2835,7 +2835,7 @@ Mensile apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -2951,7 +2951,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3319,7 +3319,7 @@ Dividendi apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -3355,7 +3355,7 @@ Convalida dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -3435,7 +3435,7 @@ Annuale apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -3443,7 +3443,7 @@ Importa i dividendi apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3771,7 +3771,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -3987,7 +3987,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -4375,7 +4379,7 @@ Configurazione dello scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -5506,11 +5510,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -6232,7 +6236,7 @@ L'attuale prezzo di mercato è apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6240,7 +6244,7 @@ Prova apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6316,11 +6320,11 @@ Investimento apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6540,7 +6544,7 @@ Ops! Sembra tu stia facendo troppe richieste. Rallenta un po' per favore. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6604,7 +6608,7 @@ Questa azione non è permessa. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6652,7 +6656,7 @@ Confermi di voler chiudere il tuo account Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6700,7 +6704,7 @@ Ops! C'è stato un errore impostando l'autenticazione biometrica. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7028,7 +7032,7 @@ Errore apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7052,7 +7056,7 @@ Inattivo apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7096,7 +7100,7 @@ - Change with currency effect Change + Change with currency effect Change Cambio con effetto valuta Cambia apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -7104,7 +7108,7 @@ - Performance with currency effect Performance + Performance with currency effect Performance Prestazioni con effetto valuta Prestazioni apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -7351,9 +7355,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Ottieni accesso a oltre 100’000+ titoli da oltre 50 borse + + Get access to 80’000+ tickers from over 50 exchanges + Ottieni accesso a oltre 100’000+ titoli da oltre 50 borse libs/ui/src/lib/i18n.ts 24 @@ -7526,7 +7530,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7534,7 +7538,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7542,7 +7546,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7550,7 +7554,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7638,7 +7642,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7654,7 +7658,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7665,6 +7669,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + \ No newline at end of file diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 18cf83bb3..53efeab95 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -74,7 +74,7 @@ Wil je deze verleende toegang echt intrekken? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -498,7 +498,7 @@ Annuleren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -526,7 +526,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -542,7 +542,7 @@ Opslaan apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -570,7 +570,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1054,7 +1054,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -1322,7 +1322,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1342,7 +1342,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1357,16 +1357,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1374,7 +1370,7 @@ Gegevensstoring melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -1478,15 +1474,15 @@ Oké apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -1662,7 +1658,7 @@ Voer je couponcode in: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -1670,7 +1666,7 @@ Kon je kortingscode niet inwisselen apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -1678,7 +1674,7 @@ Je couponcode is ingewisseld apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -1686,7 +1682,7 @@ Herladen apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -1694,7 +1690,7 @@ Wil je deze aanmeldingsmethode echt verwijderen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -1768,6 +1764,10 @@ Locale Locatie + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -2322,7 +2322,7 @@ Opmerking apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2378,7 +2378,7 @@ Gegevens importeren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -2386,7 +2386,7 @@ Importeren is voltooid apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -2530,7 +2530,7 @@ Activiteiten importeren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -2642,7 +2642,7 @@ Deze functie is momenteel niet beschikbaar. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -2650,11 +2650,11 @@ Oeps! Er ging iets mis. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -2662,15 +2662,15 @@ Probeer het later nog eens. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -2834,7 +2834,7 @@ Maandelijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -2950,7 +2950,7 @@ Automatisch apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3318,7 +3318,7 @@ Dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -3354,7 +3354,7 @@ Gegevens valideren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -3434,7 +3434,7 @@ Jaarlijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -3442,7 +3442,7 @@ Importeer dividenden apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3770,7 +3770,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -3986,7 +3986,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -4374,7 +4378,7 @@ Scraper instellingen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -5505,11 +5509,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -6231,7 +6235,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6239,7 +6243,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6315,11 +6319,11 @@ Investment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6539,7 +6543,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6603,7 +6607,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6651,7 +6655,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6699,7 +6703,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7027,7 +7031,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,16 +7099,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,7 +7657,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 38b8fe231..2942a4898 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -276,11 +276,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -839,7 +839,7 @@ Czy na pewno chcesz cofnąć przyznany dostęp? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -1347,7 +1347,7 @@ Anuluj apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1375,7 +1375,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1391,7 +1391,7 @@ Zapisz apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1419,7 +1419,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1679,7 +1679,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1699,7 +1699,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1727,7 +1727,7 @@ Konfiguracja Scrapera apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -1735,7 +1735,7 @@ Notatka apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1963,7 +1963,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -2042,16 +2046,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -2319,7 +2319,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -2599,7 +2599,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -2803,7 +2803,7 @@ Zgłoś Błąd Danych apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -3043,7 +3043,7 @@ Wpisz kod kuponu: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -3051,7 +3051,7 @@ Nie udało się zrealizować kodu kuponu apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -3059,7 +3059,7 @@ Kupon został zrealizowany apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -3067,7 +3067,7 @@ Odśwież apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -3103,7 +3103,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3111,7 +3111,7 @@ Czy na pewno chcesz usunąć tą metode logowania? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -3157,6 +3157,10 @@ Locale Ustawienia Regionalne + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -3279,7 +3283,7 @@ Ta funkcja jest obecnie niedostępna. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -3287,15 +3291,15 @@ Spróbuj ponownie później. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -3303,11 +3307,11 @@ Ups! Coś poszło nie tak. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -3315,15 +3319,15 @@ Okej apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -4355,7 +4359,7 @@ Importuj Aktywności apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -4363,7 +4367,7 @@ Impotruj Dywidendy apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -4371,7 +4375,7 @@ Importowanie danych... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -4379,7 +4383,7 @@ Importowanie zakończone apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -4387,7 +4391,7 @@ Weryfikacja danych... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -4663,7 +4667,7 @@ Dywidenda apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -4683,7 +4687,7 @@ Miesięcznie apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -4691,7 +4695,7 @@ Rocznie apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -6231,7 +6235,7 @@ Obecna cena rynkowa wynosi apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6239,7 +6243,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6315,11 +6319,11 @@ Inwestycje apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6539,7 +6543,7 @@ Ups! Wygląda na to, że wykonujesz zbyt wiele zapytań. Proszę, zwolnij trochę. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6603,7 +6607,7 @@ To działanie jest niedozwolone. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6651,7 +6655,7 @@ Czy na pewno chcesz zamknąć swoje konto Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6699,7 +6703,7 @@ Ups! Wystąpił błąd podczas konfigurowania uwierzytelniania biometrycznego. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7027,7 +7031,7 @@ Błąd apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Nieaktywny apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,16 +7099,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Uzyskaj dostęp do ponad 100 000 pasków notowań giełdowych z ponad 50 giełd + + Get access to 80’000+ tickers from over 50 exchanges + Uzyskaj dostęp do ponad 100 000 pasków notowań giełdowych z ponad 50 giełd libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ Nie udało się wygenerować klucza API apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Ustaw ten klucz API w samodzielnie hostowanym środowisku: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ Klucz API dostawcy danych Premium Ghostfolio apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Czy na pewno chcesz wygenerować nowy klucz API? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,7 +7657,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 61ff18a29..8b9b7ac03 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -70,7 +70,7 @@ Pretende realmente revogar este acesso concedido? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -558,7 +558,7 @@ Cancelar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -586,7 +586,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -602,7 +602,7 @@ Guardar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -630,7 +630,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1242,7 +1242,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -1630,7 +1630,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1650,7 +1650,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1665,16 +1665,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1682,7 +1678,7 @@ Dados do Relatório com Problema apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -1774,7 +1770,7 @@ Esta funcionalidade está atualmente indisponível. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -1782,15 +1778,15 @@ Por favor tente novamente mais tarde. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -1798,11 +1794,11 @@ Oops! Ocorreu um erro. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -1810,15 +1806,15 @@ OK apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -1898,7 +1894,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -1906,7 +1902,7 @@ Por favor, insira o seu código de cupão: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -1914,7 +1910,7 @@ Não foi possível resgatar o código de cupão apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -1922,7 +1918,7 @@ Código de cupão foi resgatado apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -1930,7 +1926,7 @@ Atualizar apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -1938,7 +1934,7 @@ Deseja realmente remover este método de início de sessão? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -2032,6 +2028,10 @@ Locale Localidade + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -2458,7 +2458,7 @@ Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2474,7 +2474,7 @@ A importar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -2482,7 +2482,7 @@ A importação foi concluída apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -2654,7 +2654,7 @@ Mensalmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -2922,7 +2922,7 @@ Importar Atividades apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -3362,7 +3362,7 @@ A validar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -3386,7 +3386,7 @@ Dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -3434,7 +3434,7 @@ Anualmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -3442,7 +3442,7 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3770,7 +3770,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -3986,7 +3986,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -4374,7 +4378,7 @@ Scraper Configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -5505,11 +5509,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -6231,7 +6235,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6239,7 +6243,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6315,11 +6319,11 @@ Investment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6539,7 +6543,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6603,7 +6607,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6651,7 +6655,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6699,7 +6703,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7027,7 +7031,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,16 +7099,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,7 +7657,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index a598fd6d1..3c7d3f102 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -276,11 +276,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -815,7 +815,7 @@ Bu erişim iznini geri almayı gerçekten istiyor musunuz? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -1311,7 +1311,7 @@ İptal apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1339,7 +1339,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1355,7 +1355,7 @@ Kaydet apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1383,7 +1383,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1611,7 +1611,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1631,7 +1631,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1651,7 +1651,7 @@ Veri Toplayıcı Yapılandırması apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -1659,7 +1659,7 @@ Not apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1782,16 +1782,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -1875,7 +1871,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -2171,7 +2171,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -2639,7 +2639,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -2647,7 +2647,7 @@ Rapor Veri Sorunu apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -2863,7 +2863,7 @@ Bu özellik şu an için mevcut değil. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -2871,15 +2871,15 @@ Daha sonra tekrar deneyiniz. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -2887,11 +2887,11 @@ Hay Allah! Bir şeyler yanlış gitti. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -2899,15 +2899,15 @@ Tamam apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -3835,7 +3835,7 @@ İşlemleri İçe Aktar apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -3843,7 +3843,7 @@ Temettüleri İçe Aktar apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -3851,7 +3851,7 @@ Veri içe aktarılıyor... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -3859,7 +3859,7 @@ İçe aktarma tamamlandı apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -3867,7 +3867,7 @@ Veri doğrulanıyor... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -4151,7 +4151,7 @@ Temettü apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -4171,7 +4171,7 @@ Aylık apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -4179,7 +4179,7 @@ Yıllık apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -4939,7 +4939,7 @@ Otomatik apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -4947,7 +4947,7 @@ Lütfen kupon kodunuzu girin: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -4955,7 +4955,7 @@ Kupon kodu kullanılamadı apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -4963,7 +4963,7 @@ Kupon kodu kullanıldı apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -4971,7 +4971,7 @@ Yeniden Yükle apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -4979,7 +4979,7 @@ Bu giriş yöntemini kaldırmayı gerçekten istiyor musunuz? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -5065,6 +5065,10 @@ Locale Yerel Ayarlar + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -6231,7 +6235,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6239,7 +6243,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6315,11 +6319,11 @@ Investment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6539,7 +6543,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6603,7 +6607,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6651,7 +6655,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6699,7 +6703,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7027,7 +7031,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7051,7 +7055,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7095,16 +7099,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7350,9 +7354,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7525,7 +7529,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7533,7 +7537,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7541,7 +7545,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7549,7 +7553,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7637,7 +7641,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7653,7 +7657,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index cb2cbb57d..26690077b 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -653,11 +653,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -891,7 +891,7 @@ Посилання скопійовано в буфер обміну apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -899,7 +899,7 @@ Ви дійсно хочете відкликати цей наданий доступ? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -1659,7 +1659,7 @@ Помилка apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -1667,7 +1667,7 @@ Поточна ринкова ціна apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -1723,7 +1723,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1743,7 +1743,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1771,7 +1771,7 @@ Конфігурація скребка apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -1779,7 +1779,7 @@ Тест apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -1787,7 +1787,11 @@ URL apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1803,7 +1807,7 @@ Примітка apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1819,7 +1823,7 @@ Скасувати apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1847,7 +1851,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1863,7 +1867,7 @@ Зберегти apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1891,7 +1895,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -2254,16 +2258,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -2635,20 +2635,20 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 - Change with currency effect Change - Зміна з урахуванням валютного ефекту Зміна + Change with currency effect Change + Зміна з урахуванням валютного ефекту Зміна apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Прибутковість з урахуванням валютного ефекту валюти Прибутковість + Performance with currency effect Performance + Прибутковість з урахуванням валютного ефекту валюти Прибутковість apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -2751,7 +2751,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -2767,7 +2767,7 @@ Повідомити про збій даних apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -3511,7 +3511,7 @@ Не вдалося згенерувати ключ API apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -3519,15 +3519,15 @@ ОК apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -3535,7 +3535,7 @@ Встановіть цей ключ API у вашому self-hosted середовищі: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -3543,7 +3543,7 @@ Ключ API Ghostfolio Premium Data Provider apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -3551,7 +3551,7 @@ Ви дійсно хочете згенерувати новий ключ API? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -3559,7 +3559,7 @@ Не вдалося обміняти код купона apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -3567,7 +3567,7 @@ Код купона був обміняний apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -3575,7 +3575,7 @@ Перезавантажити apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -3583,7 +3583,7 @@ Будь ласка, введіть ваш код купона. apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -3627,7 +3627,7 @@ Автоматичний apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3635,7 +3635,7 @@ Ви дійсно хочете закрити ваш обліковий запис Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -3643,7 +3643,7 @@ Ви дійсно хочете вилучити цей спосіб входу? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -3651,7 +3651,7 @@ Упс! Виникла помилка під час налаштування біометричної автентифікації. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -3705,6 +3705,10 @@ Locale Локалізація + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -3831,7 +3835,7 @@ Ця функція наразі недоступна. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -3839,15 +3843,15 @@ Спробуйте ще раз пізніше. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -3855,7 +3859,7 @@ Ця дія заборонена. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -3863,11 +3867,11 @@ Упс! Щось пішло не так. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -3875,7 +3879,7 @@ Упс! Здається, ви робите занадто багато запитів. Будь ласка, пригальмуй трохи. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -5007,7 +5011,7 @@ Імпортувати активності apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -5015,7 +5019,7 @@ Імпорт дивідендів apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -5023,7 +5027,7 @@ Імпортуються дані... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -5031,7 +5035,7 @@ Імпорт завершено apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -5039,7 +5043,7 @@ Перевірка даних... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -5347,7 +5351,7 @@ Дивіденди apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -5359,11 +5363,11 @@ Інвестиції apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5375,7 +5379,7 @@ Щомісячно apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -5383,7 +5387,7 @@ Щорічно apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -5591,7 +5595,7 @@ Неактивний apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7132,9 +7136,9 @@ 402 - - Get access to 100’000+ tickers from over 50 exchanges - Отримайте доступ до 100 000+ тікерів з понад 50 бірж + + Get access to 80’000+ tickers from over 50 exchanges + Отримайте доступ до 100 000+ тікерів з понад 50 бірж libs/ui/src/lib/i18n.ts 24 @@ -7645,7 +7649,7 @@ Запит AI скопійовано в буфер обміну apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7664,6 +7668,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 0b7afdfa9..ac05bc01a 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -271,11 +271,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -810,7 +810,7 @@ Do you really want to revoke this granted access? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -1297,7 +1297,7 @@ Cancel apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1325,7 +1325,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1340,7 +1340,7 @@ Save apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1368,7 +1368,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1606,7 +1606,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1625,7 +1625,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1650,14 +1650,14 @@ Scraper Configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 Note apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1866,7 +1866,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1939,16 +1943,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -2188,7 +2188,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -2440,7 +2440,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -2623,7 +2623,7 @@ Report Data Glitch apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -2843,28 +2843,28 @@ Please enter your coupon code. apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 Could not redeem coupon code apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 Coupon code has been redeemed apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 Reload apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -2896,14 +2896,14 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 Do you really want to remove this sign in method? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -2943,6 +2943,10 @@ Locale + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -3051,48 +3055,48 @@ This feature is currently unavailable. apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 Please try again later. apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 Oops! Something went wrong. apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 Okay apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -4015,35 +4019,35 @@ Import Activities apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 Import Dividends apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 Importing data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 Import has been completed apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 Validating data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -4290,7 +4294,7 @@ Dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -4308,14 +4312,14 @@ Monthly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 Yearly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -5679,14 +5683,14 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -5768,11 +5772,11 @@ Investment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5946,7 +5950,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -5995,7 +5999,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6051,7 +6055,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6086,7 +6090,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -6373,7 +6377,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -6394,7 +6398,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -6447,7 +6451,7 @@ - Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -6461,7 +6465,7 @@ - Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 @@ -6656,8 +6660,8 @@ 70 - - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -6832,28 +6836,28 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -6916,14 +6920,14 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -6933,6 +6937,83 @@ 16 + + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index 9aaa47267..680906979 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -277,11 +277,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 43 + 39 apps/client/src/app/core/http-response.interceptor.ts - 72 + 77 apps/client/src/app/core/paths.ts @@ -840,7 +840,7 @@ 您真的要撤销此授予的访问权限吗? apps/client/src/app/components/access-table/access-table.component.ts - 78 + 79 @@ -1356,7 +1356,7 @@ 取消 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 357 + 432 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1384,7 +1384,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 427 + 400 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1400,7 +1400,7 @@ 保存 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 364 + 439 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1428,7 +1428,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 434 + 407 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1688,7 +1688,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 308 + 383 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1708,7 +1708,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 319 + 394 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1736,7 +1736,7 @@ 刮削配置 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 283 + 295 @@ -1744,7 +1744,7 @@ 笔记 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 344 + 419 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1980,7 +1980,11 @@ 网址 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 331 + 354 + + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 406 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -2059,16 +2063,12 @@ 87 - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 377 - - - apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 414 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 4 - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 383 + libs/ui/src/lib/tags-selector/tags-selector.component.html + 16 @@ -2336,7 +2336,7 @@ apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 159 + 160 @@ -2616,7 +2616,7 @@ apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 154 + 178 @@ -2820,7 +2820,7 @@ 报告数据故障 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 433 + 385 @@ -3060,7 +3060,7 @@ 请输入您的优惠券代码: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 213 + 208 @@ -3068,7 +3068,7 @@ 无法兑换优惠券代码 apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 177 + 172 @@ -3076,7 +3076,7 @@ 优惠券代码已兑换 apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 190 + 185 @@ -3084,7 +3084,7 @@ 重新加载 apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 191 + 186 @@ -3120,7 +3120,7 @@ 自动 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 39 + 40 @@ -3128,7 +3128,7 @@ 您确实要删除此登录方法吗? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 248 + 249 @@ -3174,6 +3174,10 @@ Locale 语言环境 + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 322 + apps/client/src/app/components/user-account-settings/user-account-settings.html 127 @@ -3296,7 +3300,7 @@ 此功能目前无法使用。 apps/client/src/app/core/http-response.interceptor.ts - 53 + 54 @@ -3304,15 +3308,15 @@ 请稍后再试。 apps/client/src/app/core/http-response.interceptor.ts - 55 + 56 apps/client/src/app/core/http-response.interceptor.ts - 80 + 85 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 143 + 144 @@ -3320,11 +3324,11 @@ 哎呀!出了些问题。 apps/client/src/app/core/http-response.interceptor.ts - 78 + 83 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 141 + 142 @@ -3332,15 +3336,15 @@ 好的 apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 152 + 147 apps/client/src/app/core/http-response.interceptor.ts - 81 + 86 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 144 + 145 @@ -4372,7 +4376,7 @@ 导入活动 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 46 + 47 @@ -4380,7 +4384,7 @@ 导入股息 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 87 + 88 @@ -4388,7 +4392,7 @@ 正在导入数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 125 + 126 @@ -4396,7 +4400,7 @@ 导入已完成 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 133 + 134 @@ -4404,7 +4408,7 @@ 验证数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 239 + 242 @@ -4680,7 +4684,7 @@ 股息 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 41 + 42 libs/ui/src/lib/i18n.ts @@ -4700,7 +4704,7 @@ 每月 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 54 + 55 @@ -4708,7 +4712,7 @@ 每年 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 55 + 56 @@ -6240,7 +6244,7 @@ 当前市场价格为 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 326 + 399 @@ -6248,7 +6252,7 @@ 测试 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 301 + 372 @@ -6340,11 +6344,11 @@ 投资 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 46 + 47 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 60 + 61 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6540,7 +6544,7 @@ 哎呀!看来您提出了太多要求。请慢一点。 apps/client/src/app/core/http-response.interceptor.ts - 96 + 103 @@ -6604,7 +6608,7 @@ This action is not allowed. apps/client/src/app/core/http-response.interceptor.ts - 61 + 64 @@ -6652,7 +6656,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 174 + 175 @@ -6700,7 +6704,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 302 + 303 @@ -7028,7 +7032,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 317 + 390 @@ -7052,7 +7056,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 173 + 197 @@ -7096,16 +7100,16 @@ - Change with currency effect Change - Change with currency effect Change + Change with currency effect Change + Change with currency effect Change apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 50 - Performance with currency effect Performance - Performance with currency effect Performance + Performance with currency effect Performance + Performance with currency effect Performance apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html 69 @@ -7351,9 +7355,9 @@ 23 - - Get access to 100’000+ tickers from over 50 exchanges - Get access to 100’000+ tickers from over 50 exchanges + + Get access to 80’000+ tickers from over 50 exchanges + Get access to 80’000+ tickers from over 50 exchanges libs/ui/src/lib/i18n.ts 24 @@ -7526,7 +7530,7 @@ Could not generate an API key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 139 + 134 @@ -7534,7 +7538,7 @@ Set this API key in your self-hosted environment: apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 154 + 149 @@ -7542,7 +7546,7 @@ Ghostfolio Premium Data Provider API Key apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 157 + 152 @@ -7550,7 +7554,7 @@ Do you really want to generate a new API key? apps/client/src/app/components/user-account-membership/user-account-membership.component.ts - 162 + 157 @@ -7638,7 +7642,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 149 + 153 @@ -7654,7 +7658,7 @@ Link has been copied to the clipboard apps/client/src/app/components/access-table/access-table.component.ts - 64 + 65 @@ -7665,6 +7669,94 @@ 16 + + Regional Market Cluster Risks + Regional Market Cluster Risks + + apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html + 154 + + + + Lazy + Lazy + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + Instant + Instant + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Default Market Price + Default Market Price + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 300 + + + + Mode + Mode + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 328 + + + + Selector + Selector + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 341 + + + + HTTP Request Headers + HTTP Request Headers + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html + 310 + + + + end of day + end of day + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 93 + + + + real-time + real-time + + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts + 97 + + + + Open Duck.ai + Open Duck.ai + + apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts + 154 + + + + Create + Create + + libs/ui/src/lib/tags-selector/tags-selector.component.html + 50 + + diff --git a/libs/common/src/lib/helper.spec.ts b/libs/common/src/lib/helper.spec.ts index 1126c3573..25779cf39 100644 --- a/libs/common/src/lib/helper.spec.ts +++ b/libs/common/src/lib/helper.spec.ts @@ -1,4 +1,7 @@ -import { extractNumberFromString } from '@ghostfolio/common/helper'; +import { + extractNumberFromString, + getNumberFormatGroup +} from '@ghostfolio/common/helper'; describe('Helper', () => { describe('Extract number from string', () => { @@ -32,8 +35,85 @@ describe('Helper', () => { ).toEqual(99999.99); }); + it('Get decimal number (comma notation) for locale where currency is not grouped by default', () => { + expect( + extractNumberFromString({ locale: 'es-ES', value: '999,99' }) + ).toEqual(999.99); + }); + it('Not a number', () => { expect(extractNumberFromString({ value: 'X' })).toEqual(NaN); }); }); + + describe('Get number format group', () => { + let languageGetter: jest.SpyInstance; + + beforeEach(() => { + languageGetter = jest.spyOn(window.navigator, 'language', 'get'); + }); + + it('Get de-CH number format group', () => { + expect(getNumberFormatGroup('de-CH')).toEqual('’'); + }); + + it('Get de-CH number format group when it is default', () => { + languageGetter.mockReturnValue('de-CH'); + expect(getNumberFormatGroup()).toEqual('’'); + }); + + it('Get de-DE number format group', () => { + expect(getNumberFormatGroup('de-DE')).toEqual('.'); + }); + + it('Get de-DE number format group when it is default', () => { + languageGetter.mockReturnValue('de-DE'); + expect(getNumberFormatGroup()).toEqual('.'); + }); + + it('Get en-GB number format group', () => { + expect(getNumberFormatGroup('en-GB')).toEqual(','); + }); + + it('Get en-GB number format group when it is default', () => { + languageGetter.mockReturnValue('en-GB'); + expect(getNumberFormatGroup()).toEqual(','); + }); + + it('Get en-US number format group', () => { + expect(getNumberFormatGroup('en-US')).toEqual(','); + }); + + it('Get en-US number format group when it is default', () => { + languageGetter.mockReturnValue('en-US'); + expect(getNumberFormatGroup()).toEqual(','); + }); + + it('Get es-ES number format group', () => { + expect(getNumberFormatGroup('es-ES')).toEqual('.'); + }); + + it('Get es-ES number format group when it is default', () => { + languageGetter.mockReturnValue('es-ES'); + expect(getNumberFormatGroup()).toEqual('.'); + }); + + it('Get ru-RU number format group', () => { + expect(getNumberFormatGroup('ru-RU')).toEqual(' '); + }); + + it('Get ru-RU number format group when it is default', () => { + languageGetter.mockReturnValue('ru-RU'); + expect(getNumberFormatGroup()).toEqual(' '); + }); + + it('Get zh-CN number format group', () => { + expect(getNumberFormatGroup('zh-CN')).toEqual(','); + }); + + it('Get zh-CN number format group when it is default', () => { + languageGetter.mockReturnValue('zh-CN'); + expect(getNumberFormatGroup()).toEqual(','); + }); + }); }); diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index dd07c23fa..bd0c74189 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -251,7 +251,9 @@ export function getNumberFormatDecimal(aLocale?: string) { } export function getNumberFormatGroup(aLocale = getLocale()) { - const formatObject = new Intl.NumberFormat(aLocale).formatToParts(9999.99); + const formatObject = new Intl.NumberFormat(aLocale, { + useGrouping: true + }).formatToParts(9999.99); return formatObject.find((object) => { return object.type === 'group'; diff --git a/libs/common/src/lib/interfaces/holding.interface.ts b/libs/common/src/lib/interfaces/holding.interface.ts index 5a0df62f6..e963bc5a7 100644 --- a/libs/common/src/lib/interfaces/holding.interface.ts +++ b/libs/common/src/lib/interfaces/holding.interface.ts @@ -1,5 +1,5 @@ export interface Holding { - allocationInPercentage?: number; + allocationInPercentage: number; name: string; valueInBaseCurrency: number; } diff --git a/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts b/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts index 858ffa31b..4a31ef7b2 100644 --- a/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts +++ b/libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts @@ -9,6 +9,9 @@ export interface XRayRulesSettings { EconomicMarketClusterRiskEmergingMarkets?: RuleSettings; EmergencyFundSetup?: RuleSettings; FeeRatioInitialInvestment?: RuleSettings; + RegionalMarketClusterRiskEmergingMarkets?: RuleSettings; + RegionalMarketClusterRiskEurope?: RuleSettings; + RegionalMarketClusterRiskNorthAmerica?: RuleSettings; } interface RuleSettings { diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index 63d5805cd..e4c820fb7 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -202,6 +202,16 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$100', slogan: 'All your wealth, in one place.' }, + { + founded: 2018, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'fey', + name: 'Fey', + origin: 'Canada', + pricingPerYear: '$300', + slogan: 'Make better investments.' + }, { founded: 2023, hasFreePlan: true, diff --git a/libs/ui/.storybook/preview.js b/libs/ui/.storybook/preview.js index 37eb3a59d..e69de29bb 100644 --- a/libs/ui/.storybook/preview.js +++ b/libs/ui/.storybook/preview.js @@ -1 +0,0 @@ -// import '!style-loader!css-loader!sass-loader!../../../apps/client/src/styles.scss'; diff --git a/libs/ui/project.json b/libs/ui/project.json index 58e959344..1b3f0e4e7 100644 --- a/libs/ui/project.json +++ b/libs/ui/project.json @@ -44,7 +44,12 @@ "outputDir": "dist/storybook/ui", "configDir": "libs/ui/.storybook", "browserTarget": "ui:build-storybook", - "compodoc": false + "compodoc": false, + "styles": [ + "apps/client/src/assets/fonts/inter.css", + "apps/client/src/styles/theme.scss", + "apps/client/src/styles.scss" + ] }, "configurations": { "ci": { diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts index caa0b15e6..7fbb1e621 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor.component.ts @@ -261,7 +261,9 @@ export class GfHistoricalMarketDataEditorComponent this.snackBar.open( $localize`Oops! Could not parse historical data.`, undefined, - { duration: ms('3 seconds') } + { + duration: ms('3 seconds') + } ); } } diff --git a/libs/ui/src/lib/i18n.ts b/libs/ui/src/lib/i18n.ts index 81b5b9216..2af142ac4 100644 --- a/libs/ui/src/lib/i18n.ts +++ b/libs/ui/src/lib/i18n.ts @@ -21,7 +21,7 @@ const locales = { MONTH: $localize`Month`, MONTHS: $localize`Months`, OTHER: $localize`Other`, - PROFESSIONAL_DATA_PROVIDER_TOOLTIP_PREMIUM: $localize`Get access to 100’000+ tickers from over 50 exchanges`, + PROFESSIONAL_DATA_PROVIDER_TOOLTIP_PREMIUM: $localize`Get access to 80’000+ tickers from over 50 exchanges`, PRESET_ID: $localize`Preset`, RETIREMENT_PROVISION: $localize`Retirement Provision`, SATELLITE: $localize`Satellite`, diff --git a/libs/ui/src/lib/logo/logo.component.stories.ts b/libs/ui/src/lib/logo/logo.component.stories.ts index c720ebd92..50f047184 100644 --- a/libs/ui/src/lib/logo/logo.component.stories.ts +++ b/libs/ui/src/lib/logo/logo.component.stories.ts @@ -25,7 +25,7 @@ export const Large: Story = { } }; -export const NoLabel: Story = { +export const WithoutLabel: Story = { args: { showLabel: false } diff --git a/libs/ui/src/lib/tags-selector/index.ts b/libs/ui/src/lib/tags-selector/index.ts new file mode 100644 index 000000000..360bce671 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/index.ts @@ -0,0 +1 @@ +export * from './tags-selector.component'; diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.html b/libs/ui/src/lib/tags-selector/tags-selector.component.html new file mode 100644 index 000000000..4f3929423 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -0,0 +1,60 @@ +
+
+ @if (readonly) { +
Tags
+ @if (tags?.length > 0) { + + @for (tag of tags; track tag) { + {{ tag.name }} + } + + } @else { +
-
+ } + } @else { + + Tags + + @for (tag of tagsSelected(); track tag.id) { + + {{ tag.name }} + + + } + + + + @for (tag of filteredOptions | async; track tag.id) { + + {{ tag.name }} + + } + + @if (hasPermissionToCreateTags && tagInputControl.value) { + + + + Create "{{ + tagInputControl.value.trim() + }}" + + + } + + + } +
+
diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.scss b/libs/ui/src/lib/tags-selector/tags-selector.component.scss new file mode 100644 index 000000000..5d4e87f30 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts b/libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts new file mode 100644 index 000000000..8d1431b46 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.stories.ts @@ -0,0 +1,95 @@ +import { CommonModule } from '@angular/common'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { Meta, moduleMetadata, StoryObj } from '@storybook/angular'; + +import { GfTagsSelectorComponent } from './tags-selector.component'; + +export default { + title: 'Tags Selector', + component: GfTagsSelectorComponent, + decorators: [ + moduleMetadata({ + imports: [CommonModule, NoopAnimationsModule] + }) + ] +} as Meta; + +type Story = StoryObj; + +const OPTIONS = [ + { + id: '3ef7e6d9-4598-4eb2-b0e8-00e61cfc0ea6', + name: 'Gambling', + userId: 'c6a71541-d0e3-4e22-ae83-b5e5611b6695' + }, + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + }, + { + id: 'RETIREMENT_FUND', + name: 'Retirement Fund', + userId: null + } +]; + +export const Default: Story = { + args: { + tags: [ + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + } + ], + tagsAvailable: OPTIONS + } +}; + +export const CreateCustomTags: Story = { + args: { + hasPermissionToCreateTags: true, + tags: [ + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + } + ], + tagsAvailable: OPTIONS + } +}; + +export const Readonly: Story = { + args: { + readonly: true, + tags: [ + { + id: 'EMERGENCY_FUND', + name: 'Emergency Fund', + userId: null + }, + { + id: 'RETIREMENT_FUND', + name: 'Retirement Fund', + userId: null + } + ], + tagsAvailable: OPTIONS + } +}; + +export const WithoutValue: Story = { + args: { + tags: [], + tagsAvailable: OPTIONS + } +}; + +export const WithoutOptions: Story = { + args: { + tags: [], + tagsAvailable: [] + } +}; diff --git a/libs/ui/src/lib/tags-selector/tags-selector.component.ts b/libs/ui/src/lib/tags-selector/tags-selector.component.ts new file mode 100644 index 000000000..611c1e938 --- /dev/null +++ b/libs/ui/src/lib/tags-selector/tags-selector.component.ts @@ -0,0 +1,133 @@ +import { COMMA, ENTER } from '@angular/cdk/keycodes'; +import { CommonModule } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + CUSTOM_ELEMENTS_SCHEMA, + ElementRef, + EventEmitter, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + signal, + ViewChild +} from '@angular/core'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { + MatAutocompleteModule, + MatAutocompleteSelectedEvent +} from '@angular/material/autocomplete'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { Tag } from '@prisma/client'; +import { BehaviorSubject, Subject, takeUntil } from 'rxjs'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + FormsModule, + MatAutocompleteModule, + MatChipsModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-tags-selector', + styleUrls: ['./tags-selector.component.scss'], + templateUrl: 'tags-selector.component.html' +}) +export class GfTagsSelectorComponent implements OnInit, OnChanges, OnDestroy { + @Input() hasPermissionToCreateTags = false; + @Input() readonly = false; + @Input() tags: Tag[]; + @Input() tagsAvailable: Tag[]; + + @Output() tagsChanged = new EventEmitter(); + + @ViewChild('tagInput') tagInput: ElementRef; + + public filteredOptions: Subject = new BehaviorSubject([]); + public readonly separatorKeysCodes: number[] = [COMMA, ENTER]; + public readonly tagInputControl = new FormControl(''); + public readonly tagsSelected = signal([]); + + private unsubscribeSubject = new Subject(); + + public constructor() { + this.tagInputControl.valueChanges + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((value) => { + this.filteredOptions.next(this.filterTags(value)); + }); + } + + public ngOnInit() { + this.tagsSelected.set(this.tags); + this.updateFilters(); + } + + public ngOnChanges() { + this.tagsSelected.set(this.tags); + this.updateFilters(); + } + + public onAddTag(event: MatAutocompleteSelectedEvent) { + let tag = this.tagsAvailable.find(({ id }) => { + return id === event.option.value; + }); + + if (!tag && this.hasPermissionToCreateTags) { + tag = { + id: undefined, + name: event.option.value as string, + userId: null + }; + } + + this.tagsSelected.update((tags) => { + return [...(tags ?? []), tag]; + }); + + this.tagsChanged.emit(this.tagsSelected()); + this.tagInput.nativeElement.value = ''; + this.tagInputControl.setValue(undefined); + } + + public onRemoveTag(tag: Tag) { + this.tagsSelected.update((tags) => { + return tags.filter(({ id }) => { + return id !== tag.id; + }); + }); + + this.tagsChanged.emit(this.tagsSelected()); + this.updateFilters(); + } + + public ngOnDestroy() { + this.unsubscribeSubject.next(); + this.unsubscribeSubject.complete(); + } + + private filterTags(query: string = ''): Tag[] { + const tags = this.tagsSelected() ?? []; + const tagIds = tags.map(({ id }) => { + return id; + }); + + return this.tagsAvailable.filter(({ id, name }) => { + return ( + !tagIds.includes(id) && name.toLowerCase().includes(query.toLowerCase()) + ); + }); + } + + private updateFilters() { + this.filteredOptions.next(this.filterTags()); + } +} diff --git a/package-lock.json b/package-lock.json index ca112661a..c760d3593 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.135.0", + "version": "2.138.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.135.0", + "version": "2.138.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { @@ -40,7 +40,7 @@ "@nestjs/platform-express": "10.4.15", "@nestjs/schedule": "4.1.2", "@nestjs/serve-static": "4.0.2", - "@prisma/client": "6.2.1", + "@prisma/client": "6.3.0", "@simplewebauthn/browser": "9.0.1", "@simplewebauthn/server": "9.0.3", "@stripe/stripe-js": "5.4.0", @@ -48,7 +48,7 @@ "await-lock": "^2.2.2", "big.js": "6.2.2", "bootstrap": "4.6.0", - "bull": "4.16.4", + "bull": "4.16.5", "cache-manager": "5.7.6", "cache-manager-redis-yet": "5.1.4", "chart.js": "4.4.7", @@ -73,7 +73,7 @@ "lodash": "4.17.21", "marked": "15.0.4", "ms": "3.0.0-canary.1", - "ng-extract-i18n-merge": "2.13.1", + "ng-extract-i18n-merge": "2.14.1", "ngx-device-detector": "9.0.0", "ngx-markdown": "19.0.0", "ngx-skeleton-loader": "9.0.0", @@ -87,7 +87,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.1", "stripe": "17.3.0", - "svgmap": "2.6.0", + "svgmap": "2.12.2", "twitter-api-v2": "1.14.2", "uuid": "11.0.5", "yahoo-finance2": "2.11.3", @@ -126,7 +126,7 @@ "@storybook/addon-interactions": "8.4.7", "@storybook/angular": "8.4.7", "@storybook/core-server": "8.4.7", - "@trivago/prettier-plugin-sort-imports": "4.3.0", + "@trivago/prettier-plugin-sort-imports": "5.2.1", "@types/big.js": "6.2.2", "@types/cache-manager": "4.0.6", "@types/color": "4.2.0", @@ -152,7 +152,7 @@ "nx": "20.3.3", "prettier": "3.4.2", "prettier-plugin-organize-attributes": "1.0.0", - "prisma": "6.2.1", + "prisma": "6.3.0", "react": "18.2.0", "react-dom": "18.2.0", "replace-in-file": "8.3.0", @@ -2589,46 +2589,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", @@ -8707,71 +8667,75 @@ "license": "MIT" }, "node_modules/@prisma/client": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.2.1.tgz", - "integrity": "sha512-msKY2iRLISN8t5X0Tj7hU0UWet1u0KuxSPHWuf3IRkB4J95mCvGpyQBfQ6ufcmvKNOMQSq90O2iUmJEN2e5fiA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.3.0.tgz", + "integrity": "sha512-BY3Fi28PUSk447Bpv22LhZp4HgNPo7NsEN+EteM1CLDnLjig5863jpW+3c3HHLFmml+nB/eJv1CjSriFZ8z7Cg==", "hasInstallScript": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" }, "peerDependencies": { - "prisma": "*" + "prisma": "*", + "typescript": ">=5.1.0" }, "peerDependenciesMeta": { "prisma": { "optional": true + }, + "typescript": { + "optional": true } } }, "node_modules/@prisma/debug": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.2.1.tgz", - "integrity": "sha512-0KItvt39CmQxWkEw6oW+RQMD6RZ43SJWgEUnzxN8VC9ixMysa7MzZCZf22LCK5DSooiLNf8vM3LHZm/I/Ni7bQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.3.0.tgz", + "integrity": "sha512-m1lQv//0Rc5RG8TBpNUuLCxC35Ghi5XfpPmL83Gh04/GICHD2J5H2ndMlaljrUNaQDF9dOxIuFAYP1rE9wkXkg==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.2.1.tgz", - "integrity": "sha512-lTBNLJBCxVT9iP5I7Mn6GlwqAxTpS5qMERrhebkUhtXpGVkBNd/jHnNJBZQW4kGDCKaQg/r2vlJYkzOHnAb7ZQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.3.0.tgz", + "integrity": "sha512-RXqYhlZb9sx/xkUfYIZuEPn7sT0WgTxNOuEYQ7AGw3IMpP9QGVEDVsluc/GcNkM8NTJszeqk8AplJzI9lm7Jxw==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.2.1", - "@prisma/engines-version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", - "@prisma/fetch-engine": "6.2.1", - "@prisma/get-platform": "6.2.1" + "@prisma/debug": "6.3.0", + "@prisma/engines-version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", + "@prisma/fetch-engine": "6.3.0", + "@prisma/get-platform": "6.3.0" } }, "node_modules/@prisma/engines-version": { - "version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69.tgz", - "integrity": "sha512-7tw1qs/9GWSX6qbZs4He09TOTg1ff3gYsB3ubaVNN0Pp1zLm9NC5C5MZShtkz7TyQjx7blhpknB7HwEhlG+PrQ==", + "version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0.tgz", + "integrity": "sha512-R/ZcMuaWZT2UBmgX3Ko6PAV3f8//ZzsjRIG1eKqp3f2rqEqVtCv+mtzuH2rBPUC9ujJ5kCb9wwpxeyCkLcHVyA==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.2.1.tgz", - "integrity": "sha512-OO7O9d6Mrx2F9i+Gu1LW+DGXXyUFkP7OE5aj9iBfA/2jjDXEJjqa9X0ZmM9NZNo8Uo7ql6zKm6yjDcbAcRrw1A==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.3.0.tgz", + "integrity": "sha512-GBy0iT4f1mH31ePzfcpVSUa7JLRTeq4914FG2vR3LqDwRweSm4ja1o5flGDz+eVIa/BNYfkBvRRxv4D6ve6Eew==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.2.1", - "@prisma/engines-version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", - "@prisma/get-platform": "6.2.1" + "@prisma/debug": "6.3.0", + "@prisma/engines-version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", + "@prisma/get-platform": "6.3.0" } }, "node_modules/@prisma/get-platform": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.2.1.tgz", - "integrity": "sha512-zp53yvroPl5m5/gXYLz7tGCNG33bhG+JYCm74ohxOq1pPnrL47VQYFfF3RbTZ7TzGWCrR3EtoiYMywUBw7UK6Q==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.3.0.tgz", + "integrity": "sha512-V8zZ1d0xfyi6FjpNP4AcYuwSpGcdmu35OXWnTPm8IW594PYALzKXHwIa9+o0f+Lo9AecFWrwrwaoYe56UNfTtQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.2.1" + "@prisma/debug": "6.3.0" } }, "node_modules/@redis/bloom": { @@ -10328,161 +10292,40 @@ } }, "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", - "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.1.tgz", + "integrity": "sha512-NDZndt0fmVThIx/8cExuJHLZagUVzfGCoVrwH9x6aZvwfBdkrDFTYujecek6X2WpG4uUFsVaPg5+aNQPSyjcmw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@babel/generator": "7.17.7", - "@babel/parser": "^7.20.5", - "@babel/traverse": "7.23.2", - "@babel/types": "7.17.0", - "javascript-natural-sort": "0.7.1", + "@babel/generator": "^7.26.2", + "@babel/parser": "^7.26.2", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "javascript-natural-sort": "^0.7.1", "lodash": "^4.17.21" }, + "engines": { + "node": ">18.12" + }, "peerDependencies": { "@vue/compiler-sfc": "3.x", - "prettier": "2.x - 3.x" + "prettier": "2.x - 3.x", + "prettier-plugin-svelte": "3.x", + "svelte": "4.x || 5.x" }, "peerDependenciesMeta": { "@vue/compiler-sfc": { "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "svelte": { + "optional": true } } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator/node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -13354,12 +13197,12 @@ } }, "node_modules/bull": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.4.tgz", - "integrity": "sha512-CF+nGsJyfsCC9MJL8hFxqXzbwq+jGBXhaz1j15G+5N/XtKIPFUUy5O1mfWWKbKunfuH/x+UV4NYRQDHSkjCOgA==", + "version": "4.16.5", + "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.5.tgz", + "integrity": "sha512-lDsx2BzkKe7gkCYiT5Acj02DpTwDznl/VNN7Psn7M3USPG7Vs/BaClZJJTAG+ufAR9++N1/NiUTdaFBWDIl5TQ==", "license": "MIT", "dependencies": { - "cron-parser": "^4.2.1", + "cron-parser": "^4.9.0", "get-port": "^5.1.1", "ioredis": "^5.3.2", "lodash": "^4.17.21", @@ -24680,9 +24523,9 @@ "license": "MIT" }, "node_modules/ng-extract-i18n-merge": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/ng-extract-i18n-merge/-/ng-extract-i18n-merge-2.13.1.tgz", - "integrity": "sha512-aU+shz0VSe0qqKYmlpg42P2C6Ol6eQ+DZDTYzQM4PTMfEBWJNFtl+c7B+MA68/AzdpcNPKu0BWJLZchCdZtjhQ==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/ng-extract-i18n-merge/-/ng-extract-i18n-merge-2.14.1.tgz", + "integrity": "sha512-hymcJcjfXJ+0r3EQShaSGmsST0AV3usgJuNMf6l04X+nIsgUPLMrXPBB/hVVVlAOjRcEB7RamKnfmexa5Rq1tw==", "license": "MIT", "dependencies": { "@angular-devkit/architect": "^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0 || ^0.1800.0 || ^0.1900.0", @@ -27026,14 +26869,14 @@ } }, "node_modules/prisma": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.2.1.tgz", - "integrity": "sha512-hhyM0H13pQleQ+br4CkzGizS5I0oInoeTw3JfLw1BRZduBSQxPILlJLwi+46wZzj9Je7ndyQEMGw/n5cN2fknA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.3.0.tgz", + "integrity": "sha512-y+Zh3Qg+xGCWyyrNUUNaFW/OltaV/yXYuTa0WRgYkz5LGyifmAsgpv94I47+qGRocZrMGcbF2A/78/oO2zgifA==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/engines": "6.2.1" + "@prisma/engines": "6.3.0" }, "bin": { "prisma": "build/index.js" @@ -27043,6 +26886,14 @@ }, "optionalDependencies": { "fsevents": "2.3.3" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/prismjs": { @@ -29608,12 +29459,12 @@ "license": "BSD-2-Clause" }, "node_modules/svgmap": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.6.0.tgz", - "integrity": "sha512-MePkVjgYlHwEfCSuGt+wB6WX6Z2fTD6yDtqZO5syzKYH7gamt1Hp9f/Bw5R49OvBtbsF7WCaGR0/GhewZGGA+w==", + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.12.2.tgz", + "integrity": "sha512-SCX1Oys3v1dz3mTEbQha+6lrHGyu3LwXBhcgW0HlTh7waQDMFqNUKD8hADvDaPkPapRvNCLMnXaVD1Pbxbnhow==", "license": "MIT", "dependencies": { - "svg-pan-zoom": "^3.6.1" + "svg-pan-zoom": "^3.6.2" } }, "node_modules/svgo": { @@ -29963,16 +29814,6 @@ "devOptional": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/package.json b/package.json index cca49ffd2..e42ea51d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.135.0", + "version": "2.138.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", @@ -87,7 +87,7 @@ "@nestjs/platform-express": "10.4.15", "@nestjs/schedule": "4.1.2", "@nestjs/serve-static": "4.0.2", - "@prisma/client": "6.2.1", + "@prisma/client": "6.3.0", "@simplewebauthn/browser": "9.0.1", "@simplewebauthn/server": "9.0.3", "@stripe/stripe-js": "5.4.0", @@ -95,7 +95,7 @@ "await-lock": "^2.2.2", "big.js": "6.2.2", "bootstrap": "4.6.0", - "bull": "4.16.4", + "bull": "4.16.5", "cache-manager": "5.7.6", "cache-manager-redis-yet": "5.1.4", "chart.js": "4.4.7", @@ -120,7 +120,7 @@ "lodash": "4.17.21", "marked": "15.0.4", "ms": "3.0.0-canary.1", - "ng-extract-i18n-merge": "2.13.1", + "ng-extract-i18n-merge": "2.14.1", "ngx-device-detector": "9.0.0", "ngx-markdown": "19.0.0", "ngx-skeleton-loader": "9.0.0", @@ -134,7 +134,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.1", "stripe": "17.3.0", - "svgmap": "2.6.0", + "svgmap": "2.12.2", "twitter-api-v2": "1.14.2", "uuid": "11.0.5", "yahoo-finance2": "2.11.3", @@ -173,7 +173,7 @@ "@storybook/addon-interactions": "8.4.7", "@storybook/angular": "8.4.7", "@storybook/core-server": "8.4.7", - "@trivago/prettier-plugin-sort-imports": "4.3.0", + "@trivago/prettier-plugin-sort-imports": "5.2.1", "@types/big.js": "6.2.2", "@types/cache-manager": "4.0.6", "@types/color": "4.2.0", @@ -199,7 +199,7 @@ "nx": "20.3.3", "prettier": "3.4.2", "prettier-plugin-organize-attributes": "1.0.0", - "prisma": "6.2.1", + "prisma": "6.3.0", "react": "18.2.0", "react-dom": "18.2.0", "replace-in-file": "8.3.0", @@ -215,6 +215,6 @@ "node": ">=20" }, "prisma": { - "seed": "node prisma/seed.js" + "seed": "npx ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" } } diff --git a/prisma/seed.js b/prisma/seed.ts similarity index 87% rename from prisma/seed.js rename to prisma/seed.ts index beafbed44..f68f8375b 100644 --- a/prisma/seed.js +++ b/prisma/seed.ts @@ -1,4 +1,5 @@ -const { PrismaClient } = require('@prisma/client'); +import { PrismaClient } from '@prisma/client'; + const prisma = new PrismaClient(); async function main() {