Browse Source

Merge branch 'main' into fix/fix-charts-for-ytd

pull/1598/head
Thomas Kaul 3 years ago
committed by GitHub
parent
commit
612f447f3b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      CHANGELOG.md
  2. 77
      README.md
  3. 28
      apps/api/src/app/import/import.controller.ts
  4. 6
      apps/api/src/app/import/import.module.ts
  5. 93
      apps/api/src/app/import/import.service.ts
  6. 5
      apps/api/src/app/info/info.service.ts
  7. 34
      apps/api/src/app/portfolio/portfolio.service.ts
  8. 37
      apps/api/src/helper/object.helper.ts
  9. 71
      apps/api/src/interceptors/transform-data-source-in-response.interceptor.ts
  10. 7
      apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts
  11. 7
      apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts
  12. 9
      apps/api/src/models/rules/currency-cluster-risk/current-investment.ts
  13. 7
      apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts
  14. 14
      apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts
  15. 6
      apps/api/src/services/data-provider/data-provider.module.ts
  16. 21
      apps/api/src/services/data-provider/data-provider.service.ts
  17. 14
      apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
  18. 14
      apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts
  19. 14
      apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts
  20. 12
      apps/api/src/services/data-provider/interfaces/data-provider.interface.ts
  21. 14
      apps/api/src/services/data-provider/manual/manual.service.ts
  22. 14
      apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts
  23. 103
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
  24. 2
      apps/client/src/app/app.component.scss
  25. 2
      apps/client/src/app/components/access-table/access-table.component.scss
  26. 2
      apps/client/src/app/components/accounts-table/accounts-table.component.scss
  27. 2
      apps/client/src/app/components/admin-jobs/admin-jobs.scss
  28. 2
      apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.scss
  29. 2
      apps/client/src/app/components/admin-market-data/admin-market-data.scss
  30. 2
      apps/client/src/app/components/admin-overview/admin-overview.scss
  31. 2
      apps/client/src/app/components/admin-users/admin-users.scss
  32. 2
      apps/client/src/app/components/header/header.component.scss
  33. 2
      apps/client/src/app/components/home-holdings/home-holdings.scss
  34. 2
      apps/client/src/app/components/home-market/home-market.scss
  35. 2
      apps/client/src/app/components/home-overview/home-overview.scss
  36. 2
      apps/client/src/app/components/home-summary/home-summary.scss
  37. 2
      apps/client/src/app/components/positions/positions.component.scss
  38. 9
      apps/client/src/app/components/world-map-chart/world-map-chart.component.ts
  39. 8
      apps/client/src/app/pages/account/account-page.html
  40. 2
      apps/client/src/app/pages/admin/admin-page.scss
  41. 2
      apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html
  42. 2
      apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html
  43. 8
      apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html
  44. 4
      apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html
  45. 2
      apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html
  46. 43
      apps/client/src/app/pages/faq/faq-page.html
  47. 3
      apps/client/src/app/pages/features/features-page.html
  48. 2
      apps/client/src/app/pages/home/home-page.scss
  49. 18
      apps/client/src/app/pages/landing/landing-page.component.ts
  50. 15
      apps/client/src/app/pages/landing/landing-page.html
  51. 2
      apps/client/src/app/pages/landing/landing-page.module.ts
  52. 6
      apps/client/src/app/pages/landing/landing-page.scss
  53. 20
      apps/client/src/app/pages/portfolio/activities/activities-page.component.ts
  54. 1
      apps/client/src/app/pages/portfolio/activities/activities-page.html
  55. 69
      apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts
  56. 31
      apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html
  57. 9
      apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.module.ts
  58. 2
      apps/client/src/app/pages/portfolio/activities/import-activities-dialog/interfaces/interfaces.ts
  59. 6
      apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
  60. 3
      apps/client/src/app/pages/portfolio/allocations/allocations-page.html
  61. 2
      apps/client/src/app/pages/portfolio/portfolio-page.scss
  62. 2
      apps/client/src/app/pages/pricing/pricing-page.html
  63. 2
      apps/client/src/app/pages/zen/zen-page.scss
  64. 7
      apps/client/src/app/services/data.service.ts
  65. 4
      apps/client/src/app/services/import-activities.service.ts
  66. 40
      apps/client/src/assets/sitemap.xml
  67. 90
      apps/client/src/locales/messages.de.xlf
  68. 90
      apps/client/src/locales/messages.es.xlf
  69. 727
      apps/client/src/locales/messages.fr.xlf
  70. 90
      apps/client/src/locales/messages.it.xlf
  71. 90
      apps/client/src/locales/messages.nl.xlf
  72. 90
      apps/client/src/locales/messages.pt.xlf
  73. 86
      apps/client/src/locales/messages.xlf
  74. 4
      apps/client/src/styles.scss
  75. 74
      apps/client/src/styles/bootstrap.scss
  76. 2
      apps/client/src/styles/ghostfolio-style.scss
  77. 1
      libs/common/src/lib/config.ts
  78. 2
      libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts
  79. 1
      libs/common/src/lib/interfaces/historical-data-item.interface.ts
  80. 2
      libs/common/src/lib/interfaces/info-item.interface.ts
  81. 3
      libs/common/src/lib/types/account-with-platform.type.ts
  82. 2
      libs/common/src/lib/types/index.ts
  83. 4
      libs/common/src/lib/types/order-with-account.type.ts
  84. 2
      libs/ui/src/lib/activities-filter/activities-filter.component.scss
  85. 21
      libs/ui/src/lib/activities-table/activities-table.component.html
  86. 2
      libs/ui/src/lib/activities-table/activities-table.component.scss
  87. 15
      libs/ui/src/lib/activities-table/activities-table.component.ts
  88. 2
      libs/ui/src/lib/holdings-table/holdings-table.component.scss
  89. 2
      package.json

27
CHANGELOG.md

@ -11,6 +11,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed the grouping by month / year of the dividend and investment timeline
## 1.226.0 - 2023-01-11
### Added
- Added the language localization for Français (`fr`)
- Extended the landing page by a global heat map of subscribers
- Added support for the thousand separator in the global heat map component
### Changed
- Improved the form of the import dividends dialog (disable while loading)
- Removed the deprecated `~` in _Sass_ imports
### Fixed
- Fixed an exception in the _X-ray_ section
## 1.225.0 - 2023-01-07
### Added
- Added support for importing dividends from a data provider
### Changed
- Extended the Frequently Asked Questions (FAQ) page
## 1.224.0 - 2023-01-04
### Added

77
README.md

