diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f18565c7..3917c2041 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Improved the language localization for Spanish (`es`) +- Restructured the response of the portfolio report endpoint (_X-ray_) + +### Fixed + +- Excluded the holdings originated of `FEE`, `INTEREST` and `LIABILITY` activities from the closed holdings on the portfolio holdings page + +## 2.185.0 - 2025-07-26 + +### Added + +- Added a _Storybook_ story for the activity type component +- Added a _Storybook_ story for the toggle component + +### Changed + +- Extended the import functionality by custom asset profiles +- Migrated the get country and sector weightings, dividends, ETF holdings, ETF info, historical price, profile, quote and symbol search functionalities of the _Financial Modeling Prep_ service to its stable API version - Refactored the toggle component to standalone - Improved the language localization for Dutch (`nl`) -- Improved the language localization for Spanish (`es`) +- Improved the language localization for Portuguese (`pt`) - Improved the language localization for Turkish (`tr`) - Upgraded the _Stripe_ dependencies - Upgraded `angular` from version `19.2.1` to `20.0.7` @@ -23,8 +41,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed the date format of the retirement date in the _FIRE_ calculator - Fixed an issue with the permissions of the impersonation mode related to the onboarding on the overview tab of the home page - Fixed an issue with the permissions of the impersonation mode related to the manage activities button of the holdings tab on the home page +- Fixed an issue with the currency detection related to `USD.AX` in the _Yahoo Finance_ service ## 2.184.0 - 2025-07-22 diff --git a/README.md b/README.md index f2e9de4f1..02f17fe49 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ ## Ghostfolio Premium -Our official **[Ghostfolio Premium](https://ghostfol.io/en/pricing)** cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development. +Our official **[Ghostfolio Premium](https://ghostfol.io/en/pricing)** cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. If you prefer to run Ghostfolio on your own infrastructure, please find further instructions in the [Self-hosting](#self-hosting) section. diff --git a/apps/api/src/app/admin/create-asset-profile.dto.ts b/apps/api/src/app/admin/create-asset-profile.dto.ts new file mode 100644 index 000000000..8041b0f0e --- /dev/null +++ b/apps/api/src/app/admin/create-asset-profile.dto.ts @@ -0,0 +1,92 @@ +import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code'; + +import { AssetClass, AssetSubClass, DataSource, Prisma } from '@prisma/client'; +import { + IsArray, + IsBoolean, + IsEnum, + IsObject, + IsOptional, + IsString, + IsUrl +} from 'class-validator'; + +export class CreateAssetProfileDto { + @IsEnum(AssetClass, { each: true }) + @IsOptional() + assetClass?: AssetClass; + + @IsEnum(AssetSubClass, { each: true }) + @IsOptional() + assetSubClass?: AssetSubClass; + + @IsOptional() + @IsString() + comment?: string; + + @IsArray() + @IsOptional() + countries?: Prisma.InputJsonArray; + + @IsCurrencyCode() + currency: string; + + @IsOptional() + @IsString() + cusip?: string; + + @IsEnum(DataSource) + dataSource: DataSource; + + @IsOptional() + @IsString() + figi?: string; + + @IsOptional() + @IsString() + figiComposite?: string; + + @IsOptional() + @IsString() + figiShareClass?: string; + + @IsArray() + @IsOptional() + holdings?: Prisma.InputJsonArray; + + @IsBoolean() + @IsOptional() + isActive?: boolean; + + @IsOptional() + @IsString() + isin?: string; + + @IsOptional() + @IsString() + name?: string; + + @IsObject() + @IsOptional() + scraperConfiguration?: Prisma.InputJsonObject; + + @IsArray() + @IsOptional() + sectors?: Prisma.InputJsonArray; + + @IsString() + symbol: string; + + @IsObject() + @IsOptional() + symbolMapping?: { + [dataProvider: string]: string; + }; + + @IsOptional() + @IsUrl({ + protocols: ['https'], + require_protocol: true + }) + url?: string; +} diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index 9c9d20682..54fd0763d 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -195,7 +195,6 @@ export class ExportService { figiComposite, figiShareClass, holdings: holdings as unknown as Prisma.JsonArray, - id, isActive, isin, marketData: marketDataByAssetProfile[id], diff --git a/apps/api/src/app/import/create-asset-profile-with-market-data.dto.ts b/apps/api/src/app/import/create-asset-profile-with-market-data.dto.ts new file mode 100644 index 000000000..fd90ab1af --- /dev/null +++ b/apps/api/src/app/import/create-asset-profile-with-market-data.dto.ts @@ -0,0 +1,17 @@ +import { MarketData } from '@ghostfolio/common/interfaces'; + +import { DataSource } from '@prisma/client'; +import { IsArray, IsEnum, IsOptional } from 'class-validator'; + +import { CreateAssetProfileDto } from '../admin/create-asset-profile.dto'; + +export class CreateAssetProfileWithMarketDataDto extends CreateAssetProfileDto { + @IsEnum([DataSource.MANUAL], { + message: `dataSource must be '${DataSource.MANUAL}'` + }) + dataSource: DataSource; + + @IsArray() + @IsOptional() + marketData?: MarketData[]; +} diff --git a/apps/api/src/app/import/import-data.dto.ts b/apps/api/src/app/import/import-data.dto.ts index 207c8152b..138d16961 100644 --- a/apps/api/src/app/import/import-data.dto.ts +++ b/apps/api/src/app/import/import-data.dto.ts @@ -4,16 +4,23 @@ import { Type } from 'class-transformer'; import { IsArray, IsOptional, ValidateNested } from 'class-validator'; import { CreateAccountWithBalancesDto } from './create-account-with-balances.dto'; +import { CreateAssetProfileWithMarketDataDto } from './create-asset-profile-with-market-data.dto'; export class ImportDataDto { - @IsOptional() @IsArray() + @IsOptional() @Type(() => CreateAccountWithBalancesDto) @ValidateNested({ each: true }) - accounts: CreateAccountWithBalancesDto[]; + accounts?: CreateAccountWithBalancesDto[]; @IsArray() @Type(() => CreateOrderDto) @ValidateNested({ each: true }) activities: CreateOrderDto[]; + + @IsArray() + @IsOptional() + @Type(() => CreateAssetProfileWithMarketDataDto) + @ValidateNested({ each: true }) + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; } diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index 081541fee..8c06bdc6d 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -73,6 +73,7 @@ export class ImportController { maxActivitiesToImport, accountsWithBalancesDto: importData.accounts ?? [], activitiesDto: importData.activities, + assetProfilesWithMarketDataDto: importData.assetProfiles ?? [], user: this.request.user }); diff --git a/apps/api/src/app/import/import.module.ts b/apps/api/src/app/import/import.module.ts index 142a939a6..fb6c29fc5 100644 --- a/apps/api/src/app/import/import.module.ts +++ b/apps/api/src/app/import/import.module.ts @@ -9,6 +9,7 @@ import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptor import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; +import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module'; import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; @@ -27,6 +28,7 @@ import { ImportService } from './import.service'; DataGatheringModule, DataProviderModule, ExchangeRateDataModule, + MarketDataModule, OrderModule, PlatformModule, PortfolioModule, diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index e41dcd819..d23427616 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -10,6 +10,7 @@ import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; +import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config'; @@ -31,6 +32,7 @@ import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns'; import { omit, uniqBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; +import { CreateAssetProfileDto } from '../admin/create-asset-profile.dto'; import { ImportDataDto } from './import-data.dto'; @Injectable() @@ -40,6 +42,7 @@ export class ImportService { private readonly configurationService: ConfigurationService, private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, + private readonly marketDataService: MarketDataService, private readonly orderService: OrderService, private readonly platformService: PlatformService, private readonly portfolioService: PortfolioService, @@ -148,17 +151,20 @@ export class ImportService { public async import({ accountsWithBalancesDto, activitiesDto, + assetProfilesWithMarketDataDto, isDryRun = false, maxActivitiesToImport, user }: { accountsWithBalancesDto: ImportDataDto['accounts']; activitiesDto: ImportDataDto['activities']; + assetProfilesWithMarketDataDto: ImportDataDto['assetProfiles']; isDryRun?: boolean; maxActivitiesToImport: number; user: UserWithSettings; }): Promise { const accountIdMapping: { [oldAccountId: string]: string } = {}; + const assetProfileSymbolMapping: { [oldSymbol: string]: string } = {}; const userCurrency = user.settings.settings.baseCurrency; if (!isDryRun && accountsWithBalancesDto?.length) { @@ -230,6 +236,63 @@ export class ImportService { } } + if (!isDryRun && assetProfilesWithMarketDataDto?.length) { + const existingAssetProfiles = + await this.symbolProfileService.getSymbolProfiles( + assetProfilesWithMarketDataDto.map(({ dataSource, symbol }) => { + return { dataSource, symbol }; + }) + ); + + for (const assetProfileWithMarketData of assetProfilesWithMarketDataDto) { + // Check if there is any existing asset profile + const existingAssetProfile = existingAssetProfiles.find( + ({ dataSource, symbol }) => { + return ( + dataSource === assetProfileWithMarketData.dataSource && + symbol === assetProfileWithMarketData.symbol + ); + } + ); + + // If there is no asset profile or if the asset profile belongs to a different user, then create a new asset profile + if (!existingAssetProfile || existingAssetProfile.userId !== user.id) { + const assetProfile: CreateAssetProfileDto = omit( + assetProfileWithMarketData, + 'marketData' + ); + + // Asset profile belongs to a different user + if (existingAssetProfile) { + const symbol = uuidv4(); + assetProfileSymbolMapping[assetProfile.symbol] = symbol; + assetProfile.symbol = symbol; + } + + // Create a new asset profile + const assetProfileObject: Prisma.SymbolProfileCreateInput = { + ...assetProfile, + user: { connect: { id: user.id } } + }; + + await this.symbolProfileService.add(assetProfileObject); + } + + // Insert or update market data + const marketDataObjects = assetProfileWithMarketData.marketData.map( + (marketData) => { + return { + ...marketData, + dataSource: assetProfileWithMarketData.dataSource, + symbol: assetProfileWithMarketData.symbol + } as Prisma.MarketDataUpdateInput; + } + ); + + await this.marketDataService.updateMany({ data: marketDataObjects }); + } + } + for (const activity of activitiesDto) { if (!activity.dataSource) { if (['FEE', 'INTEREST', 'LIABILITY'].includes(activity.type)) { @@ -240,11 +303,16 @@ export class ImportService { } } - // If a new account is created, then update the accountId in all activities if (!isDryRun) { - if (Object.keys(accountIdMapping).includes(activity.accountId)) { + // If a new account is created, then update the accountId in all activities + if (accountIdMapping[activity.accountId]) { activity.accountId = accountIdMapping[activity.accountId]; } + + // If a new asset profile is created, then update the symbol in all activities + if (assetProfileSymbolMapping[activity.symbol]) { + activity.symbol = assetProfileSymbolMapping[activity.symbol]; + } } } diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 185c1cd80..78323a332 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -13,6 +13,7 @@ import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfac import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { + INVESTMENT_ACTIVITY_TYPES, PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS, PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE_PRIORITY_HIGH, @@ -287,10 +288,12 @@ export abstract class PortfolioCalculator { firstIndex--; } - const positions: TimelinePosition[] = []; + const errors: ResponseError['errors'] = []; let hasAnySymbolMetricsErrors = false; - const errors: ResponseError['errors'] = []; + const positions: (TimelinePosition & { + includeInHoldings: boolean; + })[] = []; const accumulatedValuesByDate: { [date: string]: { @@ -409,6 +412,7 @@ export abstract class PortfolioCalculator { grossPerformanceWithCurrencyEffect: !hasErrors ? (grossPerformanceWithCurrencyEffect ?? null) : null, + includeInHoldings: item.includeInHoldings, investment: totalInvestment, investmentWithCurrencyEffect: totalInvestmentWithCurrencyEffect, marketPrice: @@ -605,14 +609,23 @@ export abstract class PortfolioCalculator { const overall = this.calculateOverallPerformance(positions); + const positionsIncludedInHoldings = positions + .filter(({ includeInHoldings }) => { + return includeInHoldings; + }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(({ includeInHoldings, ...rest }) => { + return rest; + }); + return { ...overall, errors, historicalData, - positions, totalInterestWithCurrencyEffect, totalLiabilitiesWithCurrencyEffect, - hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors + hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors, + positions: positionsIncludedInHoldings }; } @@ -935,6 +948,7 @@ export abstract class PortfolioCalculator { dividend: new Big(0), fee: oldAccumulatedSymbol.fee.plus(fee), firstBuyDate: oldAccumulatedSymbol.firstBuyDate, + includeInHoldings: oldAccumulatedSymbol.includeInHoldings, quantity: newQuantity, tags: oldAccumulatedSymbol.tags.concat(tags), transactionCount: oldAccumulatedSymbol.transactionCount + 1 @@ -950,6 +964,7 @@ export abstract class PortfolioCalculator { averagePrice: unitPrice, dividend: new Big(0), firstBuyDate: date, + includeInHoldings: INVESTMENT_ACTIVITY_TYPES.includes(type), investment: unitPrice.mul(quantity).mul(factor), quantity: quantity.mul(factor), transactionCount: 1 diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts index 31c6afe66..aaf2c4302 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts @@ -116,37 +116,7 @@ describe('PortfolioCalculator', () => { currentValueInBaseCurrency: new Big('0'), errors: [], hasErrors: true, - positions: [ - { - averagePrice: new Big('0'), - currency: 'USD', - dataSource: 'MANUAL', - dividend: new Big('0'), - dividendInBaseCurrency: new Big('0'), - fee: new Big('49'), - feeInBaseCurrency: new Big('49'), - firstBuyDate: '2021-09-01', - grossPerformance: null, - grossPerformancePercentage: null, - grossPerformancePercentageWithCurrencyEffect: null, - grossPerformanceWithCurrencyEffect: null, - investment: new Big('0'), - investmentWithCurrencyEffect: new Big('0'), - marketPrice: null, - marketPriceInBaseCurrency: 0, - netPerformance: null, - netPerformancePercentage: null, - netPerformancePercentageWithCurrencyEffectMap: null, - netPerformanceWithCurrencyEffectMap: null, - quantity: new Big('0'), - symbol: '2c463fb3-af07-486e-adb0-8301b3d72141', - tags: [], - timeWeightedInvestment: new Big('0'), - timeWeightedInvestmentWithCurrencyEffect: new Big('0'), - transactionCount: 1, - valueInBaseCurrency: new Big('0') - } - ], + positions: [], totalFeesWithCurrencyEffect: new Big('49'), totalInterestWithCurrencyEffect: new Big('0'), totalInvestment: new Big('0'), diff --git a/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts b/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts index 0d648322f..f4ceadf3b 100644 --- a/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/transaction-point-symbol.interface.ts @@ -8,6 +8,7 @@ export interface TransactionPointSymbol { dividend: Big; fee: Big; firstBuyDate: string; + includeInHoldings: boolean; investment: Big; quantity: Big; skipErrors: boolean; diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 2c71a4668..17cf41702 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -655,11 +655,11 @@ export class PortfolioController { this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && this.request.user.subscription.type === 'Basic' ) { - for (const rule in report.rules) { - report.rules[rule] = null; + for (const rule in report['x-ray'].rules) { + report['x-ray'].rules[rule] = null; } - report.statistics = { + report['x-ray'].statistics = { rulesActiveCount: 0, rulesFulfilledCount: 0 }; diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 88d6e7d60..c5b9c2148 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1156,7 +1156,7 @@ export class PortfolioService { }) ).toNumber(); - const rules: PortfolioReportResponse['rules'] = { + const rules: PortfolioReportResponse['x-ray']['rules'] = { accountClusterRisk: summary.activityCount > 0 ? await this.rulesService.evaluate( @@ -1311,7 +1311,12 @@ export class PortfolioService { : undefined }; - return { rules, statistics: this.getReportStatistics(rules) }; + return { + 'x-ray': { + rules, + statistics: this.getReportStatistics(rules) + } + }; } public async updateTags({ @@ -1731,8 +1736,8 @@ export class PortfolioService { } private getReportStatistics( - evaluatedRules: PortfolioReportResponse['rules'] - ): PortfolioReportResponse['statistics'] { + evaluatedRules: PortfolioReportResponse['x-ray']['rules'] + ): PortfolioReportResponse['x-ray']['statistics'] { const rulesActiveCount = Object.values(evaluatedRules) .flat() .filter((rule) => { diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts index 8a8ab1f08..c37a9fe3e 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.spec.ts @@ -47,11 +47,21 @@ describe('YahooFinanceDataEnhancerService', () => { 'BTC-USD' ) ).toEqual('BTCUSD'); + expect( + await yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( + 'USD.AX' + ) + ).toEqual('USD.AX'); expect( await yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( 'EURUSD=X' ) ).toEqual('EURUSD'); + expect( + await yahooFinanceDataEnhancerService.convertFromYahooFinanceSymbol( + 'USDCHF=X' + ) + ).toEqual('USDCHF'); }); it('convertToYahooFinanceSymbol', async () => { @@ -65,6 +75,16 @@ describe('YahooFinanceDataEnhancerService', () => { 'DOGEUSD' ) ).toEqual('DOGE-USD'); + expect( + await yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + 'EURUSD' + ) + ).toEqual('EURUSD=X'); + expect( + await yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( + 'USD.AX' + ) + ).toEqual('USD.AX'); expect( await yahooFinanceDataEnhancerService.convertToYahooFinanceSymbol( 'USDCHF' 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 8b76ae86b..54167bc5b 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 @@ -63,7 +63,8 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { if ( isCurrency( aSymbol.substring(0, aSymbol.length - DEFAULT_CURRENCY.length) - ) + ) && + isCurrency(aSymbol.substring(aSymbol.length - DEFAULT_CURRENCY.length)) ) { return `${aSymbol}=X`; } else if ( diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index a9f171f13..2dcb689a7 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -46,7 +46,6 @@ import { @Injectable() export class FinancialModelingPrepService implements DataProviderInterface { private apiKey: string; - private readonly URL = this.getUrl({ version: 3 }); public constructor( private readonly configurationService: ConfigurationService, @@ -81,7 +80,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { ); } else if (this.cryptocurrencyService.isCryptocurrency(symbol)) { const [quote] = await fetch( - `${this.URL}/quote/${symbol}?apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/quote?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -95,7 +94,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { response.name = quote.name; } else { const [assetProfile] = await fetch( - `${this.URL}/profile/${symbol}?apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/profile?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -109,7 +108,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { if (assetSubClass === AssetSubClass.ETF) { const etfCountryWeightings = await fetch( - `${this.URL}/etf-country-weightings/${symbol}?apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/etf/country-weightings?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -133,45 +132,38 @@ export class FinancialModelingPrepService implements DataProviderInterface { } ); - const [etfInformation] = await fetch( - `${this.getUrl({ version: 4 })}/etf-info?symbol=${symbol}&apikey=${this.apiKey}`, + const etfHoldings = await fetch( + `${this.getUrl({ version: 'stable' })}/etf/holdings?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } ).then((res) => res.json()); - if (etfInformation.website) { - response.url = etfInformation.website; - } + const sortedTopHoldings = etfHoldings + .sort((a, b) => { + return b.weightPercentage - a.weightPercentage; + }) + .slice(0, 10); - const [portfolioDate] = await fetch( - `${this.getUrl({ version: 4 })}/etf-holdings/portfolio-date?symbol=${symbol}&apikey=${this.apiKey}`, + response.holdings = sortedTopHoldings.map( + ({ name, weightPercentage }) => { + return { name, weight: weightPercentage / 100 }; + } + ); + + const [etfInformation] = await fetch( + `${this.getUrl({ version: 'stable' })}/etf/info?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } ).then((res) => res.json()); - if (portfolioDate) { - const etfHoldings = await fetch( - `${this.getUrl({ version: 4 })}/etf-holdings?date=${portfolioDate.date}&symbol=${symbol}&apikey=${this.apiKey}`, - { - signal: AbortSignal.timeout(requestTimeout) - } - ).then((res) => res.json()); - - const sortedTopHoldings = etfHoldings - .sort((a, b) => { - return b.pctVal - a.pctVal; - }) - .slice(0, 10); - - response.holdings = sortedTopHoldings.map(({ name, pctVal }) => { - return { name, weight: pctVal / 100 }; - }); + if (etfInformation.website) { + response.url = etfInformation.website; } const etfSectorWeightings = await fetch( - `${this.URL}/etf-sector-weightings/${symbol}?apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/etf/sector-weightings?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } @@ -181,7 +173,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { ({ sector, weightPercentage }) => { return { name: sector, - weight: parseFloat(weightPercentage.slice(0, -1)) / 100 + weight: weightPercentage / 100 }; } ); @@ -246,14 +238,14 @@ export class FinancialModelingPrepService implements DataProviderInterface { [date: string]: IDataProviderHistoricalResponse; } = {}; - const { historical = [] } = await fetch( - `${this.URL}/historical-price-full/stock_dividend/${symbol}?apikey=${this.apiKey}`, + const dividends = await fetch( + `${this.getUrl({ version: 'stable' })}/dividends?symbol=${symbol}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout(requestTimeout) } ).then((res) => res.json()); - historical + dividends .filter(({ date }) => { return ( (isSameDay(parseISO(date), from) || @@ -307,21 +299,21 @@ export class FinancialModelingPrepService implements DataProviderInterface { ? addYears(currentFrom, MAX_YEARS_PER_REQUEST) : to; - const { historical = [] } = await fetch( - `${this.URL}/historical-price-full/${symbol}?apikey=${this.apiKey}&from=${format(currentFrom, DATE_FORMAT)}&to=${format(currentTo, DATE_FORMAT)}`, + const historical = await fetch( + `${this.getUrl({ version: 'stable' })}/historical-price-eod/full?symbol=${symbol}&apikey=${this.apiKey}&from=${format(currentFrom, DATE_FORMAT)}&to=${format(currentTo, DATE_FORMAT)}`, { signal: AbortSignal.timeout(requestTimeout) } ).then((res) => res.json()); - for (const { adjClose, date } of historical) { + for (const { close, date } of historical) { if ( (isSameDay(parseDate(date), currentFrom) || isAfter(parseDate(date), currentFrom)) && isBefore(parseDate(date), currentTo) ) { result[symbol][date] = { - marketPrice: adjClose + marketPrice: close }; } } @@ -454,7 +446,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { }); } else { const result = await fetch( - `${this.URL}/search?query=${query}&apikey=${this.apiKey}`, + `${this.getUrl({ version: 'stable' })}/search-symbol?query=${query}&apikey=${this.apiKey}`, { signal: AbortSignal.timeout( this.configurationService.get('REQUEST_TIMEOUT') diff --git a/apps/client/src/app/components/header/header.component.html b/apps/client/src/app/components/header/header.component.html index 3f443dfea..ec62e41fe 100644 --- a/apps/client/src/app/components/header/header.component.html +++ b/apps/client/src/app/components/header/header.component.html @@ -205,7 +205,7 @@ { + this.hasImpersonationId = !!impersonationId; this.impersonationId = impersonationId; }); diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index e4a369d41..33d9139ea 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -1,4 +1,3 @@ -import { GfToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -12,6 +11,7 @@ import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { HoldingType, HoldingsViewMode } from '@ghostfolio/common/types'; import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; +import { GfToggleComponent } from '@ghostfolio/ui/toggle'; import { GfTreemapChartComponent } from '@ghostfolio/ui/treemap-chart'; import { CommonModule } from '@angular/common'; diff --git a/apps/client/src/app/components/home-holdings/home-holdings.html b/apps/client/src/app/components/home-holdings/home-holdings.html index 8f9276fa5..87d0a514d 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.html +++ b/apps/client/src/app/components/home-holdings/home-holdings.html @@ -28,7 +28,7 @@ [defaultValue]="holdingType" [isLoading]="false" [options]="holdingTypeOptions" - (change)="onChangeHoldingType($event.value)" + (valueChange)="onChangeHoldingType($event.value)" /> diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index db3e59f59..06fccd650 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -1,5 +1,4 @@ import { GfPortfolioPerformanceModule } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.module'; -import { GfToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { LayoutService } from '@ghostfolio/client/core/layout.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -43,7 +42,6 @@ import { takeUntil } from 'rxjs/operators'; templateUrl: './home-overview.html' }) export class GfHomeOverviewComponent implements OnDestroy, OnInit { - public dateRangeOptions = GfToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public deviceType: string; public errors: AssetProfileIdentifier[]; public hasError: boolean; diff --git a/apps/client/src/app/components/markets/markets.component.ts b/apps/client/src/app/components/markets/markets.component.ts index 153c1ea14..91c28e1c7 100644 --- a/apps/client/src/app/components/markets/markets.component.ts +++ b/apps/client/src/app/components/markets/markets.component.ts @@ -1,5 +1,4 @@ import { GfFearAndGreedIndexModule } from '@ghostfolio/client/components/fear-and-greed-index/fear-and-greed-index.module'; -import { GfToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { resetHours } from '@ghostfolio/common/helper'; @@ -13,6 +12,7 @@ import { import { FearAndGreedIndexMode } from '@ghostfolio/common/types'; import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; +import { GfToggleComponent } from '@ghostfolio/ui/toggle'; import { ChangeDetectionStrategy, diff --git a/apps/client/src/app/components/markets/markets.html b/apps/client/src/app/components/markets/markets.html index 947772d57..90ddbba06 100644 --- a/apps/client/src/app/components/markets/markets.html +++ b/apps/client/src/app/components/markets/markets.html @@ -9,7 +9,7 @@ [defaultValue]="fearAndGreedIndexMode" [isLoading]="false" [options]="fearAndGreedIndexModeOptions" - (change)="onChangeFearAndGreedIndexMode($event.value)" + (valueChange)="onChangeFearAndGreedIndexMode($event.value)" /> } diff --git a/apps/client/src/app/pages/api/api-page.component.ts b/apps/client/src/app/pages/api/api-page.component.ts index 7b385ec2f..87fc164af 100644 --- a/apps/client/src/app/pages/api/api-page.component.ts +++ b/apps/client/src/app/pages/api/api-page.component.ts @@ -44,7 +44,7 @@ export class GfApiPageComponent implements OnInit { this.historicalData$ = this.fetchHistoricalData({ symbol: 'AAPL' }); this.isinLookupItems$ = this.fetchLookupItems({ query: 'US0378331005' }); this.lookupItems$ = this.fetchLookupItems({ query: 'apple' }); - this.quotes$ = this.fetchQuotes({ symbols: ['AAPL', 'VOO.US'] }); + this.quotes$ = this.fetchQuotes({ symbols: ['AAPL', 'VOO'] }); this.status$ = this.fetchStatus(); } diff --git a/apps/client/src/app/pages/faq/overview/faq-overview-page.html b/apps/client/src/app/pages/faq/overview/faq-overview-page.html index bc7f6ba37..24caf8d97 100644 --- a/apps/client/src/app/pages/faq/overview/faq-overview-page.html +++ b/apps/client/src/app/pages/faq/overview/faq-overview-page.html @@ -133,8 +133,9 @@ class="d-inline-block ml-1" [enableLink]="false" /> - subscription to finance the hosting infrastructure, a positive rating - in the + subscription to finance the operational costs for the hosting + infrastructure and professional data providers, a positive rating in + the Google Play Store is a fully managed Ghostfolio cloud offering for ambitious investors. - Revenue is used to cover the costs of the hosting infrastructure and - to fund ongoing development. It is the Open Source code base with some - extras like the + Revenue is used to cover operational costs for the hosting + infrastructure and professional data providers, and to fund ongoing + development. It is the Open Source code base with some extras like the markets overview and a professional data provider. 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 b9f0986ac..660e7265e 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 @@ -1,4 +1,5 @@ -import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; +import { CreateAccountWithBalancesDto } from '@ghostfolio/api/app/import/create-account-with-balances.dto'; +import { CreateAssetProfileWithMarketDataDto } from '@ghostfolio/api/app/import/create-asset-profile-with-market-data.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; @@ -75,9 +76,10 @@ import { ImportActivitiesDialogParams } from './interfaces/interfaces'; templateUrl: 'import-activities-dialog.html' }) export class GfImportActivitiesDialog implements OnDestroy { - public accounts: CreateAccountDto[] = []; + public accounts: CreateAccountWithBalancesDto[] = []; public activities: Activity[] = []; public assetProfileForm: FormGroup; + public assetProfiles: CreateAssetProfileWithMarketDataDto[] = []; public dataSource: MatTableDataSource; public details: any[] = []; public deviceType: string; @@ -166,7 +168,8 @@ export class GfImportActivitiesDialog implements OnDestroy { await this.importActivitiesService.importSelectedActivities({ accounts: this.accounts, - activities: this.selectedActivities + activities: this.selectedActivities, + assetProfiles: this.assetProfiles }); this.snackBar.open( @@ -293,6 +296,7 @@ export class GfImportActivitiesDialog implements OnDestroy { const content = JSON.parse(fileContent); this.accounts = content.accounts; + this.assetProfiles = content.assetProfiles; if (!isArray(content.activities)) { if (isArray(content.orders)) { @@ -323,6 +327,7 @@ export class GfImportActivitiesDialog implements OnDestroy { await this.importActivitiesService.importJson({ accounts: content.accounts, activities: content.activities, + assetProfiles: content.assetProfiles, isDryRun: true }); this.activities = activities; 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 b56a1fe5a..02be40250 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 @@ -1,6 +1,5 @@ import { GfBenchmarkComparatorModule } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.module'; import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; -import { GfToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -17,6 +16,7 @@ import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import type { AiPromptMode, GroupBy } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfToggleComponent } from '@ghostfolio/ui/toggle'; import { GfValueComponent } from '@ghostfolio/ui/value'; import { Clipboard } from '@angular/cdk/clipboard'; @@ -68,7 +68,6 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { public benchmarkDataItems: HistoricalDataItem[] = []; public benchmarks: Partial[]; public bottom3: PortfolioPosition[]; - public dateRangeOptions = GfToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public deviceType: string; public dividendsByGroup: InvestmentItem[]; public dividendTimelineDataLabel = $localize`Dividend`; diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 56c95e40f..477d47b40 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -375,7 +375,7 @@ [defaultValue]="mode" [isLoading]="false" [options]="modeOptions" - (change)="onChangeGroupBy($event.value)" + (valueChange)="onChangeGroupBy($event.value)" /> @if (streaks) { @@ -432,7 +432,7 @@ [defaultValue]="mode" [isLoading]="false" [options]="modeOptions" - (change)="onChangeGroupBy($event.value)" + (valueChange)="onChangeGroupBy($event.value)" />
diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts index 5aabfc749..cad7d41e9 100644 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts +++ b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts @@ -47,7 +47,7 @@ export class GfXRayPageComponent { public inactiveRules: PortfolioReportRule[]; public isLoading = false; public regionalMarketClusterRiskRules: PortfolioReportRule[]; - public statistics: PortfolioReportResponse['statistics']; + public statistics: PortfolioReportResponse['x-ray']['statistics']; public user: User; private unsubscribeSubject = new Subject(); @@ -115,7 +115,7 @@ export class GfXRayPageComponent { this.dataService .fetchPortfolioReport() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ rules, statistics }) => { + .subscribe(({ 'x-ray': { rules, statistics } }) => { this.inactiveRules = this.mergeInactiveRules(rules); this.statistics = statistics; @@ -161,7 +161,7 @@ export class GfXRayPageComponent { } private mergeInactiveRules( - rules: PortfolioReportResponse['rules'] + rules: PortfolioReportResponse['x-ray']['rules'] ): PortfolioReportRule[] { let inactiveRules: PortfolioReportRule[] = []; diff --git a/apps/client/src/app/pages/pricing/pricing-page.html b/apps/client/src/app/pages/pricing/pricing-page.html index c13766b75..ea68b74eb 100644 --- a/apps/client/src/app/pages/pricing/pricing-page.html +++ b/apps/client/src/app/pages/pricing/pricing-page.html @@ -6,8 +6,9 @@

Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option - for most people. Revenue is used to cover the costs of the hosting - infrastructure and to fund ongoing development. + for most people. Revenue is used to cover operational costs for the + hosting infrastructure and professional data providers, and to fund + ongoing development.

If you prefer to run Ghostfolio on your own infrastructure, please diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts index a4ffa7ec4..033ae7e24 100644 --- a/apps/client/src/app/services/import-activities.service.ts +++ b/apps/client/src/app/services/import-activities.service.ts @@ -1,4 +1,5 @@ -import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; +import { CreateAccountWithBalancesDto } from '@ghostfolio/api/app/import/create-account-with-balances.dto'; +import { CreateAssetProfileWithMarketDataDto } from '@ghostfolio/api/app/import/create-asset-profile-with-market-data.dto'; import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { parseDate as parseDateHelper } from '@ghostfolio/common/helper'; @@ -73,20 +74,22 @@ export class ImportActivitiesService { public importJson({ accounts, activities, + assetProfiles, isDryRun = false }: { activities: CreateOrderDto[]; - accounts?: CreateAccountDto[]; + accounts?: CreateAccountWithBalancesDto[]; + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; isDryRun?: boolean; }): Promise<{ activities: Activity[]; - accounts?: CreateAccountDto[]; }> { return new Promise((resolve, reject) => { this.postImport( { accounts, - activities + activities, + assetProfiles }, isDryRun ) @@ -106,13 +109,14 @@ export class ImportActivitiesService { public importSelectedActivities({ accounts, - activities + activities, + assetProfiles }: { - accounts: CreateAccountDto[]; + accounts?: CreateAccountWithBalancesDto[]; activities: Activity[]; + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; }): Promise<{ activities: Activity[]; - accounts?: CreateAccountDto[]; }> { const importData: CreateOrderDto[] = []; @@ -120,7 +124,7 @@ export class ImportActivitiesService { importData.push(this.convertToCreateOrderDto(activity)); } - return this.importJson({ accounts, activities: importData }); + return this.importJson({ accounts, assetProfiles, activities: importData }); } private convertToCreateOrderDto({ @@ -383,7 +387,11 @@ export class ImportActivitiesService { } private postImport( - aImportData: { accounts: CreateAccountDto[]; activities: CreateOrderDto[] }, + aImportData: { + accounts?: CreateAccountWithBalancesDto[]; + activities: CreateOrderDto[]; + assetProfiles?: CreateAssetProfileWithMarketDataDto[]; + }, aIsDryRun = false ) { return this.http.post<{ activities: Activity[] }>( diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 0ee70a08f..e1f80d47e 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -22,7 +22,7 @@ Iniciar sessió apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -2199,7 +2199,7 @@ Oooh! El testimoni de seguretat és incorrecte. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -2913,10 +2913,6 @@ Today Avui - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -2925,10 +2921,6 @@ YTD YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -2937,10 +2929,6 @@ 1Y 1 any - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -2949,10 +2937,6 @@ 5Y 5 anys - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -2961,10 +2945,6 @@ Max Màx - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -3311,7 +3291,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -3331,7 +3311,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -3347,7 +3327,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -4372,7 +4352,7 @@ Activitats d’importació apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -4380,7 +4360,7 @@ Importar dividends apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -4388,7 +4368,7 @@ S’estan important dades... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -4396,7 +4376,7 @@ La importació s’ha completat apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -4404,7 +4384,7 @@ S’estan validant les dades... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -4692,7 +4672,7 @@ Dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -4704,11 +4684,11 @@ Inversió apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -4720,7 +4700,7 @@ Mensualment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -4728,7 +4708,7 @@ Anualment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -5809,7 +5789,7 @@ Import total previst libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -7171,7 +7151,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Performance apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index d8dd963fc..b2f396c01 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -1026,7 +1026,7 @@ Einloggen apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1042,7 +1042,7 @@ Ups! Falsches Sicherheits-Token. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1412,10 +1412,6 @@ Today Heute - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -1424,10 +1420,6 @@ YTD YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -1436,10 +1428,6 @@ 1Y 1J - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -1448,10 +1436,6 @@ 5Y 5J - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -1460,10 +1444,6 @@ Max Max - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -1482,7 +1462,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -2346,7 +2326,7 @@ Daten importieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -2354,7 +2334,7 @@ Der Import wurde abgeschlossen apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -2486,7 +2466,7 @@ Aktivitäten importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -2606,7 +2586,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -2618,7 +2598,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -2746,7 +2726,7 @@ Projizierter Gesamtbetrag libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2754,7 +2734,7 @@ Monatlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -3282,7 +3262,7 @@ Dividenden apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3310,7 +3290,7 @@ Daten validieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3378,7 +3358,7 @@ Jährlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -3386,7 +3366,7 @@ Dividenden importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -5908,11 +5888,11 @@ Investition apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7195,7 +7175,7 @@ KI-Anweisung wurde in die Zwischenablage kopiert apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7283,7 +7263,7 @@ Öffne Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7315,7 +7295,7 @@ Performance apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 86e47b1dc..bde88d6ee 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -1011,7 +1011,7 @@ Iniciar sesión apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1027,7 +1027,7 @@ Vaya! Token de seguridad incorrecto. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1397,10 +1397,6 @@ Today Hoy - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -1409,10 +1405,6 @@ YTD Desde principio de año - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -1421,10 +1413,6 @@ 1Y 1 año - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -1433,10 +1421,6 @@ 5Y 5 años - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -1445,10 +1429,6 @@ Max Máximo - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -1467,7 +1447,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -2331,7 +2311,7 @@ Importando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -2339,7 +2319,7 @@ La importación se ha completado apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -2471,7 +2451,7 @@ Importar operaciones apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -2587,7 +2567,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -2603,7 +2583,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -2731,7 +2711,7 @@ Importe total previsto libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2767,7 +2747,7 @@ Mensual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -3259,7 +3239,7 @@ Dividendo apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3295,7 +3275,7 @@ Validando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3363,7 +3343,7 @@ Anual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -3371,7 +3351,7 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -5885,11 +5865,11 @@ Inversión apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7172,7 +7152,7 @@ El aviso de IA ha sido copiado al portapapeles apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7260,7 +7240,7 @@ Abrir Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7292,7 +7272,7 @@ Rendimiento apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index 4137eb9b1..f13b9246a 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -1322,7 +1322,7 @@ Se connecter apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1338,7 +1338,7 @@ Oups! Jeton de Sécurité Incorrect. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1712,10 +1712,6 @@ Today Aujourd’hui - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -1724,10 +1720,6 @@ YTD CDA - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -1736,10 +1728,6 @@ 1Y 1A - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -1748,10 +1736,6 @@ 5Y 5A - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -1760,10 +1744,6 @@ Max Max - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -1790,7 +1770,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -1802,7 +1782,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -1818,7 +1798,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -2502,7 +2482,7 @@ Import des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -2510,7 +2490,7 @@ L’import est terminé apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -2518,7 +2498,7 @@ Validation des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -2702,7 +2682,7 @@ Dividende apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -2722,7 +2702,7 @@ Mensuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -2986,7 +2966,7 @@ Importer Activités apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -3066,7 +3046,7 @@ Montant Total Prévu libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -3362,7 +3342,7 @@ Annuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -3370,7 +3350,7 @@ Importer Dividendes apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -5884,11 +5864,11 @@ Investissement apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7171,7 +7151,7 @@ Le prompt IA a été copié dans le presse-papiers apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Ouvrir Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Performance apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 18d523377..07bc27401 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -1011,7 +1011,7 @@ Accedi apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1027,7 +1027,7 @@ Ops! Token di sicurezza errato. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1397,10 +1397,6 @@ Today Oggi - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -1409,10 +1405,6 @@ YTD anno corrente - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -1421,10 +1413,6 @@ 1Y 1 anno - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -1433,10 +1421,6 @@ 5Y 5 anni - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -1445,10 +1429,6 @@ Max Massimo - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -1467,7 +1447,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -2331,7 +2311,7 @@ Importazione dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -2339,7 +2319,7 @@ L’importazione è stata completata apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -2471,7 +2451,7 @@ Importa le attività apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -2587,7 +2567,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -2603,7 +2583,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -2731,7 +2711,7 @@ Importo totale previsto libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2767,7 +2747,7 @@ Mensile apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -3259,7 +3239,7 @@ Dividendi apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3295,7 +3275,7 @@ Convalida dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3363,7 +3343,7 @@ Annuale apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -3371,7 +3351,7 @@ Importa i dividendi apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -5885,11 +5865,11 @@ Investimento apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7172,7 +7152,7 @@ L’AI prompt è stato copiato negli appunti apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7260,7 +7240,7 @@ Apri Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7292,7 +7272,7 @@ Prestazione apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index ca5e850b3..44259c0fd 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -1010,7 +1010,7 @@ Aanmelden apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1026,7 +1026,7 @@ Oeps! Onjuiste beveiligingstoken. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1396,10 +1396,6 @@ Today Vandaag - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -1408,10 +1404,6 @@ YTD YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -1420,10 +1412,6 @@ 1Y 1J - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -1432,10 +1420,6 @@ 5Y 5J - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -1444,10 +1428,6 @@ Max Max - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -1466,7 +1446,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -2330,7 +2310,7 @@ Gegevens importeren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -2338,7 +2318,7 @@ Importeren is voltooid apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -2470,7 +2450,7 @@ Activiteiten importeren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -2586,7 +2566,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -2602,7 +2582,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -2730,7 +2710,7 @@ Verwacht totaalbedrag libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -2766,7 +2746,7 @@ Maandelijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -3258,7 +3238,7 @@ Dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3294,7 +3274,7 @@ Gegevens valideren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3362,7 +3342,7 @@ Jaarlijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -3370,7 +3350,7 @@ Importeer dividenden apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -5884,11 +5864,11 @@ Investering apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7171,7 +7151,7 @@ AI-prompt is naar het klembord gekopieerd apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Prestatie apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 64e5ad94e..651b15e25 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -1995,7 +1995,7 @@ Zaloguj się apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -2011,7 +2011,7 @@ Ups! Nieprawidłowy token bezpieczeństwa. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -2673,10 +2673,6 @@ Today Dziś - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -2685,10 +2681,6 @@ YTD Liczony od początku roku (year-to-date) - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -2697,10 +2689,6 @@ 1Y 1 rok - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -2709,10 +2697,6 @@ 5Y 5 lat - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -2721,10 +2705,6 @@ Max Maksimum - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -3015,7 +2995,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -3027,7 +3007,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -3043,7 +3023,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -3999,7 +3979,7 @@ Importuj Aktywności apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -4007,7 +3987,7 @@ Impotruj Dywidendy apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -4015,7 +3995,7 @@ Importowanie danych... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -4023,7 +4003,7 @@ Importowanie zakończone apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -4031,7 +4011,7 @@ Weryfikacja danych... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -4303,7 +4283,7 @@ Dywidenda apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -4323,7 +4303,7 @@ Miesięcznie apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -4331,7 +4311,7 @@ Rocznie apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -5244,7 +5224,7 @@ Przewidywana Łączna Kwota libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -5884,11 +5864,11 @@ Inwestycje apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7171,7 +7151,7 @@ Prompt AI został skopiowany do schowka apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Otwórz Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Wydajność apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index ecbcbf0dc..a0af13730 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -1194,7 +1194,7 @@ Iniciar sessão apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1210,7 +1210,7 @@ Oops! Token de Segurança Incorreto. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1696,10 +1696,6 @@ Today Hoje - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -1708,10 +1704,6 @@ YTD AATD - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -1720,10 +1712,6 @@ 1Y 1A - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -1732,10 +1720,6 @@ 5Y 5A - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -1744,10 +1728,6 @@ Max Máx - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -1774,7 +1754,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -1786,7 +1766,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -1802,7 +1782,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -2442,7 +2422,7 @@ A importar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -2450,7 +2430,7 @@ A importação foi concluída apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -2618,7 +2598,7 @@ Mensalmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -2866,7 +2846,7 @@ Importar Atividades apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -2946,7 +2926,7 @@ Montante Total Projetado libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -3290,7 +3270,7 @@ A validar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3314,7 +3294,7 @@ Dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3362,7 +3342,7 @@ Anualmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -3370,7 +3350,7 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -5884,11 +5864,11 @@ Investimento apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7171,7 +7151,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Performance apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8181,7 +8161,7 @@ Emerging Markets - Emerging Markets + Mercados Emergentes apps/client/src/app/pages/i18n/i18n-page.html 113 @@ -8213,7 +8193,7 @@ No accounts have been set up - No accounts have been set up + Nenhuma conta foi configurada apps/client/src/app/pages/i18n/i18n-page.html 20 @@ -8221,7 +8201,7 @@ Your net worth is managed by 0 accounts - Your net worth is managed by 0 accounts + Seu patrimônio líquido é gerenciado por 0 contas apps/client/src/app/pages/i18n/i18n-page.html 32 @@ -8229,7 +8209,7 @@ Asia-Pacific - Asia-Pacific + Ásia-Pacífico apps/client/src/app/pages/i18n/i18n-page.html 152 @@ -8261,7 +8241,7 @@ Emerging Markets - Emerging Markets + Mercados Emergentes apps/client/src/app/pages/i18n/i18n-page.html 166 @@ -8293,7 +8273,7 @@ Europe - Europe + Europa apps/client/src/app/pages/i18n/i18n-page.html 182 @@ -8325,7 +8305,7 @@ Japan - Japan + Japão apps/client/src/app/pages/i18n/i18n-page.html 196 @@ -8357,7 +8337,7 @@ North America - North America + América do Norte apps/client/src/app/pages/i18n/i18n-page.html 210 @@ -8389,7 +8369,7 @@ Find Ghostfolio on GitHub - Find Ghostfolio on GitHub + Encontre o Ghostfolio no GitHub apps/client/src/app/pages/about/overview/about-overview-page.html 74 @@ -8401,7 +8381,7 @@ Join the Ghostfolio Slack community - Join the Ghostfolio Slack community + Junte-se à comunidade do Ghostfolio Slack apps/client/src/app/pages/about/overview/about-overview-page.html 84 @@ -8409,7 +8389,7 @@ Follow Ghostfolio on X (formerly Twitter) - Follow Ghostfolio on X (formerly Twitter) + Siga o Ghostfolio no X (antigo Twitter) apps/client/src/app/pages/about/overview/about-overview-page.html 93 @@ -8417,7 +8397,7 @@ Send an e-mail - Send an e-mail + Enviar um e-mail apps/client/src/app/pages/about/overview/about-overview-page.html 103 @@ -8425,7 +8405,7 @@ Follow Ghostfolio on LinkedIn - Follow Ghostfolio on LinkedIn + Siga o Ghostfolio no LinkedIn apps/client/src/app/pages/about/overview/about-overview-page.html 122 @@ -8433,7 +8413,7 @@ Ghostfolio is an independent & bootstrapped business - Ghostfolio is an independent & bootstrapped business + Ghostfolio é um negócio independente e autossuficiente apps/client/src/app/pages/about/overview/about-overview-page.html 132 @@ -8441,7 +8421,7 @@ Support Ghostfolio - Support Ghostfolio + Apoie o Ghostfolio apps/client/src/app/pages/about/overview/about-overview-page.html 141 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 29867abcd..84b990640 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -1843,7 +1843,7 @@ Giriş apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1859,7 +1859,7 @@ Hay Allah! Güvenlik anahtarı yanlış. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -2513,10 +2513,6 @@ Today Bugün - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -2525,10 +2521,6 @@ YTD YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -2537,10 +2529,6 @@ 1Y 1Y - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -2549,10 +2537,6 @@ 5Y 5Y - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -2561,10 +2545,6 @@ Max Maks. - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -2591,7 +2571,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -2603,7 +2583,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -2619,7 +2599,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -3479,7 +3459,7 @@ İşlemleri İçe Aktar apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -3487,7 +3467,7 @@ Temettüleri İçe Aktar apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -3495,7 +3475,7 @@ Veri içe aktarılıyor... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -3503,7 +3483,7 @@ İçe aktarma tamamlandı apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -3511,7 +3491,7 @@ Veri doğrulanıyor... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3791,7 +3771,7 @@ Temettü apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3811,7 +3791,7 @@ Aylık apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -3819,7 +3799,7 @@ Yıllık apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -4960,7 +4940,7 @@ Hesaplanan Toplam Tutar libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -5884,11 +5864,11 @@ Yatırım apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7171,7 +7151,7 @@ Yapay zeka istemi panoya kopyalandı apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Duck.ai’yi aç apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Performans apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 68b809f88..31de6c802 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -22,7 +22,7 @@ Увійти apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -2295,7 +2295,7 @@ Упс! Неправильний Секретний Токен. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -3057,10 +3057,6 @@ Today Сьогодні - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -3069,10 +3065,6 @@ YTD З початку року - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -3081,10 +3073,6 @@ 1Y 1 рік - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -3093,10 +3081,6 @@ 5Y 5 років - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -3105,10 +3089,6 @@ Max Максимум - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -3203,7 +3183,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -3527,7 +3507,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -3547,7 +3527,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -4600,7 +4580,7 @@ Імпортувати активності apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -4608,7 +4588,7 @@ Імпорт дивідендів apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -4616,7 +4596,7 @@ Імпортуються дані... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -4624,7 +4604,7 @@ Імпорт завершено apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -4632,7 +4612,7 @@ Перевірка даних... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -4936,7 +4916,7 @@ Дивіденди apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -4948,11 +4928,11 @@ Інвестиції apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -4964,7 +4944,7 @@ Щомісячно apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -4972,7 +4952,7 @@ Щорічно apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -6431,7 +6411,7 @@ Прогнозована загальна сума libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -7179,7 +7159,7 @@ Запит AI скопійовано в буфер обміну apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7259,7 +7239,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7291,7 +7271,7 @@ Performance apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 5958052ff..9ec300d4c 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -1885,7 +1885,7 @@ Sign in apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -1900,7 +1900,7 @@ Oops! Incorrect Security Token. apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -2502,10 +2502,6 @@ Today - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -2513,10 +2509,6 @@ YTD - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -2524,10 +2516,6 @@ 1Y - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -2535,10 +2523,6 @@ 5Y - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -2546,10 +2530,6 @@ Max - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -2807,7 +2787,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -2818,7 +2798,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -2833,7 +2813,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -3682,35 +3662,35 @@ Import Activities apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 Import Dividends apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 Importing data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 Import has been completed apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 Validating data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -3953,7 +3933,7 @@ Dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -3971,14 +3951,14 @@ Monthly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 Yearly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -4838,7 +4818,7 @@ Projected Total Amount libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -5374,11 +5354,11 @@ Investment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -6485,7 +6465,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -6562,7 +6542,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -6590,7 +6570,7 @@ Performance apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index 83205275d..1c7301eb2 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -2004,7 +2004,7 @@ 登入 apps/client/src/app/components/header/header.component.ts - 257 + 259 libs/common/src/lib/routes/routes.ts @@ -2020,7 +2020,7 @@ 哎呀!安全令牌不正确。 apps/client/src/app/components/header/header.component.ts - 272 + 274 apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -2682,10 +2682,6 @@ Today 今天 - - apps/client/src/app/components/toggle/toggle.component.ts - 24 - libs/ui/src/lib/assistant/assistant.component.ts 348 @@ -2694,10 +2690,6 @@ YTD 年初至今 - - apps/client/src/app/components/toggle/toggle.component.ts - 25 - libs/ui/src/lib/assistant/assistant.component.ts 360 @@ -2706,10 +2698,6 @@ 1Y 1年 - - apps/client/src/app/components/toggle/toggle.component.ts - 26 - libs/ui/src/lib/assistant/assistant.component.ts 370 @@ -2718,10 +2706,6 @@ 5Y 5年 - - apps/client/src/app/components/toggle/toggle.component.ts - 27 - libs/ui/src/lib/assistant/assistant.component.ts 395 @@ -2730,10 +2714,6 @@ Max 最大限度 - - apps/client/src/app/components/toggle/toggle.component.ts - 28 - libs/ui/src/lib/assistant/assistant.component.ts 401 @@ -3024,7 +3004,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 183 + 186 @@ -3036,7 +3016,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 181 + 184 @@ -3052,7 +3032,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 184 + 187 @@ -4008,7 +3988,7 @@ 导入活动记录 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 84 + 86 @@ -4016,7 +3996,7 @@ 导入股息 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 127 + 129 @@ -4024,7 +4004,7 @@ 正在导入数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 165 + 167 @@ -4032,7 +4012,7 @@ 导入已完成 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 173 + 176 @@ -4040,7 +4020,7 @@ 验证数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 281 + 284 @@ -4312,7 +4292,7 @@ 股息 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 74 + 73 libs/ui/src/lib/i18n.ts @@ -4332,7 +4312,7 @@ 每月 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 89 + 88 @@ -4340,7 +4320,7 @@ 每年 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 90 + 89 @@ -5301,7 +5281,7 @@ 预计总额 libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 57 + 59 @@ -5909,11 +5889,11 @@ 投资 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 79 + 78 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 95 + 94 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -7172,7 +7152,7 @@ AI 提示已复制到剪贴板 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 198 + 197 @@ -7260,7 +7240,7 @@ 打开 Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 199 + 198 @@ -7292,7 +7272,7 @@ 表现 apps/client/src/app/components/home-overview/home-overview.component.ts - 57 + 55 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 5aee7e0e6..467716575 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -1,4 +1,4 @@ -import { AssetClass, AssetSubClass, DataSource } from '@prisma/client'; +import { AssetClass, AssetSubClass, DataSource, Type } from '@prisma/client'; import { JobOptions, JobStatus } from 'bull'; import ms from 'ms'; @@ -118,6 +118,12 @@ export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true }; +export const INVESTMENT_ACTIVITY_TYPES = [ + Type.BUY, + Type.DIVIDEND, + Type.SELL +] as Type[]; + export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME = 'PORTFOLIO'; export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true diff --git a/libs/common/src/lib/interfaces/export.interface.ts b/libs/common/src/lib/interfaces/export.interface.ts index 905e33b06..16a49b0ef 100644 --- a/libs/common/src/lib/interfaces/export.interface.ts +++ b/libs/common/src/lib/interfaces/export.interface.ts @@ -8,6 +8,7 @@ import { } from '@prisma/client'; import { AccountBalance } from './account-balance.interface'; +import { MarketData } from './market-data.interface'; export interface Export { accounts: (Omit & { @@ -23,8 +24,11 @@ export interface Export { | 'updatedAt' | 'userId' > & { dataSource: DataSource; date: string; symbol: string })[]; - assetProfiles: (Omit & { - marketData: { date: string; marketPrice: number }[]; + assetProfiles: (Omit< + SymbolProfile, + 'createdAt' | 'id' | 'updatedAt' | 'userId' + > & { + marketData: MarketData[]; })[]; meta: { date: string; diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index 611a5c963..52ca76b3a 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -25,6 +25,7 @@ import type { InfoItem } from './info-item.interface'; import type { InvestmentItem } from './investment-item.interface'; import type { LineChartItem } from './line-chart-item.interface'; import type { LookupItem } from './lookup-item.interface'; +import type { MarketData } from './market-data.interface'; import type { PortfolioChart } from './portfolio-chart.interface'; import type { PortfolioDetails } from './portfolio-details.interface'; import type { PortfolioDividends } from './portfolio-dividends.interface'; @@ -111,6 +112,7 @@ export { LineChartItem, LookupItem, LookupResponse, + MarketData, MarketDataDetailsResponse, MarketDataOfMarketsResponse, OAuthResponse, diff --git a/libs/common/src/lib/interfaces/market-data.interface.ts b/libs/common/src/lib/interfaces/market-data.interface.ts new file mode 100644 index 000000000..b7a410cba --- /dev/null +++ b/libs/common/src/lib/interfaces/market-data.interface.ts @@ -0,0 +1,4 @@ +export interface MarketData { + date: string; + marketPrice: number; +} diff --git a/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts b/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts index 35ff033eb..7ede7a5ed 100644 --- a/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts +++ b/libs/common/src/lib/interfaces/responses/portfolio-report.interface.ts @@ -1,9 +1,11 @@ import { PortfolioReportRule } from '../portfolio-report-rule.interface'; export interface PortfolioReportResponse { - rules: { [group: string]: PortfolioReportRule[] }; - statistics: { - rulesActiveCount: number; - rulesFulfilledCount: number; + 'x-ray': { + rules: { [group: string]: PortfolioReportRule[] }; + statistics: { + rulesActiveCount: number; + rulesFulfilledCount: number; + }; }; } diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index dd9a821b6..51d847300 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -101,6 +101,33 @@ export const personalFinanceTools: Product[] = [ regions: ['Global'], slogan: 'Take control of your financial future' }, + { + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'capitally', + name: 'Capitally', + origin: 'Poland', + pricingPerYear: '€50', + slogan: 'Optimize your investments performance' + }, + { + founded: 2022, + isArchived: true, + key: 'capmon', + name: 'CapMon.org', + origin: 'Germany', + note: 'CapMon.org was discontinued in 2023', + slogan: 'Next Generation Assets Tracking' + }, + { + founded: 2024, + hasFreePlan: true, + isOpenSource: true, + key: 'cleverbilling', + languages: ['Español'], + name: 'CleverBilling', + slogan: 'Toma el control total de tus finanzas.' + }, { founded: 2017, hasFreePlan: true, @@ -122,35 +149,6 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$120', slogan: 'The leading Crypto Portfolio Tracker & Tax Calculator' }, - { - founded: 2022, - hasFreePlan: true, - hasSelfHostingAbility: false, - key: 'degiro-portfolio-tracker-by-capitalyse', - languages: ['English'], - name: 'DEGIRO Portfolio Tracker by Capitalyse', - origin: 'Netherlands', - pricingPerYear: '€24', - slogan: 'Democratizing Data Analytics' - }, - { - hasFreePlan: true, - hasSelfHostingAbility: false, - key: 'capitally', - name: 'Capitally', - origin: 'Poland', - pricingPerYear: '€50', - slogan: 'Optimize your investments performance' - }, - { - founded: 2022, - isArchived: true, - key: 'capmon', - name: 'CapMon.org', - origin: 'Germany', - note: 'CapMon.org was discontinued in 2023', - slogan: 'Next Generation Assets Tracking' - }, { founded: 2019, key: 'compound-planning', @@ -183,6 +181,28 @@ export const personalFinanceTools: Product[] = [ name: 'De.Fi', slogan: 'DeFi Portfolio Tracker' }, + { + founded: 2016, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'defi-portfolio-tracker-by-zerion', + languages: ['English'], + name: 'DeFi Portfolio Tracker by Zerion', + origin: 'United States', + pricingPerYear: '$99', + slogan: 'DeFi Portfolio Tracker for All Chains' + }, + { + founded: 2022, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'degiro-portfolio-tracker-by-capitalyse', + languages: ['English'], + name: 'DEGIRO Portfolio Tracker by Capitalyse', + origin: 'Netherlands', + pricingPerYear: '€24', + slogan: 'Democratizing Data Analytics' + }, { founded: 2017, hasFreePlan: true, @@ -194,6 +214,15 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$150', slogan: 'The app to track all your investments. Make smart moves only.' }, + { + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'digrin', + languages: ['English'], + name: 'Digrin', + pricingPerYear: '$49.90', + slogan: 'Dividend Portfolio Tracker' + }, { founded: 2019, hasFreePlan: true, @@ -464,12 +493,11 @@ export const personalFinanceTools: Product[] = [ }, { founded: 2021, - hasSelfHostingAbility: false, isArchived: true, key: 'maybe-finance', languages: ['English'], name: 'Maybe Finance', - note: 'Maybe Finance was discontinued in 2023', + note: 'Maybe Finance was discontinued in 2023, relaunched in 2024, and discontinued again in 2025', origin: 'United States', pricingPerYear: '$145', regions: ['United States'], @@ -532,6 +560,17 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$60', slogan: 'Gain financial control and keep your data private.' }, + { + founded: 2025, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'monsy', + languages: ['English'], + name: 'Monsy', + origin: 'Indonesia', + pricingPerYear: '$20', + slogan: 'Smart, simple, stress-free money tracking.' + }, { hasFreePlan: true, hasSelfHostingAbility: false, @@ -858,6 +897,16 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$348', slogan: 'Virtual Family Office for Smart Wealth Management' }, + { + founded: 2020, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'walletguide', + name: 'Walletguide', + origin: 'Germany', + pricingPerYear: '€90', + slogan: 'Personal finance reimagined with AI' + }, { hasSelfHostingAbility: false, key: 'wallmine', diff --git a/libs/ui/src/lib/activity-type/activity-type.component.stories.ts b/libs/ui/src/lib/activity-type/activity-type.component.stories.ts new file mode 100644 index 000000000..349cf6a7b --- /dev/null +++ b/libs/ui/src/lib/activity-type/activity-type.component.stories.ts @@ -0,0 +1,30 @@ +import { CommonModule } from '@angular/common'; +import { IonIcon } from '@ionic/angular/standalone'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; + +import { GfActivityTypeComponent } from './activity-type.component'; + +export default { + title: 'Activity Type', + component: GfActivityTypeComponent, + decorators: [ + moduleMetadata({ + imports: [CommonModule, IonIcon] + }) + ], + argTypes: { + activityType: { + control: 'select', + options: ['BUY', 'DIVIDEND', 'FEE', 'INTEREST', 'LIABILITY', 'SELL'] + } + } +} as Meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + activityType: 'BUY' + } +}; diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html index 31c7b334d..60d5204e1 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html @@ -31,7 +31,9 @@ Retirement Date

- {{ calculatorForm.get('retirementDate').value | date: 'MMMM YYYY' }} + {{ + calculatorForm.get('retirementDate')?.value | date: 'MMMM yyyy' + }}
; + +type Story = StoryObj; + +export const Default: Story = { + args: { + defaultValue: '1d', + isLoading: false, + options: [ + { label: 'Today', value: '1d' }, + { label: 'YTD', value: 'ytd' }, + { label: '1Y', value: '1y' }, + { label: '5Y', value: '5y' }, + { label: 'Max', value: 'max' } + ] + } +}; diff --git a/apps/client/src/app/components/toggle/toggle.component.ts b/libs/ui/src/lib/toggle/toggle.component.ts similarity index 66% rename from apps/client/src/app/components/toggle/toggle.component.ts rename to libs/ui/src/lib/toggle/toggle.component.ts index 8f1a13df3..be460f7fa 100644 --- a/apps/client/src/app/components/toggle/toggle.component.ts +++ b/libs/ui/src/lib/toggle/toggle.component.ts @@ -20,19 +20,11 @@ import { MatRadioModule } from '@angular/material/radio'; templateUrl: './toggle.component.html' }) export class GfToggleComponent implements OnChanges { - public static DEFAULT_DATE_RANGE_OPTIONS: ToggleOption[] = [ - { label: $localize`Today`, value: '1d' }, - { label: $localize`YTD`, value: 'ytd' }, - { label: $localize`1Y`, value: '1y' }, - { label: $localize`5Y`, value: '5y' }, - { label: $localize`Max`, value: 'max' } - ]; - @Input() defaultValue: string; @Input() isLoading: boolean; - @Input() options: ToggleOption[]; + @Input() options: ToggleOption[] = []; - @Output() change = new EventEmitter>(); + @Output() valueChange = new EventEmitter>(); public optionFormControl = new FormControl(undefined); @@ -41,6 +33,6 @@ export class GfToggleComponent implements OnChanges { } public onValueChange() { - this.change.emit({ value: this.optionFormControl.value }); + this.valueChange.emit({ value: this.optionFormControl.value }); } } diff --git a/package-lock.json b/package-lock.json index 2183cfaef..de5631a10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.184.0", + "version": "2.185.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.184.0", + "version": "2.185.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 86ff201e0..c9fc0f07d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.184.0", + "version": "2.185.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", diff --git a/test/import/ok/sample.json b/test/import/ok/sample.json index 01bcc60d9..4ebb323de 100644 --- a/test/import/ok/sample.json +++ b/test/import/ok/sample.json @@ -16,6 +16,7 @@ "value": 1000 } ], + "comment": null, "currency": "USD", "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", "isExcluded": false, @@ -23,30 +24,80 @@ "platformId": null } ], + "assetProfiles": [ + { + "assetClass": null, + "assetSubClass": null, + "comment": null, + "countries": [], + "currency": "USD", + "cusip": null, + "dataSource": "MANUAL", + "figi": null, + "figiComposite": null, + "figiShareClass": null, + "holdings": [], + "isActive": true, + "isin": null, + "marketData": [], + "name": "Account Opening Fee", + "scraperConfiguration": null, + "sectors": [], + "symbol": "14a69cb9-1e31-43fa-b320-83703d8ed74b", + "symbolMapping": {}, + "url": null + }, + { + "assetClass": null, + "assetSubClass": null, + "comment": null, + "countries": [], + "currency": "USD", + "cusip": null, + "dataSource": "MANUAL", + "figi": null, + "figiComposite": null, + "figiShareClass": null, + "holdings": [], + "isActive": true, + "isin": null, + "marketData": [], + "name": "Penthouse Apartment", + "scraperConfiguration": null, + "sectors": [], + "symbol": "7e91b7d4-1430-4212-8380-289a06c9bbc1", + "symbolMapping": {}, + "url": null + } + ], + "platforms": [], + "tags": [], "activities": [ { "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", "comment": null, - "fee": 0, + "fee": 49, "quantity": 0, - "type": "BUY", + "type": "FEE", "unitPrice": 0, "currency": "USD", - "dataSource": "YAHOO", - "date": "2050-06-06T00:00:00.000Z", - "symbol": "US5949181045" + "dataSource": "MANUAL", + "date": "2021-09-01T00:00:00.000Z", + "symbol": "14a69cb9-1e31-43fa-b320-83703d8ed74b", + "tags": [] }, { - "accountId": null, - "comment": null, - "fee": 0, - "quantity": 1, + "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", + "comment": "My first order 🤓", + "fee": 19, + "quantity": 5, "type": "BUY", - "unitPrice": 500000, + "unitPrice": 298.58, "currency": "USD", - "dataSource": "MANUAL", - "date": "2022-01-01T00:00:00.000Z", - "symbol": "Penthouse Apartment" + "dataSource": "YAHOO", + "date": "2021-09-16T00:00:00.000Z", + "symbol": "MSFT", + "tags": [] }, { "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", @@ -58,31 +109,39 @@ "currency": "USD", "dataSource": "YAHOO", "date": "2021-11-17T00:00:00.000Z", - "symbol": "MSFT" + "symbol": "MSFT", + "tags": [] }, { - "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "comment": "My first order 🤓", - "fee": 19, - "quantity": 5, + "accountId": null, + "comment": null, + "fee": 0, + "quantity": 1, "type": "BUY", - "unitPrice": 298.58, + "unitPrice": 500000, "currency": "USD", - "dataSource": "YAHOO", - "date": "2021-09-16T00:00:00.000Z", - "symbol": "MSFT" + "dataSource": "MANUAL", + "date": "2022-01-01T00:00:00.000Z", + "symbol": "7e91b7d4-1430-4212-8380-289a06c9bbc1", + "tags": [] }, { "accountId": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", "comment": null, - "fee": 49, + "fee": 0, "quantity": 0, - "type": "FEE", + "type": "BUY", "unitPrice": 0, "currency": "USD", - "dataSource": "MANUAL", - "date": "2021-09-01T00:00:00.000Z", - "symbol": "Account Opening Fee" + "dataSource": "YAHOO", + "date": "2050-06-06T00:00:00.000Z", + "symbol": "MSFT", + "tags": [] + } + ], + "user": { + "settings": { + "currency": "USD" } - ] + } }