Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
2466f4ff5d | |||
8f3a9bdfbb | |||
44dfd2bd48 | |||
3fc2228f1d | |||
b018819a1f | |||
ac9311d783 | |||
e23ce0f35d | |||
f4b52aa41c | |||
655b040d4d | |||
0f637a5d0f | |||
3f85c327f5 | |||
c2df99072d | |||
e8afbcad9c | |||
e6d8de781b | |||
6e1935899f | |||
169cb85b66 | |||
fe6658d0ac | |||
1f0381228e | |||
f4b63b5de5 | |||
e45a0ad068 | |||
81c6cc021d | |||
859b24aa5b | |||
2bc325f182 | |||
a6186c23e2 |
47
CHANGELOG.md
47
CHANGELOG.md
@ -5,6 +5,53 @@ 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
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added a blog post: _Hacktoberfest 2022_
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improved the usage of the value component in the admin control panel
|
||||||
|
- Improved the language localization for Español (`es`)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed the usage of the value component on the allocations page
|
||||||
|
|
||||||
## 1.200.0 - 01.10.2022
|
## 1.200.0 - 01.10.2022
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -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 ||
|
||||||
|
@ -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 {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.redisCacheService.set(
|
if (storeInCache) {
|
||||||
this.CACHE_KEY_BENCHMARKS,
|
await this.redisCacheService.set(
|
||||||
JSON.stringify(benchmarks),
|
this.CACHE_KEY_BENCHMARKS,
|
||||||
ms('4 hours') / 1000
|
JSON.stringify(benchmarks),
|
||||||
);
|
ms('4 hours') / 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return benchmarks;
|
return benchmarks;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,11 @@ export class FrontendMiddleware implements NestMiddleware {
|
|||||||
req.path === '/en/blog/2022/08/500-stars-on-github/'
|
req.path === '/en/blog/2022/08/500-stars-on-github/'
|
||||||
) {
|
) {
|
||||||
featureGraphicPath = 'assets/images/blog/500-stars-on-github.jpg';
|
featureGraphicPath = 'assets/images/blog/500-stars-on-github.jpg';
|
||||||
|
} else if (
|
||||||
|
req.path === '/en/blog/2022/10/hacktoberfest-2022' ||
|
||||||
|
req.path === '/en/blog/2022/10/hacktoberfest-2022/'
|
||||||
|
) {
|
||||||
|
featureGraphicPath = 'assets/images/blog/hacktoberfest-2022.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
dates.push(resetHours(end));
|
if (!isSameDay(last(dates), 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({
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
9
apps/api/src/services/api/api.module.ts
Normal file
9
apps/api/src/services/api/api.module.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ApiService } from './api.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
exports: [ApiService],
|
||||||
|
providers: [ApiService]
|
||||||
|
})
|
||||||
|
export class ApiModule {}
|
42
apps/api/src/services/api/api.service.ts
Normal file
42
apps/api/src/services/api/api.service.ts
Normal 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'
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -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(
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +95,13 @@ const routes: Routes = [
|
|||||||
'./pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.module'
|
'./pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.module'
|
||||||
).then((m) => m.FiveHundredStarsOnGitHubPageModule)
|
).then((m) => m.FiveHundredStarsOnGitHubPageModule)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'blog/2022/10/hacktoberfest-2022',
|
||||||
|
loadChildren: () =>
|
||||||
|
import(
|
||||||
|
'./pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.module'
|
||||||
|
).then((m) => m.Hacktoberfest2022PageModule)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'demo',
|
path: 'demo',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
|
@ -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"
|
||||||
|
@ -5,15 +5,26 @@
|
|||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div class="d-flex my-3">
|
<div class="d-flex my-3">
|
||||||
<div class="w-50" i18n>User Count</div>
|
<div class="w-50" i18n>User Count</div>
|
||||||
<div class="w-50">{{ userCount }}</div>
|
<div class="w-50">
|
||||||
|
<gf-value
|
||||||
|
precision="0"
|
||||||
|
[locale]="user?.settings?.locale"
|
||||||
|
[value]="userCount"
|
||||||
|
></gf-value>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex my-3">
|
<div class="d-flex my-3">
|
||||||
<div class="w-50" i18n>Activity Count</div>
|
<div class="w-50" i18n>Activity Count</div>
|
||||||
<div class="w-50">
|
<div class="w-50">
|
||||||
<ng-container *ngIf="transactionCount">
|
<gf-value
|
||||||
{{ transactionCount }} ({{ transactionCount / userCount | number
|
precision="0"
|
||||||
: '1.2-2' }} <span i18n>per User</span>)
|
[locale]="user?.settings?.locale"
|
||||||
</ng-container>
|
[value]="transactionCount"
|
||||||
|
></gf-value>
|
||||||
|
<div *ngIf="transactionCount && userCount">
|
||||||
|
{{ transactionCount / userCount | number : '1.2-2' }}
|
||||||
|
<span i18n>per User</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex my-3">
|
<div class="d-flex my-3">
|
||||||
|
@ -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="align-items-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="align-items-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="align-items-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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
|
||||||
|
|
||||||
|
import { Hacktoberfest2022PageComponent } from './hacktoberfest-2022-page.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
canActivate: [AuthGuard],
|
||||||
|
component: Hacktoberfest2022PageComponent,
|
||||||
|
path: '',
|
||||||
|
title: 'Hacktoberfest 2022'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class Hacktoberfest2022RoutingModule {}
|
@ -0,0 +1,9 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
host: { class: 'page' },
|
||||||
|
selector: 'gf-hacktoberfest-2022-page',
|
||||||
|
styleUrls: ['./hacktoberfest-2022-page.scss'],
|
||||||
|
templateUrl: './hacktoberfest-2022-page.html'
|
||||||
|
})
|
||||||
|
export class Hacktoberfest2022PageComponent {}
|
@ -0,0 +1,178 @@
|
|||||||
|
<div class="blog container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8 offset-md-2">
|
||||||
|
<article>
|
||||||
|
<div class="mb-4 text-center">
|
||||||
|
<h1 class="mb-1">Hacktoberfest 2022</h1>
|
||||||
|
<div class="mb-3 text-muted"><small>2022-10-01</small></div>
|
||||||
|
<img
|
||||||
|
alt="Hacktoberfest 2022 with Ghostfolio Teaser"
|
||||||
|
class="rounded w-100"
|
||||||
|
src="../assets/images/blog/hacktoberfest-2022.png"
|
||||||
|
title="Hacktoberfest 2022 with Ghostfolio"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<section class="mb-4">
|
||||||
|
<p>
|
||||||
|
We are very excited to join
|
||||||
|
<a href="https://hacktoberfest.com">Hacktoberfest</a> for the first
|
||||||
|
time with <a href="https://ghostfol.io">Ghostfolio</a> and meet new
|
||||||
|
and ambitious open-source contributors. Hacktoberfest is a
|
||||||
|
month-long celebration of open-source projects, their maintainers,
|
||||||
|
and the entire community of contributors. Each October, open source
|
||||||
|
maintainers from all over the world give extra attention to new
|
||||||
|
contributors while guiding them through their first pull requests on
|
||||||
|
<a href="https://github.com/ghostfolio/ghostfolio">GitHub</a>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-4">
|
||||||
|
<h2 class="h4">About Ghostfolio</h2>
|
||||||
|
<p>
|
||||||
|
Ghostfolio is a modern web application to manage your personal
|
||||||
|
finance. The software presents the current assets in real time and
|
||||||
|
supports the decision making of future investments. Whether
|
||||||
|
rebalancing the asset classes (stocks, ETFs, cryptocurrencies, etc.)
|
||||||
|
of your portfolio or financing an apartment, Ghostfolio offers
|
||||||
|
solid, data-driven decision support.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Ghostfolio is written in
|
||||||
|
<a href="https://www.typescriptlang.org">TypeScript</a> and
|
||||||
|
organized as an <a href="https://nx.dev">Nx</a> workspace. The
|
||||||
|
backend is based on <a href="https://nestjs.com">NestJS</a> using
|
||||||
|
<a href="https://www.postgresql.org">PostgreSQL</a> as a database
|
||||||
|
together with <a href="https://www.prisma.io">Prisma</a> and
|
||||||
|
<a href="https://redis.io">Redis</a> for caching. The frontend is
|
||||||
|
built with <a href="https://angular.io">Angular</a>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-4">
|
||||||
|
<h2 class="h4">How to contribute?</h2>
|
||||||
|
<p>
|
||||||
|
Every contribution matters. This can be implementing new features,
|
||||||
|
fixing bugs, refactoring the code, improving the documentation,
|
||||||
|
adding more unit tests, or translating into another language.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Are you not yet familiar with our code base? That is not a problem.
|
||||||
|
We have applied the label <code>hacktoberfest</code> to a few
|
||||||
|
<a
|
||||||
|
href="https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3Ahacktoberfest"
|
||||||
|
>issues</a
|
||||||
|
>
|
||||||
|
and
|
||||||
|
<a
|
||||||
|
href="https://github.com/ghostfolio/ghostfolio/discussions?discussions_q=label%3Ahacktoberfest"
|
||||||
|
>ideas</a
|
||||||
|
>
|
||||||
|
that are well suited for newcomers.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The official Hacktoberfest website provides some valuable
|
||||||
|
<a
|
||||||
|
href="https://hacktoberfest.com/participation/#beginner-resources"
|
||||||
|
>resources for beginners</a
|
||||||
|
>
|
||||||
|
to start contributing in open source.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-4">
|
||||||
|
<h2 class="h4">Get support</h2>
|
||||||
|
<p>
|
||||||
|
If you have further questions or ideas, please join our growing
|
||||||
|
<a href="https://ghostfolio.slack.com">Slack community</a> or get in
|
||||||
|
touch on Twitter
|
||||||
|
<a href="https://twitter.com/ghostfolio_">@ghostfolio_</a> or by
|
||||||
|
email via <a href="mailto:hi@ghostfol.io">hi@ghostfol.io</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We look forward to hearing from you.<br />
|
||||||
|
Thomas from Ghostfolio
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="mb-4">
|
||||||
|
<ul class="list-inline">
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Angular</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Community</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Cryptocurrency</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">ETF</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Finance</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Fintech</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Ghostfolio</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">GitHub</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Hacktoberfest</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Investment</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">NestJS</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Nx</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">October</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Open Source</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">OSS</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Personal Finance</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Portfolio</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Portfolio Tracker</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Prisma</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Software</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Stock</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">TypeScript</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Wealth</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Wealth Management</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Web3</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<span class="badge badge-light">Web 3.0</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,13 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { Hacktoberfest2022RoutingModule } from './hacktoberfest-2022-page-routing.module';
|
||||||
|
import { Hacktoberfest2022PageComponent } from './hacktoberfest-2022-page.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [Hacktoberfest2022PageComponent],
|
||||||
|
imports: [CommonModule, Hacktoberfest2022RoutingModule, RouterModule],
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
|
})
|
||||||
|
export class Hacktoberfest2022PageModule {}
|
@ -0,0 +1,3 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -2,6 +2,30 @@
|
|||||||
<div class="mb-5 row">
|
<div class="mb-5 row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3 class="mb-3 text-center" i18n>Blog</h3>
|
<h3 class="mb-3 text-center" i18n>Blog</h3>
|
||||||
|
<mat-card class="mb-3">
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="container p-0">
|
||||||
|
<div class="flex-nowrap no-gutters row">
|
||||||
|
<a
|
||||||
|
class="d-flex w-100"
|
||||||
|
href="../en/blog/2022/10/hacktoberfest-2022"
|
||||||
|
>
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<div class="h6 m-0 text-truncate">Hacktoberfest 2022</div>
|
||||||
|
<div class="d-flex text-muted">2022-10-01</div>
|
||||||
|
</div>
|
||||||
|
<div class="align-items-center d-flex">
|
||||||
|
<ion-icon
|
||||||
|
class="chevron text-muted"
|
||||||
|
name="chevron-forward-outline"
|
||||||
|
size="small"
|
||||||
|
></ion-icon>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
<mat-card class="mb-3">
|
<mat-card class="mb-3">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div class="container p-0">
|
<div class="container p-0">
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<mat-card class="mb-3">
|
<mat-card class="mb-3">
|
||||||
<mat-card-header class="overflow-hidden w-100">
|
<mat-card-header class="mb-2 overflow-hidden w-100">
|
||||||
<mat-card-title class="text-truncate" i18n
|
<mat-card-title class="m-0 text-truncate" i18n
|
||||||
>Proportion of Net Worth</mat-card-title
|
>Proportion of Net Worth</mat-card-title
|
||||||
>
|
>
|
||||||
<gf-value
|
<gf-value
|
||||||
class="align-items-end flex-grow-1 ml-2"
|
class="flex-grow-1 justify-content-end l-2"
|
||||||
size="medium"
|
size="medium"
|
||||||
[isPercent]="true"
|
[isPercent]="true"
|
||||||
[value]="isLoading ? undefined : portfolioDetails?.filteredValueInPercentage"
|
[value]="isLoading ? undefined : portfolioDetails?.filteredValueInPercentage"
|
||||||
|
@ -122,24 +122,21 @@ 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 }) => {
|
this.firstOrderDate = new Date(chart?.[0]?.date ?? new Date());
|
||||||
this.firstOrderDate = new Date(chart?.[0]?.date ?? new Date());
|
this.performanceDataItems = chart;
|
||||||
this.performanceDataItems = chart;
|
|
||||||
|
|
||||||
this.updateBenchmarkDataItems();
|
this.updateBenchmarkDataItems();
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -25,7 +25,6 @@ import {
|
|||||||
Filter,
|
Filter,
|
||||||
InfoItem,
|
InfoItem,
|
||||||
OAuthResponse,
|
OAuthResponse,
|
||||||
PortfolioChart,
|
|
||||||
PortfolioDetails,
|
PortfolioDetails,
|
||||||
PortfolioInvestments,
|
PortfolioInvestments,
|
||||||
PortfolioPerformanceResponse,
|
PortfolioPerformanceResponse,
|
||||||
@ -74,60 +73,19 @@ 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(',')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 }) => {
|
|
||||||
for (const activity of activities) {
|
|
||||||
activity.createdAt = parseISO(activity.createdAt);
|
|
||||||
activity.date = parseISO(activity.date);
|
|
||||||
}
|
|
||||||
return { activities };
|
|
||||||
})
|
})
|
||||||
);
|
.pipe(
|
||||||
|
map(({ activities }) => {
|
||||||
|
for (const activity of activities) {
|
||||||
|
activity.createdAt = parseISO(activity.createdAt);
|
||||||
|
activity.date = parseISO(activity.date);
|
||||||
|
}
|
||||||
|
return { activities };
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchAdminData() {
|
public fetchAdminData() {
|
||||||
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BIN
apps/client/src/assets/images/blog/hacktoberfest-2022.png
Normal file
BIN
apps/client/src/assets/images/blog/hacktoberfest-2022.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
@ -6,70 +6,74 @@
|
|||||||
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io</loc>
|
<loc>https://ghostfol.io</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio</loc>
|
<loc>https://ghostfol.io/de/blog/2021/07/hallo-ghostfolio</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/about</loc>
|
<loc>https://ghostfol.io/en/about</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/about/changelog</loc>
|
<loc>https://ghostfol.io/en/about/changelog</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/blog</loc>
|
<loc>https://ghostfol.io/en/blog</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/blog/2021/07/hello-ghostfolio</loc>
|
<loc>https://ghostfol.io/en/blog/2021/07/hello-ghostfolio</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source</loc>
|
<loc>https://ghostfol.io/en/blog/2022/01/ghostfolio-first-months-in-open-source</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity</loc>
|
<loc>https://ghostfol.io/en/blog/2022/07/ghostfolio-meets-internet-identity</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order</loc>
|
<loc>https://ghostfol.io/en/blog/2022/07/how-do-i-get-my-finances-in-order</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/blog/2022/08/500-stars-on-github</loc>
|
<loc>https://ghostfol.io/en/blog/2022/08/500-stars-on-github</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
|
</url>
|
||||||
|
<url>
|
||||||
|
<loc>https://ghostfol.io/en/blog/2022/10/hacktoberfest-2022</loc>
|
||||||
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/demo</loc>
|
<loc>https://ghostfol.io/en/demo</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/faq</loc>
|
<loc>https://ghostfol.io/en/faq</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/features</loc>
|
<loc>https://ghostfol.io/en/features</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/markets</loc>
|
<loc>https://ghostfol.io/en/markets</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/pricing</loc>
|
<loc>https://ghostfol.io/en/pricing</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/register</loc>
|
<loc>https://ghostfol.io/en/register</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://ghostfol.io/en/resources</loc>
|
<loc>https://ghostfol.io/en/resources</loc>
|
||||||
<lastmod>2022-09-01T00:00:00+00:00</lastmod>
|
<lastmod>2022-10-01T00:00:00+00:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
</urlset>
|
</urlset>
|
||||||
|
@ -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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> pro Jahr<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> oder <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> pro Monat<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> entnehmen, bezogen auf dein Gesamtanlagevermögen von <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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>
|
||||||
|
@ -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 {transaction} otras {transactions}}"/> </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 {transaction} otras {transactions}}</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>
|
||||||
@ -1460,7 +1460,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="220a4641dcde60d1d86ceec62886b1878f1578d3" datatype="html">
|
<trans-unit id="220a4641dcde60d1d86ceec62886b1878f1578d3" datatype="html">
|
||||||
<source>Update account</source>
|
<source>Update account</source>
|
||||||
<target state="translated">Mejorar cuenta</target>
|
<target state="translated">Editar cuenta</target>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html</context>
|
<context context-type="sourcefile">apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html</context>
|
||||||
<context context-type="linenumber">2</context>
|
<context context-type="linenumber">2</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">
|
||||||
@ -2660,7 +2660,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">Tipo de cuenta</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>
|
||||||
@ -2668,12 +2668,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">Excluido del análisis</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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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>
|
||||||
|
@ -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'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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> all'anno<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> o <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> al mese<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, sulla base dei tuoi asset totali pari a <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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>
|
||||||
|
@ -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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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>
|
||||||
|
@ -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="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerYear?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="font-weight-bold" >"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="withdrawalRatePerMonth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span >"/>, based on your total assets of <x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="<gf-value class="d-inline-block" [currency]="user?.settings?.baseCurrency" [locale]="user?.settings?.locale" [value]="fireWealth?.toNumber()" >"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="</gf-value>"/> 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>
|
||||||
|
@ -230,5 +230,6 @@ Simple.args = {
|
|||||||
date: '2021-03-18',
|
date: '2021-03-18',
|
||||||
value: 86666.03082624623
|
value: 86666.03082624623
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
isAnimated: true
|
||||||
};
|
};
|
||||||
|
@ -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({
|
||||||
|
@ -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
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ghostfolio",
|
"name": "ghostfolio",
|
||||||
"version": "1.200.0",
|
"version": "1.203.0",
|
||||||
"homepage": "https://ghostfol.io",
|
"homepage": "https://ghostfol.io",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Reference in New Issue
Block a user