Compare commits

..

18 Commits

Author SHA1 Message Date
2466f4ff5d Release 1.203.0 (#1338) 2022-10-08 14:22:43 +02:00
8f3a9bdfbb Feature/refactor animation configuration (#1337)
* Refactor animation configuration

* Update changelog
2022-10-08 14:21:17 +02:00
44dfd2bd48 Add animation to line chart (#1328) 2022-10-08 13:47:48 +02:00
3fc2228f1d Feature/switch to new performance calculation (#1336)
* Switch to new performance calculation

* Update changelog
2022-10-08 13:20:52 +02:00
b018819a1f Bugfix/fix todays performance and chart calculation (#1333)
* Fix today's performance and chart calculation

* Update changelog
2022-10-08 13:20:25 +02:00
ac9311d783 Bugfix/fix alignment in users table (#1335)
* Fix alignment

* Update changelog
2022-10-08 11:38:58 +02:00
e23ce0f35d Feature/improve gui of benchmark comparator (#1334)
* Improve GUI

* Update changelog
2022-10-08 11:07:42 +02:00
f4b52aa41c Add Italian localization for the 4% rule (#1329)
* Update messages.it.xlf
2022-10-08 11:05:53 +02:00
655b040d4d Add missing title (#1332) 2022-10-07 20:54:05 +02:00
0f637a5d0f Release 1.202.0 (#1331) 2022-10-07 20:49:57 +02:00
3f85c327f5 Bugfix/fix text truncation in value component (#1330)
* Fix text truncation

* Update changelog
2022-10-07 20:48:39 +02:00
c2df99072d Feature/refactor filters (#1299)
* Refactor filters

Co-Authored-By: Zakaria YAHI <9142557+ZakYahi@users.noreply.github.com>
2022-10-07 20:39:29 +02:00
e8afbcad9c Feature/localize 4 percentage rule (#1327)
* Setup translation for 4% rule

* Update changelog
2022-10-07 20:21:52 +02:00
e6d8de781b Feature/improve wording in twitter bot service (#1326)
* Improve wording

* Update changelog
2022-10-06 20:52:34 +02:00
6e1935899f Bugfix/fix cryptocurrency symbols with less than 3 characters (#1325)
* Fix cryptocurrency symbols with less than 3 characters

* Update changelog
2022-10-06 15:15:36 +02:00
169cb85b66 Improve Italian translation (#1318)
* Update messages.it.xlf
2022-10-05 07:53:03 +02:00
fe6658d0ac Update messages.es.xlf (#1319) 2022-10-04 17:43:25 +02:00
1f0381228e Feature/improve caching of benchmarks (#1320)
* Improve caching

* Update changelog
2022-10-04 17:39:51 +02:00
33 changed files with 495 additions and 574 deletions

View File

@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 1.203.0 - 08.10.2022
### Added
- Supported a progressive line animation in the line chart component
### Changed
- Moved the benchmark comparator from experimental to general availability
- Improved the user interface of the benchmark comparator
### Fixed
- Fixed an issue in the performance and chart calculation of today
- Fixed the alignment of the value component in the admin control panel
## 1.202.0 - 07.10.2022
### Added
- Added support for a translated 4% rule in the _FIRE_ section
### Changed
- Improved the caching of the benchmarks in the markets overview (only cache if fetching was successful)
- Improved the wording in the twitter bot service
### Fixed
- Fixed the support for cryptocurrencies having a symbol with less than 3 characters (e.g. `SC-USD`)
- Fixed the text truncation in the value component
## 1.201.0 - 01.10.2022 ## 1.201.0 - 01.10.2022
### Added ### Added

View File

@ -95,11 +95,10 @@ export class AccountController {
); );
let accountsWithAggregations = let accountsWithAggregations =
await this.portfolioService.getAccountsWithAggregations( await this.portfolioService.getAccountsWithAggregations({
impersonationUserId || this.request.user.id, userId: impersonationUserId || this.request.user.id,
undefined, withExcludedAccounts: true
true });
);
if ( if (
impersonationUserId || impersonationUserId ||
@ -139,11 +138,11 @@ export class AccountController {
); );
let accountsWithAggregations = let accountsWithAggregations =
await this.portfolioService.getAccountsWithAggregations( await this.portfolioService.getAccountsWithAggregations({
impersonationUserId || this.request.user.id, filters: [{ id, type: 'ACCOUNT' }],
[{ id, type: 'ACCOUNT' }], userId: impersonationUserId || this.request.user.id,
true withExcludedAccounts: true
); });
if ( if (
impersonationUserId || impersonationUserId ||

View File

@ -73,6 +73,7 @@ export class BenchmarkService {
} }
const allTimeHighs = await Promise.all(promises); const allTimeHighs = await Promise.all(promises);
let storeInCache = true;
benchmarks = allTimeHighs.map((allTimeHigh, index) => { benchmarks = allTimeHighs.map((allTimeHigh, index) => {
const { marketPrice } = const { marketPrice } =
@ -85,6 +86,8 @@ export class BenchmarkService {
allTimeHigh, allTimeHigh,
marketPrice marketPrice
); );
} else {
storeInCache = false;
} }
return { return {
@ -100,11 +103,13 @@ export class BenchmarkService {
}; };
}); });
if (storeInCache) {
await this.redisCacheService.set( await this.redisCacheService.set(
this.CACHE_KEY_BENCHMARKS, this.CACHE_KEY_BENCHMARKS,
JSON.stringify(benchmarks), JSON.stringify(benchmarks),
ms('4 hours') / 1000 ms('4 hours') / 1000
); );
}
return benchmarks; return benchmarks;
} }

View File

@ -3,8 +3,8 @@ import { nullifyValuesInObjects } from '@ghostfolio/api/helper/object.helper';
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor'; import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; 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 { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor';
import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { ImpersonationService } from '@ghostfolio/api/services/impersonation.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation.service';
import { Filter } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types'; import type { RequestWithUser } from '@ghostfolio/common/types';
import { import {
@ -36,6 +36,7 @@ import { UpdateOrderDto } from './update-order.dto';
@Controller('order') @Controller('order')
export class OrderController { export class OrderController {
public constructor( public constructor(
private readonly apiService: ApiService,
private readonly impersonationService: ImpersonationService, private readonly impersonationService: ImpersonationService,
private readonly orderService: OrderService, private readonly orderService: OrderService,
@Inject(REQUEST) private readonly request: RequestWithUser, @Inject(REQUEST) private readonly request: RequestWithUser,
@ -73,30 +74,11 @@ export class OrderController {
@Query('assetClasses') filterByAssetClasses?: string, @Query('assetClasses') filterByAssetClasses?: string,
@Query('tags') filterByTags?: string @Query('tags') filterByTags?: string
): Promise<Activities> { ): Promise<Activities> {
const accountIds = filterByAccounts?.split(',') ?? []; const filters = this.apiService.buildFiltersFromQueryParams({
const assetClasses = filterByAssetClasses?.split(',') ?? []; filterByAccounts,
const tagIds = filterByTags?.split(',') ?? []; filterByAssetClasses,
filterByTags
const filters: Filter[] = [ });
...accountIds.map((accountId) => {
return <Filter>{
id: accountId,
type: 'ACCOUNT'
};
}),
...assetClasses.map((assetClass) => {
return <Filter>{
id: assetClass,
type: 'ASSET_CLASS'
};
}),
...tagIds.map((tagId) => {
return <Filter>{
id: tagId,
type: 'TAG'
};
})
];
const impersonationUserId = const impersonationUserId =
await this.impersonationService.validateImpersonationId( await this.impersonationService.validateImpersonationId(

View File

@ -2,6 +2,7 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { CacheModule } from '@ghostfolio/api/app/cache/cache.module'; import { CacheModule } from '@ghostfolio/api/app/cache/cache.module';
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module';
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module';
import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering.module';
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
@ -18,6 +19,7 @@ import { OrderService } from './order.service';
controllers: [OrderController], controllers: [OrderController],
exports: [OrderService], exports: [OrderService],
imports: [ imports: [
ApiModule,
CacheModule, CacheModule,
ConfigurationModule, ConfigurationModule,
DataGatheringModule, DataGatheringModule,

View File

@ -14,6 +14,7 @@ import {
format, format,
isAfter, isAfter,
isBefore, isBefore,
isSameDay,
isSameMonth, isSameMonth,
isSameYear, isSameYear,
max, max,
@ -187,7 +188,9 @@ export class PortfolioCalculator {
day = addDays(day, step); day = addDays(day, step);
} }
if (!isSameDay(last(dates), end)) {
dates.push(resetHours(end)); dates.push(resetHours(end));
}
for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) { for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) {
dataGatheringItems.push({ dataGatheringItems.push({

View File

@ -7,18 +7,16 @@ import {
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor'; import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; 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 { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor';
import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service';
import { parseDate } from '@ghostfolio/common/helper'; import { parseDate } from '@ghostfolio/common/helper';
import { import {
Filter,
PortfolioChart,
PortfolioDetails, PortfolioDetails,
PortfolioInvestments, PortfolioInvestments,
PortfolioPerformanceResponse, PortfolioPerformanceResponse,
PortfolioPublicDetails, PortfolioPublicDetails,
PortfolioReport, PortfolioReport
PortfolioSummary
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface';
import type { import type {
@ -52,6 +50,7 @@ export class PortfolioController {
public constructor( public constructor(
private readonly accessService: AccessService, private readonly accessService: AccessService,
private readonly apiService: ApiService,
private readonly configurationService: ConfigurationService, private readonly configurationService: ConfigurationService,
private readonly exchangeRateDataService: ExchangeRateDataService, private readonly exchangeRateDataService: ExchangeRateDataService,
private readonly portfolioService: PortfolioService, private readonly portfolioService: PortfolioService,
@ -61,55 +60,6 @@ export class PortfolioController {
this.baseCurrency = this.configurationService.get('BASE_CURRENCY'); this.baseCurrency = this.configurationService.get('BASE_CURRENCY');
} }
@Get('chart')
@UseGuards(AuthGuard('jwt'))
public async getChart(
@Headers('impersonation-id') impersonationId: string,
@Query('range') range
): Promise<PortfolioChart> {
const historicalDataContainer = await this.portfolioService.getChart(
impersonationId,
range
);
let chartData = historicalDataContainer.items;
let hasError = false;
chartData.forEach((chartDataItem) => {
if (hasNotDefinedValuesInObject(chartDataItem)) {
hasError = true;
}
});
if (
impersonationId ||
this.userService.isRestrictedView(this.request.user)
) {
let maxValue = 0;
chartData.forEach((portfolioItem) => {
if (portfolioItem.value > maxValue) {
maxValue = portfolioItem.value;
}
});
chartData = chartData.map((historicalDataItem) => {
return {
...historicalDataItem,
marketPrice: Number((historicalDataItem.value / maxValue).toFixed(2))
};
});
}
return {
hasError,
chart: chartData,
isAllTimeHigh: historicalDataContainer.isAllTimeHigh,
isAllTimeLow: historicalDataContainer.isAllTimeLow
};
}
@Get('details') @Get('details')
@UseGuards(AuthGuard('jwt')) @UseGuards(AuthGuard('jwt'))
@UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(RedactValuesInResponseInterceptor)
@ -123,32 +73,11 @@ export class PortfolioController {
): Promise<PortfolioDetails & { hasError: boolean }> { ): Promise<PortfolioDetails & { hasError: boolean }> {
let hasError = false; let hasError = false;
const accountIds = filterByAccounts?.split(',') ?? []; const filters = this.apiService.buildFiltersFromQueryParams({
const assetClasses = filterByAssetClasses?.split(',') ?? []; filterByAccounts,
const tagIds = filterByTags?.split(',') ?? []; filterByAssetClasses,
filterByTags
const filters: Filter[] = [ });
...accountIds.map((accountId) => {
return <Filter>{
id: accountId,
type: 'ACCOUNT'
};
}),
...assetClasses.map((assetClass) => {
return <Filter>{
id: assetClass,
type: 'ASSET_CLASS'
};
}),
...tagIds.map((tagId) => {
return <Filter>{
id: tagId,
type: 'TAG'
};
})
];
let portfolioSummary: PortfolioSummary;
const { const {
accounts, accounts,
@ -158,18 +87,18 @@ export class PortfolioController {
holdings, holdings,
summary, summary,
totalValueInBaseCurrency totalValueInBaseCurrency
} = await this.portfolioService.getDetails( } = await this.portfolioService.getDetails({
filters,
impersonationId, impersonationId,
this.request.user.id, dateRange: range,
range, userId: this.request.user.id
filters });
);
if (hasErrors || hasNotDefinedValuesInObject(holdings)) { if (hasErrors || hasNotDefinedValuesInObject(holdings)) {
hasError = true; hasError = true;
} }
portfolioSummary = summary; let portfolioSummary = summary;
if ( if (
impersonationId || impersonationId ||
@ -295,32 +224,6 @@ export class PortfolioController {
return { firstOrderDate: parseDate(investments[0]?.date), investments }; return { firstOrderDate: parseDate(investments[0]?.date), investments };
} }
@Get('performance')
@UseGuards(AuthGuard('jwt'))
@UseInterceptors(TransformDataSourceInResponseInterceptor)
public async getPerformance(
@Headers('impersonation-id') impersonationId: string,
@Query('range') range
): Promise<PortfolioPerformanceResponse> {
const performanceInformation = await this.portfolioService.getPerformance(
impersonationId,
range
);
if (
impersonationId ||
this.request.user.Settings.settings.viewMode === 'ZEN' ||
this.userService.isRestrictedView(this.request.user)
) {
performanceInformation.performance = nullifyValuesInObject(
performanceInformation.performance,
['currentGrossPerformance', 'currentValue']
);
}
return performanceInformation;
}
@Get('performance') @Get('performance')
@UseGuards(AuthGuard('jwt')) @UseGuards(AuthGuard('jwt'))
@UseInterceptors(TransformDataSourceInResponseInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor)
@ -400,12 +303,12 @@ export class PortfolioController {
hasDetails = user.subscription.type === 'Premium'; hasDetails = user.subscription.type === 'Premium';
} }
const { holdings } = await this.portfolioService.getDetails( const { holdings } = await this.portfolioService.getDetails({
access.userId, dateRange: 'max',
access.userId, filters: [{ id: 'EQUITY', type: 'ASSET_CLASS' }],
'max', impersonationId: access.userId,
[{ id: 'EQUITY', type: 'ASSET_CLASS' }] userId: access.userId
); });
const portfolioPublicDetails: PortfolioPublicDetails = { const portfolioPublicDetails: PortfolioPublicDetails = {
hasDetails, hasDetails,

View File

@ -2,6 +2,7 @@ import { AccessModule } from '@ghostfolio/api/app/access/access.module';
import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { OrderModule } from '@ghostfolio/api/app/order/order.module';
import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module';
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration.module';
import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering.module';
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
@ -22,6 +23,7 @@ import { RulesService } from './rules.service';
exports: [PortfolioService], exports: [PortfolioService],
imports: [ imports: [
AccessModule, AccessModule,
ApiModule,
ConfigurationModule, ConfigurationModule,
DataGatheringModule, DataGatheringModule,
DataProviderModule, DataProviderModule,

View File

@ -107,15 +107,19 @@ export class PortfolioService {
this.baseCurrency = this.configurationService.get('BASE_CURRENCY'); this.baseCurrency = this.configurationService.get('BASE_CURRENCY');
} }
public async getAccounts( public async getAccounts({
aUserId: string, filters,
aFilters?: Filter[], userId,
withExcludedAccounts = false withExcludedAccounts = false
): Promise<AccountWithValue[]> { }: {
const where: Prisma.AccountWhereInput = { userId: aUserId }; filters?: Filter[];
userId: string;
withExcludedAccounts?: boolean;
}): Promise<AccountWithValue[]> {
const where: Prisma.AccountWhereInput = { userId: userId };
if (aFilters?.[0].id && aFilters?.[0].type === 'ACCOUNT') { if (filters?.[0].id && filters?.[0].type === 'ACCOUNT') {
where.id = aFilters[0].id; where.id = filters[0].id;
} }
const [accounts, details] = await Promise.all([ const [accounts, details] = await Promise.all([
@ -124,13 +128,12 @@ export class PortfolioService {
include: { Order: true, Platform: true }, include: { Order: true, Platform: true },
orderBy: { name: 'asc' } orderBy: { name: 'asc' }
}), }),
this.getDetails( this.getDetails({
aUserId, filters,
aUserId, userId,
undefined, withExcludedAccounts,
aFilters, impersonationId: userId
withExcludedAccounts })
)
]); ]);
const userCurrency = this.request.user.Settings.settings.baseCurrency; const userCurrency = this.request.user.Settings.settings.baseCurrency;
@ -168,16 +171,20 @@ export class PortfolioService {
}); });
} }
public async getAccountsWithAggregations( public async getAccountsWithAggregations({
aUserId: string, filters,
aFilters?: Filter[], userId,
withExcludedAccounts = false withExcludedAccounts = false
): Promise<Accounts> { }: {
const accounts = await this.getAccounts( filters?: Filter[];
aUserId, userId: string;
aFilters, withExcludedAccounts?: boolean;
}): Promise<Accounts> {
const accounts = await this.getAccounts({
filters,
userId,
withExcludedAccounts withExcludedAccounts
); });
let totalBalanceInBaseCurrency = new Big(0); let totalBalanceInBaseCurrency = new Big(0);
let totalValueInBaseCurrency = new Big(0); let totalValueInBaseCurrency = new Big(0);
let transactionCount = 0; let transactionCount = 0;
@ -421,14 +428,21 @@ export class PortfolioService {
}; };
} }
public async getDetails( public async getDetails({
aImpersonationId: string, impersonationId,
aUserId: string, userId,
aDateRange: DateRange = 'max', dateRange = 'max',
aFilters?: Filter[], filters,
withExcludedAccounts = false withExcludedAccounts = false
): Promise<PortfolioDetails & { hasErrors: boolean }> { }: {
const userId = await this.getUserId(aImpersonationId, aUserId); impersonationId: string;
userId: string;
dateRange?: DateRange;
filters?: Filter[];
withExcludedAccounts?: boolean;
}): Promise<PortfolioDetails & { hasErrors: boolean }> {
// TODO:
userId = await this.getUserId(impersonationId, userId);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const emergencyFund = new Big( const emergencyFund = new Big(
@ -441,9 +455,9 @@ export class PortfolioService {
const { orders, portfolioOrders, transactionPoints } = const { orders, portfolioOrders, transactionPoints } =
await this.getTransactionPoints({ await this.getTransactionPoints({
filters,
userId, userId,
withExcludedAccounts, withExcludedAccounts
filters: aFilters
}); });
const portfolioCalculator = new PortfolioCalculator({ const portfolioCalculator = new PortfolioCalculator({
@ -457,15 +471,15 @@ export class PortfolioService {
const portfolioStart = parseDate( const portfolioStart = parseDate(
transactionPoints[0]?.date ?? format(new Date(), DATE_FORMAT) transactionPoints[0]?.date ?? format(new Date(), DATE_FORMAT)
); );
const startDate = this.getStartDate(aDateRange, portfolioStart); const startDate = this.getStartDate(dateRange, portfolioStart);
const currentPositions = await portfolioCalculator.getCurrentPositions( const currentPositions = await portfolioCalculator.getCurrentPositions(
startDate startDate
); );
const cashDetails = await this.accountService.getCashDetails({ const cashDetails = await this.accountService.getCashDetails({
filters,
userId, userId,
currency: userCurrency, currency: userCurrency
filters: aFilters
}); });
const holdings: PortfolioDetails['holdings'] = {}; const holdings: PortfolioDetails['holdings'] = {};
@ -475,10 +489,10 @@ export class PortfolioService {
let filteredValueInBaseCurrency = currentPositions.currentValue; let filteredValueInBaseCurrency = currentPositions.currentValue;
if ( if (
aFilters?.length === 0 || filters?.length === 0 ||
(aFilters?.length === 1 && (filters?.length === 1 &&
aFilters[0].type === 'ASSET_CLASS' && filters[0].type === 'ASSET_CLASS' &&
aFilters[0].id === 'CASH') filters[0].id === 'CASH')
) { ) {
filteredValueInBaseCurrency = filteredValueInBaseCurrency.plus( filteredValueInBaseCurrency = filteredValueInBaseCurrency.plus(
cashDetails.balanceInBaseCurrency cashDetails.balanceInBaseCurrency
@ -574,10 +588,10 @@ export class PortfolioService {
} }
if ( if (
aFilters?.length === 0 || filters?.length === 0 ||
(aFilters?.length === 1 && (filters?.length === 1 &&
aFilters[0].type === 'ASSET_CLASS' && filters[0].type === 'ASSET_CLASS' &&
aFilters[0].id === 'CASH') filters[0].id === 'CASH')
) { ) {
const cashPositions = await this.getCashPositions({ const cashPositions = await this.getCashPositions({
cashDetails, cashDetails,
@ -593,15 +607,15 @@ export class PortfolioService {
} }
const accounts = await this.getValueOfAccounts({ const accounts = await this.getValueOfAccounts({
filters,
orders, orders,
portfolioItemsNow, portfolioItemsNow,
userCurrency, userCurrency,
userId, userId,
withExcludedAccounts, withExcludedAccounts
filters: aFilters
}); });
const summary = await this.getSummary(aImpersonationId); const summary = await this.getSummary({ impersonationId });
return { return {
accounts, accounts,
@ -942,77 +956,6 @@ export class PortfolioService {
}; };
} }
public async getPerformance(
aImpersonationId: string,
aDateRange: DateRange = 'max'
): Promise<PortfolioPerformanceResponse> {
const userId = await this.getUserId(aImpersonationId, this.request.user.id);
const { portfolioOrders, transactionPoints } =
await this.getTransactionPoints({
userId
});
const portfolioCalculator = new PortfolioCalculator({
currency: this.request.user.Settings.settings.baseCurrency,
currentRateService: this.currentRateService,
orders: portfolioOrders
});
if (transactionPoints?.length <= 0) {
return {
hasErrors: false,
performance: {
currentGrossPerformance: 0,
currentGrossPerformancePercent: 0,
currentNetPerformance: 0,
currentNetPerformancePercent: 0,
currentValue: 0
}
};
}
portfolioCalculator.setTransactionPoints(transactionPoints);
const portfolioStart = parseDate(transactionPoints[0].date);
const startDate = this.getStartDate(aDateRange, portfolioStart);
const currentPositions = await portfolioCalculator.getCurrentPositions(
startDate
);
const hasErrors = currentPositions.hasErrors;
const currentValue = currentPositions.currentValue.toNumber();
const currentGrossPerformance = currentPositions.grossPerformance;
let currentGrossPerformancePercent =
currentPositions.grossPerformancePercentage;
const currentNetPerformance = currentPositions.netPerformance;
let currentNetPerformancePercent =
currentPositions.netPerformancePercentage;
if (currentGrossPerformance.mul(currentGrossPerformancePercent).lt(0)) {
// If algebraic sign is different, harmonize it
currentGrossPerformancePercent = currentGrossPerformancePercent.mul(-1);
}
if (currentNetPerformance.mul(currentNetPerformancePercent).lt(0)) {
// If algebraic sign is different, harmonize it
currentNetPerformancePercent = currentNetPerformancePercent.mul(-1);
}
return {
errors: currentPositions.errors,
hasErrors: currentPositions.hasErrors || hasErrors,
performance: {
currentValue,
currentGrossPerformance: currentGrossPerformance.toNumber(),
currentGrossPerformancePercent:
currentGrossPerformancePercent.toNumber(),
currentNetPerformance: currentNetPerformance.toNumber(),
currentNetPerformancePercent: currentNetPerformancePercent.toNumber()
}
};
}
public async getPerformanceV2({ public async getPerformanceV2({
dateRange = 'max', dateRange = 'max',
impersonationId impersonationId
@ -1379,14 +1322,18 @@ export class PortfolioService {
return portfolioStart; return portfolioStart;
} }
private async getSummary( private async getSummary({
aImpersonationId: string impersonationId
): Promise<PortfolioSummary> { }: {
impersonationId: string;
}): Promise<PortfolioSummary> {
const userCurrency = this.request.user.Settings.settings.baseCurrency; const userCurrency = this.request.user.Settings.settings.baseCurrency;
const userId = await this.getUserId(aImpersonationId, this.request.user.id); const userId = await this.getUserId(impersonationId, this.request.user.id);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const performanceInformation = await this.getPerformance(aImpersonationId); const performanceInformation = await this.getPerformanceV2({
impersonationId
});
const { balanceInBaseCurrency } = await this.accountService.getCashDetails({ const { balanceInBaseCurrency } = await this.accountService.getCashDetails({
userId, userId,

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { ApiService } from './api.service';
@Module({
exports: [ApiService],
providers: [ApiService]
})
export class ApiModule {}

View File

@ -0,0 +1,42 @@
import { Filter } from '@ghostfolio/common/interfaces';
import { Injectable } from '@nestjs/common';
@Injectable()
export class ApiService {
public constructor() {}
public buildFiltersFromQueryParams({
filterByAccounts,
filterByAssetClasses,
filterByTags
}: {
filterByAccounts?: string;
filterByAssetClasses?: string;
filterByTags?: string;
}): Filter[] {
const accountIds = filterByAccounts?.split(',') ?? [];
const assetClasses = filterByAssetClasses?.split(',') ?? [];
const tagIds = filterByTags?.split(',') ?? [];
return [
...accountIds.map((accountId) => {
return <Filter>{
id: accountId,
type: 'ACCOUNT'
};
}),
...assetClasses.map((assetClass) => {
return <Filter>{
id: assetClass,
type: 'ASSET_CLASS'
};
}),
...tagIds.map((tagId) => {
return <Filter>{
id: tagId,
type: 'TAG'
};
})
];
}
}

View File

@ -58,8 +58,15 @@ export class YahooFinanceService implements DataProviderInterface {
* DOGEUSD -> DOGE-USD * DOGEUSD -> DOGE-USD
*/ */
public convertToYahooFinanceSymbol(aSymbol: string) { public convertToYahooFinanceSymbol(aSymbol: string) {
if (aSymbol.includes(this.baseCurrency) && aSymbol.length >= 6) { if (
if (isCurrency(aSymbol.substring(0, aSymbol.length - 3))) { aSymbol.includes(this.baseCurrency) &&
aSymbol.length > this.baseCurrency.length
) {
if (
isCurrency(
aSymbol.substring(0, aSymbol.length - this.baseCurrency.length)
)
) {
return `${aSymbol}=X`; return `${aSymbol}=X`;
} else if ( } else if (
this.cryptocurrencyService.isCryptocurrency( this.cryptocurrencyService.isCryptocurrency(

View File

@ -53,13 +53,15 @@ export class TwitterBotService {
symbolItem.marketPrice symbolItem.marketPrice
); );
let status = `Current Market Mood: ${emoji} ${text} (${symbolItem.marketPrice}/100)`; let status = `Current market mood is ${emoji} ${text.toLowerCase()} (${
symbolItem.marketPrice
}/100)`;
const benchmarkListing = await this.getBenchmarkListing(3); const benchmarkListing = await this.getBenchmarkListing(3);
if (benchmarkListing?.length > 1) { if (benchmarkListing?.length > 1) {
status += '\n\n'; status += '\n\n';
status += % from ATH\n'; status += '± from ATH in %\n';
status += benchmarkListing; status += benchmarkListing;
} }

View File

@ -2,6 +2,7 @@
<gf-line-chart <gf-line-chart
class="mb-4" class="mb-4"
[historicalDataItems]="historicalDataItems" [historicalDataItems]="historicalDataItems"
[isAnimated]="true"
[locale]="locale" [locale]="locale"
[showXAxis]="true" [showXAxis]="true"
[showYAxis]="true" [showYAxis]="true"

View File

@ -43,23 +43,23 @@
<td class="mat-cell px-1 py-2 text-right"> <td class="mat-cell px-1 py-2 text-right">
{{ formatDistanceToNow(userItem.createdAt) }} {{ formatDistanceToNow(userItem.createdAt) }}
</td> </td>
<td class="mat-cell px-1 py-2"> <td class="mat-cell px-1 py-2 text-right">
<gf-value <gf-value
class="justify-content-end" class="d-inline-block justify-content-end"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"
[value]="userItem.accountCount" [value]="userItem.accountCount"
></gf-value> ></gf-value>
</td> </td>
<td class="mat-cell px-1 py-2"> <td class="mat-cell px-1 py-2 text-right">
<gf-value <gf-value
class="justify-content-end" class="d-inline-block justify-content-end"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"
[value]="userItem.transactionCount" [value]="userItem.transactionCount"
></gf-value> ></gf-value>
</td> </td>
<td class="mat-cell px-1 py-2"> <td class="mat-cell px-1 py-2 text-right">
<gf-value <gf-value
class="justify-content-end" class="d-inline-block justify-content-end"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"
[precision]="0" [precision]="0"
[value]="userItem.engagement" [value]="userItem.engagement"

View File

@ -1,8 +1,7 @@
<div class="row"> <div class="row">
<div class="col-md-6 col-xs-12 d-flex"> <div class="col-md-6 col-xs-12 d-flex">
<div class="align-items-center d-flex flex-grow-1 h5 mb-0 text-truncate"> <div class="align-items-center d-flex flex-grow-1 h5 mb-0 text-truncate">
<span i18n>Benchmarks</span> <span i18n>Performance</span>
<sup i18n>Beta</sup>
<gf-premium-indicator <gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'" *ngIf="user?.subscription?.type === 'Basic'"
class="ml-1" class="ml-1"
@ -14,6 +13,7 @@
appearance="outline" appearance="outline"
class="w-100 without-hint" class="w-100 without-hint"
color="accent" color="accent"
[hidden]="benchmarks?.length === 0"
> >
<mat-label i18n>Compare with...</mat-label> <mat-label i18n>Compare with...</mat-label>
<mat-select <mat-select
@ -21,6 +21,7 @@
[value]="benchmark" [value]="benchmark"
(selectionChange)="onChangeBenchmark($event.value)" (selectionChange)="onChangeBenchmark($event.value)"
> >
<mat-option [value]="null"></mat-option>
<mat-option <mat-option
*ngFor="let symbolProfile of benchmarks" *ngFor="let symbolProfile of benchmarks"
[value]="symbolProfile.id" [value]="symbolProfile.id"

View File

@ -11,6 +11,7 @@
yMax="100" yMax="100"
yMin="0" yMin="0"
[historicalDataItems]="historicalData" [historicalDataItems]="historicalData"
[isAnimated]="true"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"
[showXAxis]="true" [showXAxis]="true"
[showYAxis]="true" [showYAxis]="true"

View File

@ -107,8 +107,7 @@ export class HomeOverviewComponent implements OnDestroy, OnInit {
this.dataService this.dataService
.fetchPortfolioPerformance({ .fetchPortfolioPerformance({
range: this.user?.settings?.dateRange, range: this.user?.settings?.dateRange
version: this.user?.settings?.isExperimentalFeatures ? 2 : 1
}) })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe((response) => { .subscribe((response) => {
@ -117,35 +116,12 @@ export class HomeOverviewComponent implements OnDestroy, OnInit {
this.performance = response.performance; this.performance = response.performance;
this.isLoadingPerformance = false; this.isLoadingPerformance = false;
if (this.user?.settings?.isExperimentalFeatures) {
this.historicalDataItems = response.chart.map(({ date, value }) => { this.historicalDataItems = response.chart.map(({ date, value }) => {
return { return {
date, date,
value value
}; };
}); });
} else {
this.dataService
.fetchChart({
range: this.user?.settings?.dateRange,
version: 1
})
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((chartData) => {
this.historicalDataItems = chartData.chart.map(
({ date, value }) => {
return {
date,
value
};
}
);
this.isAllTimeHigh = chartData.isAllTimeHigh;
this.isAllTimeLow = chartData.isAllTimeLow;
this.changeDetectorRef.markForCheck();
});
}
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
}); });

View File

@ -15,16 +15,16 @@
<gf-line-chart <gf-line-chart
class="position-absolute" class="position-absolute"
symbol="Performance" symbol="Performance"
[currency]="user?.settings?.isExperimentalFeatures ? undefined : user?.settings?.baseCurrency" unit="%"
[historicalDataItems]="historicalDataItems" [historicalDataItems]="historicalDataItems"
[hidden]="historicalDataItems?.length === 0" [hidden]="historicalDataItems?.length === 0"
[isAnimated]="user?.settings?.dateRange === '1d' ? false : true"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"
[ngClass]="{ 'pr-3': deviceType === 'mobile' }" [ngClass]="{ 'pr-3': deviceType === 'mobile' }"
[showGradient]="true" [showGradient]="true"
[showLoader]="false" [showLoader]="false"
[showXAxis]="false" [showXAxis]="false"
[showYAxis]="false" [showYAxis]="false"
[unit]="user?.settings?.isExperimentalFeatures ? '%' : undefined"
></gf-line-chart> ></gf-line-chart>
</div> </div>
</div> </div>

View File

@ -25,6 +25,7 @@
[benchmarkDataItems]="benchmarkDataItems" [benchmarkDataItems]="benchmarkDataItems"
[currency]="SymbolProfile?.currency" [currency]="SymbolProfile?.currency"
[historicalDataItems]="historicalDataItems" [historicalDataItems]="historicalDataItems"
[isAnimated]="true"
[locale]="data.locale" [locale]="data.locale"
[showGradient]="true" [showGradient]="true"
[showXAxis]="true" [showXAxis]="true"

View File

@ -122,13 +122,11 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
} }
private update() { private update() {
if (this.user.settings.isExperimentalFeatures) {
this.isLoadingBenchmarkComparator = true; this.isLoadingBenchmarkComparator = true;
this.dataService this.dataService
.fetchPortfolioPerformance({ .fetchPortfolioPerformance({
range: this.user?.settings?.dateRange, range: this.user?.settings?.dateRange
version: 2
}) })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ chart }) => { .subscribe(({ chart }) => {
@ -139,7 +137,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
}); });
}
this.dataService this.dataService
.fetchInvestments() .fetchInvestments()
@ -210,6 +207,8 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
}); });
} else { } else {
this.benchmarkDataItems = [];
this.isLoadingBenchmarkComparator = false; this.isLoadingBenchmarkComparator = false;
} }
} }

View File

@ -1,6 +1,6 @@
<div class="container"> <div class="container">
<h3 class="d-flex justify-content-center mb-3" i18n>Analysis</h3> <h3 class="d-flex justify-content-center mb-3" i18n>Analysis</h3>
<div *ngIf="user?.settings?.isExperimentalFeatures" class="mb-5 row"> <div class="mb-5 row">
<div class="col-lg"> <div class="col-lg">
<gf-benchmark-comparator <gf-benchmark-comparator
class="h-100" class="h-100"

View File

@ -35,7 +35,7 @@
}" }"
></ngx-skeleton-loader> ></ngx-skeleton-loader>
</div> </div>
<div *ngIf="!isLoading"> <div *ngIf="!isLoading" i18n>
If you retire today, you would be able to withdraw If you retire today, you would be able to withdraw
<span class="font-weight-bold" <span class="font-weight-bold"
><gf-value ><gf-value

View File

@ -25,7 +25,6 @@ import {
Filter, Filter,
InfoItem, InfoItem,
OAuthResponse, OAuthResponse,
PortfolioChart,
PortfolioDetails, PortfolioDetails,
PortfolioInvestments, PortfolioInvestments,
PortfolioPerformanceResponse, PortfolioPerformanceResponse,
@ -74,52 +73,11 @@ export class DataService {
}: { }: {
filters?: Filter[]; filters?: Filter[];
}): Observable<Activities> { }): Observable<Activities> {
let params = new HttpParams(); return this.http
.get<any>('/api/v1/order', {
if (filters?.length > 0) { params: this.buildFiltersAsQueryParams({ filters })
const {
ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass,
TAG: filtersByTag
} = groupBy(filters, (filter) => {
return filter.type;
});
if (filtersByAccount) {
params = params.append(
'accounts',
filtersByAccount
.map(({ id }) => {
return id;
}) })
.join(',') .pipe(
);
}
if (filtersByAssetClass) {
params = params.append(
'assetClasses',
filtersByAssetClass
.map(({ id }) => {
return id;
})
.join(',')
);
}
if (filtersByTag) {
params = params.append(
'tags',
filtersByTag
.map(({ id }) => {
return id;
})
.join(',')
);
}
}
return this.http.get<any>('/api/v1/order', { params }).pipe(
map(({ activities }) => { map(({ activities }) => {
for (const activity of activities) { for (const activity of activities) {
activity.createdAt = parseISO(activity.createdAt); activity.createdAt = parseISO(activity.createdAt);
@ -135,30 +93,8 @@ export class DataService {
} }
public fetchAdminMarketData({ filters }: { filters?: Filter[] }) { public fetchAdminMarketData({ filters }: { filters?: Filter[] }) {
let params = new HttpParams();
if (filters?.length > 0) {
const { ASSET_SUB_CLASS: filtersByAssetSubClass } = groupBy(
filters,
(filter) => {
return filter.type;
}
);
if (filtersByAssetSubClass) {
params = params.append(
'assetSubClasses',
filtersByAssetSubClass
.map(({ id }) => {
return id;
})
.join(',')
);
}
}
return this.http.get<AdminMarketData>('/api/v1/admin/market-data', { return this.http.get<AdminMarketData>('/api/v1/admin/market-data', {
params params: this.buildFiltersAsQueryParams({ filters })
}); });
} }
@ -201,12 +137,6 @@ export class DataService {
return this.http.get<BenchmarkResponse>('/api/v1/benchmark'); return this.http.get<BenchmarkResponse>('/api/v1/benchmark');
} }
public fetchChart({ range, version }: { range: DateRange; version: number }) {
return this.http.get<PortfolioChart>(`/api/v${version}/portfolio/chart`, {
params: { range }
});
}
public fetchExport(activityIds?: string[]) { public fetchExport(activityIds?: string[]) {
let params = new HttpParams(); let params = new HttpParams();
@ -306,54 +236,9 @@ export class DataService {
}: { }: {
filters?: Filter[]; filters?: Filter[];
}): Observable<PortfolioDetails> { }): Observable<PortfolioDetails> {
let params = new HttpParams();
if (filters?.length > 0) {
const {
ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass,
TAG: filtersByTag
} = groupBy(filters, (filter) => {
return filter.type;
});
if (filtersByAccount) {
params = params.append(
'accounts',
filtersByAccount
.map(({ id }) => {
return id;
})
.join(',')
);
}
if (filtersByAssetClass) {
params = params.append(
'assetClasses',
filtersByAssetClass
.map(({ id }) => {
return id;
})
.join(',')
);
}
if (filtersByTag) {
params = params.append(
'tags',
filtersByTag
.map(({ id }) => {
return id;
})
.join(',')
);
}
}
return this.http return this.http
.get<any>('/api/v1/portfolio/details', { .get<any>('/api/v1/portfolio/details', {
params params: this.buildFiltersAsQueryParams({ filters })
}) })
.pipe( .pipe(
map((response) => { map((response) => {
@ -367,15 +252,9 @@ export class DataService {
); );
} }
public fetchPortfolioPerformance({ public fetchPortfolioPerformance({ range }: { range: DateRange }) {
range,
version
}: {
range: DateRange;
version: number;
}) {
return this.http.get<PortfolioPerformanceResponse>( return this.http.get<PortfolioPerformanceResponse>(
`/api/v${version}/portfolio/performance`, `/api/v2/portfolio/performance`,
{ params: { range } } { params: { range } }
); );
} }
@ -458,4 +337,53 @@ export class DataService {
couponCode couponCode
}); });
} }
private buildFiltersAsQueryParams({ filters }: { filters?: Filter[] }) {
let params = new HttpParams();
if (filters?.length > 0) {
const {
ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass,
TAG: filtersByTag
} = groupBy(filters, (filter) => {
return filter.type;
});
if (filtersByAccount) {
params = params.append(
'accounts',
filtersByAccount
.map(({ id }) => {
return id;
})
.join(',')
);
}
if (filtersByAssetClass) {
params = params.append(
'assetClasses',
filtersByAssetClass
.map(({ id }) => {
return id;
})
.join(',')
);
}
if (filtersByTag) {
params = params.append(
'tags',
filtersByTag
.map(({ id }) => {
return id;
})
.join(',')
);
}
}
return params;
}
} }

View File

@ -15,7 +15,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ccb2a809018b32a96c813ae69126ce05976109ce" datatype="html"> <trans-unit id="ccb2a809018b32a96c813ae69126ce05976109ce" datatype="html">
<source>The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term.</source> <source>The risk of loss in trading can be substantial. It is not advisable to invest money you may need in the short term.</source>
<target state="translated">Das Ausfallrisiko beim Börsenhandel kann erheblich sein. Es ist nicht ratsam, Geld zu investieren, welches Sie kurzfristig benötigen.</target> <target state="translated">Das Ausfallrisiko beim Börsenhandel kann erheblich sein. Es ist nicht ratsam, Geld zu investieren, welches du kurzfristig benötigst.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/app.component.html</context> <context context-type="sourcefile">apps/client/src/app/app.component.html</context>
<context context-type="linenumber">55,56</context> <context context-type="linenumber">55,56</context>
@ -418,7 +418,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">17</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html"> <trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html">
@ -490,7 +490,7 @@
<target state="translated">pro Benutzer</target> <target state="translated">pro Benutzer</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html"> <trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html">
@ -498,7 +498,7 @@
<target state="translated">Letzte Daten einholen</target> <target state="translated">Letzte Daten einholen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">44</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html"> <trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html">
@ -506,7 +506,7 @@
<target state="translated">Alle Daten einholen</target> <target state="translated">Alle Daten einholen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">46</context> <context context-type="linenumber">57</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html"> <trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html">
@ -518,7 +518,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">60</context> <context context-type="linenumber">71</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html"> <trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html">
@ -526,7 +526,7 @@
<target state="translated">Wechselkurse</target> <target state="translated">Wechselkurse</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">78</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html"> <trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html">
@ -534,7 +534,7 @@
<target state="translated">Währung hinzufügen</target> <target state="translated">Währung hinzufügen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">106</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html"> <trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html">
@ -542,7 +542,7 @@
<target state="translated">Systemmeldung</target> <target state="translated">Systemmeldung</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">112</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html"> <trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html">
@ -550,7 +550,7 @@
<target state="translated">Systemmeldung setzen</target> <target state="translated">Systemmeldung setzen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">134</context> <context context-type="linenumber">145</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html"> <trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html">
@ -558,7 +558,7 @@
<target state="translated">Lese-Modus</target> <target state="translated">Lese-Modus</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">139</context> <context context-type="linenumber">150</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html"> <trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html">
@ -566,7 +566,7 @@
<target state="translated">Gutscheincodes</target> <target state="translated">Gutscheincodes</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">152</context> <context context-type="linenumber">163</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html"> <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
@ -574,7 +574,7 @@
<target state="translated">Hinzufügen</target> <target state="translated">Hinzufügen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">198</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html"> <trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html">
@ -582,7 +582,7 @@
<target state="translated">Verwaltung</target> <target state="translated">Verwaltung</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">194</context> <context context-type="linenumber">205</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html"> <trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html">
@ -590,7 +590,7 @@
<target state="translated">Cache leeren</target> <target state="translated">Cache leeren</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">198</context> <context context-type="linenumber">209</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2817099043823177227" datatype="html"> <trans-unit id="2817099043823177227" datatype="html">
@ -2314,7 +2314,7 @@
<target state="translated">Datenverwaltung</target> <target state="translated">Datenverwaltung</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">20</context> <context context-type="linenumber">31</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html"> <trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html">
@ -2659,7 +2659,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ac598d664f86ba5783915d65f2664a7f38a9d23a" datatype="html"> <trans-unit id="ac598d664f86ba5783915d65f2664a7f38a9d23a" datatype="html">
<source>Account Type</source> <source>Account Type</source>
<target state="new">Account Type</target> <target state="translated">Kontotyp</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html</context> <context context-type="sourcefile">apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html</context>
<context context-type="linenumber">25</context> <context context-type="linenumber">25</context>
@ -2667,12 +2667,20 @@
</trans-unit> </trans-unit>
<trans-unit id="98fc3013bfcbf452b9f37bbfcdb77b9b882866e3" datatype="html"> <trans-unit id="98fc3013bfcbf452b9f37bbfcdb77b9b882866e3" datatype="html">
<source>Excluded from Analysis</source> <source>Excluded from Analysis</source>
<target state="new">Excluded from Analysis</target> <target state="translated">Von der Analyse ausgenommen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">176</context> <context context-type="linenumber">176</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="458363f8e413759aa9e3235a53fd0f64cc916395" datatype="html">
<source> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </source>
<target state="translated"> Wenn du heute in den Ruhestand gehen würdest, könnest du <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> pro Jahr<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> oder <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> pro Monat<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> entnehmen, bezogen auf dein Gesamtanlagevermögen von <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> und einer Entnahmerate von 4%. </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">38,66</context>
</context-group>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@ -419,7 +419,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">17</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html"> <trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html">
@ -491,7 +491,7 @@
<target state="translated">por usario</target> <target state="translated">por usario</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html"> <trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html">
@ -499,7 +499,7 @@
<target state="translated">Recoger datos recientes</target> <target state="translated">Recoger datos recientes</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">44</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html"> <trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html">
@ -507,7 +507,7 @@
<target state="translated">Recoger todos los datos</target> <target state="translated">Recoger todos los datos</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">46</context> <context context-type="linenumber">57</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html"> <trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html">
@ -519,7 +519,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">60</context> <context context-type="linenumber">71</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html"> <trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html">
@ -527,7 +527,7 @@
<target state="translated">Tipos de cambio</target> <target state="translated">Tipos de cambio</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">78</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html"> <trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html">
@ -535,7 +535,7 @@
<target state="translated">Añadir divisa</target> <target state="translated">Añadir divisa</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">106</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html"> <trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html">
@ -543,7 +543,7 @@
<target state="translated">Mensaje del sistema</target> <target state="translated">Mensaje del sistema</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">112</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html"> <trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html">
@ -551,7 +551,7 @@
<target state="translated">Establecer mensaje</target> <target state="translated">Establecer mensaje</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">134</context> <context context-type="linenumber">145</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html"> <trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html">
@ -559,7 +559,7 @@
<target state="translated">Modo de solo lectura</target> <target state="translated">Modo de solo lectura</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">139</context> <context context-type="linenumber">150</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html"> <trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html">
@ -567,7 +567,7 @@
<target state="translated">Cupones</target> <target state="translated">Cupones</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">152</context> <context context-type="linenumber">163</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html"> <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
@ -575,7 +575,7 @@
<target state="translated">Añadir</target> <target state="translated">Añadir</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">198</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html"> <trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html">
@ -583,7 +583,7 @@
<target state="translated">Tareas domésticas</target> <target state="translated">Tareas domésticas</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">194</context> <context context-type="linenumber">205</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html"> <trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html">
@ -591,7 +591,7 @@
<target state="translated">Limpiar caché</target> <target state="translated">Limpiar caché</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">198</context> <context context-type="linenumber">209</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2817099043823177227" datatype="html"> <trans-unit id="2817099043823177227" datatype="html">
@ -968,7 +968,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e5c369abfbe1bd70f577aa03b2679797e38d7590" datatype="html"> <trans-unit id="e5c369abfbe1bd70f577aa03b2679797e38d7590" datatype="html">
<source> Fees for <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transaction} other {transactions}}"/> </source> <source> Fees for <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transaction} other {transactions}}"/> </source>
<target state="translated">Comisiones por <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transacción} otras {transacciones}}"/> </target> <target state="translated">Comisiones por <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transacción} other {transacciones}}"/> </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">77,80</context> <context context-type="linenumber">77,80</context>
@ -976,7 +976,7 @@
</trans-unit> </trans-unit>
<trans-unit id="272c7fd98af55bfa5b9d579176f1cfa25cd5489f" datatype="html"> <trans-unit id="272c7fd98af55bfa5b9d579176f1cfa25cd5489f" datatype="html">
<source>{VAR_PLURAL, plural, =1 {transaction} other {transactions}}</source> <source>{VAR_PLURAL, plural, =1 {transaction} other {transactions}}</source>
<target state="translated">{VAR_PLURAL, plural, =1 {transacción} otras {transacciones}}</target> <target state="translated">{VAR_PLURAL, plural, =1 {transacción} other {transacciones}}</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">78,79</context> <context context-type="linenumber">78,79</context>
@ -2315,7 +2315,7 @@
<target state="translated">Gestión de los datos</target> <target state="translated">Gestión de los datos</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">20</context> <context context-type="linenumber">31</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html"> <trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html">
@ -2674,6 +2674,14 @@
<context context-type="linenumber">176</context> <context context-type="linenumber">176</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="458363f8e413759aa9e3235a53fd0f64cc916395" datatype="html">
<source> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </source>
<target state="new"> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">38,66</context>
</context-group>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@ -419,7 +419,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">17</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html"> <trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html">
@ -491,7 +491,7 @@
<target state="translated">per utente</target> <target state="translated">per utente</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html"> <trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html">
@ -499,7 +499,7 @@
<target state="translated">Raccogli dati recenti</target> <target state="translated">Raccogli dati recenti</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">44</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html"> <trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html">
@ -507,7 +507,7 @@
<target state="translated">Raccogli tutti i dati</target> <target state="translated">Raccogli tutti i dati</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">46</context> <context context-type="linenumber">57</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html"> <trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html">
@ -519,7 +519,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">60</context> <context context-type="linenumber">71</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html"> <trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html">
@ -527,7 +527,7 @@
<target state="translated">Tassi di cambio</target> <target state="translated">Tassi di cambio</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">78</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html"> <trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html">
@ -535,7 +535,7 @@
<target state="translated">Aggiungi valuta</target> <target state="translated">Aggiungi valuta</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">106</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html"> <trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html">
@ -543,7 +543,7 @@
<target state="translated">Messaggio di sistema</target> <target state="translated">Messaggio di sistema</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">112</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html"> <trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html">
@ -551,7 +551,7 @@
<target state="translated">Imposta messaggio</target> <target state="translated">Imposta messaggio</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">134</context> <context context-type="linenumber">145</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html"> <trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html">
@ -559,7 +559,7 @@
<target state="translated">Modalità di sola lettura</target> <target state="translated">Modalità di sola lettura</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">139</context> <context context-type="linenumber">150</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html"> <trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html">
@ -567,7 +567,7 @@
<target state="translated">Buoni sconto</target> <target state="translated">Buoni sconto</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">152</context> <context context-type="linenumber">163</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html"> <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
@ -575,7 +575,7 @@
<target state="translated">Aggiungi</target> <target state="translated">Aggiungi</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">198</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html"> <trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html">
@ -583,7 +583,7 @@
<target state="translated">Bilancio domestico</target> <target state="translated">Bilancio domestico</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">194</context> <context context-type="linenumber">205</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html"> <trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html">
@ -591,7 +591,7 @@
<target state="translated">Svuota la cache</target> <target state="translated">Svuota la cache</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">198</context> <context context-type="linenumber">209</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2817099043823177227" datatype="html"> <trans-unit id="2817099043823177227" datatype="html">
@ -968,7 +968,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e5c369abfbe1bd70f577aa03b2679797e38d7590" datatype="html"> <trans-unit id="e5c369abfbe1bd70f577aa03b2679797e38d7590" datatype="html">
<source> Fees for <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transaction} other {transactions}}"/> </source> <source> Fees for <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transaction} other {transactions}}"/> </source>
<target state="translated">Commissioni per <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transaction} other {transactions}}"/> </target> <target state="translated">Commissioni per <x id="INTERPOLATION" equiv-text="{{ summary?.ordersCount }}"/> <x id="ICU" equiv-text="{summary?.ordersCount, plural, =1 {transazione} other {transazioni}}"/> </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">77,80</context> <context context-type="linenumber">77,80</context>
@ -976,7 +976,7 @@
</trans-unit> </trans-unit>
<trans-unit id="272c7fd98af55bfa5b9d579176f1cfa25cd5489f" datatype="html"> <trans-unit id="272c7fd98af55bfa5b9d579176f1cfa25cd5489f" datatype="html">
<source>{VAR_PLURAL, plural, =1 {transaction} other {transactions}}</source> <source>{VAR_PLURAL, plural, =1 {transaction} other {transactions}}</source>
<target state="translated">{VAR_PLURAL, plural, =1 {transaction} altre {transactions}}</target> <target state="translated">{VAR_PLURAL, plural, =1 {transazione} other {transazioni}}</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">78,79</context> <context context-type="linenumber">78,79</context>
@ -2315,7 +2315,7 @@
<target state="translated">Gestione dei dati</target> <target state="translated">Gestione dei dati</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">20</context> <context context-type="linenumber">31</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html"> <trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html">
@ -2658,22 +2658,30 @@
<context context-type="linenumber">18</context> <context context-type="linenumber">18</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="ac598d664f86ba5783915d65f2664a7f38a9d23a" datatype="html">
<source>Account Type</source>
<target state="new">Account Type</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit id="98fc3013bfcbf452b9f37bbfcdb77b9b882866e3" datatype="html"> <trans-unit id="98fc3013bfcbf452b9f37bbfcdb77b9b882866e3" datatype="html">
<source>Excluded from Analysis</source> <source>Excluded from Analysis</source>
<target state="new">Excluded from Analysis</target> <target state="translated">Escluso dall&apos;analisi</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context> <context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">176</context> <context context-type="linenumber">176</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="ac598d664f86ba5783915d65f2664a7f38a9d23a" datatype="html">
<source>Account Type</source>
<target state="translated">Tipo di account</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit id="458363f8e413759aa9e3235a53fd0f64cc916395" datatype="html">
<source> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </source>
<target state="translated">Se andassi in pensione oggi, potresti ritirare <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> all&apos;anno<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> o <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> al mese<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, sulla base dei tuoi asset totali pari a <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> e un tasso di prelievo del 4%. </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">38,66</context>
</context-group>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@ -418,7 +418,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">17</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html"> <trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html">
@ -490,7 +490,7 @@
<target state="translated">per gebruiker</target> <target state="translated">per gebruiker</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html"> <trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html">
@ -498,7 +498,7 @@
<target state="translated">Verzamel recente gegevens</target> <target state="translated">Verzamel recente gegevens</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">44</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html"> <trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html">
@ -506,7 +506,7 @@
<target state="translated">Alle gegevens verzamelen</target> <target state="translated">Alle gegevens verzamelen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">46</context> <context context-type="linenumber">57</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html"> <trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html">
@ -518,7 +518,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">60</context> <context context-type="linenumber">71</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html"> <trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html">
@ -526,7 +526,7 @@
<target state="translated">Wisselkoersen</target> <target state="translated">Wisselkoersen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">78</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html"> <trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html">
@ -534,7 +534,7 @@
<target state="translated">Valuta toevoegen</target> <target state="translated">Valuta toevoegen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">106</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html"> <trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html">
@ -542,7 +542,7 @@
<target state="translated">Systeembericht</target> <target state="translated">Systeembericht</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">112</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html"> <trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html">
@ -550,7 +550,7 @@
<target state="translated">Bericht instellen</target> <target state="translated">Bericht instellen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">134</context> <context context-type="linenumber">145</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html"> <trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html">
@ -558,7 +558,7 @@
<target state="translated">Alleen lezen</target> <target state="translated">Alleen lezen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">139</context> <context context-type="linenumber">150</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html"> <trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html">
@ -566,7 +566,7 @@
<target state="translated">Coupons</target> <target state="translated">Coupons</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">152</context> <context context-type="linenumber">163</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html"> <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
@ -574,7 +574,7 @@
<target state="translated">Toevoegen</target> <target state="translated">Toevoegen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">198</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html"> <trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html">
@ -582,7 +582,7 @@
<target state="translated">Huishouding</target> <target state="translated">Huishouding</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">194</context> <context context-type="linenumber">205</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html"> <trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html">
@ -590,7 +590,7 @@
<target state="translated">Cache legen</target> <target state="translated">Cache legen</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">198</context> <context context-type="linenumber">209</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2817099043823177227" datatype="html"> <trans-unit id="2817099043823177227" datatype="html">
@ -2314,7 +2314,7 @@
<target state="translated">Gegevensbeheer</target> <target state="translated">Gegevensbeheer</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">20</context> <context context-type="linenumber">31</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html"> <trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html">
@ -2673,6 +2673,14 @@
<context context-type="linenumber">176</context> <context context-type="linenumber">176</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="458363f8e413759aa9e3235a53fd0f64cc916395" datatype="html">
<source> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </source>
<target state="new"> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">38,66</context>
</context-group>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@ -386,7 +386,7 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">17</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html"> <trans-unit id="5eebcc824c2d34b17abba8c9ef718c5ce118a5c8" datatype="html">
@ -449,21 +449,21 @@
<source>per User</source> <source>per User</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">26</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html"> <trans-unit id="5067ede95804e0e0e2b078747848367a7373cc9b" datatype="html">
<source>Gather Recent Data</source> <source>Gather Recent Data</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">33</context> <context context-type="linenumber">44</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html"> <trans-unit id="27e27f3f7338baefacfd5668bad03ece9c5955df" datatype="html">
<source>Gather All Data</source> <source>Gather All Data</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">46</context> <context context-type="linenumber">57</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html"> <trans-unit id="cc65b67b46b69cf06ff1f16a909e61612c9d57b8" datatype="html">
@ -474,70 +474,70 @@
</context-group> </context-group>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">60</context> <context context-type="linenumber">71</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html"> <trans-unit id="37ff0697aa81b2777250c483d2ce1ebdaa5ab042" datatype="html">
<source>Exchange Rates</source> <source>Exchange Rates</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">67</context> <context context-type="linenumber">78</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html"> <trans-unit id="4567a660a7f67e254bbf13219906843e34d9f807" datatype="html">
<source>Add Currency</source> <source>Add Currency</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">106</context> <context context-type="linenumber">117</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html"> <trans-unit id="860e5f056b59410ec8db65cb53955505c6931752" datatype="html">
<source>System Message</source> <source>System Message</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">112</context> <context context-type="linenumber">123</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html"> <trans-unit id="657028d5fc9c3da8f2d667b6b15cd0df8b9a3729" datatype="html">
<source>Set Message</source> <source>Set Message</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">134</context> <context context-type="linenumber">145</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html"> <trans-unit id="7fd64c34428887e4cd56d05534b89c100b8544ad" datatype="html">
<source>Read-only Mode</source> <source>Read-only Mode</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">139</context> <context context-type="linenumber">150</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html"> <trans-unit id="e698b03c34b459b1b006d7f0473a49b9fcf5dfc1" datatype="html">
<source>Coupons</source> <source>Coupons</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">152</context> <context context-type="linenumber">163</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html"> <trans-unit id="f6755cff4957d5c3c89bafce5651f1b6fa2b1fd9" datatype="html">
<source>Add</source> <source>Add</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">187</context> <context context-type="linenumber">198</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html"> <trans-unit id="e799e6b926557f0098f41888cdf8df868eff3d47" datatype="html">
<source>Housekeeping</source> <source>Housekeeping</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">194</context> <context context-type="linenumber">205</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html"> <trans-unit id="c7ac907e52a7ce2ac70b1786eb5f403ce306ce1f" datatype="html">
<source>Flush Cache</source> <source>Flush Cache</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">198</context> <context context-type="linenumber">209</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="2817099043823177227" datatype="html"> <trans-unit id="2817099043823177227" datatype="html">
@ -2070,7 +2070,7 @@
<source>Data Management</source> <source>Data Management</source>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context> <context context-type="sourcefile">apps/client/src/app/components/admin-overview/admin-overview.html</context>
<context context-type="linenumber">20</context> <context context-type="linenumber">31</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html"> <trans-unit id="3ccabfc3dc288eaa2355ba43298c739f85951ec3" datatype="html">
@ -2389,6 +2389,13 @@
<context context-type="linenumber">25</context> <context context-type="linenumber">25</context>
</context-group> </context-group>
</trans-unit> </trans-unit>
<trans-unit id="458363f8e413759aa9e3235a53fd0f64cc916395" datatype="html">
<source> If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span &gt;"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [currency]=&quot;user?.settings?.baseCurrency&quot; [locale]=&quot;user?.settings?.locale&quot; [value]=&quot;fireWealth?.toNumber()&quot; &gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;/gf-value&gt;"/> and a withdrawal rate of 4%. </source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">38,66</context>
</context-group>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@ -230,5 +230,6 @@ Simple.args = {
date: '2021-03-18', date: '2021-03-18',
value: 86666.03082624623 value: 86666.03082624623
} }
] ],
isAnimated: true
}; };

View File

@ -48,6 +48,7 @@ export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy {
@Input() benchmarkLabel = ''; @Input() benchmarkLabel = '';
@Input() currency: string; @Input() currency: string;
@Input() historicalDataItems: LineChartItem[]; @Input() historicalDataItems: LineChartItem[];
@Input() isAnimated = false;
@Input() locale: string; @Input() locale: string;
@Input() showGradient = false; @Input() showGradient = false;
@Input() showLegend = false; @Input() showLegend = false;
@ -66,6 +67,8 @@ export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy {
public chart: Chart; public chart: Chart;
public isLoading = true; public isLoading = true;
private readonly ANIMATION_DURATION = 1200;
public constructor(private changeDetectorRef: ChangeDetectorRef) { public constructor(private changeDetectorRef: ChangeDetectorRef) {
Chart.register( Chart.register(
Filler, Filler,
@ -114,7 +117,7 @@ export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy {
private initialize() { private initialize() {
this.isLoading = true; this.isLoading = true;
const benchmarkPrices = []; const benchmarkPrices = [];
const labels = []; const labels: string[] = [];
const marketPrices = []; const marketPrices = [];
this.historicalDataItems?.forEach((historicalDataItem, index) => { this.historicalDataItems?.forEach((historicalDataItem, index) => {
@ -169,12 +172,23 @@ export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy {
this.chart.options.plugins.tooltip = <unknown>( this.chart.options.plugins.tooltip = <unknown>(
this.getTooltipPluginConfiguration() this.getTooltipPluginConfiguration()
); );
this.chart.options.animation =
this.isAnimated &&
<unknown>{
x: this.getAnimationConfigurationForAxis({ labels, axis: 'x' }),
y: this.getAnimationConfigurationForAxis({ labels, axis: 'y' })
};
this.chart.update(); this.chart.update();
} else { } else {
this.chart = new Chart(this.chartCanvas.nativeElement, { this.chart = new Chart(this.chartCanvas.nativeElement, {
data, data,
options: { options: {
animation: false, animation:
this.isAnimated &&
<unknown>{
x: this.getAnimationConfigurationForAxis({ labels, axis: 'x' }),
y: this.getAnimationConfigurationForAxis({ labels, axis: 'y' })
},
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
elements: { elements: {
point: { point: {
@ -257,6 +271,31 @@ export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy {
this.isLoading = false; this.isLoading = false;
} }
private getAnimationConfigurationForAxis({
axis,
labels
}: {
axis: 'x' | 'y';
labels: string[];
}) {
const delayBetweenPoints = this.ANIMATION_DURATION / labels.length;
return {
delay(context) {
if (context.type !== 'data' || context[`${axis}Started`]) {
return 0;
}
context[`${axis}Started`] = true;
return context.index * delayBetweenPoints;
},
duration: delayBetweenPoints,
easing: 'linear',
from: NaN,
type: 'number'
};
}
private getTooltipPluginConfiguration() { private getTooltipPluginConfiguration() {
return { return {
...getTooltipOptions({ ...getTooltipOptions({

View File

@ -1,7 +1,7 @@
<div *ngIf="icon" class="align-self-center mr-3"> <div *ngIf="icon" class="align-self-center mr-3">
<ion-icon class="h3 m-0" [name]="icon"></ion-icon> <ion-icon class="h3 m-0" [name]="icon"></ion-icon>
</div> </div>
<div> <div class="w-100">
<ng-template #label><ng-content></ng-content></ng-template> <ng-template #label><ng-content></ng-content></ng-template>
<ng-container *ngIf="value || value === 0 || value === null"> <ng-container *ngIf="value || value === 0 || value === null">
<div <div

View File

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