@ -1,34 +1,26 @@
<div align="center">
<a href="https://ghostfol.io">
<img
alt="Ghostfolio Logo"
src="https://avatars.githubusercontent.com/u/82473144?s=200"
width="100"
/>
</a>
<h1>Ghostfolio</h1>
<p>
<strong>Open Source Wealth Management Software</strong>
</p>
<p>
<a href="https://ghostfol.io"><strong>Ghostfol.io</strong></a><a href="https://ghostfol.io/en/demo"><strong>Live Demo</strong></a> | <a href="https://ghostfol.io/en/pricing"><strong>Ghostfolio Premium</strong></a> | <a href="https://ghostfol.io/en/faq"><strong>FAQ</strong></a> | <a href="https://ghostfol.io/en/blog"><strong>Blog</strong></a> | <a href="https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg"><strong>Slack</strong></a> | <a href="https://twitter.com/ghostfolio_"><strong>Twitter</strong></a>
</p>
<p>
<a href="https://www.buymeacoffee.com/ghostfolio">
<img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-Support-yellow?logo=buymeacoffee"/></a>
<a href="#contributing">
<img src="https://img.shields.io/badge/Contributions-Welcome-orange.svg"/></a>
<a href="https://www.gnu.org/licenses/agpl-3.0" rel="nofollow">
<img src="https://img.shields.io/badge/License-AGPL%20v3-blue.svg" alt="License: AGPL v3"/></a>
</p>
[<img src="https://avatars.githubusercontent.com/u/82473144?s=200" width="100" alt="Ghostfolio logo">](https://ghostfol.io)
# Ghostfolio
**Open Source Wealth Management Software**
[**Ghostfol.io**](https://ghostfol.io) | [**Live Demo**](https://ghostfol.io/en/demo) | [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) | [**FAQ**](https://ghostfol.io/en/faq) |
[**Blog**](https://ghostfol.io/en/blog) | [**Slack**](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) | [**Twitter**](https://twitter.com/ghostfolio_)
[![Shield: Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-Support-yellow?logo=buymeacoffee)](https://www.buymeacoffee.com/ghostfolio)
[![Shield: Contributions Welcome](https://img.shields.io/badge/Contributions-Welcome-orange.svg)](#contributing)
[![Shield: License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
</div>
**Ghostfolio** is an open source wealth management software built with web technology. The application empowers busy people to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. The software is designed for personal use in continuous operation.
<div align="center" style="margin-top: 1rem; margin-bottom: 1rem;">
<a href="https://www.youtube.com/watch?v=yY6ObSQVJZk">
<img src="./apps/client/src/assets/images/video-preview.jpg" width="600"></a>
<div align="center">
[<img src="./apps/client/src/assets/images/video-preview.jpg" width="600" alt="Preview image of the Ghostfolio video trailer">](https://www.youtube.com/watch?v=yY6ObSQVJZk)
</div>
## Ghostfolio Premium
@ -48,7 +40,7 @@ Ghostfolio is for you if you are...
- 🧘 into minimalism
- 🧺 caring about diversifying your financial resources
- 🆓 interested in financial independence
- 🙅 saying no to spreadsheets in 2022
- 🙅 saying no to spreadsheets in 2023
- 😎 still reading this list
## Features
@ -63,8 +55,10 @@ Ghostfolio is for you if you are...
- ✅ Zen Mode
- ✅ Progressive Web App (PWA) with a mobile-first design
<div align="center" style="margin-top: 1rem; margin-bottom: 1rem;">
<img src="./apps/client/src/assets/images/screenshot.png" width="300">
<div align="center">
<img src="./apps/client/src/assets/images/screenshot.png" width="300" alt="Image of a phone showing the Ghostfolio app open">
</div>
## Technology Stack
@ -84,13 +78,9 @@ The frontend is built with [Angular](https://angular.io) and uses [Angular Mater
We provide official container images hosted on [Docker Hub](https://hub.docker.com/r/ghostfolio/ghostfolio) for `linux/amd64` and `linux/arm64`.
<div align="center">
<a href="https://www.buymeacoffee.com/ghostfolio">
<img
alt="Buy me a coffee button"
src="./apps/client/src/assets/images/button-buy-me-a-coffee.png"
width="150"
/>
</a>
[<img src="./apps/client/src/assets/images/button-buy-me-a-coffee.png" width="150" alt="Buy me a coffee button"/>](https://www.buymeacoffee.com/ghostfolio)
</div>
### Supported Environment Variables
@ -175,10 +165,13 @@ Please follow the instructions of the Ghostfolio [Unraid Community App](https://
### Start Server
<ol type="a">
<li>Debug: Run <code>yarn watch:server</code> and click "Launch Program" in <a href="https://code.visualstudio.com">Visual Studio Code</a></li>
<li>Serve: Run <code>yarn start:server</code></li>
</ol>
#### Debug
Run `yarn watch:server` and click _Launch Program_ in [Visual Studio Code](https://code.visualstudio.com)
#### Serve
Run `yarn start:server`
### Start Client
@ -278,10 +271,10 @@ Ghostfolio is **100% free** and **open source**. We encourage and support an act
Not sure what to work on? We have got some ideas. Please join the Ghostfolio [Slack channel](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg), tweet to [@ghostfolio\_](https://twitter.com/ghostfolio_) or send an e-mail to hi@ghostfol.io. We would love to hear from you.
If you like to support this project, get **[Ghostfolio Premium](https://ghostfol.io/en/pricing)** or **[Buy me a coffee](https://www.buymeacoffee.com/ghostfolio)**.
If you like to support this project, get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio).
## License
© 2022 [Ghostfolio](https://ghostfol.io)
© 2023 [Ghostfolio](https://ghostfol.io)
Licensed under the [AGPLv3 License](https://www.gnu.org/licenses/agpl-3.0.html).

28
apps/api/src/app/import/import.controller.ts

@ -1,19 +1,26 @@
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor';
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor';
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
import { ImportResponse } from '@ghostfolio/common/interfaces';
import type { RequestWithUser } from '@ghostfolio/common/types';
import {
Body,
Controller,
Get,
HttpException,
Inject,
Logger,
Param,
Post,
Query,
UseGuards
UseGuards,
UseInterceptors
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { DataSource } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { isEmpty } from 'lodash';
import { ImportDataDto } from './import-data.dto';
import { ImportService } from './import.service';
@ -74,4 +81,23 @@ export class ImportController {
);
}
}
@Get('dividends/:dataSource/:symbol')
@UseGuards(AuthGuard('jwt'))
@UseInterceptors(TransformDataSourceInRequestInterceptor)
@UseInterceptors(TransformDataSourceInResponseInterceptor)
public async gatherDividends(
@Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string
): Promise<ImportResponse> {
const userCurrency = this.request.user.Settings.settings.baseCurrency;
const activities = await this.importService.getDividends({
dataSource,
symbol,
userCurrency
});
return { activities };
}
}

6
apps/api/src/app/import/import.module.ts

@ -1,12 +1,14 @@
import { AccountModule } from '@ghostfolio/api/app/account/account.module';
import { CacheModule } from '@ghostfolio/api/app/cache/cache.module';
import { OrderModule } from '@ghostfolio/api/app/order/order.module';
import { PortfolioModule } from '@ghostfolio/api/app/portfolio/portfolio.module';
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module';
import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering.module';
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module';
import { PrismaModule } from '@ghostfolio/api/services/prisma.module';
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile.module';
import { Module } from '@nestjs/common';
import { ImportController } from './import.controller';
@ -22,8 +24,10 @@ import { ImportService } from './import.service';
DataProviderModule,
ExchangeRateDataModule,
OrderModule,
PortfolioModule,
PrismaModule,
RedisCacheModule
RedisCacheModule,
SymbolProfileModule
],
providers: [ImportService]
})

93
apps/api/src/app/import/import.service.ts

@ -2,9 +2,16 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { OrderService } from '@ghostfolio/api/app/order/order.service';
import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
import { OrderWithAccount } from '@ghostfolio/common/types';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service';
import { parseDate } from '@ghostfolio/common/helper';
import { UniqueAsset } from '@ghostfolio/common/interfaces';
import {
AccountWithPlatform,
OrderWithAccount
} from '@ghostfolio/common/types';
import { Injectable } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client';
import Big from 'big.js';
@ -17,9 +24,81 @@ export class ImportService {
private readonly accountService: AccountService,
private readonly dataProviderService: DataProviderService,
private readonly exchangeRateDataService: ExchangeRateDataService,
private readonly orderService: OrderService
private readonly orderService: OrderService,
private readonly portfolioService: PortfolioService,
private readonly symbolProfileService: SymbolProfileService
) {}
public async getDividends({
dataSource,
symbol,
userCurrency
}: UniqueAsset & { userCurrency: string }): Promise<Activity[]> {
try {
const { firstBuyDate, historicalData, orders } =
await this.portfolioService.getPosition(dataSource, undefined, symbol);
const [[assetProfile], dividends] = await Promise.all([
this.symbolProfileService.getSymbolProfiles([
{
dataSource,
symbol
}
]),
await this.dataProviderService.getDividends({
dataSource,
symbol,
from: parseDate(firstBuyDate),
granularity: 'day',
to: new Date()
})
]);
const accounts = orders.map((order) => {
return order.Account;
});
const Account = this.isUniqueAccount(accounts) ? accounts[0] : undefined;
return Object.entries(dividends).map(([dateString, { marketPrice }]) => {
const quantity =
historicalData.find((historicalDataItem) => {
return historicalDataItem.date === dateString;
})?.quantity ?? 0;
const value = new Big(quantity).mul(marketPrice).toNumber();
return {
Account,
quantity,
value,
accountId: Account?.id,
accountUserId: undefined,
comment: undefined,
createdAt: undefined,
date: parseDate(dateString),
fee: 0,
feeInBaseCurrency: 0,
id: assetProfile.id,
isDraft: false,
SymbolProfile: <SymbolProfile>(<unknown>assetProfile),
symbolProfileId: assetProfile.id,
type: 'DIVIDEND',
unitPrice: marketPrice,
updatedAt: undefined,
userId: Account?.userId,
valueInBaseCurrency: this.exchangeRateDataService.toCurrency(
value,
assetProfile.currency,
userCurrency
)
};
});
} catch {
return [];
}
}
public async import({
activitiesDto,
isDryRun = false,
@ -161,6 +240,16 @@ export class ImportService {
return activities;
}
private isUniqueAccount(accounts: AccountWithPlatform[]) {
const uniqueAccountIds = new Set<string>();
for (const account of accounts) {
uniqueAccountIds.add(account.id);
}
return uniqueAccountIds.size === 1;
}
private async validateActivities({
activitiesDto,
maxActivitiesToImport,

5
apps/api/src/app/info/info.service.ts

@ -7,6 +7,7 @@ import { PropertyService } from '@ghostfolio/api/services/property/property.serv
import { TagService } from '@ghostfolio/api/services/tag/tag.service';
import {
DEMO_USER_ID,
PROPERTY_COUNTRIES_OF_SUBSCRIBERS,
PROPERTY_IS_READ_ONLY_MODE,
PROPERTY_SLACK_COMMUNITY_USERS,
PROPERTY_STRIPE_CONFIG,
@ -92,6 +93,10 @@ export class InfoService {
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
globalPermissions.push(permissions.enableSubscription);
info.countriesOfSubscribers =
((await this.propertyService.getByKey(
PROPERTY_COUNTRIES_OF_SUBSCRIBERS
)) as string[]) ?? [];
info.stripePublicKey = this.configurationService.get('STRIPE_PUBLIC_KEY');
}

34
apps/api/src/app/portfolio/portfolio.service.ts

@ -660,8 +660,9 @@ export class PortfolioService {
}
const positionCurrency = orders[0].SymbolProfile.currency;
const [SymbolProfile] =
await this.symbolProfileService.getSymbolProfilesBySymbols([aSymbol]);
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([
{ dataSource: aDataSource, symbol: aSymbol }
]);
const portfolioOrders: PortfolioOrder[] = orders
.filter((order) => {
@ -745,6 +746,7 @@ export class PortfolioService {
historicalDataArray.push({
averagePrice: orders[0].unitPrice,
date: firstBuyDate,
quantity: orders[0].quantity,
value: orders[0].unitPrice
});
}
@ -761,6 +763,7 @@ export class PortfolioService {
j++;
}
let currentAveragePrice = 0;
let currentQuantity = 0;
const currentSymbol = transactionPoints[j].items.find(
(item) => item.symbol === aSymbol
);
@ -768,11 +771,13 @@ export class PortfolioService {
currentAveragePrice = currentSymbol.quantity.eq(0)
? 0
: currentSymbol.investment.div(currentSymbol.quantity).toNumber();
currentQuantity = currentSymbol.quantity.toNumber();
}
historicalDataArray.push({
date,
averagePrice: currentAveragePrice,
quantity: currentQuantity,
value: marketPrice
});
@ -905,12 +910,14 @@ export class PortfolioService {
const positions = currentPositions.positions.filter(
(item) => !item.quantity.eq(0)
);
const dataGatheringItem = positions.map((position) => {
return {
dataSource: position.dataSource,
symbol: position.symbol
};
});
const symbols = positions.map((position) => position.symbol);
const [dataProviderResponses, symbolProfiles] = await Promise.all([
@ -1098,16 +1105,23 @@ export class PortfolioService {
portfolioStart
);
const positions = currentPositions.positions.filter(
(item) => !item.quantity.eq(0)
);
const portfolioItemsNow: { [symbol: string]: TimelinePosition } = {};
for (const position of currentPositions.positions) {
for (const position of positions) {
portfolioItemsNow[position.symbol] = position;
}
const accounts = await this.getValueOfAccounts({
orders,
portfolioItemsNow,
userId,
userCurrency
userCurrency,
userId
});
return {
rules: {
accountClusterRisk: await this.rulesService.evaluate(
@ -1131,19 +1145,19 @@ export class PortfolioService {
[
new CurrencyClusterRiskBaseCurrencyInitialInvestment(
this.exchangeRateDataService,
currentPositions
positions
),
new CurrencyClusterRiskBaseCurrencyCurrentInvestment(
this.exchangeRateDataService,
currentPositions
positions
),
new CurrencyClusterRiskInitialInvestment(
this.exchangeRateDataService,
currentPositions
positions
),
new CurrencyClusterRiskCurrentInvestment(
this.exchangeRateDataService,
currentPositions
positions
)
],
<UserSettings>this.request.user.Settings.settings
@ -1689,7 +1703,7 @@ export class PortfolioService {
for (const order of ordersByAccount) {
let currentValueOfSymbolInBaseCurrency =
order.quantity *
portfolioItemsNow[order.SymbolProfile.symbol].marketPrice;
portfolioItemsNow[order.SymbolProfile.symbol]?.marketPrice ?? 0;
let originalValueOfSymbolInBaseCurrency =
this.exchangeRateDataService.toCurrency(
order.quantity * order.unitPrice,

37
apps/api/src/helper/object.helper.ts

@ -27,3 +27,40 @@ export function nullifyValuesInObjects<T>(aObjects: T[], keys: string[]): T[] {
return nullifyValuesInObject(object, keys);
});
}
export function redactAttributes({
object,
options
}: {
object: any;
options: { attribute: string; valueMap: { [key: string]: any } }[];
}): any {
if (!object || !options || !options.length) {
return object;
}
const redactedObject = cloneDeep(object);
for (const option of options) {
if (redactedObject.hasOwnProperty(option.attribute)) {
redactedObject[option.attribute] =
option.valueMap[redactedObject[option.attribute]] ??
option.valueMap['*'] ??
redactedObject[option.attribute];
} else {
// If the attribute is not present on the current object,
// check if it exists on any nested objects
for (const property in redactedObject) {
if (typeof redactedObject[property] === 'object') {
// Recursively call the function on the nested object
redactedObject[property] = redactAttributes({
options,
object: redactedObject[property]
});
}
}
}
}
return redactedObject;
}

71
apps/api/src/interceptors/transform-data-source-in-response.interceptor.ts

@ -1,3 +1,4 @@
import { redactAttributes } from '@ghostfolio/api/helper/object.helper';
import { encodeDataSource } from '@ghostfolio/common/helper';
import {
CallHandler,
@ -5,7 +6,7 @@ import {
Injectable,
NestInterceptor
} from '@nestjs/common';
import { isArray } from 'lodash';
import { DataSource } from '@prisma/client';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@ -28,65 +29,25 @@ export class TransformDataSourceInResponseInterceptor<T>
if (
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') === true
) {
if (data.activities) {
data.activities.map((activity) => {
activity.SymbolProfile.dataSource = encodeDataSource(
activity.SymbolProfile.dataSource
);
return activity;
});
}
if (isArray(data.benchmarks)) {
data.benchmarks.map((benchmark) => {
benchmark.dataSource = encodeDataSource(benchmark.dataSource);
return benchmark;
});
}
if (data.dataSource) {
data.dataSource = encodeDataSource(data.dataSource);
}
if (data.errors) {
for (const error of data.errors) {
if (error.dataSource) {
error.dataSource = encodeDataSource(error.dataSource);
}
}
}
if (data.holdings) {
for (const symbol of Object.keys(data.holdings)) {
if (data.holdings[symbol].dataSource) {
data.holdings[symbol].dataSource = encodeDataSource(
data.holdings[symbol].dataSource
data = redactAttributes({
options: [
{
attribute: 'dataSource',
valueMap: Object.keys(DataSource).reduce(
(valueMap, dataSource) => {
valueMap[dataSource] = encodeDataSource(
DataSource[dataSource]
);
return valueMap;
},
{}
)
}
}
}
if (data.items) {
data.items.map((item) => {
item.dataSource = encodeDataSource(item.dataSource);
return item;
});
}
if (data.positions) {
data.positions.map((position) => {
position.dataSource = encodeDataSource(position.dataSource);
return position;
],
object: data
});
}
if (data.SymbolProfile) {
data.SymbolProfile.dataSource = encodeDataSource(
data.SymbolProfile.dataSource
);
}
}
return data;
})
);

7
apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts

@ -1,14 +1,13 @@
import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface';
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
import { UserSettings } from '@ghostfolio/common/interfaces';
import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule<Settings> {
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private currentPositions: CurrentPositions
private positions: TimelinePosition[]
) {
super(exchangeRateDataService, {
name: 'Current Investment: Base Currency'
@ -17,7 +16,7 @@ export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule<Setti
public evaluate(ruleSettings: Settings) {
const positionsGroupedByCurrency = this.groupCurrentPositionsByAttribute(
this.currentPositions.positions,
this.positions,
'currency',
ruleSettings.baseCurrency
);

7
apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts

@ -1,14 +1,13 @@
import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface';
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
import { UserSettings } from '@ghostfolio/common/interfaces';
import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class CurrencyClusterRiskBaseCurrencyInitialInvestment extends Rule<Settings> {
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private currentPositions: CurrentPositions
private positions: TimelinePosition[]
) {
super(exchangeRateDataService, {
name: 'Initial Investment: Base Currency'
@ -17,7 +16,7 @@ export class CurrencyClusterRiskBaseCurrencyInitialInvestment extends Rule<Setti
public evaluate(ruleSettings: Settings) {
const positionsGroupedByCurrency = this.groupCurrentPositionsByAttribute(
this.currentPositions.positions,
this.positions,
'currency',
ruleSettings.baseCurrency
);

9
apps/api/src/models/rules/currency-cluster-risk/current-investment.ts

@ -1,14 +1,13 @@
import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface';
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
import { UserSettings } from '@ghostfolio/common/interfaces';
import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class CurrencyClusterRiskCurrentInvestment extends Rule<Settings> {
public constructor(
public exchangeRateDataService: ExchangeRateDataService,
private currentPositions: CurrentPositions
protected exchangeRateDataService: ExchangeRateDataService,
private positions: TimelinePosition[]
) {
super(exchangeRateDataService, {
name: 'Current Investment'
@ -17,7 +16,7 @@ export class CurrencyClusterRiskCurrentInvestment extends Rule<Settings> {
public evaluate(ruleSettings: Settings) {
const positionsGroupedByCurrency = this.groupCurrentPositionsByAttribute(
this.currentPositions.positions,
this.positions,
'currency',
ruleSettings.baseCurrency
);

7
apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts

@ -1,14 +1,13 @@
import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface';
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
import { UserSettings } from '@ghostfolio/common/interfaces';
import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class CurrencyClusterRiskInitialInvestment extends Rule<Settings> {
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private currentPositions: CurrentPositions
private positions: TimelinePosition[]
) {
super(exchangeRateDataService, {
name: 'Initial Investment'
@ -17,7 +16,7 @@ export class CurrencyClusterRiskInitialInvestment extends Rule<Settings> {
public evaluate(ruleSettings: Settings) {
const positionsGroupedByCurrency = this.groupCurrentPositionsByAttribute(
this.currentPositions.positions,
this.positions,
'currency',
ruleSettings.baseCurrency
);

14
apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts

@ -37,6 +37,20 @@ export class AlphaVantageService implements DataProviderInterface {
};
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return {};
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',

6
apps/api/src/services/data-provider/data-provider.module.ts

@ -59,6 +59,10 @@ import { DataProviderService } from './data-provider.service';
]
}
],
exports: [DataProviderService, GhostfolioScraperApiService]
exports: [
DataProviderService,
GhostfolioScraperApiService,
YahooFinanceService
]
})
export class DataProviderModule {}

21
apps/api/src/services/data-provider/data-provider.service.ts

@ -23,6 +23,27 @@ export class DataProviderService {
private readonly prismaService: PrismaService
) {}
public async getDividends({
dataSource,
from,
granularity = 'day',
symbol,
to
}: {
dataSource: DataSource;
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return this.getDataProvider(DataSource[dataSource]).getDividends({
from,
granularity,
symbol,
to
});
}
public async getHistorical(
aItems: IDataGatheringItem[],
aGranularity: Granularity = 'month',

14
apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts

@ -37,6 +37,20 @@ export class EodHistoricalDataService implements DataProviderInterface {
};
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return {};
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',

14
apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts

@ -37,6 +37,20 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
};
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return {};
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',

14
apps/api/src/services/data-provider/google-sheets/google-sheets.service.ts

@ -34,6 +34,20 @@ export class GoogleSheetsService implements DataProviderInterface {
};
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return {};
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',

12
apps/api/src/services/data-provider/interfaces/data-provider.interface.ts

@ -11,6 +11,18 @@ export interface DataProviderInterface {
getAssetProfile(aSymbol: string): Promise<Partial<SymbolProfile>>;
getDividends({
from,
granularity,
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}): Promise<{ [date: string]: IDataProviderHistoricalResponse }>;
getHistorical(
aSymbol: string,
aGranularity: Granularity,

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

@ -29,6 +29,20 @@ export class ManualService implements DataProviderInterface {
};
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return {};
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',

14
apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts

@ -31,6 +31,20 @@ export class RapidApiService implements DataProviderInterface {
};
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
return {};
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',

103
apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

@ -160,6 +160,59 @@ export class YahooFinanceService implements DataProviderInterface {
return response;
}
public async getDividends({
from,
granularity = 'day',
symbol,
to
}: {
from: Date;
granularity: Granularity;
symbol: string;
to: Date;
}) {
if (isSameDay(from, to)) {
to = addDays(to, 1);
}
try {
const historicalResult = await yahooFinance.historical(
this.convertToYahooFinanceSymbol(symbol),
{
events: 'dividends',
interval: granularity === 'month' ? '1mo' : '1d',
period1: format(from, DATE_FORMAT),
period2: format(to, DATE_FORMAT)
}
);
const response: {
[date: string]: IDataProviderHistoricalResponse;
} = {};
for (const historicalItem of historicalResult) {
response[format(historicalItem.date, DATE_FORMAT)] = {
marketPrice: this.getConvertedValue({
symbol,
value: historicalItem.dividends
})
};
}
return response;
} catch (error) {
Logger.error(
`Could not get dividends for ${symbol} (${this.getName()}) from ${format(
from,
DATE_FORMAT
)} to ${format(to, DATE_FORMAT)}: [${error.name}] ${error.message}`,
'YahooFinanceService'
);
return {};
}
}
public async getHistorical(
aSymbol: string,
aGranularity: Granularity = 'day',
@ -172,11 +225,9 @@ export class YahooFinanceService implements DataProviderInterface {
to = addDays(to, 1);
}
const yahooFinanceSymbol = this.convertToYahooFinanceSymbol(aSymbol);
try {
const historicalResult = await yahooFinance.historical(
yahooFinanceSymbol,
this.convertToYahooFinanceSymbol(aSymbol),
{
interval: '1d',
period1: format(from, DATE_FORMAT),
@ -188,27 +239,14 @@ export class YahooFinanceService implements DataProviderInterface {
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
} = {};
// Convert symbol back
const symbol = this.convertFromYahooFinanceSymbol(yahooFinanceSymbol);
response[symbol] = {};
response[aSymbol] = {};
for (const historicalItem of historicalResult) {
let marketPrice = historicalItem.close;
if (symbol === `${this.baseCurrency}GBp`) {
// Convert GPB to GBp (pence)
marketPrice = new Big(marketPrice).mul(100).toNumber();
} else if (symbol === `${this.baseCurrency}ILA`) {
// Convert ILS to ILA
marketPrice = new Big(marketPrice).mul(100).toNumber();
} else if (symbol === `${this.baseCurrency}ZAc`) {
// Convert ZAR to ZAc (cents)
marketPrice = new Big(marketPrice).mul(100).toNumber();
}
response[symbol][format(historicalItem.date, DATE_FORMAT)] = {
marketPrice,
response[aSymbol][format(historicalItem.date, DATE_FORMAT)] = {
marketPrice: this.getConvertedValue({
symbol: aSymbol,
value: historicalItem.close
}),
performance: historicalItem.open - historicalItem.close
};
}
@ -423,6 +461,27 @@ export class YahooFinanceService implements DataProviderInterface {
return name || shortName || symbol;
}
private getConvertedValue({
symbol,
value
}: {
symbol: string;
value: number;
}) {
if (symbol === `${this.baseCurrency}GBp`) {
// Convert GPB to GBp (pence)
return new Big(value).mul(100).toNumber();
} else if (symbol === `${this.baseCurrency}ILA`) {
// Convert ILS to ILA
return new Big(value).mul(100).toNumber();
} else if (symbol === `${this.baseCurrency}ZAc`) {
// Convert ZAR to ZAc (cents)
return new Big(value).mul(100).toNumber();
}
return value;
}
private parseAssetClass(aPrice: Price): {
assetClass: AssetClass;
assetSubClass: AssetSubClass;

2
apps/client/src/app/app.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/access-table/access-table.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/accounts-table/accounts-table.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/admin-jobs/admin-jobs.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/admin-market-data/admin-market-data.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/admin-overview/admin-overview.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/admin-users/admin-users.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/header/header.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/home-holdings/home-holdings.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/home-market/home-market.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/home-overview/home-overview.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/home-summary/home-summary.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
apps/client/src/app/components/positions/positions.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

9
apps/client/src/app/components/world-map-chart/world-map-chart.component.ts

@ -7,6 +7,7 @@ import {
OnDestroy,
OnInit
} from '@angular/core';
import { getNumberFormatGroup } from '@ghostfolio/common/helper';
import svgMap from 'svgmap';
@Component({
@ -16,9 +17,10 @@ import svgMap from 'svgmap';
styleUrls: ['./world-map-chart.component.scss']
})
export class WorldMapChartComponent implements OnChanges, OnDestroy, OnInit {
@Input() baseCurrency: string;
@Input() countries: { [code: string]: { name: string; value: number } };
@Input() countries: { [code: string]: { name?: string; value: number } };
@Input() format: string;
@Input() isInPercent = false;
@Input() locale: string;
public isLoading = true;
public svgMapElement;
@ -71,7 +73,8 @@ export class WorldMapChartComponent implements OnChanges, OnDestroy, OnInit {
applyData: 'value',
data: {
value: {
format: this.isInPercent ? `{0}%` : `{0} ${this.baseCurrency}`
format: this.format,
thousandSeparator: getNumberFormatGroup(this.locale)
}
},
values: this.countries

8
apps/client/src/app/pages/account/account-page.html

@ -24,8 +24,8 @@
></gf-premium-indicator>
</div>
<div *ngIf="user?.subscription?.type === 'Premium'">
Valid until {{ user?.subscription?.expiresAt | date:
defaultDateFormat }}
<ng-container i18n>Valid until</ng-container> {{
user?.subscription?.expiresAt | date: defaultDateFormat }}
</div>
<div *ngIf="user?.subscription?.type === 'Basic'">
<ng-container *ngIf="hasPermissionForSubscription">
@ -135,10 +135,10 @@
>Español (<ng-container i18n>Community</ng-container
>)</mat-option
>
<!--<mat-option value="fr"
<mat-option value="fr"
>Français (<ng-container i18n>Community</ng-container
>)</mat-option
>-->
>
<mat-option value="it"
>Italiano (<ng-container i18n>Community</ng-container
>)</mat-option

2
apps/client/src/app/pages/admin/admin-page.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
color: rgb(var(--dark-primary-text));

2
apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.html

@ -125,7 +125,7 @@
feedback, bug reports, feature requests and of course contributions!
</p>
<p>
You can reach me by email at
You can reach me by e-mail at
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> or on Twitter
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a>.
</p>

2
apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.html

@ -99,7 +99,7 @@
>
of users. In the future, I would like to involve more contributors
to further extend the functionality of Ghostfolio (e.g. with new
reports). Get in touch with me by email at
reports). Get in touch with me by e-mail at
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> or on Twitter
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a> if you
are interested, I’m happy to discuss ideas.

8
apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.html

@ -64,15 +64,15 @@
<p>
When you authenticate with <i>Internet Identity</i>, the service
only gets a dedicated pseudonym rather than sensitive user data like
the email address or phone number. This preserves your anonymity and
prevents you being tracked on the Internet.
the e-mail address or phone number. This preserves your anonymity
and prevents you being tracked on the Internet.
</p>
</section>
<section class="mb-4">
<h2 class="h4">The key benefits in a nutshell</h2>
<ul>
<li>
Authenticate yourself securely without the need of an email
Authenticate yourself securely without the need of an e-mail
address, username, or a password: all you need is your device to
log in.
</li>
@ -89,7 +89,7 @@
<section class="mb-4">
<p>
If you would like to provide feedback or get involved in further
development of Ghostfolio, please get in touch by email via
development of Ghostfolio, please get in touch by e-mail via
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> or on Twitter
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a>.
</p>

4
apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.html

@ -62,7 +62,7 @@
new and better Internet based on decentralized blockchains to give
power back to the users. <i>Internet Identity</i> created by the
<a href="https://dfinity.org">Dfinity Foundation</a> enables you to
sign in securely and anonymously to Ghostfolio without an email
sign in securely and anonymously to Ghostfolio without an e-mail
address, username, or a password. All you need is your device with
built-in biometric authentication.
</p>
@ -90,7 +90,7 @@
onboard more contributors who are actively involved in software
engineering to realize the full potential of open source software.
If you are a web developer and interested in personal finance,
please get in touch by email via
please get in touch by e-mail via
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> or on Twitter
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a>. We are
happy to discuss ideas.

2
apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.html

@ -83,7 +83,7 @@
<a href="https://ghostfolio.slack.com">Slack community</a> or get in
touch on Twitter
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a> or by
email via <a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a>.
e-mail via <a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a>.
</p>
<p>
We look forward to hearing from you.<br />

43
apps/client/src/app/pages/faq/faq-page.html

@ -48,7 +48,7 @@
<a href="../en/blog/2022/07/ghostfolio-meets-internet-identity"
>Internet Identity</a
>) enable you to sign in securely and anonymously to Ghostfolio. There
is no need for an email address, phone number, or a username.
is no need for an e-mail address, phone number, or a username.
</mat-card-content>
</mat-card>
<mat-card class="mb-3">
@ -57,10 +57,11 @@
>This project is driven by the efforts of contributors from around the
world. The
<a href="https://github.com/ghostfolio/ghostfolio">source code</a> is
fully available as open source software (OSS). Our
fully available as open source software (OSS). Thanks to our generous
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> users and
<a href="https://www.buymeacoffee.com/ghostfolio">sponsors</a> allow
us to run a free, limited plan for new investors.</mat-card-content
<a href="https://www.buymeacoffee.com/ghostfolio">sponsors</a> we have
the ability to run a free, limited plan for new
investors.</mat-card-content
>
</mat-card>
<mat-card class="mb-3">
@ -77,7 +78,8 @@
><a [routerLink]="['/pricing']">Ghostfolio Premium</a> is a fully
managed Ghostfolio cloud offering for ambitious investors. The revenue
is used to cover the hosting infrastructure. It is the Open Source
code base with some extras like the market overview.</mat-card-content
code base with some extras like the
<a [routerLink]="['/markets']">markets overview</a>.</mat-card-content
>
</mat-card>
<mat-card class="mb-3">
@ -85,24 +87,45 @@
<mat-card-content
>Yes, you can try
<a [routerLink]="['/pricing']">Ghostfolio Premium</a> by signing up
for Ghostfolio and applying for a trial (see “My Ghostfolio”). Its
for Ghostfolio and applying for a trial (see “My Ghostfolio”). It is
easy, free and there is no commitment. You can stop using it at any
time.</mat-card-content
>
</mat-card>
<mat-card class="mb-3">
<mat-card-title
>How can I get a student discount for Ghostfolio
Premium?</mat-card-title
>
<mat-card-content
>Request your student discount
<a href="mailto:hi@ghostfol.io?Subject=Student Discount">here</a> with
your university e-mail address.</mat-card-content
>
</mat-card>
<mat-card class="mb-3">
<mat-card-title>Which devices are supported?</mat-card-title>
<mat-card-content
>Ghostfolio works in every modern web browser on smartphones, tablets
and desktop computers (where you have even more analysis options and
statistics). For Android users, there is a dedicated Ghostfolio app
available in the
and desktop computers. For <i>Android</i> users, there is a dedicated
Ghostfolio app available in the
<a
href="https://play.google.com/store/apps/details?id=ch.dotsilver.ghostfolio.twa"
>Google Play Store</a
>.</mat-card-content
>
</mat-card>
<mat-card class="mb-3">
<mat-card-title
>I cannot find my broker in the list of platforms. What can I
do?</mat-card-title
>
<mat-card-content>
Please send an e-mail with the web address of your broker to
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> and we are happy to
add it.
</mat-card-content>
</mat-card>
<mat-card class="mb-3">
<mat-card-title
>Ghostfolio sounds cool, how can I get involved?</mat-card-title
@ -117,7 +140,7 @@
>, a star on
<a href="https://github.com/ghostfolio/ghostfolio">GitHub</a>,
feedback, bug reports, feature requests and of course contributions!
You can reach us by email at
You can reach us by e-mail at
<a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a> or on Twitter
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a
>.</mat-card-content

3
apps/client/src/app/pages/features/features-page.html

@ -197,8 +197,7 @@
<div class="flex-grow-1">
<h4>Multi-Language</h4>
<p class="m-0">
Use Ghostfolio in multiple languages: English,
Dutch<ng-container *ngIf="false">, Français</ng-container>,
Use Ghostfolio in multiple languages: English, Dutch, French,
German, Italian<ng-container *ngIf="false"
>, Portuguese</ng-container
>

2
apps/client/src/app/pages/home/home-page.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
color: rgb(var(--dark-primary-text));

18
apps/client/src/app/pages/landing/landing-page.component.ts

@ -13,10 +13,14 @@ import { Subject } from 'rxjs';
templateUrl: './landing-page.html'
})
export class LandingPageComponent implements OnDestroy, OnInit {
public countriesOfSubscribersMap: {
[code: string]: { value: number };
} = {};
public currentYear = format(new Date(), 'yyyy');
public demoAuthToken: string;
public deviceType: string;
public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean;
public hasPermissionToCreateUser: boolean;
public statistics: Statistics;
public testimonials = [
@ -48,13 +52,25 @@ export class LandingPageComponent implements OnDestroy, OnInit {
private dataService: DataService,
private deviceService: DeviceDetectorService
) {
const { globalPermissions, statistics } = this.dataService.fetchInfo();
const { countriesOfSubscribers, globalPermissions, statistics } =
this.dataService.fetchInfo();
for (const country of countriesOfSubscribers) {
this.countriesOfSubscribersMap[country] = {
value: 1
};
}
this.hasPermissionForStatistics = hasPermission(
globalPermissions,
permissions.enableStatistics
);
this.hasPermissionForSubscription = hasPermission(
globalPermissions,
permissions.enableSubscription
);
this.hasPermissionToCreateUser = hasPermission(
globalPermissions,
permissions.createUserAccount

15
apps/client/src/app/pages/landing/landing-page.html

@ -269,6 +269,21 @@
</div>
</div>
<div *ngIf="hasPermissionForSubscription" class="row my-5">
<div class="col-12">
<h2 class="h4 text-center">
Members from around the globe are using
<a href="pricing"><strong>Ghostfolio Premium</strong></a>
</h2>
</div>
<div class="col-md-8 customer-map-container offset-md-2">
<gf-world-map-chart
format="👻"
[countries]="countriesOfSubscribersMap"
></gf-world-map-chart>
</div>
</div>
<div class="row my-3">
<div class="col-12">
<h2 class="h4 mb-1 text-center">

2
apps/client/src/app/pages/landing/landing-page.module.ts

@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { RouterModule } from '@angular/router';
import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module';
import { GfLogoModule } from '@ghostfolio/ui/logo';
import { GfValueModule } from '@ghostfolio/ui/value';
@ -15,6 +16,7 @@ import { LandingPageComponent } from './landing-page.component';
CommonModule,
GfLogoModule,
GfValueModule,
GfWorldMapChartModule,
LandingPageRoutingModule,
MatButtonModule,
MatCardModule,

6
apps/client/src/app/pages/landing/landing-page.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;
@ -9,6 +9,10 @@
}
}
.customer-map-container {
aspect-ratio: 16 / 9;
}
.downloads {
img {
height: 2.5rem;

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

@ -11,7 +11,7 @@ import { IcsService } from '@ghostfolio/client/services/ics/ics.service';
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { downloadAsFile } from '@ghostfolio/common/helper';
import { User } from '@ghostfolio/common/interfaces';
import { UniqueAsset, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { DataSource, Order as OrderModel } from '@prisma/client';
import { format, parseISO } from 'date-fns';
@ -198,6 +198,24 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit {
});
}
public onImportDividends() {
const dialogRef = this.dialog.open(ImportActivitiesDialog, {
data: <ImportActivitiesDialogParams>{
activityTypes: ['DIVIDEND'],
deviceType: this.deviceType,
user: this.user
},
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
});
dialogRef
.afterClosed()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
this.fetchActivities();
});
}
public onUpdateActivity(aActivity: OrderModel) {
this.router.navigate([], {
queryParams: { activityId: aActivity.id, editDialog: true }

1
apps/client/src/app/pages/portfolio/activities/activities-page.html

@ -17,6 +17,7 @@
(export)="onExport($event)"
(exportDrafts)="onExportDrafts($event)"
(import)="onImport()"
(importDividends)="onImportDividends()"
></gf-activities-table>
</div>
</div>

69
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts

@ -5,12 +5,16 @@ import {
Inject,
OnDestroy
} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { DataService } from '@ghostfolio/client/services/data.service';
import { ImportActivitiesService } from '@ghostfolio/client/services/import-activities.service';
import { isArray } from 'lodash';
import { Subject } from 'rxjs';
import { Position } from '@ghostfolio/common/interfaces';
import { AssetClass } from '@prisma/client';
import { isArray, sortBy } from 'lodash';
import { Subject, takeUntil } from 'rxjs';
import { ImportActivitiesDialogParams } from './interfaces/interfaces';
@ -24,20 +28,57 @@ export class ImportActivitiesDialog implements OnDestroy {
public activities: Activity[] = [];
public details: any[] = [];
public errorMessages: string[] = [];
public holdings: Position[] = [];
public isFileSelected = false;
public mode: 'DIVIDEND';
public selectedActivities: Activity[] = [];
public uniqueAssetForm: FormGroup;
private unsubscribeSubject = new Subject<void>();
public constructor(
private changeDetectorRef: ChangeDetectorRef,
@Inject(MAT_DIALOG_DATA) public data: ImportActivitiesDialogParams,
private dataService: DataService,
private formBuilder: FormBuilder,
public dialogRef: MatDialogRef<ImportActivitiesDialog>,
private importActivitiesService: ImportActivitiesService,
private snackBar: MatSnackBar
) {}
public ngOnInit() {}
public ngOnInit() {
this.uniqueAssetForm = this.formBuilder.group({
uniqueAsset: [undefined, Validators.required]
});
if (
this.data?.activityTypes?.length === 1 &&
this.data?.activityTypes?.[0] === 'DIVIDEND'
) {
this.mode = 'DIVIDEND';
this.uniqueAssetForm.controls['uniqueAsset'].disable();
this.dataService
.fetchPositions({
filters: [
{
id: AssetClass.EQUITY,
type: 'ASSET_CLASS'
}
],
range: 'max'
})
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ positions }) => {
this.holdings = sortBy(positions, ({ name }) => {
return name.toLowerCase();
});
this.uniqueAssetForm.controls['uniqueAsset'].enable();
this.changeDetectorRef.markForCheck();
});
}
}
public onCancel(): void {
this.dialogRef.close();
@ -71,6 +112,26 @@ export class ImportActivitiesDialog implements OnDestroy {
}
}
public onLoadDividends() {
this.uniqueAssetForm.controls['uniqueAsset'].disable();
const { dataSource, symbol } =
this.uniqueAssetForm.controls['uniqueAsset'].value;
this.dataService
.fetchDividendsImport({
dataSource,
symbol
})
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ activities }) => {
this.activities = activities;
this.isFileSelected = true;
this.changeDetectorRef.markForCheck();
});
}
public onReset() {
this.details = [];
this.errorMessages = [];
@ -95,8 +156,6 @@ export class ImportActivitiesDialog implements OnDestroy {
reader.onload = async (readerEvent) => {
const fileContent = readerEvent.target.result as string;
console.log(fileContent);
try {
if (file.name.endsWith('.json')) {
const content = JSON.parse(fileContent);

31
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html

@ -7,6 +7,31 @@
<div class="flex-grow-1" mat-dialog-content>
<ng-container *ngIf="!isFileSelected">
<ng-container *ngIf="mode === 'DIVIDEND'; else selectFile">
<form [formGroup]="uniqueAssetForm" (ngSubmit)="onLoadDividends()">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Holding</mat-label>
<mat-select formControlName="uniqueAsset">
<mat-option
*ngFor="let holding of holdings"
[value]="{dataSource: holding.dataSource, symbol: holding.symbol}"
>{{ holding.name }}</mat-option
>
</mat-select>
</mat-form-field>
<div class="d-flex justify-content-center flex-column">
<button
color="primary"
mat-flat-button
type="submit"
[disabled]="!uniqueAssetForm.valid"
>
<span i18n>Load Dividends</span>
</button>
</div>
</form>
</ng-container>
<ng-template #selectFile>
<div class="d-flex justify-content-center flex-column">
<button
class="py-3"
@ -18,7 +43,9 @@
<span i18n>Choose File</span>
</button>
<p class="mb-0 mt-4 text-center">
<span class="mr-1" i18n>The following file formats are supported:</span>
<span class="mr-1" i18n
>The following file formats are supported:</span
>
<a
href="https://github.com/ghostfolio/ghostfolio/blob/main/test/import/ok.csv"
target="_blank"
@ -32,6 +59,7 @@
>
</p>
</div>
</ng-template>
</ng-container>
<ng-container *ngIf="isFileSelected">
<ng-container *ngIf="errorMessages.length === 0; else errorMessage">
@ -47,6 +75,7 @@
[locale]="data?.user?.settings?.locale"
[showActions]="false"
[showCheckbox]="true"
[showFooter]="false"
[showSymbolColumn]="false"
(selectedActivities)="updateSelection($event)"
></gf-activities-table>

9
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.module.ts

@ -1,8 +1,11 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module';
import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module';
import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module';
@ -13,12 +16,16 @@ import { ImportActivitiesDialog } from './import-activities-dialog.component';
declarations: [ImportActivitiesDialog],
imports: [
CommonModule,
FormsModule,
GfActivitiesTableModule,
GfDialogFooterModule,
GfDialogHeaderModule,
MatButtonModule,
MatDialogModule,
MatExpansionModule
MatExpansionModule,
MatFormFieldModule,
MatSelectModule,
ReactiveFormsModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

2
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/interfaces/interfaces.ts

@ -1,6 +1,8 @@
import { User } from '@ghostfolio/common/interfaces';
import { Type } from '@prisma/client';
export interface ImportActivitiesDialogParams {
activityTypes: Type[];
deviceType: string;
user: User;
}

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

@ -84,6 +84,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
};
public user: User;
public worldMapChartFormat: string;
private unsubscribeSubject = new Subject<void>();
@ -193,6 +194,11 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
...tagFilters
];
this.worldMapChartFormat =
this.hasImpersonationId || this.user.settings.isRestrictedView
? `{0}%`
: `{0} ${this.user?.settings?.baseCurrency}`;
this.changeDetectorRef.markForCheck();
}
});

3
apps/client/src/app/pages/portfolio/allocations/allocations-page.html

@ -257,9 +257,10 @@
</mat-card-header>
<mat-card-content>
<gf-world-map-chart
[baseCurrency]="user?.settings?.baseCurrency"
[countries]="countries"
[format]="worldMapChartFormat"
[isInPercent]="hasImpersonationId || user.settings.isRestrictedView"
[locale]="user?.settings?.locale"
></gf-world-map-chart>
<div class="row">
<div class="col-xs-12 col-md-4 my-2">

2
apps/client/src/app/pages/portfolio/portfolio-page.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
color: rgb(var(--dark-primary-text));

2
apps/client/src/app/pages/pricing/pricing-page.html

@ -18,7 +18,7 @@
to use our referral link and get a Ghostfolio Premium membership for
one year. Looking for a student discount? Request it
<a href="mailto:hi@ghostfol.io?Subject=Student Discount">here</a> with
your university email address.
your university e-mail address.
</p>
<p>
If you prefer to run Ghostfolio on your own infrastructure, please

2
apps/client/src/app/pages/zen/zen-page.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
color: rgb(var(--dark-primary-text));

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

@ -24,6 +24,7 @@ import {
BenchmarkResponse,
Export,
Filter,
ImportResponse,
InfoItem,
OAuthResponse,
PortfolioDetails,
@ -119,6 +120,12 @@ export class DataService {
});
}
public fetchDividendsImport({ dataSource, symbol }: UniqueAsset) {
return this.http.get<ImportResponse>(
`/api/v1/import/dividends/${dataSource}/${symbol}`
);
}
public fetchExchangeRateForDate({
date,
symbol

4
apps/client/src/app/services/import-activities.service.ts

@ -90,13 +90,16 @@ export class ImportActivitiesService {
selectedActivities: Activity[]
): Promise<Activity[]> {
const importData: CreateOrderDto[] = [];
for (const activity of selectedActivities) {
importData.push(this.convertToCreateOrderDto(activity));
}
return this.importJson({ content: importData });
}
private convertToCreateOrderDto({
accountId,
date,
fee,
quantity,
@ -105,6 +108,7 @@ export class ImportActivitiesService {
unitPrice
}: Activity): CreateOrderDto {
return {
accountId,
fee,
quantity,
type,

40
apps/client/src/assets/sitemap.xml

@ -6,82 +6,82 @@
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://ghostfol.io</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/about</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/about/changelog</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2021/07/hello-ghostfolio</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/08/500-stars-on-github</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/10/hacktoberfest-2022</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/11/black-friday-2022</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/blog/2022/12/the-importance-of-tracking-your-personal-finances</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/demo</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/faq</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/features</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/markets</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/pricing</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/register</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
<url>
<loc>https://ghostfol.io/en/resources</loc>
<lastmod>2022-12-26T00:00:00+00:00</lastmod>
<lastmod>2023-01-05T00:00:00+00:00</lastmod>
</url>
</urlset>

90
apps/client/src/locales/messages.de.xlf

@ -182,7 +182,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">426</context>
<context context-type="linenumber">434</context>
</context-group>
</trans-unit>
<trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
@ -202,7 +202,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">442</context>
<context context-type="linenumber">450</context>
</context-group>
</trans-unit>
<trans-unit id="8280212421112607879" datatype="html">
@ -386,7 +386,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">87,91</context>
<context context-type="linenumber">116,120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html</context>
@ -894,7 +894,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">27,29</context>
<context context-type="linenumber">54,56</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/register-page.html</context>
@ -1262,7 +1262,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">66,62</context>
<context context-type="linenumber">107,103</context>
</context-group>
</trans-unit>
<trans-unit id="1726363342938046830" datatype="html">
@ -1974,7 +1974,7 @@
<target state="translated">Daten importieren...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">89</context>
</context-group>
</trans-unit>
<trans-unit id="7500216440144530775" datatype="html">
@ -1982,7 +1982,7 @@
<target state="translated">Der Import wurde abgeschlossen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">55,54</context>
<context context-type="linenumber">96,95</context>
</context-group>
</trans-unit>
<trans-unit id="5080775557941296581" datatype="html">
@ -2130,7 +2130,7 @@
<target state="translated">Aktivitäten exportieren</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">399</context>
<context context-type="linenumber">407</context>
</context-group>
</trans-unit>
<trans-unit id="db4ffd639aac51ba929921856f8b15ea29e53695" datatype="html">
@ -2138,7 +2138,7 @@
<target state="translated">Geplante Aktivitäten als ICS exportieren</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">409</context>
<context context-type="linenumber">417</context>
</context-group>
</trans-unit>
<trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
@ -2146,7 +2146,7 @@
<target state="translated">Kopieren</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">430</context>
<context context-type="linenumber">438</context>
</context-group>
</trans-unit>
<trans-unit id="d8c19dd72422ee41c5ca9ad38b80592239e0fd08" datatype="html">
@ -2154,7 +2154,7 @@
<target state="translated">Geplante Aktivität als ICS exportieren</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">438</context>
<context context-type="linenumber">446</context>
</context-group>
</trans-unit>
<trans-unit id="670983159637074283" datatype="html">
@ -2162,7 +2162,7 @@
<target state="translated">Möchtest du diese Aktivität wirklich löschen?</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">198</context>
</context-group>
</trans-unit>
<trans-unit id="170f7de02b14690fb9c1999a16926c0044bfd5c1" datatype="html">
@ -2274,7 +2274,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">65,62</context>
<context context-type="linenumber">106,103</context>
</context-group>
</trans-unit>
<trans-unit id="7224997887539831269" datatype="html">
@ -2286,7 +2286,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">104</context>
</context-group>
</trans-unit>
<trans-unit id="024cdb2814b0cb3f4ced148f1a0b9854447cb214" datatype="html">
@ -2378,7 +2378,7 @@
<target state="translated">Entwickelte Länder</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">271</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2390,7 +2390,7 @@
<target state="translated">Schwellenländer</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2402,7 +2402,7 @@
<target state="translated">Andere Länder</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2458,7 +2458,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">59</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.ts</context>
@ -2526,11 +2526,11 @@
<target state="translated">Filtern nach Konto oder Tag...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts</context>
<context context-type="linenumber">136</context>
<context context-type="linenumber">137</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">111</context>
<context context-type="linenumber">123</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
@ -2542,7 +2542,7 @@
<target state="translated">Filtern nach Konto, Währung, Symbol oder Typ...</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">376</context>
<context context-type="linenumber">387</context>
</context-group>
</trans-unit>
<trans-unit id="fbaaeb297e70b9a800acf841b9d26c19d60651ef" datatype="html">
@ -2690,7 +2690,7 @@
<target state="translated">Sparrate</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">230</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="4086606389696938932" datatype="html">
@ -2906,7 +2906,7 @@
<target state="translated">Datei auswählen</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">18,21</context>
<context context-type="linenumber">43,46</context>
</context-group>
</trans-unit>
<trans-unit id="6f9fd3da06dc9000eef0d4dcbb37747b303048e9" datatype="html">
@ -2914,7 +2914,7 @@
<target state="translated">Folgende Dateiformate werden unterstützt:</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">21,23</context>
<context context-type="linenumber">47,50</context>
</context-group>
</trans-unit>
<trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
@ -2922,7 +2922,7 @@
<target state="translated">Zurück</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">79,83</context>
<context context-type="linenumber">108,112</context>
</context-group>
</trans-unit>
<trans-unit id="ec2d3a89b366d1ca80be056e9e71f0165ae75c7b" datatype="html">
@ -2932,6 +2932,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">135</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">139</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">143</context>
@ -3002,7 +3006,7 @@
<target state="translated">Daten validieren...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">86</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="a059709f71aa4c0ac219e160e78a738682ca6a36" datatype="html">
@ -3010,7 +3014,7 @@
<target state="translated">Importieren</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">94,99</context>
<context context-type="linenumber">123,128</context>
</context-group>
</trans-unit>
<trans-unit id="1803867056160333091" datatype="html">
@ -3053,6 +3057,38 @@
<context context-type="linenumber">28</context>
</context-group>
</trans-unit>
<trans-unit id="0f845001c88b82c18535e6d44f5597061f506e42" datatype="html">
<source>Holding</source>
<target state="translated">Position</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
</trans-unit>
<trans-unit id="050be0e7937dec05c8c8ded71cebc0bb027b38f6" datatype="html">
<source>Load Dividends</source>
<target state="translated">Dividenden laden</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">29,33</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<target state="translated">Jährlich</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="c849bfcd57f5d4a2cb0a1fb3359b687f13878637" datatype="html">
<source>Import Dividends</source>
<target state="translated">Dividenden importieren</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">397</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

90
apps/client/src/locales/messages.es.xlf

@ -183,7 +183,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">426</context>
<context context-type="linenumber">434</context>
</context-group>
</trans-unit>
<trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
@ -203,7 +203,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">442</context>
<context context-type="linenumber">450</context>
</context-group>
</trans-unit>
<trans-unit id="8280212421112607879" datatype="html">
@ -387,7 +387,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">87,91</context>
<context context-type="linenumber">116,120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html</context>
@ -895,7 +895,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">27,29</context>
<context context-type="linenumber">54,56</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/register-page.html</context>
@ -1263,7 +1263,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">66,62</context>
<context context-type="linenumber">107,103</context>
</context-group>
</trans-unit>
<trans-unit id="1726363342938046830" datatype="html">
@ -1975,7 +1975,7 @@
<target state="translated">Importando datos...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">89</context>
</context-group>
</trans-unit>
<trans-unit id="7500216440144530775" datatype="html">
@ -1983,7 +1983,7 @@
<target state="translated">La importación se ha completado</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">55,54</context>
<context context-type="linenumber">96,95</context>
</context-group>
</trans-unit>
<trans-unit id="5080775557941296581" datatype="html">
@ -2131,7 +2131,7 @@
<target state="translated">Exportar operaciones</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">399</context>
<context context-type="linenumber">407</context>
</context-group>
</trans-unit>
<trans-unit id="db4ffd639aac51ba929921856f8b15ea29e53695" datatype="html">
@ -2139,7 +2139,7 @@
<target state="translated">Exportar borrador como ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">409</context>
<context context-type="linenumber">417</context>
</context-group>
</trans-unit>
<trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
@ -2147,7 +2147,7 @@
<target state="translated">Clonar</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">430</context>
<context context-type="linenumber">438</context>
</context-group>
</trans-unit>
<trans-unit id="d8c19dd72422ee41c5ca9ad38b80592239e0fd08" datatype="html">
@ -2155,7 +2155,7 @@
<target state="translated">Exportar borrador como ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">438</context>
<context context-type="linenumber">446</context>
</context-group>
</trans-unit>
<trans-unit id="670983159637074283" datatype="html">
@ -2163,7 +2163,7 @@
<target state="translated">¿Estás seguro de eliminar esta operación?</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">198</context>
</context-group>
</trans-unit>
<trans-unit id="170f7de02b14690fb9c1999a16926c0044bfd5c1" datatype="html">
@ -2271,7 +2271,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">104</context>
</context-group>
</trans-unit>
<trans-unit id="8947585964755853889" datatype="html">
@ -2287,7 +2287,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">65,62</context>
<context context-type="linenumber">106,103</context>
</context-group>
</trans-unit>
<trans-unit id="024cdb2814b0cb3f4ced148f1a0b9854447cb214" datatype="html">
@ -2303,7 +2303,7 @@
<target state="translated">Mercados desarrollados</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">271</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2351,7 +2351,7 @@
<target state="translated">Otros mercados</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2363,7 +2363,7 @@
<target state="translated">Mercados emergentes</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2459,7 +2459,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">59</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.ts</context>
@ -2519,11 +2519,11 @@
<target state="translated">Filtrar por cuenta o etiqueta...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts</context>
<context context-type="linenumber">136</context>
<context context-type="linenumber">137</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">111</context>
<context context-type="linenumber">123</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
@ -2543,7 +2543,7 @@
<target state="translated">Filtrar por cuenta, divisa, símbolo o tipo...</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">376</context>
<context context-type="linenumber">387</context>
</context-group>
</trans-unit>
<trans-unit id="3d14940af7de691ac27efb67bef3e974cbe3281c" datatype="html">
@ -2691,7 +2691,7 @@
<target state="translated">Tasa de ahorro</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">230</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="4086606389696938932" datatype="html">
@ -2907,7 +2907,7 @@
<target state="translated">Elegir archivo</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">18,21</context>
<context context-type="linenumber">43,46</context>
</context-group>
</trans-unit>
<trans-unit id="6f9fd3da06dc9000eef0d4dcbb37747b303048e9" datatype="html">
@ -2915,7 +2915,7 @@
<target state="translated">Los siguientes formatos de archivo están soportados:</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">21,23</context>
<context context-type="linenumber">47,50</context>
</context-group>
</trans-unit>
<trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
@ -2923,7 +2923,7 @@
<target state="translated">Volver</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">79,83</context>
<context context-type="linenumber">108,112</context>
</context-group>
</trans-unit>
<trans-unit id="ec2d3a89b366d1ca80be056e9e71f0165ae75c7b" datatype="html">
@ -2933,6 +2933,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">135</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">139</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">143</context>
@ -3003,7 +3007,7 @@
<target state="new">Validating data...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">86</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="a059709f71aa4c0ac219e160e78a738682ca6a36" datatype="html">
@ -3011,7 +3015,7 @@
<target state="new">Import</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">94,99</context>
<context context-type="linenumber">123,128</context>
</context-group>
</trans-unit>
<trans-unit id="1803867056160333091" datatype="html">
@ -3054,6 +3058,38 @@
<context context-type="linenumber">28</context>
</context-group>
</trans-unit>
<trans-unit id="0f845001c88b82c18535e6d44f5597061f506e42" datatype="html">
<source>Holding</source>
<target state="new">Holding</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
</trans-unit>
<trans-unit id="050be0e7937dec05c8c8ded71cebc0bb027b38f6" datatype="html">
<source>Load Dividends</source>
<target state="new">Load Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">29,33</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<target state="new">Yearly</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="c849bfcd57f5d4a2cb0a1fb3359b687f13878637" datatype="html">
<source>Import Dividends</source>
<target state="new">Import Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">397</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

727
apps/client/src/locales/messages.fr.xlf

File diff suppressed because it is too large

90
apps/client/src/locales/messages.it.xlf

@ -183,7 +183,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">426</context>
<context context-type="linenumber">434</context>
</context-group>
</trans-unit>
<trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
@ -203,7 +203,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">442</context>
<context context-type="linenumber">450</context>
</context-group>
</trans-unit>
<trans-unit id="8280212421112607879" datatype="html">
@ -387,7 +387,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">87,91</context>
<context context-type="linenumber">116,120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html</context>
@ -895,7 +895,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">27,29</context>
<context context-type="linenumber">54,56</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/register-page.html</context>
@ -1263,7 +1263,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">66,62</context>
<context context-type="linenumber">107,103</context>
</context-group>
</trans-unit>
<trans-unit id="1726363342938046830" datatype="html">
@ -1975,7 +1975,7 @@
<target state="translated">Importazione dei dati...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">89</context>
</context-group>
</trans-unit>
<trans-unit id="7500216440144530775" datatype="html">
@ -1983,7 +1983,7 @@
<target state="translated">L&apos;importazione è stata completata</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">55,54</context>
<context context-type="linenumber">96,95</context>
</context-group>
</trans-unit>
<trans-unit id="5080775557941296581" datatype="html">
@ -2131,7 +2131,7 @@
<target state="translated">Esporta le attività</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">399</context>
<context context-type="linenumber">407</context>
</context-group>
</trans-unit>
<trans-unit id="db4ffd639aac51ba929921856f8b15ea29e53695" datatype="html">
@ -2139,7 +2139,7 @@
<target state="translated">Esporta le bozze come ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">409</context>
<context context-type="linenumber">417</context>
</context-group>
</trans-unit>
<trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
@ -2147,7 +2147,7 @@
<target state="translated">Clona</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">430</context>
<context context-type="linenumber">438</context>
</context-group>
</trans-unit>
<trans-unit id="d8c19dd72422ee41c5ca9ad38b80592239e0fd08" datatype="html">
@ -2155,7 +2155,7 @@
<target state="translated">Esporta la bozza come ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">438</context>
<context context-type="linenumber">446</context>
</context-group>
</trans-unit>
<trans-unit id="670983159637074283" datatype="html">
@ -2163,7 +2163,7 @@
<target state="translated">Vuoi davvero eliminare questa attività?</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">198</context>
</context-group>
</trans-unit>
<trans-unit id="170f7de02b14690fb9c1999a16926c0044bfd5c1" datatype="html">
@ -2271,7 +2271,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">104</context>
</context-group>
</trans-unit>
<trans-unit id="8947585964755853889" datatype="html">
@ -2287,7 +2287,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">65,62</context>
<context context-type="linenumber">106,103</context>
</context-group>
</trans-unit>
<trans-unit id="024cdb2814b0cb3f4ced148f1a0b9854447cb214" datatype="html">
@ -2303,7 +2303,7 @@
<target state="translated">Mercati sviluppati</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">271</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2351,7 +2351,7 @@
<target state="translated">Altri mercati</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2363,7 +2363,7 @@
<target state="translated">Mercati emergenti</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2459,7 +2459,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">59</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.ts</context>
@ -2519,11 +2519,11 @@
<target state="translated">Filtra per account o tag...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts</context>
<context context-type="linenumber">136</context>
<context context-type="linenumber">137</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">111</context>
<context context-type="linenumber">123</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
@ -2543,7 +2543,7 @@
<target state="translated">Filtra per account, valuta, simbolo o tipo...</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">376</context>
<context context-type="linenumber">387</context>
</context-group>
</trans-unit>
<trans-unit id="3d14940af7de691ac27efb67bef3e974cbe3281c" datatype="html">
@ -2691,7 +2691,7 @@
<target state="translated">Tasso di risparmio</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">230</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="4086606389696938932" datatype="html">
@ -2907,7 +2907,7 @@
<target state="new">Choose File</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">18,21</context>
<context context-type="linenumber">43,46</context>
</context-group>
</trans-unit>
<trans-unit id="6f9fd3da06dc9000eef0d4dcbb37747b303048e9" datatype="html">
@ -2915,7 +2915,7 @@
<target state="new">The following file formats are supported:</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">21,23</context>
<context context-type="linenumber">47,50</context>
</context-group>
</trans-unit>
<trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
@ -2923,7 +2923,7 @@
<target state="new">Back</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">79,83</context>
<context context-type="linenumber">108,112</context>
</context-group>
</trans-unit>
<trans-unit id="ec2d3a89b366d1ca80be056e9e71f0165ae75c7b" datatype="html">
@ -2933,6 +2933,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">135</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">139</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">143</context>
@ -3003,7 +3007,7 @@
<target state="new">Validating data...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">86</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="a059709f71aa4c0ac219e160e78a738682ca6a36" datatype="html">
@ -3011,7 +3015,7 @@
<target state="new">Import</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">94,99</context>
<context context-type="linenumber">123,128</context>
</context-group>
</trans-unit>
<trans-unit id="1803867056160333091" datatype="html">
@ -3054,6 +3058,38 @@
<context context-type="linenumber">28</context>
</context-group>
</trans-unit>
<trans-unit id="0f845001c88b82c18535e6d44f5597061f506e42" datatype="html">
<source>Holding</source>
<target state="new">Holding</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
</trans-unit>
<trans-unit id="050be0e7937dec05c8c8ded71cebc0bb027b38f6" datatype="html">
<source>Load Dividends</source>
<target state="new">Load Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">29,33</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<target state="new">Yearly</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="c849bfcd57f5d4a2cb0a1fb3359b687f13878637" datatype="html">
<source>Import Dividends</source>
<target state="new">Import Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">397</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

90
apps/client/src/locales/messages.nl.xlf

@ -182,7 +182,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">426</context>
<context context-type="linenumber">434</context>
</context-group>
</trans-unit>
<trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
@ -202,7 +202,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">442</context>
<context context-type="linenumber">450</context>
</context-group>
</trans-unit>
<trans-unit id="8280212421112607879" datatype="html">
@ -386,7 +386,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">87,91</context>
<context context-type="linenumber">116,120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html</context>
@ -894,7 +894,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">27,29</context>
<context context-type="linenumber">54,56</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/register-page.html</context>
@ -1262,7 +1262,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">66,62</context>
<context context-type="linenumber">107,103</context>
</context-group>
</trans-unit>
<trans-unit id="1726363342938046830" datatype="html">
@ -1974,7 +1974,7 @@
<target state="translated">Gegevens importeren...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">89</context>
</context-group>
</trans-unit>
<trans-unit id="7500216440144530775" datatype="html">
@ -1982,7 +1982,7 @@
<target state="translated">Import is voltooid</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">55,54</context>
<context context-type="linenumber">96,95</context>
</context-group>
</trans-unit>
<trans-unit id="5080775557941296581" datatype="html">
@ -2130,7 +2130,7 @@
<target state="translated">Activiteiten exporteren</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">399</context>
<context context-type="linenumber">407</context>
</context-group>
</trans-unit>
<trans-unit id="db4ffd639aac51ba929921856f8b15ea29e53695" datatype="html">
@ -2138,7 +2138,7 @@
<target state="translated">Concepten exporteren als ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">409</context>
<context context-type="linenumber">417</context>
</context-group>
</trans-unit>
<trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
@ -2146,7 +2146,7 @@
<target state="translated">Kloon</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">430</context>
<context context-type="linenumber">438</context>
</context-group>
</trans-unit>
<trans-unit id="d8c19dd72422ee41c5ca9ad38b80592239e0fd08" datatype="html">
@ -2154,7 +2154,7 @@
<target state="translated">Concepten exporteren als ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">438</context>
<context context-type="linenumber">446</context>
</context-group>
</trans-unit>
<trans-unit id="670983159637074283" datatype="html">
@ -2162,7 +2162,7 @@
<target state="translated">Wilt u deze activiteit echt verwijderen?</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">198</context>
</context-group>
</trans-unit>
<trans-unit id="170f7de02b14690fb9c1999a16926c0044bfd5c1" datatype="html">
@ -2270,7 +2270,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">104</context>
</context-group>
</trans-unit>
<trans-unit id="8947585964755853889" datatype="html">
@ -2286,7 +2286,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">65,62</context>
<context context-type="linenumber">106,103</context>
</context-group>
</trans-unit>
<trans-unit id="024cdb2814b0cb3f4ced148f1a0b9854447cb214" datatype="html">
@ -2302,7 +2302,7 @@
<target state="translated">Ontwikkelde markten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">271</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2350,7 +2350,7 @@
<target state="translated">Andere markten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2362,7 +2362,7 @@
<target state="translated">Opkomende markten</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2458,7 +2458,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">59</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.ts</context>
@ -2518,11 +2518,11 @@
<target state="translated">Filter op account of tag...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts</context>
<context context-type="linenumber">136</context>
<context context-type="linenumber">137</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">111</context>
<context context-type="linenumber">123</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
@ -2542,7 +2542,7 @@
<target state="translated">Filter op rekening, valuta, symbool of type...</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">376</context>
<context context-type="linenumber">387</context>
</context-group>
</trans-unit>
<trans-unit id="3d14940af7de691ac27efb67bef3e974cbe3281c" datatype="html">
@ -2690,7 +2690,7 @@
<target state="translated">Spaarquote</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">230</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="4086606389696938932" datatype="html">
@ -2906,7 +2906,7 @@
<target state="translated">Kies bestand</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">18,21</context>
<context context-type="linenumber">43,46</context>
</context-group>
</trans-unit>
<trans-unit id="6f9fd3da06dc9000eef0d4dcbb37747b303048e9" datatype="html">
@ -2914,7 +2914,7 @@
<target state="translated">The volgende bestandsformaten worden ondersteund:</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">21,23</context>
<context context-type="linenumber">47,50</context>
</context-group>
</trans-unit>
<trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
@ -2922,7 +2922,7 @@
<target state="translated">Terug</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">79,83</context>
<context context-type="linenumber">108,112</context>
</context-group>
</trans-unit>
<trans-unit id="ec2d3a89b366d1ca80be056e9e71f0165ae75c7b" datatype="html">
@ -2932,6 +2932,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">135</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">139</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">143</context>
@ -3002,7 +3006,7 @@
<target state="translated">Gegevens valideren...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">86</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="a059709f71aa4c0ac219e160e78a738682ca6a36" datatype="html">
@ -3010,7 +3014,7 @@
<target state="translated">Importeren</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">94,99</context>
<context context-type="linenumber">123,128</context>
</context-group>
</trans-unit>
<trans-unit id="1803867056160333091" datatype="html">
@ -3053,6 +3057,38 @@
<context context-type="linenumber">28</context>
</context-group>
</trans-unit>
<trans-unit id="0f845001c88b82c18535e6d44f5597061f506e42" datatype="html">
<source>Holding</source>
<target state="translated">Participatie</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
</trans-unit>
<trans-unit id="050be0e7937dec05c8c8ded71cebc0bb027b38f6" datatype="html">
<source>Load Dividends</source>
<target state="new">Load Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">29,33</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<target state="translated">Jaarlijks</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="c849bfcd57f5d4a2cb0a1fb3359b687f13878637" datatype="html">
<source>Import Dividends</source>
<target state="new">Import Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">397</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

90
apps/client/src/locales/messages.pt.xlf

@ -242,7 +242,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">426</context>
<context context-type="linenumber">434</context>
</context-group>
</trans-unit>
<trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
@ -262,7 +262,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">442</context>
<context context-type="linenumber">450</context>
</context-group>
</trans-unit>
<trans-unit id="8280212421112607879" datatype="html">
@ -446,7 +446,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">87,91</context>
<context context-type="linenumber">116,120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html</context>
@ -1110,7 +1110,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">59</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.ts</context>
@ -1130,7 +1130,7 @@
<target state="new">Savings Rate</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">230</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="6a95e051c4fd80012488effb15d2842b2155ae5e" datatype="html">
@ -1154,7 +1154,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">27,29</context>
<context context-type="linenumber">54,56</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/register-page.html</context>
@ -1578,7 +1578,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">65,62</context>
<context context-type="linenumber">106,103</context>
</context-group>
</trans-unit>
<trans-unit id="7224997887539831269" datatype="html">
@ -1590,7 +1590,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">104</context>
</context-group>
</trans-unit>
<trans-unit id="1579692722565712588" datatype="html">
@ -1602,7 +1602,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">66,62</context>
<context context-type="linenumber">107,103</context>
</context-group>
</trans-unit>
<trans-unit id="1726363342938046830" datatype="html">
@ -2118,7 +2118,7 @@
<target state="new">Importing data...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">89</context>
</context-group>
</trans-unit>
<trans-unit id="7500216440144530775" datatype="html">
@ -2126,7 +2126,7 @@
<target state="new">Import has been completed</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">55,54</context>
<context context-type="linenumber">96,95</context>
</context-group>
</trans-unit>
<trans-unit id="73f8489a3ae4d805787b8350d3d91e03e830115b" datatype="html">
@ -2134,7 +2134,7 @@
<target state="new">Choose File</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">18,21</context>
<context context-type="linenumber">43,46</context>
</context-group>
</trans-unit>
<trans-unit id="6f9fd3da06dc9000eef0d4dcbb37747b303048e9" datatype="html">
@ -2142,7 +2142,7 @@
<target state="new">The following file formats are supported:</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">21,23</context>
<context context-type="linenumber">47,50</context>
</context-group>
</trans-unit>
<trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
@ -2150,7 +2150,7 @@
<target state="new">Back</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">79,83</context>
<context context-type="linenumber">108,112</context>
</context-group>
</trans-unit>
<trans-unit id="2666668717343771434" datatype="html">
@ -2182,11 +2182,11 @@
<target state="new">Filter by account or tag...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts</context>
<context context-type="linenumber">136</context>
<context context-type="linenumber">137</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">111</context>
<context context-type="linenumber">123</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
@ -2282,7 +2282,7 @@
<target state="new">Developed Markets</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">271</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2294,7 +2294,7 @@
<target state="new">Emerging Markets</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2306,7 +2306,7 @@
<target state="new">Other Markets</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2594,7 +2594,7 @@
<target state="new">Export Activities</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">399</context>
<context context-type="linenumber">407</context>
</context-group>
</trans-unit>
<trans-unit id="db4ffd639aac51ba929921856f8b15ea29e53695" datatype="html">
@ -2602,7 +2602,7 @@
<target state="new">Export Drafts as ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">409</context>
<context context-type="linenumber">417</context>
</context-group>
</trans-unit>
<trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
@ -2610,7 +2610,7 @@
<target state="new">Clone</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">430</context>
<context context-type="linenumber">438</context>
</context-group>
</trans-unit>
<trans-unit id="d8c19dd72422ee41c5ca9ad38b80592239e0fd08" datatype="html">
@ -2618,7 +2618,7 @@
<target state="new">Export Draft as ICS</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">438</context>
<context context-type="linenumber">446</context>
</context-group>
</trans-unit>
<trans-unit id="670983159637074283" datatype="html">
@ -2626,7 +2626,7 @@
<target state="new">Do you really want to delete this activity?</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">198</context>
</context-group>
</trans-unit>
<trans-unit id="303469635941752458" datatype="html">
@ -2634,7 +2634,7 @@
<target state="new">Filter by account, currency, symbol or type...</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">376</context>
<context context-type="linenumber">387</context>
</context-group>
</trans-unit>
<trans-unit id="170f7de02b14690fb9c1999a16926c0044bfd5c1" datatype="html">
@ -2980,6 +2980,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">135</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">139</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">143</context>
@ -3010,7 +3014,7 @@
<target state="new">Validating data...</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">86</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="a059709f71aa4c0ac219e160e78a738682ca6a36" datatype="html">
@ -3018,7 +3022,7 @@
<target state="new">Import</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">94,99</context>
<context context-type="linenumber">123,128</context>
</context-group>
</trans-unit>
<trans-unit id="7765499580020598783" datatype="html">
@ -3053,6 +3057,38 @@
<context context-type="linenumber">9</context>
</context-group>
</trans-unit>
<trans-unit id="0f845001c88b82c18535e6d44f5597061f506e42" datatype="html">
<source>Holding</source>
<target state="new">Holding</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
</trans-unit>
<trans-unit id="050be0e7937dec05c8c8ded71cebc0bb027b38f6" datatype="html">
<source>Load Dividends</source>
<target state="new">Load Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">29,33</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<target state="new">Yearly</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="c849bfcd57f5d4a2cb0a1fb3359b687f13878637" datatype="html">
<source>Import Dividends</source>
<target state="new">Import Dividends</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">397</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

86
apps/client/src/locales/messages.xlf

@ -171,7 +171,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">426</context>
<context context-type="linenumber">434</context>
</context-group>
</trans-unit>
<trans-unit id="826b25211922a1b46436589233cb6f1a163d89b7" datatype="html">
@ -190,7 +190,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">442</context>
<context context-type="linenumber">450</context>
</context-group>
</trans-unit>
<trans-unit id="8280212421112607879" datatype="html">
@ -357,7 +357,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">87,91</context>
<context context-type="linenumber">116,120</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html</context>
@ -815,7 +815,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">27,29</context>
<context context-type="linenumber">54,56</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/register/register-page.html</context>
@ -1146,7 +1146,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">66,62</context>
<context context-type="linenumber">107,103</context>
</context-group>
</trans-unit>
<trans-unit id="1726363342938046830" datatype="html">
@ -1780,14 +1780,14 @@
<source>Importing data...</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">48</context>
<context context-type="linenumber">89</context>
</context-group>
</trans-unit>
<trans-unit id="7500216440144530775" datatype="html">
<source>Import has been completed</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">55,54</context>
<context context-type="linenumber">96,95</context>
</context-group>
</trans-unit>
<trans-unit id="5080775557941296581" datatype="html">
@ -1917,35 +1917,35 @@
<source>Export Activities</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">399</context>
<context context-type="linenumber">407</context>
</context-group>
</trans-unit>
<trans-unit id="db4ffd639aac51ba929921856f8b15ea29e53695" datatype="html">
<source>Export Drafts as ICS</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">409</context>
<context context-type="linenumber">417</context>
</context-group>
</trans-unit>
<trans-unit id="54a4a3132b693575728a45a5f3154ad4c9af404b" datatype="html">
<source>Clone</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">430</context>
<context context-type="linenumber">438</context>
</context-group>
</trans-unit>
<trans-unit id="d8c19dd72422ee41c5ca9ad38b80592239e0fd08" datatype="html">
<source>Export Draft as ICS</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">438</context>
<context context-type="linenumber">446</context>
</context-group>
</trans-unit>
<trans-unit id="670983159637074283" datatype="html">
<source>Do you really want to delete this activity?</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">196</context>
<context context-type="linenumber">198</context>
</context-group>
</trans-unit>
<trans-unit id="170f7de02b14690fb9c1999a16926c0044bfd5c1" datatype="html">
@ -2040,7 +2040,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">104</context>
</context-group>
</trans-unit>
<trans-unit id="8947585964755853889" datatype="html">
@ -2055,7 +2055,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">65,62</context>
<context context-type="linenumber">106,103</context>
</context-group>
</trans-unit>
<trans-unit id="024cdb2814b0cb3f4ced148f1a0b9854447cb214" datatype="html">
@ -2069,7 +2069,7 @@
<source>Developed Markets</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">271</context>
<context context-type="linenumber">272</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2113,7 +2113,7 @@
<source>Other Markets</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">289</context>
<context context-type="linenumber">290</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2124,7 +2124,7 @@
<source>Emerging Markets</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.html</context>
<context context-type="linenumber">280</context>
<context context-type="linenumber">281</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/public/public-page.html</context>
@ -2210,7 +2210,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">59</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/fire-calculator/fire-calculator.component.ts</context>
@ -2263,11 +2263,11 @@
<source>Filter by account or tag...</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts</context>
<context context-type="linenumber">136</context>
<context context-type="linenumber">137</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">111</context>
<context context-type="linenumber">123</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts</context>
@ -2285,7 +2285,7 @@
<source>Filter by account, currency, symbol or type...</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.ts</context>
<context context-type="linenumber">376</context>
<context context-type="linenumber">387</context>
</context-group>
</trans-unit>
<trans-unit id="3d14940af7de691ac27efb67bef3e974cbe3281c" datatype="html">
@ -2415,7 +2415,7 @@
<source>Savings Rate</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/investment-chart/investment-chart.component.ts</context>
<context context-type="linenumber">230</context>
<context context-type="linenumber">239</context>
</context-group>
</trans-unit>
<trans-unit id="1270654249046226808" datatype="html">
@ -2605,21 +2605,21 @@
<source>The following file formats are supported:</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">21,23</context>
<context context-type="linenumber">47,50</context>
</context-group>
</trans-unit>
<trans-unit id="73f8489a3ae4d805787b8350d3d91e03e830115b" datatype="html">
<source>Choose File</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">18,21</context>
<context context-type="linenumber">43,46</context>
</context-group>
</trans-unit>
<trans-unit id="cda31dbd724cf5f4fa7a4274d9120651490c8a8c" datatype="html">
<source>Back</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">79,83</context>
<context context-type="linenumber">108,112</context>
</context-group>
</trans-unit>
<trans-unit id="ec2d3a89b366d1ca80be056e9e71f0165ae75c7b" datatype="html">
@ -2628,6 +2628,10 @@
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">135</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">139</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/account/account-page.html</context>
<context context-type="linenumber">143</context>
@ -2697,14 +2701,14 @@
<source>Validating data...</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts</context>
<context context-type="linenumber">86</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="a059709f71aa4c0ac219e160e78a738682ca6a36" datatype="html">
<source>Import</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">94,99</context>
<context context-type="linenumber">123,128</context>
</context-group>
</trans-unit>
<trans-unit id="3229595422546554334" datatype="html">
@ -2735,6 +2739,34 @@
<context context-type="linenumber">20</context>
</context-group>
</trans-unit>
<trans-unit id="050be0e7937dec05c8c8ded71cebc0bb027b38f6" datatype="html">
<source>Load Dividends</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">29,33</context>
</context-group>
</trans-unit>
<trans-unit id="0f845001c88b82c18535e6d44f5597061f506e42" datatype="html">
<source>Holding</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="c849bfcd57f5d4a2cb0a1fb3359b687f13878637" datatype="html">
<source>Import Dividends</source>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">397</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

4
apps/client/src/styles.scss

@ -3,9 +3,9 @@
@import './styles/bootstrap';
@import './styles/table';
@import '~angular-material-css-vars/src/lib/main';
@import 'node_modules/angular-material-css-vars/src/lib/main';
@import '~svgmap/dist/svgMap';
@import 'node_modules/svgmap/dist/svgMap';
$mat-css-dark-theme-selector: '.is-dark-theme';
$mat-css-light-theme-selector: '.is-light-theme';

74
apps/client/src/styles/bootstrap.scss

@ -5,40 +5,40 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
@import '~bootstrap/scss/mixins';
@import '~bootstrap/scss/root';
@import '~bootstrap/scss/reboot';
@import '~bootstrap/scss/type';
@import '~bootstrap/scss/images';
// @import '~bootstrap/scss/code';
@import '~bootstrap/scss/grid';
// @import '~bootstrap/scss/tables';
// @import '~bootstrap/scss/forms';
// @import '~bootstrap/scss/buttons';
// @import '~bootstrap/scss/transitions';
// @import '~bootstrap/scss/dropdown';
// @import '~bootstrap/scss/button-group';
// @import '~bootstrap/scss/input-group';
// @import '~bootstrap/scss/custom-forms';
// @import '~bootstrap/scss/nav';
// @import '~bootstrap/scss/navbar';
// @import '~bootstrap/scss/card';
// @import '~bootstrap/scss/breadcrumb';
// @import '~bootstrap/scss/pagination';
@import '~bootstrap/scss/badge';
// @import '~bootstrap/scss/jumbotron';
// @import '~bootstrap/scss/alert';
// @import '~bootstrap/scss/progress';
// @import '~bootstrap/scss/media';
// @import '~bootstrap/scss/list-group';
// @import '~bootstrap/scss/close';
// @import '~bootstrap/scss/toasts';
// @import '~bootstrap/scss/modal';
// @import '~bootstrap/scss/tooltip';
// @import '~bootstrap/scss/popover';
// @import '~bootstrap/scss/carousel';
// @import '~bootstrap/scss/spinners';
@import '~bootstrap/scss/utilities';
// @import '~bootstrap/scss/print';
@import 'node_modules/bootstrap/scss/functions';
@import 'node_modules/bootstrap/scss/variables';
@import 'node_modules/bootstrap/scss/mixins';
@import 'node_modules/bootstrap/scss/root';
@import 'node_modules/bootstrap/scss/reboot';
@import 'node_modules/bootstrap/scss/type';
@import 'node_modules/bootstrap/scss/images';
// @import 'node_modules/bootstrap/scss/code';
@import 'node_modules/bootstrap/scss/grid';
// @import 'node_modules/bootstrap/scss/tables';
// @import 'node_modules/bootstrap/scss/forms';
// @import 'node_modules/bootstrap/scss/buttons';
// @import 'node_modules/bootstrap/scss/transitions';
// @import 'node_modules/bootstrap/scss/dropdown';
// @import 'node_modules/bootstrap/scss/button-group';
// @import 'node_modules/bootstrap/scss/input-group';
// @import 'node_modules/bootstrap/scss/custom-forms';
// @import 'node_modules/bootstrap/scss/nav';
// @import 'node_modules/bootstrap/scss/navbar';
// @import 'node_modules/bootstrap/scss/card';
// @import 'node_modules/bootstrap/scss/breadcrumb';
// @import 'node_modules/bootstrap/scss/pagination';
@import 'node_modules/bootstrap/scss/badge';
// @import 'node_modules/bootstrap/scss/jumbotron';
// @import 'node_modules/bootstrap/scss/alert';
// @import 'node_modules/bootstrap/scss/progress';
// @import 'node_modules/bootstrap/scss/media';
// @import 'node_modules/bootstrap/scss/list-group';
// @import 'node_modules/bootstrap/scss/close';
// @import 'node_modules/bootstrap/scss/toasts';
// @import 'node_modules/bootstrap/scss/modal';
// @import 'node_modules/bootstrap/scss/tooltip';
// @import 'node_modules/bootstrap/scss/popover';
// @import 'node_modules/bootstrap/scss/carousel';
// @import 'node_modules/bootstrap/scss/spinners';
@import 'node_modules/bootstrap/scss/utilities';
// @import 'node_modules/bootstrap/scss/print';

2
apps/client/src/styles/ghostfolio-style.scss

@ -1,6 +1,6 @@
$mat-css-dark-theme-selector: '.is-dark-theme';
@import '~angular-material-css-vars/src/lib/public-util';
@import 'node_modules/angular-material-css-vars/src/lib/public-util';
$alpha-disabled-text: 0.38;
$alpha-hover: 0.04;

1
libs/common/src/lib/config.ts

@ -72,6 +72,7 @@ export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_OPTIONS: JobOptions = {
export const MAX_CHART_ITEMS = 365;
export const PROPERTY_BENCHMARKS = 'BENCHMARKS';
export const PROPERTY_COUNTRIES_OF_SUBSCRIBERS = 'COUNTRIES_OF_SUBSCRIBERS';
export const PROPERTY_COUPONS = 'COUPONS';
export const PROPERTY_CURRENCIES = 'CURRENCIES';
export const PROPERTY_IS_READ_ONLY_MODE = 'IS_READ_ONLY_MODE';

2
libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts

@ -8,7 +8,7 @@ export interface EnhancedSymbolProfile {
activitiesCount: number;
assetClass: AssetClass;
assetSubClass: AssetSubClass;
comment?: string;
comment: string | null;
countries: Country[];
createdAt: Date;
currency: string | null;

1
libs/common/src/lib/interfaces/historical-data-item.interface.ts

@ -4,6 +4,7 @@ export interface HistoricalDataItem {
grossPerformancePercent?: number;
netPerformance?: number;
netPerformanceInPercentage?: number;
quantity?: number;
totalInvestment?: number;
value?: number;
}

2
libs/common/src/lib/interfaces/info-item.interface.ts

@ -6,12 +6,12 @@ import { Subscription } from './subscription.interface';
export interface InfoItem {
baseCurrency: string;
benchmarks: Partial<SymbolProfile>[];
countriesOfSubscribers?: string[];
currencies: string[];
demoAuthToken: string;
fearAndGreedDataSource?: string;
globalPermissions: string[];
isReadOnlyMode?: boolean;
lastDataGathering?: Date;
platforms: { id: string; name: string }[];
statistics: Statistics;
stripePublicKey?: string;

3
libs/common/src/lib/types/account-with-platform.type.ts

@ -0,0 +1,3 @@
import { Account, Platform } from '@prisma/client';
export type AccountWithPlatform = Account & { Platform?: Platform };

2
libs/common/src/lib/types/index.ts

@ -1,4 +1,5 @@
import type { AccessWithGranteeUser } from './access-with-grantee-user.type';
import { AccountWithPlatform } from './account-with-platform.type';
import { AccountWithValue } from './account-with-value.type';
import type { ColorScheme } from './color-scheme';
import type { DateRange } from './date-range.type';
@ -13,6 +14,7 @@ import type { ViewMode } from './view-mode.type';
export type {
AccessWithGranteeUser,
AccountWithPlatform,
AccountWithValue,
ColorScheme,
DateRange,

4
libs/common/src/lib/types/order-with-account.type.ts

@ -1,6 +1,6 @@
import { Account, Order, Platform, SymbolProfile, Tag } from '@prisma/client';
import { Order, SymbolProfile, Tag } from '@prisma/client';
type AccountWithPlatform = Account & { Platform?: Platform };
import { AccountWithPlatform } from './account-with-platform.type';
export type OrderWithAccount = Order & {
Account?: AccountWithPlatform;

2
libs/ui/src/lib/activities-filter/activities-filter.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

21
libs/ui/src/lib/activities-table/activities-table.component.html

@ -117,7 +117,7 @@
<td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex align-items-center">
<div>
<span class="text-truncate">{{ element.SymbolProfile.name }}</span>
<span class="text-truncate">{{ element.SymbolProfile?.name }}</span>
<span
*ngIf="element.isDraft"
class="badge badge-secondary ml-1"
@ -126,9 +126,9 @@
>
</div>
</div>
<div *ngIf="!isUUID(element.SymbolProfile.symbol)">
<div *ngIf="!isUUID(element.SymbolProfile?.symbol)">
<small class="text-muted">{{
element.SymbolProfile.symbol | gfSymbol
element.SymbolProfile?.symbol | gfSymbol
}}</small>
</div>
</td>
@ -149,7 +149,7 @@
class="d-none d-lg-table-cell px-1"
mat-cell
>
{{ element.SymbolProfile.currency }}
{{ element.SymbolProfile?.currency }}
</td>
<td *matFooterCellDef class="d-none d-lg-table-cell px-1" mat-footer-cell>
{{ baseCurrency }}
@ -388,6 +388,14 @@
<ion-icon class="mr-2" name="cloud-upload-outline"></ion-icon>
<span i18n>Import Activities</span>
</button>
<button
*ngIf="hasPermissionToImportActivities"
mat-menu-item
(click)="onImportDividends()"
>
<ion-icon class="mr-2" name="color-wand-outline"></ion-icon>
<span i18n>Import Dividends</span>
</button>
<button
*ngIf="hasPermissionToExportActivities"
class="align-items-center d-flex"
@ -459,7 +467,10 @@
<tr
*matFooterRowDef="displayedColumns"
mat-footer-row
[ngClass]="{ 'd-none': isLoading || dataSource.data.length === 0 }"
[ngClass]="{
'd-none':
isLoading || dataSource.data.length === 0 || showFooter === false
}"
></tr>
</table>
</div>

2
libs/ui/src/lib/activities-table/activities-table.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

15
libs/ui/src/lib/activities-table/activities-table.component.ts

@ -41,8 +41,9 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
@Input() hasPermissionToOpenDetails = true;
@Input() locale: string;
@Input() pageSize = DEFAULT_PAGE_SIZE;
@Input() showActions: boolean;
@Input() showActions = true;
@Input() showCheckbox = false;
@Input() showFooter = true;
@Input() showNameColumn = true;
@Output() activityDeleted = new EventEmitter<string>();
@ -51,6 +52,7 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
@Output() export = new EventEmitter<string[]>();
@Output() exportDrafts = new EventEmitter<string[]>();
@Output() import = new EventEmitter<void>();
@Output() importDividends = new EventEmitter<UniqueAsset>();
@Output() selectedActivities = new EventEmitter<Activity[]>();
@ViewChild(MatPaginator) paginator: MatPaginator;
@ -233,6 +235,10 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
this.import.emit();
}
public onImportDividends() {
this.importDividends.emit();
}
public onOpenComment(aComment: string) {
alert(aComment);
}
@ -272,13 +278,18 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
};
}
if (activity.SymbolProfile?.currency) {
fieldValueMap[activity.SymbolProfile.currency] = {
id: activity.SymbolProfile.currency,
label: activity.SymbolProfile.currency,
type: 'TAG'
};
}
if (!isUUID(activity.SymbolProfile.symbol)) {
if (
activity.SymbolProfile?.symbol &&
!isUUID(activity.SymbolProfile.symbol)
) {
fieldValueMap[activity.SymbolProfile.symbol] = {
id: activity.SymbolProfile.symbol,
label: activity.SymbolProfile.symbol,

2
libs/ui/src/lib/holdings-table/holdings-table.component.scss

@ -1,4 +1,4 @@
@import '~apps/client/src/styles/ghostfolio-style';
@import 'apps/client/src/styles/ghostfolio-style';
:host {
display: block;

2
package.json

@ -1,6 +1,6 @@
{
"name": "ghostfolio",
"version": "1.224.0",
"version": "1.226.0",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"scripts": {

Loading…
Cancel
Save