diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e26c1369..64b3e5467 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,115 @@ 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/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.80.0 - 2024-05-08 + +### Added + +- Added the absolute change column to the holdings table on the home page + +### Changed + +- Increased the spacing around the floating action buttons (FAB) +- Set the icon column of the activities table to stick at the beginning +- Set the icon column of the holdings table to stick at the beginning +- Increased the number of attempts of queue jobs from `10` to `12` (fail later) +- Upgraded `ionicons` from version `7.3.0` to `7.4.0` + +### Fixed + +- Fixed the position detail dialog open functionality when searching for a holding in the assistant + +## 2.79.0 - 2024-05-04 + +### Changed + +- Moved the holdings table to the holdings tab of the home page +- Improved the performance labels (with and without currency effects) in the position detail dialog +- Optimized the calculations of the portfolio details endpoint + +### Fixed + +- Fixed an issue with the benchmarks in the markets overview +- Fixed an issue with the _Fear & Greed Index_ (market mood) in the markets overview + +## 2.78.0 - 2024-05-02 + +### Added + +- Added a form validation against the DTO in the create or update access dialog +- Added a form validation against the DTO in the asset profile details dialog of the admin control +- Added a form validation against the DTO in the platform management of the admin control panel +- Added a form validation against the DTO in the tag management of the admin control panel + +### Changed + +- Set the performance column of the holdings table to stick at the end +- Skipped the caching in the portfolio calculator if there are active filters (experimental) +- Improved the `INACTIVE` user role + +### Fixed + +- Fixed an issue in the calculation of the portfolio summary caused by future liabilities +- Fixed a division by zero error in the dividend yield calculation (experimental) + +## 2.77.1 - 2024-04-27 + +### Added + +- Extended the content of the _Self-Hosting_ section by the custom asset instructions on the Frequently Asked Questions (FAQ) page +- Added the caching to the portfolio calculator (experimental) + +### Changed + +- Migrated the `@ghostfolio/ui` components to control flow +- Updated the browserslist database +- Upgraded `prisma` from version `5.12.1` to `5.13.0` + +### Fixed + +- Fixed the form submit in the asset profile details dialog of the admin control due to the `url` validation +- Fixed the historical market data gathering for asset profiles with `MANUAL` data source + +## 2.76.0 - 2024-04-23 + +### Changed + +- Changed `CASH` to `LIQUIDITY` in the asset class enum + +## 2.75.1 - 2024-04-21 + +### Added + +- Added `accountId` and `date` as a unique constraint to the `AccountBalance` database schema + +### Changed + +- Improved the chart in the account detail dialog +- Improved the account balance management + +### Fixed + +- Fixed an issue with `totalValueInBaseCurrency` in the value redaction interceptor for the impersonation mode + +## 2.74.0 - 2024-04-20 + +### Added + +- Added the date range support to the portfolio holdings page +- Added support to create an account balance + +### Changed + +- Removed the date range support in the activities table on the portfolio activities page (experimental) +- Improved the language localization for German (`de`) +- Upgraded `angular` from version `17.3.3` to `17.3.5` +- Upgraded `Nx` from version `18.2.3` to `18.3.3` + +### Fixed + +- Fixed gaps in the portfolio performance charts by considering `BUY` and `SELL` activities + +## 2.73.0 - 2024-04-17 ### Added @@ -19,6 +127,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Moved the interest calculations into the portfolio calculator - Moved the liability calculations into the portfolio calculator - Moved the (wealth) item calculations into the portfolio calculator +- Let queue jobs for asset profile data gathering fail by throwing an error +- Let queue jobs for historical market data gathering fail by throwing an error +- Upgraded `yahoo-finance2` from version `2.11.1` to `2.11.2` ## 2.72.0 - 2024-04-13 diff --git a/README.md b/README.md index 234e2c941..eaf641544 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,6 @@ [![Shield: Contributions Welcome](https://img.shields.io/badge/Contributions-Welcome-orange.svg)](#contributing) [![Shield: License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) -New: [Ghostfolio 2.0](https://ghostfol.io/en/blog/2023/09/ghostfolio-2) - **Ghostfolio** is an open source wealth management software built with web technology. The application empowers busy people to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. The software is designed for personal use in continuous operation. @@ -87,23 +85,23 @@ We provide official container images hosted on [Docker Hub](https://hub.docker.c ### Supported Environment Variables -| Name | Default Value | Description | -| ------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| `ACCESS_TOKEN_SALT` | | A random string used as salt for access tokens | -| `API_KEY_COINGECKO_DEMO` |   | The _CoinGecko_ Demo API key | -| `API_KEY_COINGECKO_PRO` |   | The _CoinGecko_ Pro API | -| `DATABASE_URL` | | The database connection URL, e.g. `postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?sslmode=prefer` | -| `HOST` | `0.0.0.0` | The host where the Ghostfolio application will run on | -| `JWT_SECRET_KEY` | | A random string used for _JSON Web Tokens_ (JWT) | -| `PORT` | `3333` | The port where the Ghostfolio application will run on | -| `POSTGRES_DB` | | The name of the _PostgreSQL_ database | -| `POSTGRES_PASSWORD` | | The password of the _PostgreSQL_ database | -| `POSTGRES_USER` | | The user of the _PostgreSQL_ database | -| `REDIS_DB` | `0` | The database index of _Redis_ | -| `REDIS_HOST` | | The host where _Redis_ is running | -| `REDIS_PASSWORD` | | The password of _Redis_ | -| `REDIS_PORT` | | The port where _Redis_ is running | -| `REQUEST_TIMEOUT` | `2000` | The timeout of network requests to data providers in milliseconds | +| Name | Type | Default Value | Description | +| ------------------------ | ------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `ACCESS_TOKEN_SALT` | string | | A random string used as salt for access tokens | +| `API_KEY_COINGECKO_DEMO` | string (`optional`) |   | The _CoinGecko_ Demo API key | +| `API_KEY_COINGECKO_PRO` | string (`optional`) | | The _CoinGecko_ Pro API | +| `DATABASE_URL` | string | | The database connection URL, e.g. `postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?sslmode=prefer` | +| `HOST` | string (`optional`) | `0.0.0.0` | The host where the Ghostfolio application will run on | +| `JWT_SECRET_KEY` | string | | A random string used for _JSON Web Tokens_ (JWT) | +| `PORT` | number (`optional`) | `3333` | The port where the Ghostfolio application will run on | +| `POSTGRES_DB` | string | | The name of the _PostgreSQL_ database | +| `POSTGRES_PASSWORD` | string | | The password of the _PostgreSQL_ database | +| `POSTGRES_USER` | string | | The user of the _PostgreSQL_ database | +| `REDIS_DB` | number (`optional`) | `0` | The database index of _Redis_ | +| `REDIS_HOST` | string | | The host where _Redis_ is running | +| `REDIS_PASSWORD` | string | | The password of _Redis_ | +| `REDIS_PORT` | number | | The port where _Redis_ is running | +| `REQUEST_TIMEOUT` | number (`optional`) | `2000` | The timeout of network requests to data providers in milliseconds | ### Run with Docker Compose @@ -144,7 +142,7 @@ docker compose --env-file ./.env -f docker/docker-compose.build.yml up -d ### Home Server Systems (Community) -Ghostfolio is available for various home server systems, including [CasaOS](https://github.com/bigbeartechworld/big-bear-casaos), [Runtipi](https://www.runtipi.io/docs/apps-available), [TrueCharts](https://truecharts.org/charts/stable/ghostfolio), [Umbrel](https://apps.umbrel.com/app/ghostfolio), and [Unraid](https://unraid.net/community/apps?q=ghostfolio). +Ghostfolio is available for various home server systems, including [CasaOS](https://github.com/bigbeartechworld/big-bear-casaos), [Home Assistant](https://github.com/lildude/ha-addon-ghostfolio), [Runtipi](https://www.runtipi.io/docs/apps-available), [TrueCharts](https://truecharts.org/charts/stable/ghostfolio), [Umbrel](https://apps.umbrel.com/app/ghostfolio), and [Unraid](https://unraid.net/community/apps?q=ghostfolio). ## Development diff --git a/apps/api/src/app/account-balance/account-balance.controller.ts b/apps/api/src/app/account-balance/account-balance.controller.ts index 943d0aeb5..bc454c5ab 100644 --- a/apps/api/src/app/account-balance/account-balance.controller.ts +++ b/apps/api/src/app/account-balance/account-balance.controller.ts @@ -1,3 +1,4 @@ +import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { permissions } from '@ghostfolio/common/permissions'; @@ -5,6 +6,8 @@ import type { RequestWithUser } from '@ghostfolio/common/types'; import { Controller, + Body, + Post, Delete, HttpException, Inject, @@ -17,14 +20,44 @@ import { AccountBalance } from '@prisma/client'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { AccountBalanceService } from './account-balance.service'; +import { CreateAccountBalanceDto } from './create-account-balance.dto'; @Controller('account-balance') export class AccountBalanceController { public constructor( private readonly accountBalanceService: AccountBalanceService, + private readonly accountService: AccountService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} + @HasPermission(permissions.createAccountBalance) + @Post() + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async createAccountBalance( + @Body() data: CreateAccountBalanceDto + ): Promise { + const account = await this.accountService.account({ + id_userId: { + id: data.accountId, + userId: this.request.user.id + } + }); + + if (!account) { + throw new HttpException( + getReasonPhrase(StatusCodes.FORBIDDEN), + StatusCodes.FORBIDDEN + ); + } + + return this.accountBalanceService.createOrUpdateAccountBalance({ + accountId: account.id, + balance: data.balance, + date: data.date, + userId: account.userId + }); + } + @HasPermission(permissions.deleteAccountBalance) @Delete(':id') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @@ -32,10 +65,11 @@ export class AccountBalanceController { @Param('id') id: string ): Promise { const accountBalance = await this.accountBalanceService.accountBalance({ - id + id, + userId: this.request.user.id }); - if (!accountBalance || accountBalance.userId !== this.request.user.id) { + if (!accountBalance) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), StatusCodes.FORBIDDEN @@ -43,7 +77,8 @@ export class AccountBalanceController { } return this.accountBalanceService.deleteAccountBalance({ - id + id: accountBalance.id, + userId: accountBalance.userId }); } } diff --git a/apps/api/src/app/account-balance/account-balance.module.ts b/apps/api/src/app/account-balance/account-balance.module.ts index 1fba60fce..02323acc9 100644 --- a/apps/api/src/app/account-balance/account-balance.module.ts +++ b/apps/api/src/app/account-balance/account-balance.module.ts @@ -1,3 +1,4 @@ +import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -10,6 +11,6 @@ import { AccountBalanceService } from './account-balance.service'; controllers: [AccountBalanceController], exports: [AccountBalanceService], imports: [ExchangeRateDataModule, PrismaModule], - providers: [AccountBalanceService] + providers: [AccountBalanceService, AccountService] }) export class AccountBalanceModule {} diff --git a/apps/api/src/app/account-balance/account-balance.service.ts b/apps/api/src/app/account-balance/account-balance.service.ts index 8a9d7b83e..65393cec8 100644 --- a/apps/api/src/app/account-balance/account-balance.service.ts +++ b/apps/api/src/app/account-balance/account-balance.service.ts @@ -1,14 +1,21 @@ +import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; +import { resetHours } from '@ghostfolio/common/helper'; import { AccountBalancesResponse, Filter } from '@ghostfolio/common/interfaces'; import { UserWithSettings } from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { AccountBalance, Prisma } from '@prisma/client'; +import { parseISO } from 'date-fns'; + +import { CreateAccountBalanceDto } from './create-account-balance.dto'; @Injectable() export class AccountBalanceService { public constructor( + private readonly eventEmitter: EventEmitter2, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly prismaService: PrismaService ) {} @@ -24,20 +31,63 @@ export class AccountBalanceService { }); } - public async createAccountBalance( - data: Prisma.AccountBalanceCreateInput - ): Promise { - return this.prismaService.accountBalance.create({ - data + public async createOrUpdateAccountBalance({ + accountId, + balance, + date, + userId + }: CreateAccountBalanceDto & { + userId: string; + }): Promise { + const accountBalance = await this.prismaService.accountBalance.upsert({ + create: { + Account: { + connect: { + id_userId: { + userId, + id: accountId + } + } + }, + date: resetHours(parseISO(date)), + value: balance + }, + update: { + value: balance + }, + where: { + accountId_date: { + accountId, + date: resetHours(parseISO(date)) + } + } }); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId + }) + ); + + return accountBalance; } public async deleteAccountBalance( where: Prisma.AccountBalanceWhereUniqueInput ): Promise { - return this.prismaService.accountBalance.delete({ + const accountBalance = await this.prismaService.accountBalance.delete({ where }); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: where.userId + }) + ); + + return accountBalance; } public async getAccountBalances({ diff --git a/apps/api/src/app/account-balance/create-account-balance.dto.ts b/apps/api/src/app/account-balance/create-account-balance.dto.ts new file mode 100644 index 000000000..28e939b82 --- /dev/null +++ b/apps/api/src/app/account-balance/create-account-balance.dto.ts @@ -0,0 +1,12 @@ +import { IsISO8601, IsNumber, IsUUID } from 'class-validator'; + +export class CreateAccountBalanceDto { + @IsUUID() + accountId: string; + + @IsNumber() + balance: number; + + @IsISO8601() + date: string; +} diff --git a/apps/api/src/app/account/account.service.ts b/apps/api/src/app/account/account.service.ts index 697041645..1564fa5b3 100644 --- a/apps/api/src/app/account/account.service.ts +++ b/apps/api/src/app/account/account.service.ts @@ -1,11 +1,15 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; +import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; +import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { Filter } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { Account, Order, Platform, Prisma } from '@prisma/client'; import { Big } from 'big.js'; +import { format } from 'date-fns'; import { groupBy } from 'lodash'; import { CashDetails } from './interfaces/cash-details.interface'; @@ -14,6 +18,7 @@ import { CashDetails } from './interfaces/cash-details.interface'; export class AccountService { public constructor( private readonly accountBalanceService: AccountBalanceService, + private readonly eventEmitter: EventEmitter2, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly prismaService: PrismaService ) {} @@ -85,17 +90,20 @@ export class AccountService { data }); - await this.prismaService.accountBalance.create({ - data: { - Account: { - connect: { - id_userId: { id: account.id, userId: aUserId } - } - }, - value: data.balance - } + await this.accountBalanceService.createOrUpdateAccountBalance({ + accountId: account.id, + balance: data.balance, + date: format(new Date(), DATE_FORMAT), + userId: aUserId }); + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: account.userId + }) + ); + return account; } @@ -103,9 +111,18 @@ export class AccountService { where: Prisma.AccountWhereUniqueInput, aUserId: string ): Promise { - return this.prismaService.account.delete({ + const account = await this.prismaService.account.delete({ where }); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: account.userId + }) + ); + + return account; } public async getAccounts(aUserId: string): Promise { @@ -196,21 +213,26 @@ export class AccountService { ): Promise { const { data, where } = params; - await this.prismaService.accountBalance.create({ - data: { - Account: { - connect: { - id_userId: where.id_userId - } - }, - value: data.balance - } + await this.accountBalanceService.createOrUpdateAccountBalance({ + accountId: data.id, + balance: data.balance, + date: format(new Date(), DATE_FORMAT), + userId: aUserId }); - return this.prismaService.account.update({ + const account = await this.prismaService.account.update({ data, where }); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: account.userId + }) + ); + + return account; } public async updateAccountBalance({ @@ -242,17 +264,11 @@ export class AccountService { ); if (amountInCurrencyOfAccount) { - await this.accountBalanceService.createAccountBalance({ - date, - Account: { - connect: { - id_userId: { - userId, - id: accountId - } - } - }, - value: new Big(balance).plus(amountInCurrencyOfAccount).toNumber() + await this.accountBalanceService.createOrUpdateAccountBalance({ + accountId, + userId, + balance: new Big(balance).plus(amountInCurrencyOfAccount).toNumber(), + date: date.toISOString() }); } } diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index 2aac43a18..7df4498d7 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -416,7 +416,7 @@ export class AdminService { dataSource, marketDataItemCount, symbol, - assetClass: 'CASH', + assetClass: AssetClass.LIQUIDITY, countriesCount: 0, currency: symbol.replace(DEFAULT_CURRENCY, ''), id: undefined, diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 5f2be5c8e..67bb9e03c 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -1,3 +1,4 @@ +import { EventsModule } from '@ghostfolio/api/events/events.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { CronService } from '@ghostfolio/api/services/cron.service'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; @@ -14,6 +15,7 @@ import { import { BullModule } from '@nestjs/bull'; import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; +import { EventEmitterModule } from '@nestjs/event-emitter'; import { ScheduleModule } from '@nestjs/schedule'; import { ServeStaticModule } from '@nestjs/serve-static'; import { StatusCodes } from 'http-status-codes'; @@ -44,6 +46,7 @@ import { TagModule } from './tag/tag.module'; import { UserModule } from './user/user.module'; @Module({ + controllers: [AppController], imports: [ AdminModule, AccessModule, @@ -64,6 +67,8 @@ import { UserModule } from './user/user.module'; ConfigurationModule, DataGatheringModule, DataProviderModule, + EventEmitterModule.forRoot(), + EventsModule, ExchangeRateModule, ExchangeRateDataModule, ExportModule, @@ -109,7 +114,6 @@ import { UserModule } from './user/user.module'; TwitterBotModule, UserModule ], - controllers: [AppController], providers: [CronService] }) export class AppModule {} diff --git a/apps/api/src/app/auth/jwt.strategy.ts b/apps/api/src/app/auth/jwt.strategy.ts index c7ce38986..a8ad8fd08 100644 --- a/apps/api/src/app/auth/jwt.strategy.ts +++ b/apps/api/src/app/auth/jwt.strategy.ts @@ -2,10 +2,12 @@ import { UserService } from '@ghostfolio/api/app/user/user.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { HEADER_KEY_TIMEZONE } from '@ghostfolio/common/config'; +import { hasRole } from '@ghostfolio/common/permissions'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { HttpException, Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import * as countriesAndTimezones from 'countries-and-timezones'; +import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { ExtractJwt, Strategy } from 'passport-jwt'; @Injectable() @@ -29,6 +31,13 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { if (user) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { + if (hasRole(user, 'INACTIVE')) { + throw new HttpException( + getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), + StatusCodes.TOO_MANY_REQUESTS + ); + } + const country = countriesAndTimezones.getCountryForTimezone(timezone)?.id; @@ -45,10 +54,20 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { return user; } else { - throw ''; + throw new HttpException( + getReasonPhrase(StatusCodes.NOT_FOUND), + StatusCodes.NOT_FOUND + ); + } + } catch (error) { + if (error?.getStatus() === StatusCodes.TOO_MANY_REQUESTS) { + throw error; + } else { + throw new HttpException( + getReasonPhrase(StatusCodes.UNAUTHORIZED), + StatusCodes.UNAUTHORIZED + ); } - } catch (err) { - throw new UnauthorizedException('unauthorized', err.message); } } } diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 26df9d069..a1ddeb482 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -416,6 +416,11 @@ export class ImportService { User: { connect: { id: user.id } }, userId: user.id }); + + if (order.SymbolProfile?.symbol) { + // Update symbol that may have been assigned in createOrder() + assetProfile.symbol = order.SymbolProfile.symbol; + } } const value = new Big(quantity).mul(unitPrice).toNumber(); diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index 3dadedcaf..bf4920463 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -60,15 +60,15 @@ export class OrderController { } @Delete(':id') + @HasPermission(permissions.deleteOrder) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async deleteOrder(@Param('id') id: string): Promise { - const order = await this.orderService.order({ id }); + const order = await this.orderService.order({ + id, + userId: this.request.user.id + }); - if ( - !hasPermission(this.request.user.permissions, permissions.deleteOrder) || - !order || - order.userId !== this.request.user.id - ) { + if (!order) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), StatusCodes.FORBIDDEN @@ -88,21 +88,26 @@ export class OrderController { @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId, @Query('accounts') filterByAccounts?: string, @Query('assetClasses') filterByAssetClasses?: string, - @Query('range') dateRange: DateRange = 'max', + @Query('range') dateRange?: DateRange, @Query('skip') skip?: number, @Query('sortColumn') sortColumn?: string, @Query('sortDirection') sortDirection?: Prisma.SortOrder, @Query('tags') filterByTags?: string, @Query('take') take?: number ): Promise { + let endDate: Date; + let startDate: Date; + + if (dateRange) { + ({ endDate, startDate } = getInterval(dateRange)); + } + const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, filterByTags }); - const { endDate, startDate } = getInterval(dateRange); - const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); const userCurrency = this.request.user.Settings.settings.baseCurrency; diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index 35bfa1bcf..e976fc80d 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -1,4 +1,5 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service'; +import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event'; import { DataGatheringService } from '@ghostfolio/api/services/data-gathering/data-gathering.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; @@ -13,6 +14,7 @@ import { Filter, UniqueAsset } from '@ghostfolio/common/interfaces'; import { OrderWithAccount } from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { AssetClass, AssetSubClass, @@ -27,7 +29,6 @@ import { endOfToday, isAfter } from 'date-fns'; import { groupBy, uniqBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; -import { CreateOrderDto } from './create-order.dto'; import { Activities } from './interfaces/activities.interface'; @Injectable() @@ -35,6 +36,7 @@ export class OrderService { public constructor( private readonly accountService: AccountService, private readonly dataGatheringService: DataGatheringService, + private readonly eventEmitter: EventEmitter2, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly prismaService: PrismaService, private readonly symbolProfileService: SymbolProfileService @@ -138,7 +140,8 @@ export class OrderService { return { id }; }) } - } + }, + include: { SymbolProfile: true } }); if (updateAccountBalance === true) { @@ -160,6 +163,13 @@ export class OrderService { }); } + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: order.userId + }) + ); + return order; } @@ -174,6 +184,13 @@ export class OrderService { await this.symbolProfileService.deleteById(order.symbolProfileId); } + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: order.userId + }) + ); + return order; } @@ -182,6 +199,13 @@ export class OrderService { where }); + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: where.userId + }) + ); + return count; } @@ -455,7 +479,7 @@ export class OrderService { where }); - return this.prismaService.order.update({ + const order = await this.prismaService.order.update({ data: { ...data, isDraft, @@ -467,6 +491,15 @@ export class OrderService { }, where }); + + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId: order.userId + }) + ); + + return order; } private async orders(params: { diff --git a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts index 978f1f3aa..5d168b619 100644 --- a/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts @@ -1,10 +1,6 @@ import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; -import { PortfolioSnapshot } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-snapshot.interface'; -import { - SymbolMetrics, - TimelinePosition, - UniqueAsset -} from '@ghostfolio/common/interfaces'; +import { SymbolMetrics, UniqueAsset } from '@ghostfolio/common/interfaces'; +import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; export class MWRPortfolioCalculator extends PortfolioCalculator { protected calculateOverallPerformance( diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts index 504b5b171..51ad40c31 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts @@ -24,3 +24,7 @@ export const symbolProfileDummyData = { sectors: [], updatedAt: undefined }; + +export const userDummyData = { + id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' +}; diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts index e64c23942..762415d1e 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts @@ -1,7 +1,10 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { DateRange } from '@ghostfolio/common/types'; +import { HistoricalDataItem } from '@ghostfolio/common/interfaces'; +import { DateRange, UserWithSettings } from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; @@ -17,37 +20,59 @@ export enum PerformanceCalculationType { @Injectable() export class PortfolioCalculatorFactory { public constructor( + private readonly configurationService: ConfigurationService, private readonly currentRateService: CurrentRateService, - private readonly exchangeRateDataService: ExchangeRateDataService + private readonly exchangeRateDataService: ExchangeRateDataService, + private readonly redisCacheService: RedisCacheService ) {} public createCalculator({ + accountBalanceItems = [], activities, calculationType, currency, - dateRange = 'max' + dateRange = 'max', + hasFilters, + isExperimentalFeatures = false, + userId }: { + accountBalanceItems?: HistoricalDataItem[]; activities: Activity[]; calculationType: PerformanceCalculationType; currency: string; dateRange?: DateRange; + hasFilters: boolean; + isExperimentalFeatures?: boolean; + userId: string; }): PortfolioCalculator { + const useCache = !hasFilters && isExperimentalFeatures; + switch (calculationType) { case PerformanceCalculationType.MWR: return new MWRPortfolioCalculator({ + accountBalanceItems, activities, currency, dateRange, + useCache, + userId, + configurationService: this.configurationService, currentRateService: this.currentRateService, - exchangeRateDataService: this.exchangeRateDataService + exchangeRateDataService: this.exchangeRateDataService, + redisCacheService: this.redisCacheService }); case PerformanceCalculationType.TWR: return new TWRPortfolioCalculator({ + accountBalanceItems, activities, currency, currentRateService: this.currentRateService, dateRange, - exchangeRateDataService: this.exchangeRateDataService + useCache, + userId, + configurationService: this.configurationService, + exchangeRateDataService: this.exchangeRateDataService, + redisCacheService: this.redisCacheService }); default: throw new Error('Invalid calculation type'); diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 1d2eadfbf..e021eb2d4 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -1,13 +1,14 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { PortfolioOrder } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order.interface'; -import { PortfolioSnapshot } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-snapshot.interface'; import { TransactionPointSymbol } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point-symbol.interface'; import { TransactionPoint } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point.interface'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; import { getFactor, getInterval } from '@ghostfolio/api/helper/portfolio.helper'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; import { MAX_CHART_ITEMS } from '@ghostfolio/common/config'; @@ -23,72 +24,114 @@ import { InvestmentItem, ResponseError, SymbolMetrics, - TimelinePosition, UniqueAsset } from '@ghostfolio/common/interfaces'; +import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; import { DateRange, GroupBy } from '@ghostfolio/common/types'; +import { Logger } from '@nestjs/common'; import { Big } from 'big.js'; +import { plainToClass } from 'class-transformer'; import { differenceInDays, eachDayOfInterval, endOfDay, format, + isAfter, isBefore, isSameDay, max, + min, subDays } from 'date-fns'; -import { last, uniq, uniqBy } from 'lodash'; +import { first, last, uniq, uniqBy } from 'lodash'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; - protected orders: PortfolioOrder[]; + protected accountBalanceItems: HistoricalDataItem[]; + protected activities: PortfolioOrder[]; + private configurationService: ConfigurationService; private currency: string; private currentRateService: CurrentRateService; private dataProviderInfos: DataProviderInfo[]; + private dateRange: DateRange; private endDate: Date; private exchangeRateDataService: ExchangeRateDataService; + private redisCacheService: RedisCacheService; private snapshot: PortfolioSnapshot; private snapshotPromise: Promise; private startDate: Date; private transactionPoints: TransactionPoint[]; + private useCache: boolean; + private userId: string; public constructor({ + accountBalanceItems, activities, + configurationService, currency, currentRateService, dateRange, - exchangeRateDataService + exchangeRateDataService, + redisCacheService, + useCache, + userId }: { + accountBalanceItems: HistoricalDataItem[]; activities: Activity[]; + configurationService: ConfigurationService; currency: string; currentRateService: CurrentRateService; dateRange: DateRange; exchangeRateDataService: ExchangeRateDataService; + redisCacheService: RedisCacheService; + useCache: boolean; + userId: string; }) { + this.accountBalanceItems = accountBalanceItems; + this.configurationService = configurationService; this.currency = currency; this.currentRateService = currentRateService; + this.dateRange = dateRange; this.exchangeRateDataService = exchangeRateDataService; - this.orders = activities.map( - ({ date, fee, quantity, SymbolProfile, tags = [], type, unitPrice }) => { - return { + + this.activities = activities + .map( + ({ + date, + fee, + quantity, SymbolProfile, - tags, + tags = [], type, - date: format(date, DATE_FORMAT), - fee: new Big(fee), - quantity: new Big(quantity), - unitPrice: new Big(unitPrice) - }; - } - ); + unitPrice + }) => { + if (isAfter(date, new Date(Date.now()))) { + // Adapt date to today if activity is in future (e.g. liability) + // to include it in the interval + date = endOfDay(new Date(Date.now())); + } + + return { + SymbolProfile, + tags, + type, + date: format(date, DATE_FORMAT), + fee: new Big(fee), + quantity: new Big(quantity), + unitPrice: new Big(unitPrice) + }; + } + ) + .sort((a, b) => { + return a.date?.localeCompare(b.date); + }); - this.orders.sort((a, b) => { - return a.date?.localeCompare(b.date); - }); + this.redisCacheService = redisCacheService; + this.useCache = useCache; + this.userId = userId; const { endDate, startDate } = getInterval(dateRange); @@ -383,10 +426,6 @@ export abstract class PortfolioCalculator { dateRange?: DateRange; withDataDecimation?: boolean; }): Promise { - if (this.getTransactionPoints().length === 0) { - return []; - } - const { endDate, startDate } = getInterval(dateRange, this.getStartDate()); const daysInMarket = differenceInDays(endDate, startDate) + 1; @@ -485,6 +524,7 @@ export abstract class PortfolioCalculator { investmentValueWithCurrencyEffect: Big; totalCurrentValue: Big; totalCurrentValueWithCurrencyEffect: Big; + totalAccountBalanceWithCurrencyEffect: Big; totalInvestmentValue: Big; totalInvestmentValueWithCurrencyEffect: Big; totalNetPerformanceValue: Big; @@ -544,9 +584,24 @@ export abstract class PortfolioCalculator { }; } + let lastDate = format(this.startDate, DATE_FORMAT); + for (const currentDate of dates) { const dateString = format(currentDate, DATE_FORMAT); + accumulatedValuesByDate[dateString] = { + investmentValueWithCurrencyEffect: new Big(0), + totalAccountBalanceWithCurrencyEffect: new Big(0), + totalCurrentValue: new Big(0), + totalCurrentValueWithCurrencyEffect: new Big(0), + totalInvestmentValue: new Big(0), + totalInvestmentValueWithCurrencyEffect: new Big(0), + totalNetPerformanceValue: new Big(0), + totalNetPerformanceValueWithCurrencyEffect: new Big(0), + totalTimeWeightedInvestmentValue: new Big(0), + totalTimeWeightedInvestmentValueWithCurrencyEffect: new Big(0) + }; + for (const symbol of Object.keys(valuesBySymbol)) { const symbolValues = valuesBySymbol[symbol]; @@ -584,49 +639,94 @@ export abstract class PortfolioCalculator { dateString ] ?? new Big(0); - accumulatedValuesByDate[dateString] = { - investmentValueWithCurrencyEffect: ( - accumulatedValuesByDate[dateString] - ?.investmentValueWithCurrencyEffect ?? new Big(0) - ).add(investmentValueWithCurrencyEffect), - totalCurrentValue: ( - accumulatedValuesByDate[dateString]?.totalCurrentValue ?? new Big(0) - ).add(currentValue), - totalCurrentValueWithCurrencyEffect: ( - accumulatedValuesByDate[dateString] - ?.totalCurrentValueWithCurrencyEffect ?? new Big(0) - ).add(currentValueWithCurrencyEffect), - totalInvestmentValue: ( - accumulatedValuesByDate[dateString]?.totalInvestmentValue ?? - new Big(0) - ).add(investmentValueAccumulated), - totalInvestmentValueWithCurrencyEffect: ( - accumulatedValuesByDate[dateString] - ?.totalInvestmentValueWithCurrencyEffect ?? new Big(0) - ).add(investmentValueAccumulatedWithCurrencyEffect), - totalNetPerformanceValue: ( - accumulatedValuesByDate[dateString]?.totalNetPerformanceValue ?? - new Big(0) - ).add(netPerformanceValue), - totalNetPerformanceValueWithCurrencyEffect: ( - accumulatedValuesByDate[dateString] - ?.totalNetPerformanceValueWithCurrencyEffect ?? new Big(0) - ).add(netPerformanceValueWithCurrencyEffect), - totalTimeWeightedInvestmentValue: ( - accumulatedValuesByDate[dateString] - ?.totalTimeWeightedInvestmentValue ?? new Big(0) - ).add(timeWeightedInvestmentValue), - totalTimeWeightedInvestmentValueWithCurrencyEffect: ( - accumulatedValuesByDate[dateString] - ?.totalTimeWeightedInvestmentValueWithCurrencyEffect ?? new Big(0) - ).add(timeWeightedInvestmentValueWithCurrencyEffect) - }; + accumulatedValuesByDate[dateString].investmentValueWithCurrencyEffect = + accumulatedValuesByDate[ + dateString + ].investmentValueWithCurrencyEffect.add( + investmentValueWithCurrencyEffect + ); + + accumulatedValuesByDate[dateString].totalCurrentValue = + accumulatedValuesByDate[dateString].totalCurrentValue.add( + currentValue + ); + + accumulatedValuesByDate[ + dateString + ].totalCurrentValueWithCurrencyEffect = accumulatedValuesByDate[ + dateString + ].totalCurrentValueWithCurrencyEffect.add( + currentValueWithCurrencyEffect + ); + + accumulatedValuesByDate[dateString].totalInvestmentValue = + accumulatedValuesByDate[dateString].totalInvestmentValue.add( + investmentValueAccumulated + ); + + accumulatedValuesByDate[ + dateString + ].totalInvestmentValueWithCurrencyEffect = accumulatedValuesByDate[ + dateString + ].totalInvestmentValueWithCurrencyEffect.add( + investmentValueAccumulatedWithCurrencyEffect + ); + + accumulatedValuesByDate[dateString].totalNetPerformanceValue = + accumulatedValuesByDate[dateString].totalNetPerformanceValue.add( + netPerformanceValue + ); + + accumulatedValuesByDate[ + dateString + ].totalNetPerformanceValueWithCurrencyEffect = accumulatedValuesByDate[ + dateString + ].totalNetPerformanceValueWithCurrencyEffect.add( + netPerformanceValueWithCurrencyEffect + ); + + accumulatedValuesByDate[dateString].totalTimeWeightedInvestmentValue = + accumulatedValuesByDate[ + dateString + ].totalTimeWeightedInvestmentValue.add(timeWeightedInvestmentValue); + + accumulatedValuesByDate[ + dateString + ].totalTimeWeightedInvestmentValueWithCurrencyEffect = + accumulatedValuesByDate[ + dateString + ].totalTimeWeightedInvestmentValueWithCurrencyEffect.add( + timeWeightedInvestmentValueWithCurrencyEffect + ); + } + + if ( + this.accountBalanceItems.some(({ date }) => { + return date === dateString; + }) + ) { + accumulatedValuesByDate[ + dateString + ].totalAccountBalanceWithCurrencyEffect = new Big( + this.accountBalanceItems.find(({ date }) => { + return date === dateString; + }).value + ); + } else { + accumulatedValuesByDate[ + dateString + ].totalAccountBalanceWithCurrencyEffect = + accumulatedValuesByDate[lastDate] + ?.totalAccountBalanceWithCurrencyEffect ?? new Big(0); } + + lastDate = dateString; } return Object.entries(accumulatedValuesByDate).map(([date, values]) => { const { investmentValueWithCurrencyEffect, + totalAccountBalanceWithCurrencyEffect, totalCurrentValue, totalCurrentValueWithCurrencyEffect, totalInvestmentValue, @@ -661,6 +761,11 @@ export abstract class PortfolioCalculator { netPerformance: totalNetPerformanceValue.toNumber(), netPerformanceWithCurrencyEffect: totalNetPerformanceValueWithCurrencyEffect.toNumber(), + // TODO: Add valuables + netWorth: totalCurrentValueWithCurrencyEffect + .plus(totalAccountBalanceWithCurrencyEffect) + .toNumber(), + totalAccountBalance: totalAccountBalanceWithCurrencyEffect.toNumber(), totalInvestment: totalInvestmentValue.toNumber(), totalInvestmentValueWithCurrencyEffect: totalInvestmentValueWithCurrencyEffect.toNumber(), @@ -749,9 +854,30 @@ export abstract class PortfolioCalculator { } public getStartDate() { - return this.transactionPoints.length > 0 - ? parseDate(this.transactionPoints[0].date) - : new Date(); + let firstAccountBalanceDate: Date; + let firstActivityDate: Date; + + try { + const firstAccountBalanceDateString = first( + this.accountBalanceItems + )?.date; + firstAccountBalanceDate = firstAccountBalanceDateString + ? parseDate(firstAccountBalanceDateString) + : new Date(); + } catch (error) { + firstAccountBalanceDate = new Date(); + } + + try { + const firstActivityDateString = this.transactionPoints[0].date; + firstActivityDate = firstActivityDateString + ? parseDate(firstActivityDateString) + : new Date(); + } catch (error) { + firstActivityDate = new Date(); + } + + return min([firstAccountBalanceDate, firstActivityDate]); } protected abstract getSymbolMetrics({ @@ -799,7 +925,7 @@ export abstract class PortfolioCalculator { tags, type, unitPrice - } of this.orders) { + } of this.activities) { let currentTransactionPointItem: TransactionPointSymbol; const oldAccumulatedSymbol = symbols[SymbolProfile.symbol]; @@ -923,6 +1049,52 @@ export abstract class PortfolioCalculator { } private async initialize() { - this.snapshot = await this.computeSnapshot(this.startDate, this.endDate); + if (this.useCache) { + const startTimeTotal = performance.now(); + + const cachedSnapshot = await this.redisCacheService.get( + this.redisCacheService.getPortfolioSnapshotKey({ + userId: this.userId + }) + ); + + if (cachedSnapshot) { + this.snapshot = plainToClass( + PortfolioSnapshot, + JSON.parse(cachedSnapshot) + ); + + Logger.debug( + `Fetched portfolio snapshot from cache in ${( + (performance.now() - startTimeTotal) / + 1000 + ).toFixed(3)} seconds`, + 'PortfolioCalculator' + ); + } else { + this.snapshot = await this.computeSnapshot( + this.startDate, + this.endDate + ); + + this.redisCacheService.set( + this.redisCacheService.getPortfolioSnapshotKey({ + userId: this.userId + }), + JSON.stringify(this.snapshot), + this.configurationService.get('CACHE_QUOTES_TTL') + ); + + Logger.debug( + `Computed portfolio snapshot in ${( + (performance.now() - startTimeTotal) / + 1000 + ).toFixed(3)} seconds`, + 'PortfolioCalculator' + ); + } + } else { + this.snapshot = await this.computeSnapshot(this.startDate, this.endDate); + } } } diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index a11ae8896..340f16b87 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -101,7 +122,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts index 8d93d8b97..53ebdf19f 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -86,7 +107,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts index f26331134..bab265887 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -71,7 +92,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index 2a9ba0916..eba5d4674 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; @@ -24,6 +28,15 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + jest.mock( '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service', () => { @@ -37,11 +50,15 @@ jest.mock( ); describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -51,9 +68,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -99,7 +120,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts index 83f99e3cb..88d7adb71 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -71,7 +92,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'USD' + currency: 'USD', + hasFilters: false, + userId: userDummyData.id }); const portfolioSnapshot = await portfolioCalculator.computeSnapshot( diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts index 0642b28ed..690f1eb51 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; @@ -24,6 +28,15 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + jest.mock( '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service', () => { @@ -37,11 +50,15 @@ jest.mock( ); describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -51,9 +68,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -84,7 +105,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts index b8ef6954e..422d119b2 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -71,7 +92,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'USD' + currency: 'USD', + hasFilters: false, + userId: userDummyData.id }); const portfolioSnapshot = await portfolioCalculator.computeSnapshot( diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts index 9ef369c8f..d468e8e00 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-liability.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -53,7 +74,7 @@ describe('PortfolioCalculator', () => { const activities: Activity[] = [ { ...activityDummyData, - date: new Date('2022-01-01'), + date: new Date('2023-01-01'), // Date in future fee: 0, quantity: 1, SymbolProfile: { @@ -71,64 +92,17 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'USD' + currency: 'USD', + hasFilters: false, + userId: userDummyData.id }); - const portfolioSnapshot = await portfolioCalculator.computeSnapshot( - parseDate('2022-01-01') - ); - spy.mockRestore(); - expect(portfolioSnapshot).toEqual({ - currentValueInBaseCurrency: new Big('0'), - errors: [], - grossPerformance: new Big('0'), - grossPerformancePercentage: new Big('0'), - grossPerformancePercentageWithCurrencyEffect: new Big('0'), - grossPerformanceWithCurrencyEffect: new Big('0'), - hasErrors: true, - netPerformance: new Big('0'), - netPerformancePercentage: new Big('0'), - netPerformancePercentageWithCurrencyEffect: new Big('0'), - netPerformanceWithCurrencyEffect: new Big('0'), - positions: [ - { - averagePrice: new Big('3000'), - currency: 'USD', - dataSource: 'MANUAL', - dividend: new Big('0'), - dividendInBaseCurrency: new Big('0'), - fee: new Big('0'), - firstBuyDate: '2022-01-01', - grossPerformance: null, - grossPerformancePercentage: null, - grossPerformancePercentageWithCurrencyEffect: null, - grossPerformanceWithCurrencyEffect: null, - investment: new Big('0'), - investmentWithCurrencyEffect: new Big('0'), - marketPrice: null, - marketPriceInBaseCurrency: 3000, - netPerformance: null, - netPerformancePercentage: null, - netPerformancePercentageWithCurrencyEffect: null, - netPerformanceWithCurrencyEffect: null, - quantity: new Big('0'), - symbol: '55196015-1365-4560-aa60-8751ae6d18f8', - tags: [], - timeWeightedInvestment: new Big('0'), - timeWeightedInvestmentWithCurrencyEffect: new Big('0'), - transactionCount: 1, - valueInBaseCurrency: new Big('0') - } - ], - totalFeesWithCurrencyEffect: new Big('0'), - totalInterestWithCurrencyEffect: new Big('0'), - totalInvestment: new Big('0'), - totalInvestmentWithCurrencyEffect: new Big('0'), - totalLiabilitiesWithCurrencyEffect: new Big('0'), - totalValuablesWithCurrencyEffect: new Big('0') - }); + const liabilitiesInBaseCurrency = + await portfolioCalculator.getLiabilitiesInBaseCurrency(); + + expect(liabilitiesInBaseCurrency).toEqual(new Big(3000)); }); }); }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts index e50ce4194..094c6cc2e 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock'; import { parseDate } from '@ghostfolio/common/helper'; @@ -24,6 +28,15 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + jest.mock( '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service', () => { @@ -37,11 +50,15 @@ jest.mock( ); describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -51,9 +68,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -99,7 +120,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'USD' + currency: 'USD', + hasFilters: false, + userId: userDummyData.id }); const portfolioSnapshot = await portfolioCalculator.computeSnapshot( diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts index 1d69abfbf..6bb432bfc 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts @@ -1,9 +1,13 @@ +import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -19,12 +23,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -34,9 +51,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -49,7 +70,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities: [], calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const start = subDays(new Date(Date.now()), 10); @@ -90,7 +113,12 @@ describe('PortfolioCalculator', () => { expect(investments).toEqual([]); - expect(investmentsByMonth).toEqual([]); + expect(investmentsByMonth).toEqual([ + { + date: '2021-12-01', + investment: 0 + } + ]); }); }); }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index 3d63f1a5d..f65d2ba61 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -86,7 +107,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts index 6f0b03800..902f710ee 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -1,7 +1,8 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { activityDummyData, - symbolProfileDummyData + symbolProfileDummyData, + userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PerformanceCalculationType, @@ -9,6 +10,9 @@ import { } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { parseDate } from '@ghostfolio/common/helper'; @@ -23,12 +27,25 @@ jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { }; }); +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -38,9 +55,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); @@ -86,7 +107,9 @@ describe('PortfolioCalculator', () => { const portfolioCalculator = factory.createCalculator({ activities, calculationType: PerformanceCalculationType.TWR, - currency: 'CHF' + currency: 'CHF', + hasFilters: false, + userId: userDummyData.id }); const chartData = await portfolioCalculator.getChartData({ @@ -113,6 +136,8 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentage: 0, netPerformanceInPercentageWithCurrencyEffect: 0, netPerformanceWithCurrencyEffect: 0, + netWorth: 151.6, + totalAccountBalance: 0, totalInvestment: 151.6, totalInvestmentValueWithCurrencyEffect: 151.6, value: 151.6, @@ -126,6 +151,8 @@ describe('PortfolioCalculator', () => { netPerformanceInPercentage: 13.100263852242744, netPerformanceInPercentageWithCurrencyEffect: 13.100263852242744, netPerformanceWithCurrencyEffect: 19.86, + netWorth: 0, + totalAccountBalance: 0, totalInvestment: 0, totalInvestmentValueWithCurrencyEffect: 0, value: 0, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts index 365593846..536581070 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.spec.ts @@ -1,13 +1,19 @@ import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; let factory: PortfolioCalculatorFactory; + let redisCacheService: RedisCacheService; beforeEach(() => { + configurationService = new ConfigurationService(); + currentRateService = new CurrentRateService(null, null, null, null); exchangeRateDataService = new ExchangeRateDataService( @@ -17,9 +23,13 @@ describe('PortfolioCalculator', () => { null ); + redisCacheService = new RedisCacheService(null, null); + factory = new PortfolioCalculatorFactory( + configurationService, currentRateService, - exchangeRateDataService + exchangeRateDataService, + redisCacheService ); }); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts index 7dcef89cb..f8b62a940 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts @@ -1,13 +1,9 @@ import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator'; import { PortfolioOrderItem } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order-item.interface'; -import { PortfolioSnapshot } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-snapshot.interface'; import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; -import { - SymbolMetrics, - TimelinePosition, - UniqueAsset -} from '@ghostfolio/common/interfaces'; +import { SymbolMetrics, UniqueAsset } from '@ghostfolio/common/interfaces'; +import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models'; import { Logger } from '@nestjs/common'; import { Big } from 'big.js'; @@ -188,6 +184,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { [date: string]: Big; } = {}; + let totalAccountBalanceInBaseCurrency = new Big(0); let totalDividend = new Big(0); let totalDividendInBaseCurrency = new Big(0); let totalInterest = new Big(0); @@ -206,7 +203,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { let valueAtStartDateWithCurrencyEffect: Big; // Clone orders to keep the original values in this.orders - let orders: PortfolioOrderItem[] = cloneDeep(this.orders).filter( + let orders: PortfolioOrderItem[] = cloneDeep(this.activities).filter( ({ SymbolProfile }) => { return SymbolProfile.symbol === symbol; } @@ -237,6 +234,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { timeWeightedInvestmentValues: {}, timeWeightedInvestmentValuesWithCurrencyEffect: {}, timeWeightedInvestmentWithCurrencyEffect: new Big(0), + totalAccountBalanceInBaseCurrency: new Big(0), totalDividend: new Big(0), totalDividendInBaseCurrency: new Big(0), totalInterest: new Big(0), @@ -286,6 +284,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { timeWeightedInvestmentValues: {}, timeWeightedInvestmentValuesWithCurrencyEffect: {}, timeWeightedInvestmentWithCurrencyEffect: new Big(0), + totalAccountBalanceInBaseCurrency: new Big(0), totalDividend: new Big(0), totalDividendInBaseCurrency: new Big(0), totalInterest: new Big(0), @@ -334,8 +333,10 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { if (isChartMode) { const datesWithOrders = {}; - for (const order of orders) { - datesWithOrders[order.date] = true; + for (const { date, type } of orders) { + if (['BUY', 'SELL'].includes(type)) { + datesWithOrders[date] = true; + } } while (isBefore(day, end)) { @@ -396,11 +397,46 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { if (PortfolioCalculator.ENABLE_LOGGING) { console.log(); console.log(); - console.log(i + 1, order.type, order.itemType); + console.log( + i + 1, + order.date, + order.type, + order.itemType ? `(${order.itemType})` : '' + ); } const exchangeRateAtOrderDate = exchangeRates[order.date]; + if (order.type === 'DIVIDEND') { + const dividend = order.quantity.mul(order.unitPrice); + + totalDividend = totalDividend.plus(dividend); + totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus( + dividend.mul(exchangeRateAtOrderDate ?? 1) + ); + } else if (order.type === 'INTEREST') { + const interest = order.quantity.mul(order.unitPrice); + + totalInterest = totalInterest.plus(interest); + totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus( + interest.mul(exchangeRateAtOrderDate ?? 1) + ); + } else if (order.type === 'ITEM') { + const valuables = order.quantity.mul(order.unitPrice); + + totalValuables = totalValuables.plus(valuables); + totalValuablesInBaseCurrency = totalValuablesInBaseCurrency.plus( + valuables.mul(exchangeRateAtOrderDate ?? 1) + ); + } else if (order.type === 'LIABILITY') { + const liabilities = order.quantity.mul(order.unitPrice); + + totalLiabilities = totalLiabilities.plus(liabilities); + totalLiabilitiesInBaseCurrency = totalLiabilitiesInBaseCurrency.plus( + liabilities.mul(exchangeRateAtOrderDate ?? 1) + ); + } + if (order.itemType === 'start') { // Take the unit price of the order as the market price if there are no // orders of this symbol before the start date @@ -483,13 +519,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { } if (PortfolioCalculator.ENABLE_LOGGING) { - console.log('totalInvestment', totalInvestment.toNumber()); - - console.log( - 'totalInvestmentWithCurrencyEffect', - totalInvestmentWithCurrencyEffect.toNumber() - ); - console.log('order.quantity', order.quantity.toNumber()); console.log('transactionInvestment', transactionInvestment.toNumber()); @@ -536,36 +565,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { totalUnits = totalUnits.plus(order.quantity.mul(getFactor(order.type))); - if (order.type === 'DIVIDEND') { - const dividend = order.quantity.mul(order.unitPrice); - - totalDividend = totalDividend.plus(dividend); - totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus( - dividend.mul(exchangeRateAtOrderDate ?? 1) - ); - } else if (order.type === 'INTEREST') { - const interest = order.quantity.mul(order.unitPrice); - - totalInterest = totalInterest.plus(interest); - totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus( - interest.mul(exchangeRateAtOrderDate ?? 1) - ); - } else if (order.type === 'ITEM') { - const valuables = order.quantity.mul(order.unitPrice); - - totalValuables = totalValuables.plus(valuables); - totalValuablesInBaseCurrency = totalValuablesInBaseCurrency.plus( - valuables.mul(exchangeRateAtOrderDate ?? 1) - ); - } else if (order.type === 'LIABILITY') { - const liabilities = order.quantity.mul(order.unitPrice); - - totalLiabilities = totalLiabilities.plus(liabilities); - totalLiabilitiesInBaseCurrency = totalLiabilitiesInBaseCurrency.plus( - liabilities.mul(exchangeRateAtOrderDate ?? 1) - ); - } - const valueOfInvestment = totalUnits.mul(order.unitPriceInBaseCurrency); const valueOfInvestmentWithCurrencyEffect = totalUnits.mul( @@ -875,6 +874,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { netPerformanceValuesWithCurrencyEffect, timeWeightedInvestmentValues, timeWeightedInvestmentValuesWithCurrencyEffect, + totalAccountBalanceInBaseCurrency, totalDividend, totalDividendInBaseCurrency, totalInterest, diff --git a/apps/api/src/app/portfolio/current-rate.service.mock.ts b/apps/api/src/app/portfolio/current-rate.service.mock.ts index ed9229691..8ac1d15bd 100644 --- a/apps/api/src/app/portfolio/current-rate.service.mock.ts +++ b/apps/api/src/app/portfolio/current-rate.service.mock.ts @@ -8,6 +8,13 @@ import { GetValuesParams } from './interfaces/get-values-params.interface'; function mockGetValue(symbol: string, date: Date) { switch (symbol) { + case '55196015-1365-4560-aa60-8751ae6d18f8': + if (isSameDay(parseDate('2022-01-31'), date)) { + return { marketPrice: 3000 }; + } + + return { marketPrice: 0 }; + case 'BALN.SW': if (isSameDay(parseDate('2021-11-12'), date)) { return { marketPrice: 146 }; diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-positions.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-positions.interface.ts deleted file mode 100644 index fa6141a7a..000000000 --- a/apps/api/src/app/portfolio/interfaces/portfolio-positions.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Position } from '@ghostfolio/common/interfaces'; - -export interface PortfolioPositions { - positions: Position[]; -} diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts deleted file mode 100644 index d89734987..000000000 --- a/apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ResponseError, TimelinePosition } from '@ghostfolio/common/interfaces'; - -import { Big } from 'big.js'; - -export interface PortfolioSnapshot extends ResponseError { - currentValueInBaseCurrency: Big; - grossPerformance: Big; - grossPerformanceWithCurrencyEffect: Big; - grossPerformancePercentage: Big; - grossPerformancePercentageWithCurrencyEffect: Big; - netAnnualizedPerformance?: Big; - netAnnualizedPerformanceWithCurrencyEffect?: Big; - netPerformance: Big; - netPerformanceWithCurrencyEffect: Big; - netPerformancePercentage: Big; - netPerformancePercentageWithCurrencyEffect: Big; - positions: TimelinePosition[]; - totalFeesWithCurrencyEffect: Big; - totalInterestWithCurrencyEffect: Big; - totalInvestment: Big; - totalInvestmentWithCurrencyEffect: Big; - totalLiabilitiesWithCurrencyEffect: Big; - totalValuablesWithCurrencyEffect: Big; -} diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 56c0a231c..ed3c0f174 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -47,11 +47,11 @@ import { } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; +import { AssetClass, AssetSubClass } from '@prisma/client'; import { Big } from 'big.js'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { PortfolioPositionDetail } from './interfaces/portfolio-position-detail.interface'; -import { PortfolioPositions } from './interfaces/portfolio-positions.interface'; import { PortfolioService } from './portfolio.service'; @Controller('portfolio') @@ -128,14 +128,19 @@ export class PortfolioController { const totalValue = Object.values(holdings) .filter(({ assetClass, assetSubClass }) => { - return assetClass !== 'CASH' && assetSubClass !== 'CASH'; + return ( + assetClass !== AssetClass.LIQUIDITY && + assetSubClass !== AssetSubClass.CASH + ); }) .map(({ valueInBaseCurrency }) => { return valueInBaseCurrency; }) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => { + return a + b; + }, 0); - for (const [symbol, portfolioPosition] of Object.entries(holdings)) { + for (const [, portfolioPosition] of Object.entries(holdings)) { portfolioPosition.investment = portfolioPosition.investment / totalInvestment; portfolioPosition.valueInPercentage = @@ -159,21 +164,21 @@ export class PortfolioController { portfolioSummary = nullifyValuesInObject(summary, [ 'cash', 'committedFunds', - 'currentGrossPerformance', - 'currentGrossPerformanceWithCurrencyEffect', - 'currentNetPerformance', - 'currentNetPerformanceWithCurrencyEffect', 'currentNetWorth', - 'currentValue', + 'currentValueInBaseCurrency', 'dividendInBaseCurrency', 'emergencyFund', 'excludedAccountsAndActivities', 'fees', 'filteredValueInBaseCurrency', 'fireWealth', + 'grossPerformance', + 'grossPerformanceWithCurrencyEffect', 'interest', 'items', 'liabilities', + 'netPerformance', + 'netPerformanceWithCurrencyEffect', 'totalBuy', 'totalInvestment', 'totalSell', @@ -185,11 +190,11 @@ export class PortfolioController { holdings[symbol] = { ...portfolioPosition, assetClass: - hasDetails || portfolioPosition.assetClass === 'CASH' + hasDetails || portfolioPosition.assetClass === AssetClass.LIQUIDITY ? portfolioPosition.assetClass : undefined, assetSubClass: - hasDetails || portfolioPosition.assetSubClass === 'CASH' + hasDetails || portfolioPosition.assetSubClass === AssetSubClass.CASH ? portfolioPosition.assetSubClass : undefined, countries: hasDetails ? portfolioPosition.countries : [], @@ -290,6 +295,7 @@ export class PortfolioController { @Query('assetClasses') filterByAssetClasses?: string, @Query('holdingType') filterByHoldingType?: string, @Query('query') filterBySearchQuery?: string, + @Query('range') dateRange: DateRange = 'max', @Query('tags') filterByTags?: string ): Promise { const filters = this.apiService.buildFiltersFromQueryParams({ @@ -301,6 +307,7 @@ export class PortfolioController { }); const { holdings } = await this.portfolioService.getDetails({ + dateRange, filters, impersonationId, userId: this.request.user.id @@ -441,10 +448,14 @@ export class PortfolioController { .div(performanceInformation.performance.totalInvestment) .toNumber(), valueInPercentage: - performanceInformation.performance.currentValue === 0 + performanceInformation.performance.currentValueInBaseCurrency === + 0 ? 0 : new Big(value) - .div(performanceInformation.performance.currentValue) + .div( + performanceInformation.performance + .currentValueInBaseCurrency + ) .toNumber() }; } @@ -453,12 +464,12 @@ export class PortfolioController { performanceInformation.performance = nullifyValuesInObject( performanceInformation.performance, [ - 'currentGrossPerformance', - 'currentGrossPerformanceWithCurrencyEffect', - 'currentNetPerformance', - 'currentNetPerformanceWithCurrencyEffect', 'currentNetWorth', - 'currentValue', + 'currentValueInBaseCurrency', + 'grossPerformance', + 'grossPerformanceWithCurrencyEffect', + 'netPerformance', + 'netPerformanceWithCurrencyEffect', 'totalInvestment' ] ); @@ -475,39 +486,13 @@ export class PortfolioController { ); performanceInformation.performance = nullifyValuesInObject( performanceInformation.performance, - ['currentNetPerformance', 'currentNetPerformancePercent'] + ['netPerformance'] ); } return performanceInformation; } - @Get('positions') - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - @UseInterceptors(RedactValuesInResponseInterceptor) - @UseInterceptors(TransformDataSourceInResponseInterceptor) - public async getPositions( - @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, - @Query('accounts') filterByAccounts?: string, - @Query('assetClasses') filterByAssetClasses?: string, - @Query('query') filterBySearchQuery?: string, - @Query('range') dateRange: DateRange = 'max', - @Query('tags') filterByTags?: string - ): Promise { - const filters = this.apiService.buildFiltersFromQueryParams({ - filterByAccounts, - filterByAssetClasses, - filterBySearchQuery, - filterByTags - }); - - return this.portfolioService.getPositions({ - dateRange, - filters, - impersonationId - }); - } - @Get('public/:accessId') @UseInterceptors(TransformDataSourceInResponseInterceptor) public async getPublic( diff --git a/apps/api/src/app/portfolio/portfolio.module.ts b/apps/api/src/app/portfolio/portfolio.module.ts index 6b06bf02d..5659f2a7e 100644 --- a/apps/api/src/app/portfolio/portfolio.module.ts +++ b/apps/api/src/app/portfolio/portfolio.module.ts @@ -2,6 +2,7 @@ import { AccessModule } from '@ghostfolio/api/app/access/access.module'; import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.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/configuration.module'; @@ -35,6 +36,7 @@ import { RulesService } from './rules.service'; MarketDataModule, OrderModule, PrismaModule, + RedisCacheModule, SymbolProfileModule, UserModule ], diff --git a/apps/api/src/app/portfolio/portfolio.service.spec.ts b/apps/api/src/app/portfolio/portfolio.service.spec.ts index 7654b7df3..92970f547 100644 --- a/apps/api/src/app/portfolio/portfolio.service.spec.ts +++ b/apps/api/src/app/portfolio/portfolio.service.spec.ts @@ -27,7 +27,7 @@ describe('PortfolioService', () => { portfolioService .getAnnualizedPerformancePercent({ daysInMarket: NaN, // differenceInDays of date-fns returns NaN for the same day - netPerformancePercent: new Big(0) + netPerformancePercentage: new Big(0) }) .toNumber() ).toEqual(0); @@ -36,7 +36,7 @@ describe('PortfolioService', () => { portfolioService .getAnnualizedPerformancePercent({ daysInMarket: 0, - netPerformancePercent: new Big(0) + netPerformancePercentage: new Big(0) }) .toNumber() ).toEqual(0); @@ -48,7 +48,7 @@ describe('PortfolioService', () => { portfolioService .getAnnualizedPerformancePercent({ daysInMarket: 65, // < 1 year - netPerformancePercent: new Big(0.1025) + netPerformancePercentage: new Big(0.1025) }) .toNumber() ).toBeCloseTo(0.729705); @@ -57,7 +57,7 @@ describe('PortfolioService', () => { portfolioService .getAnnualizedPerformancePercent({ daysInMarket: 365, // 1 year - netPerformancePercent: new Big(0.05) + netPerformancePercentage: new Big(0.05) }) .toNumber() ).toBeCloseTo(0.05); @@ -69,7 +69,7 @@ describe('PortfolioService', () => { portfolioService .getAnnualizedPerformancePercent({ daysInMarket: 575, // > 1 year - netPerformancePercent: new Big(0.2374) + netPerformancePercentage: new Big(0.2374) }) .toNumber() ).toBeCloseTo(0.145); diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 95a68eaae..a98887ca9 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -29,6 +29,7 @@ import { EnhancedSymbolProfile, Filter, HistoricalDataItem, + InvestmentItem, PortfolioDetails, PortfolioInvestments, PortfolioPerformanceResponse, @@ -36,10 +37,9 @@ import { PortfolioReport, PortfolioSummary, Position, - TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces'; -import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; +import { TimelinePosition } from '@ghostfolio/common/models'; import type { AccountWithValue, DateRange, @@ -54,6 +54,7 @@ import { Account, Type as ActivityType, AssetClass, + AssetSubClass, DataSource, Order, Platform, @@ -64,7 +65,6 @@ import { differenceInDays, format, isAfter, - isBefore, isSameMonth, isSameYear, parseISO, @@ -208,16 +208,16 @@ export class PortfolioService { public getAnnualizedPerformancePercent({ daysInMarket, - netPerformancePercent + netPerformancePercentage }: { daysInMarket: number; - netPerformancePercent: Big; + netPerformancePercentage: Big; }): Big { if (isNumber(daysInMarket) && daysInMarket > 0) { const exponent = new Big(365).div(daysInMarket).toNumber(); return new Big( - Math.pow(netPerformancePercent.plus(1).toNumber(), exponent) + Math.pow(netPerformancePercentage.plus(1).toNumber(), exponent) ).minus(1); } @@ -277,8 +277,13 @@ export class PortfolioService { const portfolioCalculator = this.calculatorFactory.createCalculator({ activities, + dateRange, + userId, calculationType: PerformanceCalculationType.TWR, - currency: this.request.user.Settings.settings.baseCurrency + currency: this.request.user.Settings.settings.baseCurrency, + hasFilters: filters?.length > 0, + isExperimentalFeatures: + this.request.user.Settings.settings.isExperimentalFeatures }); const items = await portfolioCalculator.getChart({ @@ -352,8 +357,12 @@ export class PortfolioService { const portfolioCalculator = this.calculatorFactory.createCalculator({ activities, dateRange, + userId, calculationType: PerformanceCalculationType.TWR, - currency: userCurrency + currency: userCurrency, + hasFilters: true, // disable cache + isExperimentalFeatures: + this.request.user?.Settings.settings.isExperimentalFeatures }); const { currentValueInBaseCurrency, hasErrors, positions } = @@ -377,7 +386,7 @@ export class PortfolioService { }) ?? false; const isFilteredByCash = filters?.some(({ id, type }) => { - return id === 'CASH' && type === 'ASSET_CLASS'; + return id === AssetClass.LIQUIDITY && type === 'ASSET_CLASS'; }); const isFilteredByClosedHoldings = @@ -392,8 +401,8 @@ export class PortfolioService { if ( filters?.length === 0 || (filters?.length === 1 && - filters[0].type === 'ASSET_CLASS' && - filters[0].id === 'CASH') + filters[0].id === AssetClass.LIQUIDITY && + filters[0].type === 'ASSET_CLASS') ) { filteredValueInBaseCurrency = filteredValueInBaseCurrency.plus( cashDetails.balanceInBaseCurrency @@ -648,11 +657,15 @@ export class PortfolioService { ]); const portfolioCalculator = this.calculatorFactory.createCalculator({ + userId, activities: orders.filter((order) => { return ['BUY', 'DIVIDEND', 'ITEM', 'SELL'].includes(order.type); }), calculationType: PerformanceCalculationType.TWR, - currency: userCurrency + currency: userCurrency, + hasFilters: true, + isExperimentalFeatures: + this.request.user.Settings.settings.isExperimentalFeatures }); const portfolioStart = portfolioCalculator.getStartDate(); @@ -691,17 +704,21 @@ export class PortfolioService { const dividendYieldPercent = this.getAnnualizedPerformancePercent({ daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), - netPerformancePercent: dividendInBaseCurrency.div( - timeWeightedInvestment - ) + netPerformancePercentage: timeWeightedInvestment.eq(0) + ? new Big(0) + : dividendInBaseCurrency.div(timeWeightedInvestment) }); const dividendYieldPercentWithCurrencyEffect = this.getAnnualizedPerformancePercent({ daysInMarket: differenceInDays(new Date(), parseDate(firstBuyDate)), - netPerformancePercent: dividendInBaseCurrency.div( - timeWeightedInvestmentWithCurrencyEffect + netPerformancePercentage: timeWeightedInvestmentWithCurrencyEffect.eq( + 0 ) + ? new Big(0) + : dividendInBaseCurrency.div( + timeWeightedInvestmentWithCurrencyEffect + ) }); const historicalData = await this.dataProviderService.getHistorical( @@ -822,11 +839,19 @@ export class PortfolioService { ); if (isEmpty(historicalData)) { - historicalData = await this.dataProviderService.getHistoricalRaw( - [{ dataSource: DataSource.YAHOO, symbol: aSymbol }], - portfolioStart, - new Date() - ); + try { + historicalData = await this.dataProviderService.getHistoricalRaw({ + dataGatheringItems: [ + { dataSource: DataSource.YAHOO, symbol: aSymbol } + ], + from: portfolioStart, + to: new Date() + }); + } catch { + historicalData = { + [aSymbol]: {} + }; + } } const historicalDataArray: HistoricalDataItem[] = []; @@ -911,8 +936,12 @@ export class PortfolioService { const portfolioCalculator = this.calculatorFactory.createCalculator({ activities, dateRange, + userId, calculationType: PerformanceCalculationType.TWR, - currency: this.request.user.Settings.settings.baseCurrency + currency: this.request.user.Settings.settings.baseCurrency, + hasFilters: filters?.length > 0, + isExperimentalFeatures: + this.request.user.Settings.settings.isExperimentalFeatures }); let { hasErrors, positions } = await portfolioCalculator.getSnapshot(); @@ -1048,11 +1077,16 @@ export class PortfolioService { ) => { const formattedDate = format(date, DATE_FORMAT); - // Store the item in the map, overwriting if the date already exists - map[formattedDate] = { - date: formattedDate, - value: valueInBaseCurrency - }; + if (map[formattedDate]) { + // If the value exists, add the current value to the existing one + map[formattedDate].value += valueInBaseCurrency; + } else { + // Otherwise, initialize the value for that date + map[formattedDate] = { + date: formattedDate, + value: valueInBaseCurrency + }; + } return map; }, @@ -1060,7 +1094,7 @@ export class PortfolioService { ) ); - const { endDate, startDate } = getInterval(dateRange); + const { endDate } = getInterval(dateRange); const { activities } = await this.orderService.getOrders({ endDate, @@ -1076,26 +1110,31 @@ export class PortfolioService { firstOrderDate: undefined, hasErrors: false, performance: { - currentGrossPerformance: 0, - currentGrossPerformancePercent: 0, - currentGrossPerformancePercentWithCurrencyEffect: 0, - currentGrossPerformanceWithCurrencyEffect: 0, - currentNetPerformance: 0, - currentNetPerformancePercent: 0, - currentNetPerformancePercentWithCurrencyEffect: 0, - currentNetPerformanceWithCurrencyEffect: 0, currentNetWorth: 0, - currentValue: 0, + currentValueInBaseCurrency: 0, + grossPerformance: 0, + grossPerformancePercentage: 0, + grossPerformancePercentageWithCurrencyEffect: 0, + grossPerformanceWithCurrencyEffect: 0, + netPerformance: 0, + netPerformancePercentage: 0, + netPerformancePercentageWithCurrencyEffect: 0, + netPerformanceWithCurrencyEffect: 0, totalInvestment: 0 } }; } const portfolioCalculator = this.calculatorFactory.createCalculator({ + accountBalanceItems, activities, dateRange, + userId, calculationType: PerformanceCalculationType.TWR, - currency: userCurrency + currency: userCurrency, + hasFilters: filters?.length > 0, + isExperimentalFeatures: + this.request.user.Settings.settings.isExperimentalFeatures }); const { @@ -1115,14 +1154,16 @@ export class PortfolioService { let currentNetPerformance = netPerformance; - let currentNetPerformancePercent = netPerformancePercentage; + let currentNetPerformancePercentage = netPerformancePercentage; - let currentNetPerformancePercentWithCurrencyEffect = + let currentNetPerformancePercentageWithCurrencyEffect = netPerformancePercentageWithCurrencyEffect; let currentNetPerformanceWithCurrencyEffect = netPerformanceWithCurrencyEffect; + let currentNetWorth = 0; + const items = await portfolioCalculator.getChart({ dateRange }); @@ -1134,62 +1175,41 @@ export class PortfolioService { if (itemOfToday) { currentNetPerformance = new Big(itemOfToday.netPerformance); - currentNetPerformancePercent = new Big( + currentNetPerformancePercentage = new Big( itemOfToday.netPerformanceInPercentage ).div(100); - currentNetPerformancePercentWithCurrencyEffect = new Big( + currentNetPerformancePercentageWithCurrencyEffect = new Big( itemOfToday.netPerformanceInPercentageWithCurrencyEffect ).div(100); currentNetPerformanceWithCurrencyEffect = new Big( itemOfToday.netPerformanceWithCurrencyEffect ); - } - - accountBalanceItems = accountBalanceItems.filter(({ date }) => { - return !isBefore(parseDate(date), startDate); - }); - - const accountBalanceItemOfToday = accountBalanceItems.find(({ date }) => { - return date === format(new Date(), DATE_FORMAT); - }); - if (!accountBalanceItemOfToday) { - accountBalanceItems.push({ - date: format(new Date(), DATE_FORMAT), - value: last(accountBalanceItems)?.value ?? 0 - }); + currentNetWorth = itemOfToday.netWorth; } - const mergedHistoricalDataItems = this.mergeHistoricalDataItems( - accountBalanceItems, - items - ); - - const currentHistoricalDataItem = last(mergedHistoricalDataItems); - const currentNetWorth = currentHistoricalDataItem?.netWorth ?? 0; - return { errors, hasErrors, - chart: mergedHistoricalDataItems, + chart: items, firstOrderDate: parseDate(items[0]?.date), performance: { currentNetWorth, - currentGrossPerformance: grossPerformance.toNumber(), - currentGrossPerformancePercent: grossPerformancePercentage.toNumber(), - currentGrossPerformancePercentWithCurrencyEffect: + currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(), + grossPerformance: grossPerformance.toNumber(), + grossPerformancePercentage: grossPerformancePercentage.toNumber(), + grossPerformancePercentageWithCurrencyEffect: grossPerformancePercentageWithCurrencyEffect.toNumber(), - currentGrossPerformanceWithCurrencyEffect: + grossPerformanceWithCurrencyEffect: grossPerformanceWithCurrencyEffect.toNumber(), - currentNetPerformance: currentNetPerformance.toNumber(), - currentNetPerformancePercent: currentNetPerformancePercent.toNumber(), - currentNetPerformancePercentWithCurrencyEffect: - currentNetPerformancePercentWithCurrencyEffect.toNumber(), - currentNetPerformanceWithCurrencyEffect: + netPerformance: currentNetPerformance.toNumber(), + netPerformancePercentage: currentNetPerformancePercentage.toNumber(), + netPerformancePercentageWithCurrencyEffect: + currentNetPerformancePercentageWithCurrencyEffect.toNumber(), + netPerformanceWithCurrencyEffect: currentNetPerformanceWithCurrencyEffect.toNumber(), - currentValue: currentValueInBaseCurrency.toNumber(), totalInvestment: totalInvestment.toNumber() } }; @@ -1207,8 +1227,12 @@ export class PortfolioService { const portfolioCalculator = this.calculatorFactory.createCalculator({ activities, + userId, calculationType: PerformanceCalculationType.TWR, - currency: this.request.user.Settings.settings.baseCurrency + currency: this.request.user.Settings.settings.baseCurrency, + hasFilters: false, + isExperimentalFeatures: + this.request.user.Settings.settings.isExperimentalFeatures }); let { totalFeesWithCurrencyEffect, positions, totalInvestment } = @@ -1431,8 +1455,8 @@ export class PortfolioService { return { currency, allocationInPercentage: 0, - assetClass: AssetClass.CASH, - assetSubClass: AssetClass.CASH, + assetClass: AssetClass.LIQUIDITY, + assetSubClass: AssetSubClass.CASH, countries: [], dataSource: undefined, dateOfFirstActivity: undefined, @@ -1582,11 +1606,6 @@ export class PortfolioService { userId = await this.getUserId(impersonationId, userId); const user = await this.userService.user({ id: userId }); - const performanceInformation = await this.getPerformance({ - impersonationId, - userId - }); - const { activities } = await this.orderService.getOrders({ userCurrency, userId, @@ -1604,6 +1623,19 @@ export class PortfolioService { } } + const { + currentValueInBaseCurrency, + grossPerformance, + grossPerformancePercentage, + grossPerformancePercentageWithCurrencyEffect, + grossPerformanceWithCurrencyEffect, + netPerformance, + netPerformancePercentage, + netPerformancePercentageWithCurrencyEffect, + netPerformanceWithCurrencyEffect, + totalInvestment + } = await portfolioCalculator.getSnapshot(); + const dividendInBaseCurrency = await portfolioCalculator.getDividendInBaseCurrency(); @@ -1672,7 +1704,7 @@ export class PortfolioService { .toNumber(); const netWorth = new Big(balanceInBaseCurrency) - .plus(performanceInformation.performance.currentValue) + .plus(currentValueInBaseCurrency) .plus(valuables) .plus(excludedAccountsAndActivities) .minus(liabilities) @@ -1682,21 +1714,18 @@ export class PortfolioService { const annualizedPerformancePercent = this.getAnnualizedPerformancePercent({ daysInMarket, - netPerformancePercent: new Big( - performanceInformation.performance.currentNetPerformancePercent - ) + netPerformancePercentage: new Big(netPerformancePercentage) })?.toNumber(); const annualizedPerformancePercentWithCurrencyEffect = this.getAnnualizedPerformancePercent({ daysInMarket, - netPerformancePercent: new Big( - performanceInformation.performance.currentNetPerformancePercentWithCurrencyEffect + netPerformancePercentage: new Big( + netPerformancePercentageWithCurrencyEffect ) })?.toNumber(); return { - ...performanceInformation.performance, annualizedPerformancePercent, annualizedPerformancePercentWithCurrencyEffect, cash, @@ -1705,6 +1734,7 @@ export class PortfolioService { totalBuy, totalSell, committedFunds: committedFunds.toNumber(), + currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(), dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), emergencyFund: { assets: emergencyFundPositionsValueInBaseCurrency, @@ -1718,15 +1748,28 @@ export class PortfolioService { filteredValueInPercentage: netWorth ? filteredValueInBaseCurrency.div(netWorth).toNumber() : undefined, - fireWealth: new Big(performanceInformation.performance.currentValue) + fireWealth: new Big(currentValueInBaseCurrency) .minus(emergencyFundPositionsValueInBaseCurrency) .toNumber(), + grossPerformance: grossPerformance.toNumber(), + grossPerformancePercentage: grossPerformancePercentage.toNumber(), + grossPerformancePercentageWithCurrencyEffect: + grossPerformancePercentageWithCurrencyEffect.toNumber(), + grossPerformanceWithCurrencyEffect: + grossPerformanceWithCurrencyEffect.toNumber(), interest: interest.toNumber(), items: valuables.toNumber(), liabilities: liabilities.toNumber(), + netPerformance: netPerformance.toNumber(), + netPerformancePercentage: netPerformancePercentage.toNumber(), + netPerformancePercentageWithCurrencyEffect: + netPerformancePercentageWithCurrencyEffect.toNumber(), + netPerformanceWithCurrencyEffect: + netPerformanceWithCurrencyEffect.toNumber(), ordersCount: activities.filter(({ type }) => { - return type === 'BUY' || type === 'SELL'; + return ['BUY', 'SELL'].includes(type); }).length, + totalInvestment: totalInvestment.toNumber(), totalValueInBaseCurrency: netWorth }; } @@ -1901,44 +1944,4 @@ export class PortfolioService { return { accounts, platforms }; } - - private mergeHistoricalDataItems( - accountBalanceItems: HistoricalDataItem[], - performanceChartItems: HistoricalDataItem[] - ): HistoricalDataItem[] { - const historicalDataItemsMap: { [date: string]: HistoricalDataItem } = {}; - let latestAccountBalance = 0; - - for (const item of accountBalanceItems.concat(performanceChartItems)) { - const isAccountBalanceItem = accountBalanceItems.includes(item); - - const totalAccountBalance = isAccountBalanceItem - ? item.value - : latestAccountBalance; - - if (isAccountBalanceItem && performanceChartItems.length > 0) { - latestAccountBalance = item.value; - } else { - historicalDataItemsMap[item.date] = { - ...item, - totalAccountBalance, - netWorth: - (isAccountBalanceItem ? 0 : item.value) + totalAccountBalance - }; - } - } - - // Convert to an array and sort by date in ascending order - const historicalDataItems = Object.keys(historicalDataItemsMap).map( - (date) => { - return historicalDataItemsMap[date]; - } - ); - - historicalDataItems.sort((a, b) => { - return new Date(a.date).getTime() - new Date(b.date).getTime(); - }); - - return historicalDataItems; - } } diff --git a/apps/api/src/app/redis-cache/redis-cache.service.mock.ts b/apps/api/src/app/redis-cache/redis-cache.service.mock.ts new file mode 100644 index 000000000..2422e88ab --- /dev/null +++ b/apps/api/src/app/redis-cache/redis-cache.service.mock.ts @@ -0,0 +1,13 @@ +import { RedisCacheService } from './redis-cache.service'; + +export const RedisCacheServiceMock = { + get: (key: string): Promise => { + return Promise.resolve(null); + }, + getPortfolioSnapshotKey: (userId: string): string => { + return `portfolio-snapshot-${userId}`; + }, + set: (key: string, value: string, ttlInSeconds?: number): Promise => { + return Promise.resolve(value); + } +}; diff --git a/apps/api/src/app/redis-cache/redis-cache.service.ts b/apps/api/src/app/redis-cache/redis-cache.service.ts index 3891cc5ab..53b177b4f 100644 --- a/apps/api/src/app/redis-cache/redis-cache.service.ts +++ b/apps/api/src/app/redis-cache/redis-cache.service.ts @@ -24,6 +24,10 @@ export class RedisCacheService { return this.cache.get(key); } + public getPortfolioSnapshotKey({ userId }: { userId: string }) { + return `portfolio-snapshot-${userId}`; + } + public getQuoteKey({ dataSource, symbol }: UniqueAsset) { return `quote-${getAssetProfileIdentifier({ dataSource, symbol })}`; } diff --git a/apps/api/src/app/symbol/symbol.service.ts b/apps/api/src/app/symbol/symbol.service.ts index 9a3f7a3a0..90259a776 100644 --- a/apps/api/src/app/symbol/symbol.service.ts +++ b/apps/api/src/app/symbol/symbol.service.ts @@ -74,11 +74,21 @@ export class SymbolService { date = new Date(), symbol }: IDataGatheringItem): Promise { - const historicalData = await this.dataProviderService.getHistoricalRaw( - [{ dataSource, symbol }], - date, - date - ); + let historicalData: { + [symbol: string]: { + [date: string]: IDataProviderHistoricalResponse; + }; + } = { + [symbol]: {} + }; + + try { + historicalData = await this.dataProviderService.getHistoricalRaw({ + dataGatheringItems: [{ dataSource, symbol }], + from: date, + to: date + }); + } catch {} return { marketPrice: diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index 14c545192..39e78dcdc 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -2,11 +2,7 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorat import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { User, UserSettings } from '@ghostfolio/common/interfaces'; -import { - hasPermission, - hasRole, - permissions -} from '@ghostfolio/common/permissions'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import type { RequestWithUser } from '@ghostfolio/common/types'; import { @@ -63,13 +59,6 @@ export class UserController { public async getUser( @Headers('accept-language') acceptLanguage: string ): Promise { - if (hasRole(this.request.user, 'INACTIVE')) { - throw new HttpException( - getReasonPhrase(StatusCodes.TOO_MANY_REQUESTS), - StatusCodes.TOO_MANY_REQUESTS - ); - } - return this.userService.getUser( this.request.user, acceptLanguage?.split(',')?.[0] diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 4cc60770f..3a370d88a 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -1,5 +1,6 @@ import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service'; import { environment } from '@ghostfolio/api/environments/environment'; +import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; @@ -25,6 +26,7 @@ import { import { UserWithSettings } from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { Prisma, Role, User } from '@prisma/client'; import { differenceInDays } from 'date-fns'; import { sortBy, without } from 'lodash'; @@ -37,6 +39,7 @@ export class UserService { public constructor( private readonly configurationService: ConfigurationService, + private readonly eventEmitter: EventEmitter2, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly subscriptionService: SubscriptionService, @@ -437,11 +440,9 @@ export class UserService { userId: string; userSettings: UserSettings; }) { - const settings = userSettings as unknown as Prisma.JsonObject; - - await this.prismaService.settings.upsert({ + const { settings } = await this.prismaService.settings.upsert({ create: { - settings, + settings: userSettings as unknown as Prisma.JsonObject, User: { connect: { id: userId @@ -449,14 +450,21 @@ export class UserService { } }, update: { - settings + settings: userSettings as unknown as Prisma.JsonObject }, where: { userId } }); - return; + this.eventEmitter.emit( + PortfolioChangedEvent.getName(), + new PortfolioChangedEvent({ + userId + }) + ); + + return settings; } private getRandomString(length: number) { diff --git a/apps/api/src/events/events.module.ts b/apps/api/src/events/events.module.ts new file mode 100644 index 000000000..0e6b25ba4 --- /dev/null +++ b/apps/api/src/events/events.module.ts @@ -0,0 +1,11 @@ +import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; + +import { Module } from '@nestjs/common'; + +import { PortfolioChangedListener } from './portfolio-changed.listener'; + +@Module({ + imports: [RedisCacheModule], + providers: [PortfolioChangedListener] +}) +export class EventsModule {} diff --git a/apps/api/src/events/portfolio-changed.event.ts b/apps/api/src/events/portfolio-changed.event.ts new file mode 100644 index 000000000..a3b0710fb --- /dev/null +++ b/apps/api/src/events/portfolio-changed.event.ts @@ -0,0 +1,15 @@ +export class PortfolioChangedEvent { + private userId: string; + + public constructor({ userId }: { userId: string }) { + this.userId = userId; + } + + public static getName() { + return 'portfolio.changed'; + } + + public getUserId() { + return this.userId; + } +} diff --git a/apps/api/src/events/portfolio-changed.listener.ts b/apps/api/src/events/portfolio-changed.listener.ts new file mode 100644 index 000000000..fcf47ce6c --- /dev/null +++ b/apps/api/src/events/portfolio-changed.listener.ts @@ -0,0 +1,25 @@ +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; + +import { Injectable, Logger } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; + +import { PortfolioChangedEvent } from './portfolio-changed.event'; + +@Injectable() +export class PortfolioChangedListener { + public constructor(private readonly redisCacheService: RedisCacheService) {} + + @OnEvent(PortfolioChangedEvent.getName()) + handlePortfolioChangedEvent(event: PortfolioChangedEvent) { + Logger.log( + `Portfolio of user '${event.getUserId()}' has changed`, + 'PortfolioChangedListener' + ); + + this.redisCacheService.remove( + this.redisCacheService.getPortfolioSnapshotKey({ + userId: event.getUserId() + }) + ); + } +} diff --git a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts b/apps/api/src/interceptors/redact-values-in-response.interceptor.ts index 78ae918d2..17d4e3c17 100644 --- a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts +++ b/apps/api/src/interceptors/redact-values-in-response.interceptor.ts @@ -57,6 +57,7 @@ export class RedactValuesInResponseInterceptor 'quantity', 'symbolMapping', 'totalBalanceInBaseCurrency', + 'totalValueInBaseCurrency', 'unitPrice', 'value', 'valueInBaseCurrency' diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index ba37f4e94..8397f3e46 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -1,7 +1,8 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { groupBy } from '@ghostfolio/common/helper'; -import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces'; +import { UserSettings } from '@ghostfolio/common/interfaces'; +import { TimelinePosition } from '@ghostfolio/common/models'; import { EvaluationResult } from './interfaces/evaluation-result.interface'; import { RuleInterface } from './interfaces/rule.interface'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts index 39406e6c2..372250dbc 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts @@ -1,7 +1,8 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces'; +import { UserSettings } from '@ghostfolio/common/interfaces'; +import { TimelinePosition } from '@ghostfolio/common/models'; export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule { private positions: TimelinePosition[]; diff --git a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts index 078aaba9b..8ebb24ac0 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts @@ -1,7 +1,8 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces'; +import { UserSettings } from '@ghostfolio/common/interfaces'; +import { TimelinePosition } from '@ghostfolio/common/models'; export class CurrencyClusterRiskCurrentInvestment extends Rule { private positions: TimelinePosition[]; diff --git a/apps/api/src/services/data-gathering/data-gathering.processor.ts b/apps/api/src/services/data-gathering/data-gathering.processor.ts index bf960048c..11eda2e7a 100644 --- a/apps/api/src/services/data-gathering/data-gathering.processor.ts +++ b/apps/api/src/services/data-gathering/data-gathering.processor.ts @@ -37,7 +37,17 @@ export class DataGatheringProcessor { @Process({ concurrency: 1, name: GATHER_ASSET_PROFILE_PROCESS }) public async gatherAssetProfile(job: Job) { try { + Logger.log( + `Asset profile data gathering has been started for ${job.data.symbol} (${job.data.dataSource})`, + `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS})` + ); + await this.dataGatheringService.gatherAssetProfiles([job.data]); + + Logger.log( + `Asset profile data gathering has been completed for ${job.data.symbol} (${job.data.dataSource})`, + `DataGatheringProcessor (${GATHER_ASSET_PROFILE_PROCESS})` + ); } catch (error) { Logger.error( error, @@ -62,11 +72,11 @@ export class DataGatheringProcessor { `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS})` ); - const historicalData = await this.dataProviderService.getHistoricalRaw( - [{ dataSource, symbol }], - currentDate, - new Date() - ); + const historicalData = await this.dataProviderService.getHistoricalRaw({ + dataGatheringItems: [{ dataSource, symbol }], + from: currentDate, + to: new Date() + }); const data: Prisma.MarketDataUpdateInput[] = []; let lastMarketPrice: number; diff --git a/apps/api/src/services/data-gathering/data-gathering.service.ts b/apps/api/src/services/data-gathering/data-gathering.service.ts index b2b0c371c..31a0040a5 100644 --- a/apps/api/src/services/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/data-gathering/data-gathering.service.ts @@ -104,11 +104,11 @@ export class DataGatheringService { symbol: string; }) { try { - const historicalData = await this.dataProviderService.getHistoricalRaw( - [{ dataSource, symbol }], - date, - date - ); + const historicalData = await this.dataProviderService.getHistoricalRaw({ + dataGatheringItems: [{ dataSource, symbol }], + from: date, + to: date + }); const marketPrice = historicalData[symbol][format(date, DATE_FORMAT)].marketPrice; @@ -230,17 +230,12 @@ export class DataGatheringService { error, 'DataGatheringService' ); + + if (uniqueAssets.length === 1) { + throw error; + } } } - - Logger.log( - `Asset profile data gathering has been completed for ${uniqueAssets - .map(({ dataSource, symbol }) => { - return `${symbol} (${dataSource})`; - }) - .join(',')}.`, - 'DataGatheringService' - ); } public async gatherSymbols({ diff --git a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts index d17ba4b7e..d673dd7aa 100644 --- a/apps/api/src/services/data-provider/coingecko/coingecko.service.ts +++ b/apps/api/src/services/data-provider/coingecko/coingecko.service.ts @@ -59,7 +59,7 @@ export class CoinGeckoService implements DataProviderInterface { }): Promise> { const response: Partial = { symbol, - assetClass: AssetClass.CASH, + assetClass: AssetClass.LIQUIDITY, assetSubClass: AssetSubClass.CRYPTOCURRENCY, currency: DEFAULT_CURRENCY, dataSource: this.getName() @@ -243,7 +243,7 @@ export class CoinGeckoService implements DataProviderInterface { return { name, symbol, - assetClass: AssetClass.CASH, + assetClass: AssetClass.LIQUIDITY, assetSubClass: AssetSubClass.CRYPTOCURRENCY, currency: DEFAULT_CURRENCY, dataProviderInfo: this.getDataProviderInfo(), diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index c6edef0ca..35fa9604a 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -266,7 +266,7 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { switch (quoteType?.toLowerCase()) { case 'cryptocurrency': - assetClass = AssetClass.CASH; + assetClass = AssetClass.LIQUIDITY; assetSubClass = AssetSubClass.CRYPTOCURRENCY; break; case 'equity': diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index 9afdab1dc..26fc171b5 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -233,15 +233,17 @@ export class DataProviderService { } } - public async getHistoricalRaw( - aDataGatheringItems: UniqueAsset[], - from: Date, - to: Date - ): Promise<{ + public async getHistoricalRaw({ + dataGatheringItems, + from, + to + }: { + dataGatheringItems: UniqueAsset[]; + from: Date; + to: Date; + }): Promise<{ [symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; }> { - let dataGatheringItems = aDataGatheringItems; - for (const { currency, rootCurrency } of DERIVED_CURRENCIES) { if ( this.hasCurrency({ @@ -330,6 +332,8 @@ export class DataProviderService { } } catch (error) { Logger.error(error, 'DataProviderService'); + + throw error; } return result; @@ -395,7 +399,8 @@ export class DataProviderService { numberOfItemsInCache > 1 ? 's' : '' } from cache in ${((performance.now() - startTimeTotal) / 1000).toFixed( 3 - )} seconds` + )} seconds`, + 'DataProviderService' ); } @@ -501,7 +506,8 @@ export class DataProviderService { } from ${dataSource} in ${( (performance.now() - startTimeDataSource) / 1000 - ).toFixed(3)} seconds` + ).toFixed(3)} seconds`, + 'DataProviderService' ); try { @@ -531,14 +537,15 @@ export class DataProviderService { await Promise.all(promises); - Logger.debug('------------------------------------------------'); + Logger.debug('--------------------------------------------------------'); Logger.debug( `Fetched ${items.length} quote${items.length > 1 ? 's' : ''} in ${( (performance.now() - startTimeTotal) / 1000 - ).toFixed(3)} seconds` + ).toFixed(3)} seconds`, + 'DataProviderService' ); - Logger.debug('================================================'); + Logger.debug('========================================================'); return response; } diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts index 99104a78d..1b6abd585 100644 --- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts +++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts @@ -468,7 +468,7 @@ export class EodHistoricalDataService implements DataProviderInterface { assetSubClass = AssetSubClass.STOCK; break; case 'currency': - assetClass = AssetClass.CASH; + assetClass = AssetClass.LIQUIDITY; if (Exchange?.toLowerCase() === 'cc') { assetSubClass = AssetSubClass.CRYPTOCURRENCY; diff --git a/apps/api/src/services/data-provider/manual/manual.service.ts b/apps/api/src/services/data-provider/manual/manual.service.ts index 4ff3ba653..5066a4d3a 100644 --- a/apps/api/src/services/data-provider/manual/manual.service.ts +++ b/apps/api/src/services/data-provider/manual/manual.service.ts @@ -91,7 +91,7 @@ export class ManualService implements DataProviderInterface { headers = {}, selector, url - } = symbolProfile.scraperConfiguration ?? {}; + } = symbolProfile?.scraperConfiguration ?? {}; if (defaultMarketPrice) { const historical: { diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts index a02ddb597..683002a10 100644 --- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts @@ -449,13 +449,16 @@ export class ExchangeRateDataService { factors[format(date, DATE_FORMAT)] = factor; } } catch { - Logger.error( - `No exchange rate has been found for ${currencyFrom}${currencyTo} at ${format( - date, - DATE_FORMAT - )}. Please complement market data for ${DEFAULT_CURRENCY}${currencyFrom} and ${DEFAULT_CURRENCY}${currencyTo}.`, - 'ExchangeRateDataService' - ); + let errorMessage = `No exchange rate has been found for ${currencyFrom}${currencyTo} at ${format( + date, + DATE_FORMAT + )}. Please complement market data for ${DEFAULT_CURRENCY}${currencyFrom}`; + + if (DEFAULT_CURRENCY !== currencyTo) { + errorMessage = `${errorMessage} and ${DEFAULT_CURRENCY}${currencyTo}`; + } + + Logger.error(`${errorMessage}.`, 'ExchangeRateDataService'); } } } diff --git a/apps/client/src/app/app.module.ts b/apps/client/src/app/app.module.ts index f8b52faa9..fac59bf48 100644 --- a/apps/client/src/app/app.module.ts +++ b/apps/client/src/app/app.module.ts @@ -1,4 +1,4 @@ -import { GfLogoModule } from '@ghostfolio/ui/logo'; +import { GfLogoComponent } from '@ghostfolio/ui/logo'; import { Platform } from '@angular/cdk/platform'; import { HttpClientModule } from '@angular/common/http'; @@ -43,7 +43,7 @@ export function NgxStripeFactory(): string { BrowserAnimationsModule, BrowserModule, GfHeaderModule, - GfLogoModule, + GfLogoComponent, GfSubscriptionInterstitialDialogModule, HttpClientModule, MarkdownModule.forRoot(), diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index 537adf1d1..aeec7d2a5 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -84,55 +84,10 @@ export class AccountDetailDialog implements OnDestroy, OnInit { } public ngOnInit() { - this.dataService - .fetchAccount(this.data.accountId) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe( - ({ - balance, - currency, - name, - Platform, - transactionCount, - value, - valueInBaseCurrency - }) => { - this.balance = balance; - this.currency = currency; - - if (isNumber(balance) && isNumber(value)) { - this.equity = new Big(value).minus(balance).toNumber(); - } else { - this.equity = null; - } - - this.name = name; - this.platformName = Platform?.name ?? '-'; - this.transactionCount = transactionCount; - this.valueInBaseCurrency = valueInBaseCurrency; - - this.changeDetectorRef.markForCheck(); - } - ); - - this.dataService - .fetchPortfolioHoldings({ - filters: [ - { - type: 'ACCOUNT', - id: this.data.accountId - } - ] - }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ holdings }) => { - this.holdings = holdings; - - this.changeDetectorRef.markForCheck(); - }); - + this.fetchAccount(); this.fetchAccountBalances(); this.fetchActivities(); + this.fetchPortfolioHoldings(); this.fetchPortfolioPerformance(); } @@ -140,15 +95,35 @@ export class AccountDetailDialog implements OnDestroy, OnInit { this.dialogRef.close(); } + public onAddAccountBalance({ + balance, + date + }: { + balance: number; + date: Date; + }) { + this.dataService + .postAccountBalance({ + balance, + date, + accountId: this.data.accountId + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.fetchAccount(); + this.fetchAccountBalances(); + this.fetchPortfolioPerformance(); + }); + } + public onDeleteAccountBalance(aId: string) { this.dataService .deleteAccountBalance(aId) .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe({ - next: () => { - this.fetchAccountBalances(); - this.fetchPortfolioPerformance(); - } + .subscribe(() => { + this.fetchAccount(); + this.fetchAccountBalances(); + this.fetchPortfolioPerformance(); }); } @@ -181,6 +156,39 @@ export class AccountDetailDialog implements OnDestroy, OnInit { this.fetchActivities(); } + private fetchAccount() { + this.dataService + .fetchAccount(this.data.accountId) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe( + ({ + balance, + currency, + name, + Platform, + transactionCount, + value, + valueInBaseCurrency + }) => { + this.balance = balance; + this.currency = currency; + + if (isNumber(balance) && isNumber(value)) { + this.equity = new Big(value).minus(balance).toNumber(); + } else { + this.equity = null; + } + + this.name = name; + this.platformName = Platform?.name ?? '-'; + this.transactionCount = transactionCount; + this.valueInBaseCurrency = valueInBaseCurrency; + + this.changeDetectorRef.markForCheck(); + } + ); + } + private fetchAccountBalances() { this.dataService .fetchAccountBalances(this.data.accountId) @@ -212,6 +220,24 @@ export class AccountDetailDialog implements OnDestroy, OnInit { }); } + private fetchPortfolioHoldings() { + this.dataService + .fetchPortfolioHoldings({ + filters: [ + { + type: 'ACCOUNT', + id: this.data.accountId + } + ] + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ holdings }) => { + this.holdings = holdings; + + this.changeDetectorRef.markForCheck(); + }); + } + private fetchPortfolioPerformance() { this.isLoadingChart = true; @@ -233,11 +259,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit { ({ date, netWorth, netWorthInPercentage }) => { return { date, - value: - this.data.hasImpersonationId || - this.user.settings.isRestrictedView - ? netWorthInPercentage - : netWorth + value: isNumber(netWorth) ? netWorth : netWorthInPercentage }; } ); diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html index 041a779c4..e092cce68 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html @@ -115,6 +115,7 @@ diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts index faba1d6d2..e404aaad1 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.module.ts @@ -1,10 +1,10 @@ import { GfDialogFooterModule } from '@ghostfolio/client/components/dialog-footer/dialog-footer.module'; import { GfDialogHeaderModule } from '@ghostfolio/client/components/dialog-header/dialog-header.module'; import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; -import { GfAccountBalancesModule } from '@ghostfolio/ui/account-balances/account-balances.module'; -import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module'; -import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfAccountBalancesComponent } from '@ghostfolio/ui/account-balances'; +import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; +import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -19,13 +19,13 @@ import { AccountDetailDialog } from './account-detail-dialog.component'; declarations: [AccountDetailDialog], imports: [ CommonModule, - GfAccountBalancesModule, - GfActivitiesTableModule, + GfAccountBalancesComponent, + GfActivitiesTableComponent, GfDialogFooterModule, GfDialogHeaderModule, - GfHoldingsTableModule, + GfHoldingsTableComponent, GfInvestmentChartModule, - GfValueModule, + GfValueComponent, MatButtonModule, MatDialogModule, MatTabsModule, diff --git a/apps/client/src/app/components/accounts-table/accounts-table.module.ts b/apps/client/src/app/components/accounts-table/accounts-table.module.ts index bae24fda3..879ca13ea 100644 --- a/apps/client/src/app/components/accounts-table/accounts-table.module.ts +++ b/apps/client/src/app/components/accounts-table/accounts-table.module.ts @@ -1,5 +1,5 @@ import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -18,7 +18,7 @@ import { AccountsTableComponent } from './accounts-table.component'; imports: [ CommonModule, GfAssetProfileIconComponent, - GfValueModule, + GfValueComponent, MatButtonModule, MatMenuModule, MatSortModule, diff --git a/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.module.ts b/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.module.ts index 9e742acba..9f4e1b3bc 100644 --- a/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.module.ts +++ b/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.module.ts @@ -1,4 +1,4 @@ -import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module'; +import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -9,7 +9,7 @@ import { GfMarketDataDetailDialogModule } from './market-data-detail-dialog/mark @NgModule({ declarations: [AdminMarketDataDetailComponent], exports: [AdminMarketDataDetailComponent], - imports: [CommonModule, GfLineChartModule, GfMarketDataDetailDialogModule], + imports: [CommonModule, GfLineChartComponent, GfMarketDataDetailDialogModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class GfAdminMarketDataDetailModule {} diff --git a/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts b/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts index 0ccf85701..61f11c9bd 100644 --- a/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts +++ b/apps/client/src/app/components/admin-market-data/admin-market-data.component.ts @@ -38,6 +38,7 @@ import { CreateAssetProfileDialogParams } from './create-asset-profile-dialog/in @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + host: { class: 'has-fab' }, selector: 'gf-admin-market-data', styleUrls: ['./admin-market-data.scss'], templateUrl: './admin-market-data.html' diff --git a/apps/client/src/app/components/admin-market-data/admin-market-data.module.ts b/apps/client/src/app/components/admin-market-data/admin-market-data.module.ts index c4cdc3bdd..73bf47f7f 100644 --- a/apps/client/src/app/components/admin-market-data/admin-market-data.module.ts +++ b/apps/client/src/app/components/admin-market-data/admin-market-data.module.ts @@ -1,5 +1,5 @@ import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; -import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module'; +import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -20,7 +20,7 @@ import { GfCreateAssetProfileDialogModule } from './create-asset-profile-dialog/ declarations: [AdminMarketDataComponent], imports: [ CommonModule, - GfActivitiesFilterModule, + GfActivitiesFilterComponent, GfAssetProfileDialogModule, GfCreateAssetProfileDialogModule, GfSymbolModule, diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index 2f0c2546b..5016a4205 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -3,6 +3,7 @@ import { UpdateMarketDataDto } from '@ghostfolio/api/app/admin/update-market-dat import { AdminMarketDataService } from '@ghostfolio/client/components/admin-market-data/admin-market-data.service'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; +import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; import { ghostfolioScraperApiSymbolPrefix } from '@ghostfolio/common/config'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { @@ -258,29 +259,29 @@ export class AssetProfileDialog implements OnDestroy, OnInit { }); } - public onSubmit() { + public async onSubmit() { let countries = []; let scraperConfiguration = {}; let sectors = []; let symbolMapping = {}; try { - countries = JSON.parse(this.assetProfileForm.controls['countries'].value); + countries = JSON.parse(this.assetProfileForm.get('countries').value); } catch {} try { scraperConfiguration = JSON.parse( - this.assetProfileForm.controls['scraperConfiguration'].value + this.assetProfileForm.get('scraperConfiguration').value ); } catch {} try { - sectors = JSON.parse(this.assetProfileForm.controls['sectors'].value); + sectors = JSON.parse(this.assetProfileForm.get('sectors').value); } catch {} try { symbolMapping = JSON.parse( - this.assetProfileForm.controls['symbolMapping'].value + this.assetProfileForm.get('symbolMapping').value ); } catch {} @@ -289,16 +290,27 @@ export class AssetProfileDialog implements OnDestroy, OnInit { scraperConfiguration, sectors, symbolMapping, - assetClass: this.assetProfileForm.controls['assetClass'].value, - assetSubClass: this.assetProfileForm.controls['assetSubClass'].value, - comment: this.assetProfileForm.controls['comment'].value ?? null, + assetClass: this.assetProfileForm.get('assetClass').value, + assetSubClass: this.assetProfileForm.get('assetSubClass').value, + comment: this.assetProfileForm.get('comment').value || null, currency: (( - (this.assetProfileForm.controls['currency'].value) + (this.assetProfileForm.get('currency').value) ))?.value, - name: this.assetProfileForm.controls['name'].value, - url: this.assetProfileForm.controls['url'].value + name: this.assetProfileForm.get('name').value, + url: this.assetProfileForm.get('url').value || null }; + try { + await validateObjectForForm({ + classDto: UpdateAssetProfileDto, + form: this.assetProfileForm, + object: assetProfileData + }); + } catch (error) { + console.error(error); + return; + } + this.adminService .patchAssetProfile({ ...assetProfileData, @@ -314,8 +326,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit { this.adminService .testMarketData({ dataSource: this.data.dataSource, - scraperConfiguration: - this.assetProfileForm.controls['scraperConfiguration'].value, + scraperConfiguration: this.assetProfileForm.get('scraperConfiguration') + .value, symbol: this.data.symbol }) .pipe( @@ -331,9 +343,8 @@ export class AssetProfileDialog implements OnDestroy, OnInit { ' ' + price + ' ' + - (( - (this.assetProfileForm.controls['currency'].value) - ))?.value + ((this.assetProfileForm.get('currency').value)) + ?.value ); }); } diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html index b0b57df09..4f01a933e 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -302,7 +302,7 @@ mat-flat-button type="button" [disabled]=" - assetProfileForm.controls['scraperConfiguration'].value === '{}' + assetProfileForm.get('scraperConfiguration').value === '{}' " (click)="onTestMarketData()" > @@ -338,11 +338,11 @@ Url - @if (assetProfileForm.controls['url'].value) { + @if (assetProfileForm.get('url').value) { } diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts index ffde6c0ae..a872f567f 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.module.ts @@ -1,9 +1,9 @@ import { GfAdminMarketDataDetailModule } from '@ghostfolio/client/components/admin-market-data-detail/admin-market-data-detail.module'; import { AdminMarketDataService } from '@ghostfolio/client/components/admin-market-data/admin-market-data.service'; import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfCurrencySelectorModule } from '@ghostfolio/ui/currency-selector/currency-selector.module'; -import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfCurrencySelectorComponent } from '@ghostfolio/ui/currency-selector'; +import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { TextFieldModule } from '@angular/cdk/text-field'; import { CommonModule } from '@angular/common'; @@ -26,9 +26,9 @@ import { AssetProfileDialog } from './asset-profile-dialog.component'; FormsModule, GfAdminMarketDataDetailModule, GfAssetProfileIconComponent, - GfCurrencySelectorModule, - GfPortfolioProportionChartModule, - GfValueModule, + GfCurrencySelectorComponent, + GfPortfolioProportionChartComponent, + GfValueComponent, MatButtonModule, MatCheckboxModule, MatDialogModule, diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts index d5415524b..f0a47ad1b 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts @@ -59,14 +59,12 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy { this.mode === 'auto' ? this.dialogRef.close({ dataSource: - this.createAssetProfileForm.controls['searchSymbol'].value - .dataSource, - symbol: - this.createAssetProfileForm.controls['searchSymbol'].value.symbol + this.createAssetProfileForm.get('searchSymbol').value.dataSource, + symbol: this.createAssetProfileForm.get('searchSymbol').value.symbol }) : this.dialogRef.close({ dataSource: 'MANUAL', - symbol: this.createAssetProfileForm.controls['addSymbol'].value + symbol: this.createAssetProfileForm.get('addSymbol').value }); } diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts index 888abfa56..24cc90dbe 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.module.ts @@ -1,4 +1,4 @@ -import { GfSymbolAutocompleteModule } from '@ghostfolio/ui/symbol-autocomplete'; +import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -16,7 +16,7 @@ import { CreateAssetProfileDialog } from './create-asset-profile-dialog.componen imports: [ CommonModule, FormsModule, - GfSymbolAutocompleteModule, + GfSymbolAutocompleteComponent, MatDialogModule, MatButtonModule, MatFormFieldModule, diff --git a/apps/client/src/app/components/admin-overview/admin-overview.module.ts b/apps/client/src/app/components/admin-overview/admin-overview.module.ts index a5a0a35e7..da49eb858 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.module.ts +++ b/apps/client/src/app/components/admin-overview/admin-overview.module.ts @@ -1,5 +1,5 @@ import { CacheService } from '@ghostfolio/client/services/cache.service'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -19,7 +19,7 @@ import { AdminOverviewComponent } from './admin-overview.component'; imports: [ CommonModule, FormsModule, - GfValueModule, + GfValueComponent, MatButtonModule, MatCardModule, MatMenuModule, diff --git a/apps/client/src/app/components/admin-platform/admin-platform.component.ts b/apps/client/src/app/components/admin-platform/admin-platform.component.ts index 6a2a3de3c..8a2004f8d 100644 --- a/apps/client/src/app/components/admin-platform/admin-platform.component.ts +++ b/apps/client/src/app/components/admin-platform/admin-platform.component.ts @@ -143,9 +143,7 @@ export class AdminPlatformComponent implements OnInit, OnDestroy { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data) => { - const platform: CreatePlatformDto = data?.platform; - + .subscribe((platform: CreatePlatformDto | null) => { if (platform) { this.adminService .postPlatform(platform) @@ -182,9 +180,7 @@ export class AdminPlatformComponent implements OnInit, OnDestroy { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data) => { - const platform: UpdatePlatformDto = data?.platform; - + .subscribe((platform: UpdatePlatformDto | null) => { if (platform) { this.adminService .putPlatform(platform) diff --git a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts index 14d893900..518b6dd52 100644 --- a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts +++ b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.component.ts @@ -1,4 +1,14 @@ -import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; +import { CreatePlatformDto } from '@ghostfolio/api/app/platform/create-platform.dto'; +import { UpdatePlatformDto } from '@ghostfolio/api/app/platform/update-platform.dto'; +import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; + +import { + ChangeDetectionStrategy, + Component, + Inject, + OnDestroy +} from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Subject } from 'rxjs'; @@ -11,18 +21,54 @@ import { CreateOrUpdatePlatformDialogParams } from './interfaces/interfaces'; styleUrls: ['./create-or-update-platform-dialog.scss'], templateUrl: 'create-or-update-platform-dialog.html' }) -export class CreateOrUpdatePlatformDialog { +export class CreateOrUpdatePlatformDialog implements OnDestroy { + public platformForm: FormGroup; + private unsubscribeSubject = new Subject(); public constructor( @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdatePlatformDialogParams, - public dialogRef: MatDialogRef - ) {} + public dialogRef: MatDialogRef, + private formBuilder: FormBuilder + ) { + this.platformForm = this.formBuilder.group({ + name: [this.data.platform.name, Validators.required], + url: [this.data.platform.url, Validators.required] + }); + } public onCancel() { this.dialogRef.close(); } + public async onSubmit() { + try { + const platform: CreatePlatformDto | UpdatePlatformDto = { + name: this.platformForm.get('name')?.value, + url: this.platformForm.get('url')?.value + }; + + if (this.data.platform.id) { + (platform as UpdatePlatformDto).id = this.data.platform.id; + await validateObjectForForm({ + classDto: UpdatePlatformDto, + form: this.platformForm, + object: platform + }); + } else { + await validateObjectForForm({ + classDto: CreatePlatformDto, + form: this.platformForm, + object: platform + }); + } + + this.dialogRef.close(platform); + } catch (error) { + console.error(error); + } + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html index bcd3d0340..0e85cff2c 100644 --- a/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html +++ b/apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html @@ -1,17 +1,30 @@ -
+

Update platform

Add platform

Name - +
Url - + @if (data.platform.url) {
- + diff --git a/apps/client/src/app/components/admin-tag/admin-tag.component.ts b/apps/client/src/app/components/admin-tag/admin-tag.component.ts index a8bb7720a..5b5d5aa84 100644 --- a/apps/client/src/app/components/admin-tag/admin-tag.component.ts +++ b/apps/client/src/app/components/admin-tag/admin-tag.component.ts @@ -142,9 +142,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data) => { - const tag: CreateTagDto = data?.tag; - + .subscribe((tag: CreateTagDto | null) => { if (tag) { this.adminService .postTag(tag) @@ -180,9 +178,7 @@ export class AdminTagComponent implements OnInit, OnDestroy { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data) => { - const tag: UpdateTagDto = data?.tag; - + .subscribe((tag: UpdateTagDto | null) => { if (tag) { this.adminService .putTag(tag) diff --git a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts index aaa5a0221..f50974358 100644 --- a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts +++ b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.component.ts @@ -1,4 +1,14 @@ -import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; +import { CreateTagDto } from '@ghostfolio/api/app/tag/create-tag.dto'; +import { UpdateTagDto } from '@ghostfolio/api/app/tag/update-tag.dto'; +import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; + +import { + ChangeDetectionStrategy, + Component, + Inject, + OnDestroy +} from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Subject } from 'rxjs'; @@ -11,18 +21,52 @@ import { CreateOrUpdateTagDialogParams } from './interfaces/interfaces'; styleUrls: ['./create-or-update-tag-dialog.scss'], templateUrl: 'create-or-update-tag-dialog.html' }) -export class CreateOrUpdateTagDialog { +export class CreateOrUpdateTagDialog implements OnDestroy { + public tagForm: FormGroup; + private unsubscribeSubject = new Subject(); public constructor( @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateTagDialogParams, - public dialogRef: MatDialogRef - ) {} + public dialogRef: MatDialogRef, + private formBuilder: FormBuilder + ) { + this.tagForm = this.formBuilder.group({ + name: [this.data.tag.name] + }); + } public onCancel() { this.dialogRef.close(); } + public async onSubmit() { + try { + const tag: CreateTagDto | UpdateTagDto = { + name: this.tagForm.get('name')?.value + }; + + if (this.data.tag.id) { + (tag as UpdateTagDto).id = this.data.tag.id; + await validateObjectForForm({ + classDto: UpdateTagDto, + form: this.tagForm, + object: tag + }); + } else { + await validateObjectForForm({ + classDto: CreateTagDto, + form: this.tagForm, + object: tag + }); + } + + this.dialogRef.close(tag); + } catch (error) { + console.error(error); + } + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html index c2e8f4ee1..46ab1a39e 100644 --- a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html +++ b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html @@ -1,21 +1,30 @@ - +

Update tag

Add tag

Name - +
- + diff --git a/apps/client/src/app/components/admin-users/admin-users.module.ts b/apps/client/src/app/components/admin-users/admin-users.module.ts index 0e232a4ed..3f4e9f2f7 100644 --- a/apps/client/src/app/components/admin-users/admin-users.module.ts +++ b/apps/client/src/app/components/admin-users/admin-users.module.ts @@ -1,5 +1,5 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -14,8 +14,8 @@ import { AdminUsersComponent } from './admin-users.component'; exports: [], imports: [ CommonModule, - GfPremiumIndicatorModule, - GfValueModule, + GfPremiumIndicatorComponent, + GfValueComponent, MatButtonModule, MatMenuModule, MatTableModule diff --git a/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.module.ts b/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.module.ts index 2e6cae5cf..1bd4b0792 100644 --- a/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.module.ts +++ b/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.module.ts @@ -1,4 +1,4 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -15,7 +15,7 @@ import { BenchmarkComparatorComponent } from './benchmark-comparator.component'; imports: [ CommonModule, FormsModule, - GfPremiumIndicatorModule, + GfPremiumIndicatorComponent, MatSelectModule, NgxSkeletonLoaderModule, ReactiveFormsModule, diff --git a/apps/client/src/app/components/header/header.component.ts b/apps/client/src/app/components/header/header.component.ts index 1251853e7..dd1e3cc3c 100644 --- a/apps/client/src/app/components/header/header.component.ts +++ b/apps/client/src/app/components/header/header.component.ts @@ -12,7 +12,7 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { Filter, InfoItem, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { DateRange } from '@ghostfolio/common/types'; -import { AssistantComponent } from '@ghostfolio/ui/assistant/assistant.component'; +import { GfAssistantComponent } from '@ghostfolio/ui/assistant/assistant.component'; import { ChangeDetectionStrategy, @@ -62,7 +62,7 @@ export class HeaderComponent implements OnChanges { @Output() signOut = new EventEmitter(); - @ViewChild('assistant') assistantElement: AssistantComponent; + @ViewChild('assistant') assistantElement: GfAssistantComponent; @ViewChild('assistantTrigger') assistentMenuTriggerElement: MatMenuTrigger; public hasPermissionForSocialLogin: boolean; diff --git a/apps/client/src/app/components/header/header.module.ts b/apps/client/src/app/components/header/header.module.ts index 8ec816625..797ff7b6e 100644 --- a/apps/client/src/app/components/header/header.module.ts +++ b/apps/client/src/app/components/header/header.module.ts @@ -1,7 +1,7 @@ import { LoginWithAccessTokenDialogModule } from '@ghostfolio/client/components/login-with-access-token-dialog/login-with-access-token-dialog.module'; -import { GfAssistantModule } from '@ghostfolio/ui/assistant'; -import { GfLogoModule } from '@ghostfolio/ui/logo'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfAssistantComponent } from '@ghostfolio/ui/assistant'; +import { GfLogoComponent } from '@ghostfolio/ui/logo'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -17,9 +17,9 @@ import { HeaderComponent } from './header.component'; exports: [HeaderComponent], imports: [ CommonModule, - GfAssistantModule, - GfLogoModule, - GfPremiumIndicatorModule, + GfAssistantComponent, + GfLogoComponent, + GfPremiumIndicatorComponent, LoginWithAccessTokenDialogModule, MatButtonModule, MatMenuModule, diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index 9dbf9d9bf..1a556e6f4 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -1,11 +1,11 @@ -import { PositionDetailDialog } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.component'; -import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; +import { PositionDetailDialogParams } from '@ghostfolio/client/components/position-detail-dialog/interfaces/interfaces'; +import { PositionDetailDialog } from '@ghostfolio/client/components/position-detail-dialog/position-detail-dialog.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { Position, User } from '@ghostfolio/common/interfaces'; +import { PortfolioPosition, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { DateRange } from '@ghostfolio/common/types'; +import { HoldingType, ToggleOption } from '@ghostfolio/common/types'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; @@ -15,19 +15,21 @@ import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { PositionDetailDialogParams } from '../position/position-detail-dialog/interfaces/interfaces'; - @Component({ selector: 'gf-home-holdings', styleUrls: ['./home-holdings.scss'], templateUrl: './home-holdings.html' }) export class HomeHoldingsComponent implements OnDestroy, OnInit { - public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public deviceType: string; public hasImpersonationId: boolean; public hasPermissionToCreateOrder: boolean; - public positions: Position[]; + public holdings: PortfolioPosition[]; + public holdingType: HoldingType = 'ACTIVE'; + public holdingTypeOptions: ToggleOption[] = [ + { label: $localize`Active`, value: 'ACTIVE' }, + { label: $localize`Closed`, value: 'CLOSED' } + ]; public user: User; private unsubscribeSubject = new Subject(); @@ -56,6 +58,17 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { }); } }); + } + + public ngOnInit() { + this.deviceType = this.deviceService.getDeviceInfo().deviceType; + + this.impersonationStorageService + .onChangeHasImpersonation() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((impersonationId) => { + this.hasImpersonationId = !!impersonationId; + }); this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) @@ -68,37 +81,32 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { permissions.createOrder ); - this.update(); + this.holdings = undefined; + + this.fetchHoldings() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(({ holdings }) => { + this.holdings = holdings; + + this.changeDetectorRef.markForCheck(); + }); + + this.changeDetectorRef.markForCheck(); } }); } - public ngOnInit() { - this.deviceType = this.deviceService.getDeviceInfo().deviceType; + public onChangeHoldingType(aHoldingType: HoldingType) { + this.holdingType = aHoldingType; - this.impersonationStorageService - .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((impersonationId) => { - this.hasImpersonationId = !!impersonationId; - }); - } + this.holdings = undefined; - public onChangeDateRange(dateRange: DateRange) { - this.dataService - .putUserSetting({ dateRange }) + this.fetchHoldings() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.userService.remove(); - - this.userService - .get() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((user) => { - this.user = user; + .subscribe(({ holdings }) => { + this.holdings = holdings; - this.changeDetectorRef.markForCheck(); - }); + this.changeDetectorRef.markForCheck(); }); } @@ -107,6 +115,19 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { this.unsubscribeSubject.complete(); } + private fetchHoldings() { + const filters = this.userService.getFilters(); + + if (this.holdingType === 'CLOSED') { + filters.push({ id: 'CLOSED', type: 'HOLDING_TYPE' }); + } + + return this.dataService.fetchPortfolioHoldings({ + filters, + range: this.user?.settings?.dateRange + }); + } + private openPositionDialog({ dataSource, symbol @@ -147,19 +168,4 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { }); }); } - - private update() { - this.positions = undefined; - - this.dataService - .fetchPositions({ range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ positions }) => { - this.positions = positions; - - this.changeDetectorRef.markForCheck(); - }); - - this.changeDetectorRef.markForCheck(); - } } diff --git a/apps/client/src/app/components/home-holdings/home-holdings.html b/apps/client/src/app/components/home-holdings/home-holdings.html index 72328eac2..a2bd43636 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.html +++ b/apps/client/src/app/components/home-holdings/home-holdings.html @@ -1,27 +1,38 @@ -
+
-
- - - - - -
- Manage Activities +
+

Holdings

+
+
+
+
+
+
+ + @if (hasPermissionToCreateOrder && holdings?.length > 0) { + + }
diff --git a/apps/client/src/app/components/home-holdings/home-holdings.module.ts b/apps/client/src/app/components/home-holdings/home-holdings.module.ts index b6fa70e8f..f10adeab2 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.module.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.module.ts @@ -1,11 +1,9 @@ -import { GfPositionDetailDialogModule } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.module'; -import { GfPositionsModule } from '@ghostfolio/client/components/positions/positions.module'; import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; +import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; -import { MatCardModule } from '@angular/material/card'; import { RouterModule } from '@angular/router'; import { HomeHoldingsComponent } from './home-holdings.component'; @@ -14,11 +12,9 @@ import { HomeHoldingsComponent } from './home-holdings.component'; declarations: [HomeHoldingsComponent], imports: [ CommonModule, - GfPositionDetailDialogModule, - GfPositionsModule, + GfHoldingsTableComponent, GfToggleModule, MatButtonModule, - MatCardModule, RouterModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/apps/client/src/app/components/home-market/home-market.html b/apps/client/src/app/components/home-market/home-market.html index 333c612f7..0e9d51336 100644 --- a/apps/client/src/app/components/home-market/home-market.html +++ b/apps/client/src/app/components/home-market/home-market.html @@ -11,7 +11,7 @@ [colorScheme]="user?.settings?.colorScheme" [historicalDataItems]="historicalDataItems" [isAnimated]="true" - [locale]="user?.settings?.locale" + [locale]="user?.settings?.locale || undefined" [showXAxis]="true" [showYAxis]="true" [yMax]="100" @@ -30,7 +30,7 @@
@@ -55,7 +53,7 @@ [value]=" isLoading ? undefined - : performance?.currentNetPerformancePercentWithCurrencyEffect + : performance?.netPerformancePercentageWithCurrencyEffect " />
diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts index b76ecb004..4d205b761 100644 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts +++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts @@ -49,12 +49,12 @@ export class PortfolioPerformanceComponent implements OnChanges, OnInit { this.value.nativeElement.innerHTML = ''; } } else { - if (isNumber(this.performance?.currentValue)) { - new CountUp('value', this.performance?.currentValue, { + if (isNumber(this.performance?.currentValueInBaseCurrency)) { + new CountUp('value', this.performance?.currentValueInBaseCurrency, { decimal: getNumberFormatDecimal(this.locale), decimalPlaces: this.deviceType === 'mobile' && - this.performance?.currentValue >= 100000 + this.performance?.currentValueInBaseCurrency >= 100000 ? 0 : 2, duration: 1, @@ -63,8 +63,7 @@ export class PortfolioPerformanceComponent implements OnChanges, OnInit { } else if (this.showDetails === false) { new CountUp( 'value', - this.performance?.currentNetPerformancePercentWithCurrencyEffect * - 100, + this.performance?.netPerformancePercentageWithCurrencyEffect * 100, { decimal: getNumberFormatDecimal(this.locale), decimalPlaces: 2, diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts b/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts index b72f64b15..5c62cca87 100644 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts +++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts @@ -1,4 +1,4 @@ -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -9,7 +9,7 @@ import { PortfolioPerformanceComponent } from './portfolio-performance.component @NgModule({ declarations: [PortfolioPerformanceComponent], exports: [PortfolioPerformanceComponent], - imports: [CommonModule, GfValueModule, NgxSkeletonLoaderModule], + imports: [CommonModule, GfValueComponent, NgxSkeletonLoaderModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class GfPortfolioPerformanceModule {} diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index 347767011..6b80e87b6 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -9,9 +9,19 @@ class="flex-nowrap px-3 py-1 row" [hidden]="summary?.ordersCount === null" > -
+
{{ summary?.ordersCount }} - {summary?.ordersCount, plural, =1 {transaction} other {transactions}} + {summary?.ordersCount, plural, + =1 {activity} + other {activities} + } + + +
@@ -65,9 +75,7 @@ [locale]="locale" [unit]="baseCurrency" [value]=" - isLoading - ? undefined - : summary?.currentGrossPerformanceWithCurrencyEffect + isLoading ? undefined : summary?.grossPerformanceWithCurrencyEffect " />
@@ -91,7 +99,7 @@ [value]=" isLoading ? undefined - : summary?.currentGrossPerformancePercentWithCurrencyEffect + : summary?.grossPerformancePercentageWithCurrencyEffect " />
@@ -121,9 +129,7 @@ [locale]="locale" [unit]="baseCurrency" [value]=" - isLoading - ? undefined - : summary?.currentNetPerformanceWithCurrencyEffect + isLoading ? undefined : summary?.netPerformanceWithCurrencyEffect " />
@@ -147,7 +153,7 @@ [value]=" isLoading ? undefined - : summary?.currentNetPerformancePercentWithCurrencyEffect + : summary?.netPerformancePercentageWithCurrencyEffect " />
@@ -164,7 +170,7 @@ [isCurrency]="true" [locale]="locale" [unit]="baseCurrency" - [value]="isLoading ? undefined : summary?.currentValue" + [value]="isLoading ? undefined : summary?.currentValueInBaseCurrency" />
diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts index 9ceae5186..020a8fed0 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts @@ -1,5 +1,6 @@ import { getDateFnsLocale, getLocale } from '@ghostfolio/common/helper'; import { PortfolioSummary } from '@ghostfolio/common/interfaces'; +import { translate } from '@ghostfolio/ui/i18n'; import { ChangeDetectionStrategy, @@ -28,6 +29,9 @@ export class PortfolioSummaryComponent implements OnChanges, OnInit { @Output() emergencyFundChanged = new EventEmitter(); + public buyAndSellActivitiesTooltip = translate( + 'BUY_AND_SELL_ACTIVITIES_TOOLTIP' + ); public timeInMarket: string; public constructor() {} diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.module.ts b/apps/client/src/app/components/portfolio-summary/portfolio-summary.module.ts index be9f6fef8..b35f1e317 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.module.ts +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.module.ts @@ -1,14 +1,15 @@ -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { MatTooltipModule } from '@angular/material/tooltip'; import { PortfolioSummaryComponent } from './portfolio-summary.component'; @NgModule({ declarations: [PortfolioSummaryComponent], exports: [PortfolioSummaryComponent], - imports: [CommonModule, GfValueModule], + imports: [CommonModule, GfValueComponent, MatTooltipModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class GfPortfolioSummaryModule {} diff --git a/apps/client/src/app/components/position/position-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/position-detail-dialog/interfaces/interfaces.ts similarity index 100% rename from apps/client/src/app/components/position/position-detail-dialog/interfaces/interfaces.ts rename to apps/client/src/app/components/position-detail-dialog/interfaces/interfaces.ts diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.scss b/apps/client/src/app/components/position-detail-dialog/position-detail-dialog.component.scss similarity index 100% rename from apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.scss rename to apps/client/src/app/components/position-detail-dialog/position-detail-dialog.component.scss diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts b/apps/client/src/app/components/position-detail-dialog/position-detail-dialog.component.ts similarity index 95% rename from apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts rename to apps/client/src/app/components/position-detail-dialog/position-detail-dialog.component.ts index bb37b9ed5..2a0303686 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts +++ b/apps/client/src/app/components/position-detail-dialog/position-detail-dialog.component.ts @@ -56,6 +56,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { public marketPrice: number; public maxPrice: number; public minPrice: number; + public netPerformance: number; + public netPerformancePercent: number; public netPerformancePercentWithCurrencyEffect: number; public netPerformanceWithCurrencyEffect: number; public quantity: number; @@ -104,6 +106,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { marketPrice, maxPrice, minPrice, + netPerformance, + netPerformancePercent, netPerformancePercentWithCurrencyEffect, netPerformanceWithCurrencyEffect, orders, @@ -126,15 +130,15 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.feeInBaseCurrency = feeInBaseCurrency; this.firstBuyDate = firstBuyDate; this.historicalDataItems = historicalData.map( - (historicalDataItem) => { + ({ averagePrice, date, marketPrice }) => { this.benchmarkDataItems.push({ - date: historicalDataItem.date, - value: historicalDataItem.averagePrice + date, + value: averagePrice }); return { - date: historicalDataItem.date, - value: historicalDataItem.marketPrice + date, + value: marketPrice }; } ); @@ -142,6 +146,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.marketPrice = marketPrice; this.maxPrice = maxPrice; this.minPrice = minPrice; + this.netPerformance = netPerformance; + this.netPerformancePercent = netPerformancePercent; this.netPerformancePercentWithCurrencyEffect = netPerformancePercentWithCurrencyEffect; this.netPerformanceWithCurrencyEffect = diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html b/apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html similarity index 87% rename from apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html rename to apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html index 537fe104d..9ae432a35 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html +++ b/apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html @@ -37,27 +37,58 @@
- Change + @if ( + SymbolProfile?.currency && + data.baseCurrency !== SymbolProfile?.currency + ) { + Change with currency effect + } @else { + Change + }
- Performance + @if ( + SymbolProfile?.currency && + data.baseCurrency !== SymbolProfile?.currency + ) { + Performance with currency effect + } @else { + Performance + }
diff --git a/apps/client/src/app/components/position/position.component.scss b/apps/client/src/app/components/position/position.component.scss deleted file mode 100644 index 7044d7795..000000000 --- a/apps/client/src/app/components/position/position.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -:host { - display: block; - - .container { - gf-trend-indicator { - padding-top: 0.15rem; - } - - .chevron { - opacity: 0.33; - } - } -} diff --git a/apps/client/src/app/components/position/position.component.ts b/apps/client/src/app/components/position/position.component.ts deleted file mode 100644 index 3a5fbae81..000000000 --- a/apps/client/src/app/components/position/position.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { UNKNOWN_KEY } from '@ghostfolio/common/config'; -import { getLocale } from '@ghostfolio/common/helper'; -import { Position } from '@ghostfolio/common/interfaces'; - -import { - ChangeDetectionStrategy, - Component, - Input, - OnDestroy, - OnInit -} from '@angular/core'; -import { Subject } from 'rxjs'; - -@Component({ - selector: 'gf-position', - changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './position.component.html', - styleUrls: ['./position.component.scss'] -}) -export class PositionComponent implements OnDestroy, OnInit { - @Input() baseCurrency: string; - @Input() deviceType: string; - @Input() isLoading: boolean; - @Input() locale = getLocale(); - @Input() position: Position; - @Input() range: string; - - public unknownKey = UNKNOWN_KEY; - - private unsubscribeSubject = new Subject(); - - public constructor() {} - - public ngOnInit() {} - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } -} diff --git a/apps/client/src/app/components/position/position.module.ts b/apps/client/src/app/components/position/position.module.ts deleted file mode 100644 index 0b225cd04..000000000 --- a/apps/client/src/app/components/position/position.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; -import { GfTrendIndicatorModule } from '@ghostfolio/ui/trend-indicator'; -import { GfValueModule } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatDialogModule } from '@angular/material/dialog'; -import { RouterModule } from '@angular/router'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { GfPositionDetailDialogModule } from './position-detail-dialog/position-detail-dialog.module'; -import { PositionComponent } from './position.component'; - -@NgModule({ - declarations: [PositionComponent], - exports: [PositionComponent], - imports: [ - CommonModule, - GfPositionDetailDialogModule, - GfSymbolModule, - GfTrendIndicatorModule, - GfValueModule, - MatDialogModule, - NgxSkeletonLoaderModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfPositionModule {} diff --git a/apps/client/src/app/components/positions/positions.component.html b/apps/client/src/app/components/positions/positions.component.html deleted file mode 100644 index 606c59211..000000000 --- a/apps/client/src/app/components/positions/positions.component.html +++ /dev/null @@ -1,35 +0,0 @@ -
-
-
- - - - - - - - -
- -
-
-
-
-
diff --git a/apps/client/src/app/components/positions/positions.component.scss b/apps/client/src/app/components/positions/positions.component.scss deleted file mode 100644 index d3e8995a1..000000000 --- a/apps/client/src/app/components/positions/positions.component.scss +++ /dev/null @@ -1,17 +0,0 @@ -:host { - display: block; - - gf-position { - &:nth-child(even) { - background-color: rgba(0, 0, 0, var(--gf-theme-alpha-hover)); - } - } -} - -:host-context(.is-dark-theme) { - gf-position { - &:nth-child(even) { - background-color: rgba(255, 255, 255, var(--gf-theme-alpha-hover)); - } - } -} diff --git a/apps/client/src/app/components/positions/positions.component.ts b/apps/client/src/app/components/positions/positions.component.ts deleted file mode 100644 index ab9812462..000000000 --- a/apps/client/src/app/components/positions/positions.component.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { getLocale } from '@ghostfolio/common/helper'; -import { Position } from '@ghostfolio/common/interfaces'; - -import { - ChangeDetectionStrategy, - Component, - Input, - OnChanges, - OnInit -} from '@angular/core'; - -@Component({ - selector: 'gf-positions', - changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './positions.component.html', - styleUrls: ['./positions.component.scss'] -}) -export class PositionsComponent implements OnChanges, OnInit { - @Input() baseCurrency: string; - @Input() deviceType: string; - @Input() hasPermissionToCreateOrder: boolean; - @Input() locale = getLocale(); - @Input() positions: Position[]; - @Input() range: string; - - public hasPositions: boolean; - public positionsRest: Position[] = []; - public positionsWithPriority: Position[] = []; - - public constructor() {} - - public ngOnInit() {} - - public ngOnChanges() { - if (this.positions) { - this.hasPositions = this.positions.length > 0; - - if (!this.hasPositions) { - return; - } - - this.positionsRest = []; - this.positionsWithPriority = []; - - for (const portfolioPosition of this.positions) { - if (portfolioPosition.marketState === 'open' || this.range !== '1d') { - // Only show positions where the market is open in today's view - this.positionsWithPriority.push(portfolioPosition); - } else { - this.positionsRest.push(portfolioPosition); - } - } - - this.positionsRest.sort((a, b) => - (a.name || a.symbol)?.toLowerCase() > - (b.name || b.symbol)?.toLowerCase() - ? 1 - : -1 - ); - this.positionsWithPriority.sort((a, b) => - (a.name || a.symbol)?.toLowerCase() > - (b.name || b.symbol)?.toLowerCase() - ? 1 - : -1 - ); - } else { - this.hasPositions = false; - } - } -} diff --git a/apps/client/src/app/components/positions/positions.module.ts b/apps/client/src/app/components/positions/positions.module.ts deleted file mode 100644 index e9d1cb838..000000000 --- a/apps/client/src/app/components/positions/positions.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; - -import { GfPositionModule } from '../position/position.module'; -import { PositionsComponent } from './positions.component'; - -@NgModule({ - declarations: [PositionsComponent], - exports: [PositionsComponent], - imports: [ - CommonModule, - GfNoTransactionsInfoModule, - GfPositionModule, - MatButtonModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfPositionsModule {} diff --git a/apps/client/src/app/components/rules/rules.module.ts b/apps/client/src/app/components/rules/rules.module.ts index 48cd02388..26ed1d83e 100644 --- a/apps/client/src/app/components/rules/rules.module.ts +++ b/apps/client/src/app/components/rules/rules.module.ts @@ -1,12 +1,11 @@ import { GfRuleModule } from '@ghostfolio/client/components/rule/rule.module'; -import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info'; +import { GfNoTransactionsInfoComponent } from '@ghostfolio/ui/no-transactions-info'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; -import { GfPositionModule } from '../position/position.module'; import { RulesComponent } from './rules.component'; @NgModule({ @@ -14,8 +13,7 @@ import { RulesComponent } from './rules.component'; exports: [RulesComponent], imports: [ CommonModule, - GfNoTransactionsInfoModule, - GfPositionModule, + GfNoTransactionsInfoComponent, GfRuleModule, MatButtonModule, MatCardModule diff --git a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.module.ts b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.module.ts index b67d2783c..36bc931b0 100644 --- a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.module.ts +++ b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.module.ts @@ -1,4 +1,4 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -12,7 +12,7 @@ import { SubscriptionInterstitialDialog } from './subscription-interstitial-dial declarations: [SubscriptionInterstitialDialog], imports: [ CommonModule, - GfPremiumIndicatorModule, + GfPremiumIndicatorComponent, MatButtonModule, MatDialogModule, RouterModule diff --git a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts index 4c6cbbb85..d7a41f62f 100644 --- a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts +++ b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts @@ -1,5 +1,6 @@ import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto'; import { DataService } from '@ghostfolio/client/services/data.service'; +import { validateObjectForForm } from '@ghostfolio/client/util/form.util'; import { ChangeDetectionStrategy, @@ -40,22 +41,22 @@ export class CreateOrUpdateAccessDialog implements OnDestroy { alias: [this.data.access.alias], permissions: [this.data.access.permissions[0], Validators.required], type: [this.data.access.type, Validators.required], - userId: [this.data.access.grantee, Validators.required] + granteeUserId: [this.data.access.grantee, Validators.required] }); this.accessForm.get('type').valueChanges.subscribe((accessType) => { + const granteeUserIdControl = this.accessForm.get('granteeUserId'); const permissionsControl = this.accessForm.get('permissions'); - const userIdControl = this.accessForm.get('userId'); if (accessType === 'PRIVATE') { + granteeUserIdControl.setValidators(Validators.required); permissionsControl.setValidators(Validators.required); - userIdControl.setValidators(Validators.required); } else { - userIdControl.clearValidators(); + granteeUserIdControl.clearValidators(); } + granteeUserIdControl.updateValueAndValidity(); permissionsControl.updateValueAndValidity(); - userIdControl.updateValueAndValidity(); this.changeDetectorRef.markForCheck(); }); @@ -65,28 +66,38 @@ export class CreateOrUpdateAccessDialog implements OnDestroy { this.dialogRef.close(); } - public onSubmit() { + public async onSubmit() { const access: CreateAccessDto = { - alias: this.accessForm.controls['alias'].value, - granteeUserId: this.accessForm.controls['userId'].value, - permissions: [this.accessForm.controls['permissions'].value] + alias: this.accessForm.get('alias').value, + granteeUserId: this.accessForm.get('granteeUserId').value, + permissions: [this.accessForm.get('permissions').value] }; - this.dataService - .postAccess(access) - .pipe( - catchError((error) => { - if (error.status === StatusCodes.BAD_REQUEST) { - alert($localize`Oops! Could not grant access.`); - } - - return EMPTY; - }), - takeUntil(this.unsubscribeSubject) - ) - .subscribe(() => { - this.dialogRef.close({ access }); + try { + await validateObjectForForm({ + classDto: CreateAccessDto, + form: this.accessForm, + object: access }); + + this.dataService + .postAccess(access) + .pipe( + catchError((error) => { + if (error.status === StatusCodes.BAD_REQUEST) { + alert($localize`Oops! Could not grant access.`); + } + + return EMPTY; + }), + takeUntil(this.unsubscribeSubject) + ) + .subscribe(() => { + this.dialogRef.close(access); + }); + } catch (error) { + console.error(error); + } } public ngOnDestroy() { diff --git a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html index eba44adbd..951079717 100644 --- a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html +++ b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -27,7 +27,7 @@
- @if (accessForm.controls['type'].value === 'PRIVATE') { + @if (accessForm.get('type').value === 'PRIVATE') {
Permission @@ -45,7 +45,7 @@ Ghostfolio User ID { + dialogRef.afterClosed().subscribe((access: CreateAccessDto | null) => { if (access) { this.update(); } diff --git a/apps/client/src/app/components/user-account-access/user-account-access.module.ts b/apps/client/src/app/components/user-account-access/user-account-access.module.ts index c8d1cc578..93270ee3c 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.module.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.module.ts @@ -1,5 +1,5 @@ import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -17,7 +17,7 @@ import { UserAccountAccessComponent } from './user-account-access.component'; CommonModule, GfCreateOrUpdateAccessDialogModule, GfPortfolioAccessTableModule, - GfPremiumIndicatorModule, + GfPremiumIndicatorComponent, MatButtonModule, MatDialogModule, RouterModule diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts index b5f91a521..90646c09e 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.module.ts @@ -1,6 +1,6 @@ -import { GfMembershipCardModule } from '@ghostfolio/ui/membership-card'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -15,9 +15,9 @@ import { UserAccountMembershipComponent } from './user-account-membership.compon exports: [UserAccountMembershipComponent], imports: [ CommonModule, - GfMembershipCardModule, - GfPremiumIndicatorModule, - GfValueModule, + GfMembershipCardComponent, + GfPremiumIndicatorComponent, + GfValueComponent, MatButtonModule, MatCardModule, RouterModule diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts index 50d092a1e..89626a96c 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.module.ts @@ -1,4 +1,4 @@ -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -18,7 +18,7 @@ import { UserAccountSettingsComponent } from './user-account-settings.component' imports: [ CommonModule, FormsModule, - GfValueModule, + GfValueComponent, MatButtonModule, MatCardModule, MatFormFieldModule, diff --git a/apps/client/src/app/core/auth.guard.ts b/apps/client/src/app/core/auth.guard.ts index 52d1e14ab..ee5ed77cd 100644 --- a/apps/client/src/app/core/auth.guard.ts +++ b/apps/client/src/app/core/auth.guard.ts @@ -54,9 +54,10 @@ export class AuthGuard { this.router.navigate(['/' + $localize`register`]); resolve(false); } else if ( - AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) => - state.url.startsWith(publicPageRoute) - )?.length > 0 + AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) => { + const [, url] = state.url.split('/'); + return `/${url}` === publicPageRoute; + })?.length > 0 ) { resolve(true); return EMPTY; diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index 15a0d2e9f..5314c10f1 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -63,9 +63,11 @@ export class HttpResponseInterceptor implements HttpInterceptor { undefined, { duration: 6000 } ); - } else if (!error.url.endsWith('auth/anonymous')) { + } else if (!error.url.includes('/auth')) { this.snackBarRef = this.snackBar.open( - $localize`This feature requires a subscription.`, + this.hasPermissionForSubscription + ? $localize`This feature requires a subscription.` + : $localize`This action is not allowed.`, this.hasPermissionForSubscription ? $localize`Upgrade Plan` : undefined, diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.html b/apps/client/src/app/pages/about/overview/about-overview-page.html index 1a6b6c466..f196b95ba 100644 --- a/apps/client/src/app/pages/about/overview/about-overview-page.html +++ b/apps/client/src/app/pages/about/overview/about-overview-page.html @@ -77,7 +77,7 @@ mat-icon-button title="Follow Ghostfolio on X (formerly Twitter)" > - 𝕏 + { - const account: UpdateAccountDto = data?.account; - + .subscribe((account: UpdateAccountDto | null) => { if (account) { this.dataService .putAccount(account) @@ -233,6 +231,8 @@ export class AccountsPageComponent implements OnDestroy, OnInit { .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { + this.fetchAccounts(); + this.router.navigate(['.'], { relativeTo: this.route }); }); } @@ -256,9 +256,7 @@ export class AccountsPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data: any) => { - const account: CreateAccountDto = data?.account; - + .subscribe((account: CreateAccountDto | null) => { if (account) { this.dataService .postAccount(account) diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts index 4e3ef335e..91e0769fc 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts @@ -82,7 +82,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy { } public autoCompleteCheck() { - const inputValue = this.accountForm.controls['platformId'].value; + const inputValue = this.accountForm.get('platformId').value; if (typeof inputValue === 'string') { const matchingEntry = this.platforms.find(({ name }) => { @@ -90,7 +90,7 @@ export class CreateOrUpdateAccountDialog implements OnDestroy { }); if (matchingEntry) { - this.accountForm.controls['platformId'].setValue(matchingEntry); + this.accountForm.get('platformId').setValue(matchingEntry); } } } @@ -105,13 +105,13 @@ export class CreateOrUpdateAccountDialog implements OnDestroy { public async onSubmit() { const account: CreateAccountDto | UpdateAccountDto = { - balance: this.accountForm.controls['balance'].value, - comment: this.accountForm.controls['comment'].value, - currency: this.accountForm.controls['currency'].value?.value, - id: this.accountForm.controls['accountId'].value, - isExcluded: this.accountForm.controls['isExcluded'].value, - name: this.accountForm.controls['name'].value, - platformId: this.accountForm.controls['platformId'].value?.id ?? null + balance: this.accountForm.get('balance').value, + comment: this.accountForm.get('comment').value || null, + currency: this.accountForm.get('currency').value?.value, + id: this.accountForm.get('accountId').value, + isExcluded: this.accountForm.get('isExcluded').value, + name: this.accountForm.get('name').value, + platformId: this.accountForm.get('platformId').value?.id || null }; try { @@ -123,6 +123,8 @@ export class CreateOrUpdateAccountDialog implements OnDestroy { form: this.accountForm, object: account }); + + this.dialogRef.close(account as UpdateAccountDto); } else { delete (account as CreateAccountDto).id; @@ -131,9 +133,9 @@ export class CreateOrUpdateAccountDialog implements OnDestroy { form: this.accountForm, object: account }); - } - this.dialogRef.close({ account }); + this.dialogRef.close(account as CreateAccountDto); + } } catch (error) { console.error(error); } diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html index e2981462f..af97bfce3 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -39,7 +39,7 @@ (keydown.enter)="$event.stopPropagation()" /> {{ - accountForm.controls['currency']?.value?.value + accountForm.get('currency')?.value?.value }}
diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.module.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.module.ts index e2ea5d091..249715d61 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.module.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.module.ts @@ -1,5 +1,5 @@ import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfCurrencySelectorModule } from '@ghostfolio/ui/currency-selector/currency-selector.module'; +import { GfCurrencySelectorComponent } from '@ghostfolio/ui/currency-selector'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -19,7 +19,7 @@ import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog.c CommonModule, FormsModule, GfAssetProfileIconComponent, - GfCurrencySelectorModule, + GfCurrencySelectorComponent, MatAutocompleteModule, MatButtonModule, MatCheckboxModule, diff --git a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts index 60acd52b3..4547710cb 100644 --- a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts @@ -66,9 +66,9 @@ export class TransferBalanceDialog implements OnDestroy { public onSubmit() { const account: TransferBalanceDto = { - accountIdFrom: this.transferBalanceForm.controls['fromAccount'].value, - accountIdTo: this.transferBalanceForm.controls['toAccount'].value, - balance: this.transferBalanceForm.controls['balance'].value + accountIdFrom: this.transferBalanceForm.get('fromAccount').value, + accountIdTo: this.transferBalanceForm.get('toAccount').value, + balance: this.transferBalanceForm.get('balance').value }; this.dialogRef.close({ account }); diff --git a/apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts b/apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts index ab117d0a3..5820104d9 100644 --- a/apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts +++ b/apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts @@ -1,4 +1,4 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; @@ -6,7 +6,7 @@ import { RouterModule } from '@angular/router'; @Component({ host: { class: 'page' }, - imports: [GfPremiumIndicatorModule, MatButtonModule, RouterModule], + imports: [GfPremiumIndicatorComponent, MatButtonModule, RouterModule], selector: 'gf-black-friday-2022-page', standalone: true, templateUrl: './black-friday-2022-page.html' diff --git a/apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts b/apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts index 9f23f30ff..f0c88cfd4 100644 --- a/apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts +++ b/apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts @@ -1,4 +1,4 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; @@ -6,7 +6,7 @@ import { RouterModule } from '@angular/router'; @Component({ host: { class: 'page' }, - imports: [GfPremiumIndicatorModule, MatButtonModule, RouterModule], + imports: [GfPremiumIndicatorComponent, MatButtonModule, RouterModule], selector: 'gf-black-week-2023-page', standalone: true, templateUrl: './black-week-2023-page.html' diff --git a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html index 0272f535e..4445495fd 100644 --- a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html +++ b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html @@ -30,6 +30,9 @@ systems, including CasaOS, + Home Assistant, Runtipi, TrueCharts + + + How do I add a custom asset? + + +

+ If you want to track an asset that is not available from any data + provider, you can create a custom asset as follows. +

+
    +
  1. Go to the Admin Control panel
  2. +
  3. Go to the Market Data section
  4. +
  5. Create an asset profile
  6. +
  7. Select Add Manually and enter a unique symbol
  8. +
  9. Edit your asset profile
  10. +
  11. Add a new activity by searching for the symbol
  12. +
+
+
Which devices are supported? diff --git a/apps/client/src/app/pages/features/features-page.module.ts b/apps/client/src/app/pages/features/features-page.module.ts index ede263d94..fb5b00c14 100644 --- a/apps/client/src/app/pages/features/features-page.module.ts +++ b/apps/client/src/app/pages/features/features-page.module.ts @@ -1,4 +1,4 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -13,7 +13,7 @@ import { FeaturesPageComponent } from './features-page.component'; imports: [ CommonModule, FeaturesPageRoutingModule, - GfPremiumIndicatorModule, + GfPremiumIndicatorComponent, MatButtonModule, MatCardModule ], diff --git a/apps/client/src/app/pages/home/home-page-routing.module.ts b/apps/client/src/app/pages/home/home-page-routing.module.ts index bccfc2f57..f50b55192 100644 --- a/apps/client/src/app/pages/home/home-page-routing.module.ts +++ b/apps/client/src/app/pages/home/home-page-routing.module.ts @@ -22,6 +22,11 @@ const routes: Routes = [ component: HomeHoldingsComponent, title: $localize`Holdings` }, + { + path: 'holdings', + component: HomeHoldingsComponent, + title: $localize`Holdings` + }, { path: 'summary', component: HomeSummaryComponent, diff --git a/apps/client/src/app/pages/home/home-page.component.ts b/apps/client/src/app/pages/home/home-page.component.ts index 3a6a0cb26..8f8386473 100644 --- a/apps/client/src/app/pages/home/home-page.component.ts +++ b/apps/client/src/app/pages/home/home-page.component.ts @@ -1,7 +1,14 @@ +import { PositionDetailDialogParams } from '@ghostfolio/client/components/position-detail-dialog/interfaces/interfaces'; +import { PositionDetailDialog } from '@ghostfolio/client/components/position-detail-dialog/position-detail-dialog.component'; +import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { DataSource } from '@prisma/client'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -14,6 +21,7 @@ import { takeUntil } from 'rxjs/operators'; }) export class HomePageComponent implements OnDestroy, OnInit { public deviceType: string; + public hasImpersonationId: boolean; public tabs: TabConfiguration[] = []; public user: User; @@ -22,8 +30,27 @@ export class HomePageComponent implements OnDestroy, OnInit { public constructor( private changeDetectorRef: ChangeDetectorRef, private deviceService: DeviceDetectorService, + private dialog: MatDialog, + private impersonationStorageService: ImpersonationStorageService, + private route: ActivatedRoute, + private router: Router, private userService: UserService ) { + this.route.queryParams + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((params) => { + if ( + params['dataSource'] && + params['positionDetailDialog'] && + params['symbol'] + ) { + this.openPositionDialog({ + dataSource: params['dataSource'], + symbol: params['symbol'] + }); + } + }); + this.userService.stateChanged .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((state) => { @@ -59,10 +86,58 @@ export class HomePageComponent implements OnDestroy, OnInit { public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; + + this.impersonationStorageService + .onChangeHasImpersonation() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((impersonationId) => { + this.hasImpersonationId = !!impersonationId; + }); } public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } + + private openPositionDialog({ + dataSource, + symbol + }: { + dataSource: DataSource; + symbol: string; + }) { + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + + const dialogRef = this.dialog.open(PositionDetailDialog, { + autoFocus: false, + data: { + dataSource, + symbol, + baseCurrency: this.user?.settings?.baseCurrency, + colorScheme: this.user?.settings?.colorScheme, + deviceType: this.deviceType, + hasImpersonationId: this.hasImpersonationId, + hasPermissionToReportDataGlitch: hasPermission( + this.user?.permissions, + permissions.reportDataGlitch + ), + locale: this.user?.settings?.locale + }, + height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); + + dialogRef + .afterClosed() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.router.navigate(['.'], { relativeTo: this.route }); + }); + }); + } } diff --git a/apps/client/src/app/pages/landing/landing-page.html b/apps/client/src/app/pages/landing/landing-page.html index 579b35702..331defae4 100644 --- a/apps/client/src/app/pages/landing/landing-page.html +++ b/apps/client/src/app/pages/landing/landing-page.html @@ -2,12 +2,6 @@
-

Manage your wealth like a boss

diff --git a/apps/client/src/app/pages/landing/landing-page.module.ts b/apps/client/src/app/pages/landing/landing-page.module.ts index ef1d3d0ac..ca39e6023 100644 --- a/apps/client/src/app/pages/landing/landing-page.module.ts +++ b/apps/client/src/app/pages/landing/landing-page.module.ts @@ -1,7 +1,7 @@ import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; -import { GfCarouselModule } from '@ghostfolio/ui/carousel'; -import { GfLogoModule } from '@ghostfolio/ui/logo'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfCarouselComponent } from '@ghostfolio/ui/carousel'; +import { GfLogoComponent } from '@ghostfolio/ui/logo'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -16,9 +16,9 @@ import { LandingPageComponent } from './landing-page.component'; declarations: [LandingPageComponent], imports: [ CommonModule, - GfCarouselModule, - GfLogoModule, - GfValueModule, + GfCarouselComponent, + GfLogoComponent, + GfValueComponent, GfWorldMapChartModule, LandingPageRoutingModule, MatButtonModule, diff --git a/apps/client/src/app/pages/open/open-page.module.ts b/apps/client/src/app/pages/open/open-page.module.ts index ba8a94831..ab48f2d4a 100644 --- a/apps/client/src/app/pages/open/open-page.module.ts +++ b/apps/client/src/app/pages/open/open-page.module.ts @@ -1,4 +1,4 @@ -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -9,7 +9,12 @@ import { OpenPageComponent } from './open-page.component'; @NgModule({ declarations: [OpenPageComponent], - imports: [CommonModule, GfValueModule, MatCardModule, OpenPageRoutingModule], + imports: [ + CommonModule, + GfValueComponent, + MatCardModule, + OpenPageRoutingModule + ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class OpenPageModule {} diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index 3e45ec037..f75bc260b 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -1,8 +1,8 @@ import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto'; -import { PositionDetailDialogParams } from '@ghostfolio/client/components/position/position-detail-dialog/interfaces/interfaces'; -import { PositionDetailDialog } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.component'; +import { PositionDetailDialogParams } from '@ghostfolio/client/components/position-detail-dialog/interfaces/interfaces'; +import { PositionDetailDialog } from '@ghostfolio/client/components/position-detail-dialog/position-detail-dialog.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { IcsService } from '@ghostfolio/client/services/ics/ics.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -29,6 +29,7 @@ import { ImportActivitiesDialog } from './import-activities-dialog/import-activi import { ImportActivitiesDialogParams } from './import-activities-dialog/interfaces/interfaces'; @Component({ + host: { class: 'has-fab' }, selector: 'gf-activities-page', styleUrls: ['./activities-page.scss'], templateUrl: './activities-page.html' @@ -124,9 +125,6 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { this.dataService .fetchActivities({ filters: this.userService.getFilters(), - range: this.user?.settings?.isExperimentalFeatures - ? this.user?.settings?.dateRange - : undefined, skip: this.pageIndex * this.pageSize, sortColumn: this.sortColumn, sortDirection: this.sortDirection, @@ -290,9 +288,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data: any) => { - const transaction: UpdateOrderDto = data?.activity; - + .subscribe((transaction: UpdateOrderDto | null) => { if (transaction) { this.dataService .putOrder(transaction) @@ -341,9 +337,7 @@ export class ActivitiesPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((data: any) => { - const transaction: CreateOrderDto = data?.activity; - + .subscribe((transaction: CreateOrderDto | null) => { if (transaction) { this.dataService.postOrder(transaction).subscribe({ next: () => { diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts index c7c14b623..c964022be 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.module.ts @@ -1,5 +1,5 @@ import { ImportActivitiesService } from '@ghostfolio/client/services/import-activities.service'; -import { GfActivitiesTableModule } from '@ghostfolio/ui/activities-table/activities-table.module'; +import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -17,7 +17,7 @@ import { GfImportActivitiesDialogModule } from './import-activities-dialog/impor imports: [ ActivitiesPageRoutingModule, CommonModule, - GfActivitiesTableModule, + GfActivitiesTableComponent, GfCreateOrUpdateActivityDialogModule, GfImportActivitiesDialogModule, MatButtonModule, diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts index 1196de58c..f49860028 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts @@ -148,13 +148,14 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { .subscribe(async () => { let exchangeRateOfUnitPrice = 1; - this.activityForm.controls['feeInCustomCurrency'].setErrors(null); - this.activityForm.controls['unitPriceInCustomCurrency'].setErrors(null); + this.activityForm.get('feeInCustomCurrency').setErrors(null); + this.activityForm.get('unitPriceInCustomCurrency').setErrors(null); - const currency = this.activityForm.controls['currency'].value; - const currencyOfUnitPrice = - this.activityForm.controls['currencyOfUnitPrice'].value; - const date = this.activityForm.controls['date'].value; + const currency = this.activityForm.get('currency').value; + const currencyOfUnitPrice = this.activityForm.get( + 'currencyOfUnitPrice' + ).value; + const date = this.activityForm.get('date').value; if ( currency && @@ -174,104 +175,97 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { exchangeRateOfUnitPrice = marketPrice; } catch { - this.activityForm.controls['unitPriceInCustomCurrency'].setErrors({ + this.activityForm.get('unitPriceInCustomCurrency').setErrors({ invalid: true }); } } const feeInCustomCurrency = - this.activityForm.controls['feeInCustomCurrency'].value * + this.activityForm.get('feeInCustomCurrency').value * exchangeRateOfUnitPrice; const unitPriceInCustomCurrency = - this.activityForm.controls['unitPriceInCustomCurrency'].value * + this.activityForm.get('unitPriceInCustomCurrency').value * exchangeRateOfUnitPrice; - this.activityForm.controls['fee'].setValue(feeInCustomCurrency, { + this.activityForm.get('fee').setValue(feeInCustomCurrency, { emitEvent: false }); - this.activityForm.controls['unitPrice'].setValue( - unitPriceInCustomCurrency, - { - emitEvent: false - } - ); + this.activityForm.get('unitPrice').setValue(unitPriceInCustomCurrency, { + emitEvent: false + }); if ( - this.activityForm.controls['type'].value === 'BUY' || - this.activityForm.controls['type'].value === 'FEE' || - this.activityForm.controls['type'].value === 'ITEM' + this.activityForm.get('type').value === 'BUY' || + this.activityForm.get('type').value === 'FEE' || + this.activityForm.get('type').value === 'ITEM' ) { this.total = - this.activityForm.controls['quantity'].value * - this.activityForm.controls['unitPrice'].value + - this.activityForm.controls['fee'].value ?? 0; + this.activityForm.get('quantity').value * + this.activityForm.get('unitPrice').value + + this.activityForm.get('fee').value ?? 0; } else { this.total = - this.activityForm.controls['quantity'].value * - this.activityForm.controls['unitPrice'].value - - this.activityForm.controls['fee'].value ?? 0; + this.activityForm.get('quantity').value * + this.activityForm.get('unitPrice').value - + this.activityForm.get('fee').value ?? 0; } this.changeDetectorRef.markForCheck(); }); - this.activityForm.controls['accountId'].valueChanges.subscribe( - (accountId) => { - const type = this.activityForm.controls['type'].value; + this.activityForm.get('accountId').valueChanges.subscribe((accountId) => { + const type = this.activityForm.get('type').value; - if ( - type === 'FEE' || - type === 'INTEREST' || - type === 'ITEM' || - type === 'LIABILITY' - ) { - const currency = - this.data.accounts.find(({ id }) => { - return id === accountId; - })?.currency ?? this.data.user.settings.baseCurrency; + if ( + type === 'FEE' || + type === 'INTEREST' || + type === 'ITEM' || + type === 'LIABILITY' + ) { + const currency = + this.data.accounts.find(({ id }) => { + return id === accountId; + })?.currency ?? this.data.user.settings.baseCurrency; - this.activityForm.controls['currency'].setValue(currency); - this.activityForm.controls['currencyOfUnitPrice'].setValue(currency); - - if (['FEE', 'INTEREST'].includes(type)) { - if (this.activityForm.controls['accountId'].value) { - this.activityForm.controls['updateAccountBalance'].enable(); - } else { - this.activityForm.controls['updateAccountBalance'].disable(); - this.activityForm.controls['updateAccountBalance'].setValue( - false - ); - } + this.activityForm.get('currency').setValue(currency); + this.activityForm.get('currencyOfUnitPrice').setValue(currency); + + if (['FEE', 'INTEREST'].includes(type)) { + if (this.activityForm.get('accountId').value) { + this.activityForm.get('updateAccountBalance').enable(); + } else { + this.activityForm.get('updateAccountBalance').disable(); + this.activityForm.get('updateAccountBalance').setValue(false); } } } - ); + }); - this.activityForm.controls['date'].valueChanges.subscribe(() => { - if (isToday(this.activityForm.controls['date'].value)) { - this.activityForm.controls['updateAccountBalance'].enable(); + this.activityForm.get('date').valueChanges.subscribe(() => { + if (isToday(this.activityForm.get('date').value)) { + this.activityForm.get('updateAccountBalance').enable(); } else { - this.activityForm.controls['updateAccountBalance'].disable(); - this.activityForm.controls['updateAccountBalance'].setValue(false); + this.activityForm.get('updateAccountBalance').disable(); + this.activityForm.get('updateAccountBalance').setValue(false); } this.changeDetectorRef.markForCheck(); }); - this.activityForm.controls['searchSymbol'].valueChanges.subscribe(() => { - if (this.activityForm.controls['searchSymbol'].invalid) { + this.activityForm.get('searchSymbol').valueChanges.subscribe(() => { + if (this.activityForm.get('searchSymbol').invalid) { this.data.activity.SymbolProfile = null; } else if ( ['BUY', 'DIVIDEND', 'SELL'].includes( - this.activityForm.controls['type'].value + this.activityForm.get('type').value ) ) { - this.activityForm.controls['dataSource'].setValue( - this.activityForm.controls['searchSymbol'].value.dataSource - ); + this.activityForm + .get('dataSource') + .setValue(this.activityForm.get('searchSymbol').value.dataSource); this.updateSymbol(); } @@ -282,130 +276,127 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.filteredTagsObservable = this.activityForm.controls[ 'tags' ].valueChanges.pipe( - startWith(this.activityForm.controls['tags'].value), + startWith(this.activityForm.get('tags').value), map((aTags: Tag[] | null) => { return aTags ? this.filterTags(aTags) : this.tags.slice(); }) ); - this.activityForm.controls['type'].valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + this.activityForm + .get('type') + .valueChanges.pipe(takeUntil(this.unsubscribeSubject)) .subscribe((type: Type) => { if (type === 'ITEM') { - this.activityForm.controls['accountId'].removeValidators( - Validators.required - ); - this.activityForm.controls['accountId'].updateValueAndValidity(); + this.activityForm + .get('accountId') + .removeValidators(Validators.required); + this.activityForm.get('accountId').updateValueAndValidity(); const currency = this.data.accounts.find(({ id }) => { - return id === this.activityForm.controls['accountId'].value; + return id === this.activityForm.get('accountId').value; })?.currency ?? this.data.user.settings.baseCurrency; - this.activityForm.controls['currency'].setValue(currency); - this.activityForm.controls['currencyOfUnitPrice'].setValue(currency); - - this.activityForm.controls['dataSource'].removeValidators( - Validators.required - ); - this.activityForm.controls['dataSource'].updateValueAndValidity(); - this.activityForm.controls['feeInCustomCurrency'].reset(); - this.activityForm.controls['name'].setValidators(Validators.required); - this.activityForm.controls['name'].updateValueAndValidity(); - this.activityForm.controls['quantity'].setValue(1); - this.activityForm.controls['searchSymbol'].removeValidators( - Validators.required - ); - this.activityForm.controls['searchSymbol'].updateValueAndValidity(); - this.activityForm.controls['updateAccountBalance'].disable(); - this.activityForm.controls['updateAccountBalance'].setValue(false); + this.activityForm.get('currency').setValue(currency); + this.activityForm.get('currencyOfUnitPrice').setValue(currency); + + this.activityForm + .get('dataSource') + .removeValidators(Validators.required); + this.activityForm.get('dataSource').updateValueAndValidity(); + this.activityForm.get('feeInCustomCurrency').reset(); + this.activityForm.get('name').setValidators(Validators.required); + this.activityForm.get('name').updateValueAndValidity(); + this.activityForm.get('quantity').setValue(1); + this.activityForm + .get('searchSymbol') + .removeValidators(Validators.required); + this.activityForm.get('searchSymbol').updateValueAndValidity(); + this.activityForm.get('updateAccountBalance').disable(); + this.activityForm.get('updateAccountBalance').setValue(false); } else if ( type === 'FEE' || type === 'INTEREST' || type === 'LIABILITY' ) { - this.activityForm.controls['accountId'].removeValidators( - Validators.required - ); - this.activityForm.controls['accountId'].updateValueAndValidity(); + this.activityForm + .get('accountId') + .removeValidators(Validators.required); + this.activityForm.get('accountId').updateValueAndValidity(); const currency = this.data.accounts.find(({ id }) => { - return id === this.activityForm.controls['accountId'].value; + return id === this.activityForm.get('accountId').value; })?.currency ?? this.data.user.settings.baseCurrency; - this.activityForm.controls['currency'].setValue(currency); - this.activityForm.controls['currencyOfUnitPrice'].setValue(currency); + this.activityForm.get('currency').setValue(currency); + this.activityForm.get('currencyOfUnitPrice').setValue(currency); - this.activityForm.controls['dataSource'].removeValidators( - Validators.required - ); - this.activityForm.controls['dataSource'].updateValueAndValidity(); + this.activityForm + .get('dataSource') + .removeValidators(Validators.required); + this.activityForm.get('dataSource').updateValueAndValidity(); if ( (type === 'FEE' && - this.activityForm.controls['feeInCustomCurrency'].value === 0) || + this.activityForm.get('feeInCustomCurrency').value === 0) || type === 'INTEREST' || type === 'LIABILITY' ) { - this.activityForm.controls['feeInCustomCurrency'].reset(); + this.activityForm.get('feeInCustomCurrency').reset(); } - this.activityForm.controls['name'].setValidators(Validators.required); - this.activityForm.controls['name'].updateValueAndValidity(); + this.activityForm.get('name').setValidators(Validators.required); + this.activityForm.get('name').updateValueAndValidity(); if (type === 'FEE') { - this.activityForm.controls['quantity'].setValue(0); + this.activityForm.get('quantity').setValue(0); } else if (type === 'INTEREST' || type === 'LIABILITY') { - this.activityForm.controls['quantity'].setValue(1); + this.activityForm.get('quantity').setValue(1); } - this.activityForm.controls['searchSymbol'].removeValidators( - Validators.required - ); - this.activityForm.controls['searchSymbol'].updateValueAndValidity(); + this.activityForm + .get('searchSymbol') + .removeValidators(Validators.required); + this.activityForm.get('searchSymbol').updateValueAndValidity(); if (type === 'FEE') { - this.activityForm.controls['unitPriceInCustomCurrency'].setValue(0); + this.activityForm.get('unitPriceInCustomCurrency').setValue(0); } if ( ['FEE', 'INTEREST'].includes(type) && - this.activityForm.controls['accountId'].value + this.activityForm.get('accountId').value ) { - this.activityForm.controls['updateAccountBalance'].enable(); + this.activityForm.get('updateAccountBalance').enable(); } else { - this.activityForm.controls['updateAccountBalance'].disable(); - this.activityForm.controls['updateAccountBalance'].setValue(false); + this.activityForm.get('updateAccountBalance').disable(); + this.activityForm.get('updateAccountBalance').setValue(false); } } else { - this.activityForm.controls['accountId'].setValidators( - Validators.required - ); - this.activityForm.controls['accountId'].updateValueAndValidity(); - this.activityForm.controls['dataSource'].setValidators( - Validators.required - ); - this.activityForm.controls['dataSource'].updateValueAndValidity(); - this.activityForm.controls['name'].removeValidators( - Validators.required - ); - this.activityForm.controls['name'].updateValueAndValidity(); - this.activityForm.controls['searchSymbol'].setValidators( - Validators.required - ); - this.activityForm.controls['searchSymbol'].updateValueAndValidity(); - this.activityForm.controls['updateAccountBalance'].enable(); + this.activityForm.get('accountId').setValidators(Validators.required); + this.activityForm.get('accountId').updateValueAndValidity(); + this.activityForm + .get('dataSource') + .setValidators(Validators.required); + this.activityForm.get('dataSource').updateValueAndValidity(); + this.activityForm.get('name').removeValidators(Validators.required); + this.activityForm.get('name').updateValueAndValidity(); + this.activityForm + .get('searchSymbol') + .setValidators(Validators.required); + this.activityForm.get('searchSymbol').updateValueAndValidity(); + this.activityForm.get('updateAccountBalance').enable(); } this.changeDetectorRef.markForCheck(); }); - this.activityForm.controls['type'].setValue(this.data.activity?.type); + this.activityForm.get('type').setValue(this.data.activity?.type); if (this.data.activity?.id) { - this.activityForm.controls['searchSymbol'].disable(); - this.activityForm.controls['type'].disable(); + this.activityForm.get('searchSymbol').disable(); + this.activityForm.get('type').disable(); } if (this.data.activity?.SymbolProfile?.symbol) { @@ -425,14 +416,14 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { public applyCurrentMarketPrice() { this.activityForm.patchValue({ - currencyOfUnitPrice: this.activityForm.controls['currency'].value, + currencyOfUnitPrice: this.activityForm.get('currency').value, unitPriceInCustomCurrency: this.currentMarketPrice }); } public onAddTag(event: MatAutocompleteSelectedEvent) { - this.activityForm.controls['tags'].setValue([ - ...(this.activityForm.controls['tags'].value ?? []), + this.activityForm.get('tags').setValue([ + ...(this.activityForm.get('tags').value ?? []), this.tags.find(({ id }) => { return id === event.option.value; }) @@ -445,8 +436,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { } public onRemoveTag(aTag: Tag) { - this.activityForm.controls['tags'].setValue( - this.activityForm.controls['tags'].value.filter(({ id }) => { + this.activityForm.get('tags').setValue( + this.activityForm.get('tags').value.filter(({ id }) => { return id !== aTag.id; }) ); @@ -454,25 +445,24 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { public async onSubmit() { const activity: CreateOrderDto | UpdateOrderDto = { - accountId: this.activityForm.controls['accountId'].value, - assetClass: this.activityForm.controls['assetClass'].value, - assetSubClass: this.activityForm.controls['assetSubClass'].value, - comment: this.activityForm.controls['comment'].value, - currency: this.activityForm.controls['currency'].value, - customCurrency: this.activityForm.controls['currencyOfUnitPrice'].value, - date: this.activityForm.controls['date'].value, - dataSource: this.activityForm.controls['dataSource'].value, - fee: this.activityForm.controls['fee'].value, - quantity: this.activityForm.controls['quantity'].value, + accountId: this.activityForm.get('accountId').value, + assetClass: this.activityForm.get('assetClass').value, + assetSubClass: this.activityForm.get('assetSubClass').value, + comment: this.activityForm.get('comment').value || null, + currency: this.activityForm.get('currency').value, + customCurrency: this.activityForm.get('currencyOfUnitPrice').value, + date: this.activityForm.get('date').value, + dataSource: this.activityForm.get('dataSource').value, + fee: this.activityForm.get('fee').value, + quantity: this.activityForm.get('quantity').value, symbol: - this.activityForm.controls['searchSymbol'].value?.symbol === - undefined || - isUUID(this.activityForm.controls['searchSymbol'].value?.symbol) - ? this.activityForm.controls['name'].value - : this.activityForm.controls['searchSymbol'].value.symbol, - tags: this.activityForm.controls['tags'].value, - type: this.activityForm.controls['type'].value, - unitPrice: this.activityForm.controls['unitPrice'].value + this.activityForm.get('searchSymbol').value?.symbol === undefined || + isUUID(this.activityForm.get('searchSymbol').value?.symbol) + ? this.activityForm.get('name').value + : this.activityForm.get('searchSymbol').value.symbol, + tags: this.activityForm.get('tags').value, + type: this.activityForm.get('type').value, + unitPrice: this.activityForm.get('unitPrice').value }; try { @@ -485,9 +475,11 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { ignoreFields: ['dataSource', 'date'], object: activity as UpdateOrderDto }); + + this.dialogRef.close(activity as UpdateOrderDto); } else { (activity as CreateOrderDto).updateAccountBalance = - this.activityForm.controls['updateAccountBalance'].value; + this.activityForm.get('updateAccountBalance').value; await validateObjectForForm({ classDto: CreateOrderDto, @@ -495,9 +487,9 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { ignoreFields: ['dataSource', 'date'], object: activity }); - } - this.dialogRef.close({ activity }); + this.dialogRef.close(activity as CreateOrderDto); + } } catch (error) { console.error(error); } @@ -524,8 +516,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.dataService .fetchSymbolItem({ - dataSource: this.activityForm.controls['dataSource'].value, - symbol: this.activityForm.controls['searchSymbol'].value.symbol + dataSource: this.activityForm.get('dataSource').value, + symbol: this.activityForm.get('searchSymbol').value.symbol }) .pipe( catchError(() => { @@ -540,9 +532,9 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(({ currency, dataSource, marketPrice }) => { - this.activityForm.controls['currency'].setValue(currency); - this.activityForm.controls['currencyOfUnitPrice'].setValue(currency); - this.activityForm.controls['dataSource'].setValue(dataSource); + this.activityForm.get('currency').setValue(currency); + this.activityForm.get('currencyOfUnitPrice').setValue(currency); + this.activityForm.get('dataSource').setValue(dataSource); this.currentMarketPrice = marketPrice; diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html index 79ea7647a..65ba637db 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -12,7 +12,7 @@ Type {{ - typesTranslationMap[activityForm.controls['type'].value] + typesTranslationMap[activityForm.get('type').value] }} @@ -113,9 +111,9 @@
@@ -129,9 +127,7 @@
@@ -173,10 +169,10 @@ class="mb-3" [ngClass]="{ 'd-none': - activityForm.controls['type']?.value === 'FEE' || - activityForm.controls['type']?.value === 'INTEREST' || - activityForm.controls['type']?.value === 'ITEM' || - activityForm.controls['type']?.value === 'LIABILITY' + activityForm.get('type')?.value === 'FEE' || + activityForm.get('type')?.value === 'INTEREST' || + activityForm.get('type')?.value === 'ITEM' || + activityForm.get('type')?.value === 'LIABILITY' }" > @@ -186,12 +182,12 @@
+ > Dividend @@ -211,7 +207,7 @@
Oops! Could not get the historical exchange rate from {{ - activityForm.controls['date']?.value | date: defaultDateFormat + activityForm.get('date')?.value | date: defaultDateFormat }} @@ -241,7 +235,7 @@ *ngIf=" currentMarketPrice && (data.activity.type === 'BUY' || data.activity.type === 'SELL') && - isToday(activityForm.controls['date']?.value) + isToday(activityForm.get('date')?.value) " class="ml-2 mt-1 no-min-width" mat-button @@ -256,7 +250,7 @@
+ > Dividend @@ -269,7 +263,7 @@ {{ - activityForm.controls['currency'].value + activityForm.get('currency').value }}
@@ -277,9 +271,9 @@ class="mb-3" [ngClass]="{ 'd-none': - activityForm.controls['type']?.value === 'INTEREST' || - activityForm.controls['type']?.value === 'ITEM' || - activityForm.controls['type']?.value === 'LIABILITY' + activityForm.get('type')?.value === 'INTEREST' || + activityForm.get('type')?.value === 'ITEM' || + activityForm.get('type')?.value === 'LIABILITY' }" > @@ -288,19 +282,17 @@
- {{ activityForm.controls['currencyOfUnitPrice'].value }} + {{ activityForm.get('currencyOfUnitPrice').value }}
Oops! Could not get the historical exchange rate from {{ - activityForm.controls['date']?.value | date: defaultDateFormat + activityForm.get('date')?.value | date: defaultDateFormat }}
@@ -310,7 +302,7 @@ Fee {{ - activityForm.controls['currency'].value + activityForm.get('currency').value }}
@@ -328,7 +320,7 @@
Asset Class @@ -344,7 +336,7 @@
Asset Sub Class @@ -363,7 +355,7 @@ Tags diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts index 0d258f1ca..a4d28d0e0 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts @@ -1,6 +1,6 @@ import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfSymbolAutocompleteModule } from '@ghostfolio/ui/symbol-autocomplete/symbol-autocomplete.module'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -23,8 +23,8 @@ import { CreateOrUpdateActivityDialog } from './create-or-update-activity-dialog CommonModule, FormsModule, GfAssetProfileIconComponent, - GfSymbolAutocompleteModule, - GfValueModule, + GfSymbolAutocompleteComponent, + GfValueComponent, MatAutocompleteModule, MatButtonModule, MatCheckboxModule, diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts index c8d369f54..b59994811 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2,7 +2,7 @@ import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImportActivitiesService } from '@ghostfolio/client/services/import-activities.service'; -import { Position } from '@ghostfolio/common/interfaces'; +import { PortfolioPosition } from '@ghostfolio/common/interfaces'; import { StepperOrientation, @@ -43,7 +43,7 @@ export class ImportActivitiesDialog implements OnDestroy { public deviceType: string; public dialogTitle = $localize`Import Activities`; public errorMessages: string[] = []; - public holdings: Position[] = []; + public holdings: PortfolioPosition[] = []; public importStep: ImportStep = ImportStep.UPLOAD_FILE; public isLoading = false; public maxSafeInteger = Number.MAX_SAFE_INTEGER; @@ -85,10 +85,10 @@ export class ImportActivitiesDialog implements OnDestroy { this.dialogTitle = $localize`Import Dividends`; this.mode = 'DIVIDEND'; - this.uniqueAssetForm.controls['uniqueAsset'].disable(); + this.uniqueAssetForm.get('uniqueAsset').disable(); this.dataService - .fetchPositions({ + .fetchPortfolioHoldings({ filters: [ { id: AssetClass.EQUITY, @@ -98,11 +98,11 @@ export class ImportActivitiesDialog implements OnDestroy { range: 'max' }) .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ positions }) => { - this.holdings = sortBy(positions, ({ name }) => { + .subscribe(({ holdings }) => { + this.holdings = sortBy(holdings, ({ name }) => { return name.toLowerCase(); }); - this.uniqueAssetForm.controls['uniqueAsset'].enable(); + this.uniqueAssetForm.get('uniqueAsset').enable(); this.isLoading = false; @@ -167,10 +167,10 @@ export class ImportActivitiesDialog implements OnDestroy { } public onLoadDividends(aStepper: MatStepper) { - this.uniqueAssetForm.controls['uniqueAsset'].disable(); + this.uniqueAssetForm.get('uniqueAsset').disable(); const { dataSource, symbol } = - this.uniqueAssetForm.controls['uniqueAsset'].value; + this.uniqueAssetForm.get('uniqueAsset').value; this.dataService .fetchDividendsImport({ @@ -193,7 +193,7 @@ export class ImportActivitiesDialog implements OnDestroy { this.details = []; this.errorMessages = []; this.importStep = ImportStep.SELECT_ACTIVITIES; - this.uniqueAssetForm.controls['uniqueAsset'].enable(); + this.uniqueAssetForm.get('uniqueAsset').enable(); aStepper.reset(); } diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html index 032480acf..3e0a00e93 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -33,7 +33,7 @@ Holding {{ - uniqueAssetForm.controls['uniqueAsset']?.value?.name + uniqueAssetForm.get('uniqueAsset')?.value?.name }} { if (params['accountId'] && params['accountDetailDialog']) { @@ -348,8 +348,8 @@ export class AllocationsPageComponent implements OnDestroy, OnInit { name: position.name }; - if (position.assetClass !== AssetClass.CASH) { - // Prepare analysis data by continents, countries and sectors except for cash + if (position.assetClass !== AssetClass.LIQUIDITY) { + // Prepare analysis data by continents, countries and sectors except for liquidity if (position.countries.length > 0) { this.markets.developedMarkets.value += diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts index b0a027cb5..0f500ab35 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.module.ts @@ -1,7 +1,7 @@ import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; -import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -17,10 +17,10 @@ import { AllocationsPageComponent } from './allocations-page.component'; imports: [ AllocationsPageRoutingModule, CommonModule, - GfPortfolioProportionChartModule, - GfPremiumIndicatorModule, + GfPortfolioProportionChartComponent, + GfPremiumIndicatorComponent, GfWorldMapChartModule, - GfValueModule, + GfValueComponent, MatCardModule, MatDialogModule, MatProgressBarModule diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 184297b26..93dfb6517 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -1,5 +1,5 @@ -import { PositionDetailDialogParams } from '@ghostfolio/client/components/position/position-detail-dialog/interfaces/interfaces'; -import { PositionDetailDialog } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.component'; +import { PositionDetailDialogParams } from '@ghostfolio/client/components/position-detail-dialog/interfaces/interfaces'; +import { PositionDetailDialog } from '@ghostfolio/client/components/position-detail-dialog/position-detail-dialog.component'; import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -8,7 +8,7 @@ import { HistoricalDataItem, PortfolioInvestments, PortfolioPerformance, - Position, + PortfolioPosition, User } from '@ghostfolio/common/interfaces'; import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; @@ -35,7 +35,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { public benchmark: Partial; public benchmarkDataItems: HistoricalDataItem[] = []; public benchmarks: Partial[]; - public bottom3: Position[]; + public bottom3: PortfolioPosition[]; public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public daysInMarket: number; public deviceType: string; @@ -60,7 +60,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { public performanceDataItemsInPercentage: HistoricalDataItem[]; public portfolioEvolutionDataLabel = $localize`Investment`; public streaks: PortfolioInvestments['streaks']; - public top3: Position[]; + public top3: PortfolioPosition[]; public unitCurrentStreak: string; public unitLongestStreak: string; public user: User; @@ -80,7 +80,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { const { benchmarks } = this.dataService.fetchInfo(); this.benchmarks = benchmarks; - route.queryParams + this.route.queryParams .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((params) => { if ( @@ -308,23 +308,23 @@ export class AnalysisPageComponent implements OnDestroy, OnInit { }); this.dataService - .fetchPositions({ + .fetchPortfolioHoldings({ filters: this.userService.getFilters(), range: this.user?.settings?.dateRange }) .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ positions }) => { - const positionsSorted = sortBy( - positions.filter(({ netPerformancePercentageWithCurrencyEffect }) => { - return isNumber(netPerformancePercentageWithCurrencyEffect); + .subscribe(({ holdings }) => { + const holdingsSorted = sortBy( + holdings.filter(({ netPerformancePercentWithCurrencyEffect }) => { + return isNumber(netPerformancePercentWithCurrencyEffect); }), - 'netPerformancePercentageWithCurrencyEffect' + 'netPerformancePercentWithCurrencyEffect' ).reverse(); - this.top3 = positionsSorted.slice(0, 3); + this.top3 = holdingsSorted.slice(0, 3); - if (positions?.length > 3) { - this.bottom3 = positionsSorted.slice(-3).reverse(); + if (holdings?.length > 3) { + this.bottom3 = holdingsSorted.slice(-3).reverse(); } else { this.bottom3 = []; } diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 5f6acdbe2..90cf8bc06 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -42,7 +42,7 @@ [value]=" isLoadingInvestmentChart ? undefined - : performance?.currentNetPerformance + : performance?.netPerformance " />
@@ -61,7 +61,7 @@ [value]=" isLoadingInvestmentChart ? undefined - : performance?.currentNetPerformancePercent + : performance?.netPerformancePercentage " />
@@ -86,10 +86,10 @@ [value]=" isLoadingInvestmentChart ? undefined - : performance?.currentNetPerformance === null + : performance?.netPerformance === null ? null - : performance?.currentNetPerformanceWithCurrencyEffect - - performance?.currentNetPerformance + : performance?.netPerformanceWithCurrencyEffect - + performance?.netPerformance " />
@@ -108,10 +108,10 @@ [value]=" isLoadingInvestmentChart ? undefined - : performance?.currentNetPerformancePercent === null + : performance?.netPerformancePercentage === null ? null - : performance?.currentNetPerformancePercentWithCurrencyEffect - - performance?.currentNetPerformancePercent + : performance?.netPerformancePercentageWithCurrencyEffect - + performance?.netPerformancePercentage " />
@@ -131,7 +131,7 @@ [value]=" isLoadingInvestmentChart ? undefined - : performance?.currentNetPerformanceWithCurrencyEffect + : performance?.netPerformanceWithCurrencyEffect " />
@@ -150,7 +150,7 @@ [value]=" isLoadingInvestmentChart ? undefined - : performance?.currentNetPerformancePercentWithCurrencyEffect + : performance?.netPerformancePercentageWithCurrencyEffect " />
@@ -170,17 +170,17 @@
    -
  1. +
  2. -
    {{ position.name }}
    +
    {{ holding.name }}
    @@ -218,17 +216,17 @@
      -
    1. +
    2. -
      {{ position.name }}
      +
      {{ holding.name }}
      diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts index 52e45c330..b33905456 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.module.ts @@ -1,9 +1,9 @@ import { GfBenchmarkComparatorModule } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.module'; import { GfInvestmentChartModule } from '@ghostfolio/client/components/investment-chart/investment-chart.module'; import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; -import { GfActivitiesFilterModule } from '@ghostfolio/ui/activities-filter/activities-filter.module'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfActivitiesFilterComponent } from '@ghostfolio/ui/activities-filter'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -18,12 +18,12 @@ import { AnalysisPageComponent } from './analysis-page.component'; imports: [ AnalysisPageRoutingModule, CommonModule, - GfActivitiesFilterModule, + GfActivitiesFilterComponent, GfBenchmarkComparatorModule, GfInvestmentChartModule, - GfPremiumIndicatorModule, + GfPremiumIndicatorComponent, GfToggleModule, - GfValueModule, + GfValueComponent, MatCardModule, NgxSkeletonLoaderModule ], diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts index 90b6f204f..60e3127d9 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.module.ts @@ -1,7 +1,7 @@ import { GfRulesModule } from '@ghostfolio/client/components/rules/rules.module'; -import { GfFireCalculatorModule } from '@ghostfolio/ui/fire-calculator'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfFireCalculatorComponent } from '@ghostfolio/ui/fire-calculator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -15,10 +15,10 @@ import { FirePageComponent } from './fire-page.component'; imports: [ CommonModule, FirePageRoutingModule, - GfFireCalculatorModule, - GfPremiumIndicatorModule, + GfFireCalculatorComponent, + GfPremiumIndicatorComponent, GfRulesModule, - GfValueModule, + GfValueComponent, NgxSkeletonLoaderModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA] diff --git a/apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts b/apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts deleted file mode 100644 index 94b49a9d0..000000000 --- a/apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; - -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -import { HoldingsPageComponent } from './holdings-page.component'; - -const routes: Routes = [ - { - canActivate: [AuthGuard], - component: HoldingsPageComponent, - path: '', - title: $localize`Holdings` - } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class HoldingsPageRoutingModule {} diff --git a/apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts b/apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts deleted file mode 100644 index 8834593e1..000000000 --- a/apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { PositionDetailDialogParams } from '@ghostfolio/client/components/position/position-detail-dialog/interfaces/interfaces'; -import { PositionDetailDialog } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.component'; -import { DataService } from '@ghostfolio/client/services/data.service'; -import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; -import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { PortfolioPosition, User } from '@ghostfolio/common/interfaces'; -import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { HoldingType, ToggleOption } from '@ghostfolio/common/types'; - -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { ActivatedRoute, Router } from '@angular/router'; -import { DataSource } from '@prisma/client'; -import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; - -@Component({ - selector: 'gf-holdings-page', - styleUrls: ['./holdings-page.scss'], - templateUrl: './holdings-page.html' -}) -export class HoldingsPageComponent implements OnDestroy, OnInit { - public deviceType: string; - public hasImpersonationId: boolean; - public hasPermissionToCreateOrder: boolean; - public holdings: PortfolioPosition[]; - public holdingType: HoldingType = 'ACTIVE'; - public holdingTypeOptions: ToggleOption[] = [ - { label: $localize`Active`, value: 'ACTIVE' }, - { label: $localize`Closed`, value: 'CLOSED' } - ]; - public user: User; - - private unsubscribeSubject = new Subject(); - - public constructor( - private changeDetectorRef: ChangeDetectorRef, - private dataService: DataService, - private deviceService: DeviceDetectorService, - private dialog: MatDialog, - private impersonationStorageService: ImpersonationStorageService, - private route: ActivatedRoute, - private router: Router, - private userService: UserService - ) { - route.queryParams - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((params) => { - if ( - params['dataSource'] && - params['positionDetailDialog'] && - params['symbol'] - ) { - this.openPositionDialog({ - dataSource: params['dataSource'], - symbol: params['symbol'] - }); - } - }); - } - - public ngOnInit() { - this.deviceType = this.deviceService.getDeviceInfo().deviceType; - - this.impersonationStorageService - .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((impersonationId) => { - this.hasImpersonationId = !!impersonationId; - }); - - this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((state) => { - if (state?.user) { - this.user = state.user; - - this.hasPermissionToCreateOrder = hasPermission( - this.user.permissions, - permissions.createOrder - ); - - this.holdings = undefined; - - this.fetchHoldings() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ holdings }) => { - this.holdings = holdings; - - this.changeDetectorRef.markForCheck(); - }); - - this.changeDetectorRef.markForCheck(); - } - }); - } - - public onChangeHoldingType(aHoldingType: HoldingType) { - this.holdingType = aHoldingType; - - this.holdings = undefined; - - this.fetchHoldings() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(({ holdings }) => { - this.holdings = holdings; - - this.changeDetectorRef.markForCheck(); - }); - } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - - private fetchHoldings() { - const filters = this.userService.getFilters(); - - if (this.holdingType === 'CLOSED') { - filters.push({ id: 'CLOSED', type: 'HOLDING_TYPE' }); - } - - return this.dataService.fetchPortfolioHoldings({ - filters - }); - } - - private openPositionDialog({ - dataSource, - symbol - }: { - dataSource: DataSource; - symbol: string; - }) { - this.userService - .get() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((user) => { - this.user = user; - - const dialogRef = this.dialog.open(PositionDetailDialog, { - autoFocus: false, - data: { - dataSource, - symbol, - baseCurrency: this.user?.settings?.baseCurrency, - colorScheme: this.user?.settings?.colorScheme, - deviceType: this.deviceType, - hasImpersonationId: this.hasImpersonationId, - hasPermissionToReportDataGlitch: hasPermission( - this.user?.permissions, - permissions.reportDataGlitch - ), - locale: this.user?.settings?.locale - }, - height: this.deviceType === 'mobile' ? '97.5vh' : '80vh', - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - }); - - dialogRef - .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.router.navigate(['.'], { relativeTo: this.route }); - }); - }); - } -} diff --git a/apps/client/src/app/pages/portfolio/holdings/holdings-page.html b/apps/client/src/app/pages/portfolio/holdings/holdings-page.html deleted file mode 100644 index a2bd43636..000000000 --- a/apps/client/src/app/pages/portfolio/holdings/holdings-page.html +++ /dev/null @@ -1,38 +0,0 @@ -
      -
      -
      -

      Holdings

      -
      -
      -
      -
      -
      - -
      - - @if (hasPermissionToCreateOrder && holdings?.length > 0) { - - } -
      -
      -
      diff --git a/apps/client/src/app/pages/portfolio/holdings/holdings-page.module.ts b/apps/client/src/app/pages/portfolio/holdings/holdings-page.module.ts deleted file mode 100644 index eae26d2b3..000000000 --- a/apps/client/src/app/pages/portfolio/holdings/holdings-page.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module'; -import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; - -import { HoldingsPageRoutingModule } from './holdings-page-routing.module'; -import { HoldingsPageComponent } from './holdings-page.component'; - -@NgModule({ - declarations: [HoldingsPageComponent], - imports: [ - CommonModule, - GfHoldingsTableModule, - GfToggleModule, - HoldingsPageRoutingModule, - MatButtonModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class HoldingsPageModule {} diff --git a/apps/client/src/app/pages/portfolio/holdings/holdings-page.scss b/apps/client/src/app/pages/portfolio/holdings/holdings-page.scss deleted file mode 100644 index 5d4e87f30..000000000 --- a/apps/client/src/app/pages/portfolio/holdings/holdings-page.scss +++ /dev/null @@ -1,3 +0,0 @@ -:host { - display: block; -} diff --git a/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts b/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts index d4f93b567..6146c573c 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts +++ b/apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts @@ -16,13 +16,6 @@ const routes: Routes = [ (m) => m.AnalysisPageModule ) }, - { - path: 'holdings', - loadChildren: () => - import('./holdings/holdings-page.module').then( - (m) => m.HoldingsPageModule - ) - }, { path: 'activities', loadChildren: () => diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts index bbd70c1c9..0c980e25b 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts +++ b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts @@ -34,11 +34,6 @@ export class PortfolioPageComponent implements OnDestroy, OnInit { label: $localize`Analysis`, path: ['/portfolio'] }, - { - iconName: 'wallet-outline', - label: $localize`Holdings`, - path: ['/portfolio', 'holdings'] - }, { iconName: 'swap-vertical-outline', label: $localize`Activities`, diff --git a/apps/client/src/app/pages/pricing/pricing-page.module.ts b/apps/client/src/app/pages/pricing/pricing-page.module.ts index 19bc99ce2..cb3766f13 100644 --- a/apps/client/src/app/pages/pricing/pricing-page.module.ts +++ b/apps/client/src/app/pages/pricing/pricing-page.module.ts @@ -1,4 +1,4 @@ -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; +import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -14,7 +14,7 @@ import { PricingPageComponent } from './pricing-page.component'; declarations: [PricingPageComponent], imports: [ CommonModule, - GfPremiumIndicatorModule, + GfPremiumIndicatorComponent, MatButtonModule, MatCardModule, MatTooltipModule, diff --git a/apps/client/src/app/pages/public/public-page.module.ts b/apps/client/src/app/pages/public/public-page.module.ts index 2a595f7fe..68c43b45f 100644 --- a/apps/client/src/app/pages/public/public-page.module.ts +++ b/apps/client/src/app/pages/public/public-page.module.ts @@ -1,7 +1,7 @@ import { GfWorldMapChartModule } from '@ghostfolio/client/components/world-map-chart/world-map-chart.module'; -import { GfHoldingsTableModule } from '@ghostfolio/ui/holdings-table/holdings-table.module'; -import { GfPortfolioProportionChartModule } from '@ghostfolio/ui/portfolio-proportion-chart/portfolio-proportion-chart.module'; -import { GfValueModule } from '@ghostfolio/ui/value'; +import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; +import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -15,9 +15,9 @@ import { PublicPageComponent } from './public-page.component'; declarations: [PublicPageComponent], imports: [ CommonModule, - GfHoldingsTableModule, - GfPortfolioProportionChartModule, - GfValueModule, + GfHoldingsTableComponent, + GfPortfolioProportionChartComponent, + GfValueComponent, GfWorldMapChartModule, MatButtonModule, MatCardModule, diff --git a/apps/client/src/app/pages/register/register-page.module.ts b/apps/client/src/app/pages/register/register-page.module.ts index f0bcfd1a8..b6e917e6d 100644 --- a/apps/client/src/app/pages/register/register-page.module.ts +++ b/apps/client/src/app/pages/register/register-page.module.ts @@ -1,4 +1,4 @@ -import { GfLogoModule } from '@ghostfolio/ui/logo'; +import { GfLogoComponent } from '@ghostfolio/ui/logo'; import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @@ -13,7 +13,7 @@ import { ShowAccessTokenDialogModule } from './show-access-token-dialog/show-acc declarations: [RegisterPageComponent], imports: [ CommonModule, - GfLogoModule, + GfLogoComponent, MatButtonModule, RegisterPageRoutingModule, RouterModule, diff --git a/apps/client/src/app/pages/webauthn/webauthn-page.module.ts b/apps/client/src/app/pages/webauthn/webauthn-page.module.ts index 0ef7d12ce..93f9fe870 100644 --- a/apps/client/src/app/pages/webauthn/webauthn-page.module.ts +++ b/apps/client/src/app/pages/webauthn/webauthn-page.module.ts @@ -1,5 +1,5 @@ import { WebauthnPageComponent } from '@ghostfolio/client/pages/webauthn/webauthn-page.component'; -import { GfLogoModule } from '@ghostfolio/ui/logo'; +import { GfLogoComponent } from '@ghostfolio/ui/logo'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @@ -12,7 +12,7 @@ import { WebauthnPageRoutingModule } from './webauthn-page-routing.module'; declarations: [WebauthnPageComponent], imports: [ CommonModule, - GfLogoModule, + GfLogoComponent, MatButtonModule, MatProgressSpinnerModule, WebauthnPageRoutingModule diff --git a/apps/client/src/app/pages/webauthn/webauthn-page.scss b/apps/client/src/app/pages/webauthn/webauthn-page.scss index 5d4e87f30..e138a380b 100644 --- a/apps/client/src/app/pages/webauthn/webauthn-page.scss +++ b/apps/client/src/app/pages/webauthn/webauthn-page.scss @@ -1,3 +1,9 @@ :host { display: block; + + button { + @media (max-width: 575.98px) { + width: 100%; + } + } } diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 8a3f7d293..4f8615e41 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -6,7 +6,6 @@ import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activities } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto'; import { PortfolioPositionDetail } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-position-detail.interface'; -import { PortfolioPositions } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-positions.interface'; import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface'; import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface'; @@ -42,7 +41,11 @@ import { translate } from '@ghostfolio/ui/i18n'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; -import { DataSource, Order as OrderModel } from '@prisma/client'; +import { + AccountBalance, + DataSource, + Order as OrderModel +} from '@prisma/client'; import { format, parseISO } from 'date-fns'; import { cloneDeep, groupBy, isNumber } from 'lodash'; import { Observable } from 'rxjs'; @@ -372,21 +375,6 @@ export class DataService { }); } - public fetchPositions({ - filters, - range - }: { - filters?: Filter[]; - range: DateRange; - }): Observable { - let params = this.buildFiltersAsQueryParams({ filters }); - params = params.append('range', range); - - return this.http.get('/api/v1/portfolio/positions', { - params - }); - } - public fetchSymbols({ includeIndices = false, query @@ -464,13 +452,21 @@ export class DataService { } public fetchPortfolioHoldings({ - filters + filters, + range }: { filters?: Filter[]; - } = {}) { + range?: DateRange; + }) { + let params = this.buildFiltersAsQueryParams({ filters }); + + if (range) { + params = params.append('range', range); + } + return this.http .get('/api/v1/portfolio/holdings', { - params: this.buildFiltersAsQueryParams({ filters }) + params }) .pipe( map((response) => { @@ -603,6 +599,22 @@ export class DataService { return this.http.post(`/api/v1/account`, aAccount); } + public postAccountBalance({ + accountId, + balance, + date + }: { + accountId: string; + balance: number; + date: Date; + }) { + return this.http.post(`/api/v1/account-balance`, { + accountId, + balance, + date + }); + } + public postBenchmark(benchmark: UniqueAsset) { return this.http.post(`/api/v1/benchmark`, benchmark); } diff --git a/apps/client/src/app/util/form.util.ts b/apps/client/src/app/util/form.util.ts index d11490c7e..f629cc4a2 100644 --- a/apps/client/src/app/util/form.util.ts +++ b/apps/client/src/app/util/form.util.ts @@ -32,6 +32,14 @@ export async function validateObjectForForm({ validationError: Object.values(constraints)[0] }); } + + const formControlInCustomCurrency = form.get(`${property}InCustomCurrency`); + + if (formControlInCustomCurrency) { + formControlInCustomCurrency.setErrors({ + validationError: Object.values(constraints)[0] + }); + } } return Promise.reject(nonIgnoredErrors); diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 033f5c58d..23e492b38 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -105,12 +105,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -138,7 +138,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -146,7 +146,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -154,7 +154,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -190,35 +190,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -294,7 +294,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -314,7 +314,7 @@ Jobs löschen apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -337,8 +337,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -354,7 +354,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -362,7 +362,7 @@ Versuche apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -370,7 +370,7 @@ Erstellt apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -378,7 +378,7 @@ Abgeschlossen apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -386,7 +386,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -410,7 +410,7 @@ Daten anzeigen apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -418,7 +418,7 @@ Stacktrace anzeigen apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -426,7 +426,7 @@ Job löschen apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -446,11 +446,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -465,8 +465,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -486,11 +486,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -506,7 +506,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -530,11 +530,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -546,7 +546,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -561,8 +561,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -728,6 +728,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -837,8 +841,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -1218,10 +1222,6 @@ Aktivitäten verwalten apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -1262,7 +1262,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1326,7 +1326,7 @@ Kauf apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -1334,7 +1334,7 @@ Verkauf apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -1342,11 +1342,11 @@ Einlage apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -1354,7 +1354,7 @@ Absolute Brutto Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -1362,29 +1362,7 @@ Brutto Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - - - - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {Transaktion} other {Transaktionen}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -1392,7 +1370,7 @@ Absolute Netto Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -1400,7 +1378,7 @@ Netto Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -1408,7 +1386,7 @@ Gesamtanlagevermögen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -1416,7 +1394,7 @@ Wertsachen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -1424,7 +1402,7 @@ Notfallfonds apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -1440,7 +1418,7 @@ Kaufkraft apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -1448,7 +1426,7 @@ Gesamtvermögen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -1456,7 +1434,7 @@ Performance pro Jahr apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -1464,11 +1442,11 @@ Dividenden apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -1476,11 +1454,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -1488,7 +1466,7 @@ Bitte gib den Betrag deines Notfallfonds ein: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 @@ -1503,8 +1481,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -1523,8 +1501,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -1535,12 +1513,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -1551,8 +1529,8 @@ Report Data Glitch Datenfehler melden - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -1571,12 +1549,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -1584,7 +1562,7 @@ Alle anzeigen libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -1596,7 +1574,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -1608,7 +1586,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -1620,7 +1598,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -1632,7 +1610,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -1644,7 +1622,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -1656,7 +1634,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -1668,7 +1646,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -1676,7 +1654,7 @@ Okay apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2048,7 +2026,7 @@ Bargeld apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -2072,7 +2050,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2172,7 +2150,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -2188,11 +2166,11 @@ Märkte apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -2208,7 +2186,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -2312,7 +2290,7 @@ Zeitstrahl der Investitionen apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -2328,7 +2306,7 @@ Verlierer apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -2371,16 +2349,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -2395,7 +2369,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -2432,7 +2406,7 @@ Verkauf libs/ui/src/lib/i18n.ts - 36 + 37 @@ -2444,19 +2418,19 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 Quantity Anzahl - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2468,11 +2442,11 @@ Stückpreis apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2484,11 +2458,11 @@ Gebühr apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2508,7 +2482,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2527,12 +2501,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2544,7 +2518,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -2580,7 +2554,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -2748,7 +2722,7 @@ Möchtest du diese Aktivität wirklich löschen? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -2824,7 +2798,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2836,7 +2810,7 @@ Ups! Es ist etwas schief gelaufen. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2847,32 +2821,36 @@ Change Änderung - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price Ø Preis pro Einheit - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price Minimum Preis - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price Maximum Preis - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 @@ -2891,12 +2869,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -2907,8 +2885,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2923,8 +2901,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -2968,7 +2946,7 @@ Projizierter Gesamtbetrag libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -2984,7 +2962,7 @@ Einlage libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -2992,11 +2970,11 @@ Verzinsung libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -3004,7 +2982,7 @@ Ersparnisse libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -3032,7 +3010,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3044,7 +3022,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -3112,7 +3090,7 @@ Von der Analyse ausgenommen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3168,7 +3146,7 @@ Portfolio Wertentwicklung apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -3200,7 +3178,7 @@ Symbol libs/ui/src/lib/i18n.ts - 24 + 25 @@ -3208,7 +3186,7 @@ Tag libs/ui/src/lib/i18n.ts - 25 + 26 @@ -3216,7 +3194,7 @@ Bargeld libs/ui/src/lib/i18n.ts - 39 + 40 @@ -3224,7 +3202,7 @@ Rohstoff libs/ui/src/lib/i18n.ts - 40 + 41 @@ -3232,7 +3210,7 @@ Beteiligungskapital libs/ui/src/lib/i18n.ts - 41 + 42 @@ -3240,7 +3218,7 @@ Feste Einkünfte libs/ui/src/lib/i18n.ts - 42 + 43 @@ -3248,7 +3226,7 @@ Immobilien libs/ui/src/lib/i18n.ts - 43 + 45 @@ -3256,7 +3234,7 @@ Anleihe libs/ui/src/lib/i18n.ts - 46 + 48 @@ -3264,7 +3242,7 @@ Kryptowährung libs/ui/src/lib/i18n.ts - 47 + 49 @@ -3272,7 +3250,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -3280,7 +3258,7 @@ Investmentfonds libs/ui/src/lib/i18n.ts - 49 + 51 @@ -3288,7 +3266,7 @@ Edelmetall libs/ui/src/lib/i18n.ts - 50 + 52 @@ -3296,7 +3274,7 @@ Privates Beteiligungskapital libs/ui/src/lib/i18n.ts - 51 + 53 @@ -3304,7 +3282,7 @@ Aktie libs/ui/src/lib/i18n.ts - 52 + 54 @@ -3312,7 +3290,7 @@ Notfallfonds libs/ui/src/lib/i18n.ts - 12 + 13 @@ -3320,11 +3298,11 @@ Andere libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -3332,11 +3310,11 @@ Keine Daten verfügbar libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -3344,7 +3322,7 @@ Nordamerika libs/ui/src/lib/i18n.ts - 62 + 64 @@ -3352,7 +3330,7 @@ Afrika libs/ui/src/lib/i18n.ts - 59 + 61 @@ -3360,7 +3338,7 @@ Asien libs/ui/src/lib/i18n.ts - 60 + 62 @@ -3368,7 +3346,7 @@ Europa libs/ui/src/lib/i18n.ts - 61 + 63 @@ -3376,7 +3354,7 @@ Ozeanien libs/ui/src/lib/i18n.ts - 63 + 65 @@ -3384,7 +3362,7 @@ Südamerika libs/ui/src/lib/i18n.ts - 64 + 66 @@ -3480,7 +3458,7 @@ Zeitstrahl der Dividenden apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -3492,7 +3470,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -3564,11 +3542,11 @@ Zusammenfassung apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -3616,7 +3594,7 @@ Kern libs/ui/src/lib/i18n.ts - 8 + 9 @@ -3624,7 +3602,7 @@ Zuwendung libs/ui/src/lib/i18n.ts - 13 + 14 @@ -3632,7 +3610,7 @@ Höheres Risiko libs/ui/src/lib/i18n.ts - 14 + 15 @@ -3640,7 +3618,7 @@ Geringeres Risiko libs/ui/src/lib/i18n.ts - 17 + 18 @@ -3648,7 +3626,7 @@ Altersvorsorge libs/ui/src/lib/i18n.ts - 22 + 23 @@ -3656,7 +3634,7 @@ Satellit libs/ui/src/lib/i18n.ts - 23 + 24 @@ -3916,11 +3894,11 @@ Gebühren apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3976,7 +3954,7 @@ Einfacher Wechsel zu Ghostfolio Premium libs/ui/src/lib/i18n.ts - 10 + 11 @@ -4000,7 +3978,7 @@ Einfacher Wechsel zu Ghostfolio Premium oder Ghostfolio Open Source libs/ui/src/lib/i18n.ts - 9 + 10 @@ -4008,7 +3986,7 @@ Einfacher Wechsel zu Ghostfolio Open Source oder Ghostfolio Basic libs/ui/src/lib/i18n.ts - 11 + 12 @@ -4024,7 +4002,7 @@ Ups! Der historische Wechselkurs konnte nicht abgerufen werden vom apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4108,7 +4086,7 @@ Möchtest du wirklich alle Aktivitäten löschen? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4132,7 +4110,7 @@ Plattform bearbeiten apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -4140,7 +4118,7 @@ Plattform hinzufügen apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -4156,7 +4134,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -4180,7 +4158,7 @@ Cash-Bestand aktualisieren apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4248,7 +4226,7 @@ Diese Aktivität existiert bereits. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -4340,7 +4318,7 @@ Aktueller Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4348,7 +4326,7 @@ Längster Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4356,7 +4334,7 @@ Monate libs/ui/src/lib/i18n.ts - 19 + 20 @@ -4364,7 +4342,7 @@ Jahre libs/ui/src/lib/i18n.ts - 27 + 28 @@ -4372,7 +4350,7 @@ Monat libs/ui/src/lib/i18n.ts - 18 + 19 @@ -4380,7 +4358,7 @@ Jahr libs/ui/src/lib/i18n.ts - 26 + 27 @@ -4388,7 +4366,7 @@ Verbindlichkeiten apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -4528,7 +4506,7 @@ Verbindlichkeit libs/ui/src/lib/i18n.ts - 35 + 36 @@ -9864,7 +9842,7 @@ Kauf libs/ui/src/lib/i18n.ts - 30 + 31 @@ -9872,7 +9850,7 @@ Wertsache libs/ui/src/lib/i18n.ts - 34 + 35 @@ -9896,7 +9874,7 @@ Anlagevermögen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -9904,7 +9882,7 @@ Filtervorlage libs/ui/src/lib/i18n.ts - 21 + 22 @@ -9928,7 +9906,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -10072,7 +10050,7 @@ Sterne auf GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -10084,7 +10062,7 @@ Downloads auf Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -10184,7 +10162,7 @@ Verwalte dein Vermögen wie ein Profi apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -10192,7 +10170,7 @@ Ghostfolio ist ein Open Source Dashboard für deine persönlichen Finanzen mit Fokus auf Datenschutz. Analysiere deine Vermögensverteilung, ermittle dein Nettovermögen und treffe fundierte, datengestützte Investitionsentscheidungen. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -10200,11 +10178,11 @@ Jetzt loslegen apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -10212,7 +10190,7 @@ oder apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -10220,7 +10198,7 @@ Monatlich aktive Nutzer apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -10228,7 +10206,7 @@ Bekannt aus apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -10236,7 +10214,7 @@ Schützen Sie Ihr Vermögen. Optimieren Sie Ihre persönliche Anlagestrategie. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -10244,7 +10222,7 @@ Ghostfolio ermöglicht es geschäftigen Leuten, den Überblick über Aktien, ETFs oder Kryptowährungen zu behalten, ohne überwacht zu werden. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -10252,7 +10230,7 @@ 360° Ansicht apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -10260,7 +10238,7 @@ Web3 ready apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -10268,7 +10246,7 @@ Nutze Ghostfolio ganz anonym und behalte deine Finanzdaten. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -10276,7 +10254,7 @@ Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -10284,7 +10262,7 @@ Profitiere von kontinuierlichen Verbesserungen durch eine aktive Community. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -10292,7 +10270,7 @@ Warum Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -10300,7 +10278,7 @@ Ghostfolio ist für dich geeignet, wenn du... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -10308,7 +10286,7 @@ Aktien, ETFs oder Kryptowährungen auf unterschiedlichen Plattformen handelst apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -10316,7 +10294,7 @@ eine Buy & Hold Strategie verfolgst apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -10324,7 +10302,7 @@ dich für die Zusammensetzung deines Portfolios interessierst apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -10332,7 +10310,7 @@ Privatsphäre und Datenhoheit wertschätzt apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -10340,7 +10318,7 @@ zum Frugalismus oder Minimalismus neigst apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -10348,7 +10326,7 @@ dich um die Diversifizierung deiner finanziellen Mittel kümmerst apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -10356,7 +10334,7 @@ Interesse an finanzieller Freiheit hast apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -10364,7 +10342,7 @@ Nein sagst zu Excel-Tabellen im Jahr apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -10372,7 +10350,7 @@ diese Liste bis zum Ende liest apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -10380,7 +10358,7 @@ Erfahre mehr über Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -10388,7 +10366,7 @@ Was unsere Nutzer sagen apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -10396,7 +10374,7 @@ Nutzer aus aller Welt verwenden Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -10404,7 +10382,7 @@ Wie funktioniert Ghostfolio ? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -10412,7 +10390,7 @@ Registriere dich anonym* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -10420,7 +10398,7 @@ * Keine E-Mail-Adresse oder Kreditkarte erforderlich apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -10428,7 +10406,7 @@ Füge historische Transaktionen hinzu apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -10436,7 +10414,7 @@ Erhalte nützliche Erkenntnisse über die Zusammensetzung deines Portfolios apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -10444,7 +10422,7 @@ Bist du bereit? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -10452,7 +10430,7 @@ Melde dich jetzt an oder probiere die Live Demo aus apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -10460,11 +10438,11 @@ Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -10472,7 +10450,7 @@ Verschaffe dir einen vollständigen Überblick deiner persönlichen Finanzen über mehrere Plattformen hinweg. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -10480,7 +10458,7 @@ Beginne mit nur 3 Schritten apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -11152,7 +11130,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -11188,7 +11166,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -13195,14 +13173,6 @@ 127 - - New - Neu - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Choose or drop a file here Wählen Sie eine Datei aus oder ziehen Sie sie hierhin @@ -13240,7 +13210,7 @@ Ups! Der historische Wechselkurs konnte nicht abgerufen werden vom apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13248,7 +13218,7 @@ Gebühr libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13256,7 +13226,7 @@ Zins apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -13288,7 +13258,7 @@ Tag bearbeiten apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13296,7 +13266,7 @@ Tag hinzufügen apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13436,7 +13406,7 @@ Finde Position... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13740,7 +13710,7 @@ Ups, der Cash-Bestand Transfer ist fehlgeschlagen. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13764,7 +13734,7 @@ Extreme Angst libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13772,7 +13742,7 @@ Extreme Gier libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13780,7 +13750,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13788,7 +13758,7 @@ Ups! Die historischen Daten konnten nicht geparsed werden. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14636,7 +14606,7 @@ Möchtest du diesen Cash-Bestand wirklich löschen? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14660,7 +14630,7 @@ Der aktuelle Marktpreis ist apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14708,7 +14678,7 @@ Ups! Der Zugang konnte nicht gewährt werden. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14736,7 +14706,7 @@ Die Marktdaten sind verzögert für apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14804,7 +14774,7 @@ Seit Wochenbeginn libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14812,7 +14782,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14820,7 +14790,7 @@ Seit Monatsbeginn libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14828,7 +14798,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14836,7 +14806,7 @@ Seit Jahresbeginn libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14880,7 +14850,7 @@ Jahr libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14888,7 +14858,7 @@ Jahre libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14972,7 +14942,7 @@ Ups! Es sieht so aus, als würdest du zu viele Anfragen senden. Bitte geh es ein bisschen langsamer an. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14987,7 +14957,7 @@ Active Aktiv - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14995,7 +14965,7 @@ Closed Abgeschlossen - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15003,16 +14973,16 @@ Activity Aktivität - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividendenrendite - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15020,7 +14990,63 @@ Job ausführen apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priorität + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + Diese Aktion ist nicht zulässig. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidität + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Änderung mit Währungseffekt + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance mit Währungseffekt + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {Aktivität} other {Aktivitäten}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Kauf und Verkauf + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index c770a2dc2..51edc3b79 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -106,12 +106,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -139,7 +139,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -147,7 +147,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -155,7 +155,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -191,35 +191,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -295,7 +295,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -315,7 +315,7 @@ Elimina los trabajos apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -338,8 +338,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -355,7 +355,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -363,7 +363,7 @@ Intentos apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -371,7 +371,7 @@ Creado apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -379,7 +379,7 @@ Finalizado apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -387,7 +387,7 @@ Estado apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -411,7 +411,7 @@ Visualiza los datos apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -419,7 +419,7 @@ Visualiza Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -427,7 +427,7 @@ Elimina el trabajo apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -447,11 +447,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -466,8 +466,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -487,11 +487,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -507,7 +507,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -531,11 +531,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -547,7 +547,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -562,8 +562,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -729,6 +729,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -838,8 +842,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -1219,10 +1223,6 @@ Gestión de las operaciones apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -1263,7 +1263,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1327,7 +1327,7 @@ Compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -1335,7 +1335,7 @@ Venta apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -1343,11 +1343,11 @@ Inversión apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -1355,7 +1355,7 @@ Rendimiento bruto absoluto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -1363,26 +1363,7 @@ Rendimiento bruto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - Comisiones por - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transacción} other {transacciones}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -1390,7 +1371,7 @@ Rendimiento neto absoluto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -1398,7 +1379,7 @@ Rendimiento neto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -1406,7 +1387,7 @@ Total de activos apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -1414,7 +1395,7 @@ Objetos de valor apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -1422,7 +1403,7 @@ Fondo de emergencia apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -1438,7 +1419,7 @@ Capacidad de compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -1446,7 +1427,7 @@ Patrimonio neto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -1454,7 +1435,7 @@ Rendimiento anualizado apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -1462,11 +1443,11 @@ Dividendo apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -1474,11 +1455,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -1486,7 +1467,7 @@ Por favor, ingresa la cantidad de tu fondo de emergencia: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 @@ -1501,8 +1482,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -1521,8 +1502,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -1533,12 +1514,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -1549,8 +1530,8 @@ Report Data Glitch Reporta un anomalía de los datos - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -1569,12 +1550,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -1582,7 +1563,7 @@ Mostrar todos libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -1594,7 +1575,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -1606,7 +1587,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -1618,7 +1599,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -1630,7 +1611,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -1642,7 +1623,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -1654,7 +1635,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -1666,7 +1647,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -1674,7 +1655,7 @@ De acuerdo apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2046,7 +2027,7 @@ Efectivo apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -2070,7 +2051,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2170,7 +2151,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -2186,11 +2167,11 @@ Mercados apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -2206,7 +2187,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -2310,7 +2291,7 @@ Cronología de la inversión apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -2326,7 +2307,7 @@ Lo peor apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -2369,16 +2350,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -2393,7 +2370,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -2430,7 +2407,7 @@ Venta libs/ui/src/lib/i18n.ts - 36 + 37 @@ -2442,19 +2419,19 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 Quantity Cantidad - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2466,11 +2443,11 @@ Precio unitario apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2482,11 +2459,11 @@ Comisión apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2506,7 +2483,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2525,12 +2502,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2542,7 +2519,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -2578,7 +2555,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -2746,7 +2723,7 @@ ¿Estás seguro de eliminar esta operación? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -2818,7 +2795,7 @@ Vaya! Algo no funcionó bien. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2834,7 +2811,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2845,8 +2822,12 @@ Change Modificar - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 @@ -2877,28 +2858,28 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 Average Unit Price Precio unitario medio - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Maximum Price Precio máximo - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 @@ -2933,8 +2914,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2949,16 +2930,16 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 Minimum Price Precio mínimo - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 @@ -2966,7 +2947,7 @@ Importe total previsto libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -2974,7 +2955,7 @@ Ahorros libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -2982,11 +2963,11 @@ Interés libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -2994,7 +2975,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -3030,7 +3011,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3042,7 +3023,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -3110,7 +3091,7 @@ Excluido del análisis apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3166,7 +3147,7 @@ Evolución cartera apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -3198,7 +3179,7 @@ Símbolo libs/ui/src/lib/i18n.ts - 24 + 25 @@ -3206,7 +3187,7 @@ Etiqueta libs/ui/src/lib/i18n.ts - 25 + 26 @@ -3214,7 +3195,7 @@ Efectivo libs/ui/src/lib/i18n.ts - 39 + 40 @@ -3222,7 +3203,7 @@ Bien libs/ui/src/lib/i18n.ts - 40 + 41 @@ -3230,7 +3211,7 @@ Capital libs/ui/src/lib/i18n.ts - 41 + 42 @@ -3238,7 +3219,7 @@ Renta fija libs/ui/src/lib/i18n.ts - 42 + 43 @@ -3246,7 +3227,7 @@ Propiedad inmobiliaria libs/ui/src/lib/i18n.ts - 43 + 45 @@ -3254,7 +3235,7 @@ Bono libs/ui/src/lib/i18n.ts - 46 + 48 @@ -3262,7 +3243,7 @@ Criptomoneda libs/ui/src/lib/i18n.ts - 47 + 49 @@ -3270,7 +3251,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -3278,7 +3259,7 @@ Fondo de inversión libs/ui/src/lib/i18n.ts - 49 + 51 @@ -3286,7 +3267,7 @@ Metal precioso libs/ui/src/lib/i18n.ts - 50 + 52 @@ -3294,7 +3275,7 @@ Capital riesgo libs/ui/src/lib/i18n.ts - 51 + 53 @@ -3302,7 +3283,7 @@ Acción libs/ui/src/lib/i18n.ts - 52 + 54 @@ -3310,7 +3291,7 @@ Fondo de emergencia libs/ui/src/lib/i18n.ts - 12 + 13 @@ -3318,11 +3299,11 @@ Otros libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -3330,11 +3311,11 @@ Sin datos disponibles libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -3342,7 +3323,7 @@ América del Norte libs/ui/src/lib/i18n.ts - 62 + 64 @@ -3350,7 +3331,7 @@ África libs/ui/src/lib/i18n.ts - 59 + 61 @@ -3358,7 +3339,7 @@ Asia libs/ui/src/lib/i18n.ts - 60 + 62 @@ -3366,7 +3347,7 @@ Europa libs/ui/src/lib/i18n.ts - 61 + 63 @@ -3374,7 +3355,7 @@ Oceanía libs/ui/src/lib/i18n.ts - 63 + 65 @@ -3382,7 +3363,7 @@ América del Sur libs/ui/src/lib/i18n.ts - 64 + 66 @@ -3482,7 +3463,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -3490,7 +3471,7 @@ Dividend Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -3562,11 +3543,11 @@ Summary apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -3614,7 +3595,7 @@ Core libs/ui/src/lib/i18n.ts - 8 + 9 @@ -3622,7 +3603,7 @@ Grant libs/ui/src/lib/i18n.ts - 13 + 14 @@ -3630,7 +3611,7 @@ Higher Risk libs/ui/src/lib/i18n.ts - 14 + 15 @@ -3638,7 +3619,7 @@ Lower Risk libs/ui/src/lib/i18n.ts - 17 + 18 @@ -3646,7 +3627,7 @@ Retirement Provision libs/ui/src/lib/i18n.ts - 22 + 23 @@ -3654,7 +3635,7 @@ Satellite libs/ui/src/lib/i18n.ts - 23 + 24 @@ -3914,11 +3895,11 @@ Fees apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3974,7 +3955,7 @@ Switch to Ghostfolio Premium easily libs/ui/src/lib/i18n.ts - 10 + 11 @@ -3998,7 +3979,7 @@ Switch to Ghostfolio Premium or Ghostfolio Open Source easily libs/ui/src/lib/i18n.ts - 9 + 10 @@ -4006,7 +3987,7 @@ Switch to Ghostfolio Open Source or Ghostfolio Basic easily libs/ui/src/lib/i18n.ts - 11 + 12 @@ -4022,7 +4003,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4106,7 +4087,7 @@ Do you really want to delete all your activities? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4130,7 +4111,7 @@ Update platform apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -4138,7 +4119,7 @@ Add platform apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -4154,7 +4135,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -4178,7 +4159,7 @@ Update Cash Balance apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4246,7 +4227,7 @@ This activity already exists. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -4338,7 +4319,7 @@ Current Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4346,7 +4327,7 @@ Longest Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4354,7 +4335,7 @@ Months libs/ui/src/lib/i18n.ts - 19 + 20 @@ -4362,7 +4343,7 @@ Years libs/ui/src/lib/i18n.ts - 27 + 28 @@ -4370,7 +4351,7 @@ Month libs/ui/src/lib/i18n.ts - 18 + 19 @@ -4378,7 +4359,7 @@ Year libs/ui/src/lib/i18n.ts - 26 + 27 @@ -4386,7 +4367,7 @@ Liabilities apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -4526,7 +4507,7 @@ Liability libs/ui/src/lib/i18n.ts - 35 + 36 @@ -9862,7 +9843,7 @@ Buy libs/ui/src/lib/i18n.ts - 30 + 31 @@ -9870,7 +9851,7 @@ Valuable libs/ui/src/lib/i18n.ts - 34 + 35 @@ -9894,7 +9875,7 @@ Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -9902,7 +9883,7 @@ Preset libs/ui/src/lib/i18n.ts - 21 + 22 @@ -9926,7 +9907,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -10070,7 +10051,7 @@ Stars on GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -10082,7 +10063,7 @@ Pulls on Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -10182,7 +10163,7 @@ Manage your wealth like a boss apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -10190,7 +10171,7 @@ Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -10198,11 +10179,11 @@ Get Started apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -10210,7 +10191,7 @@ or apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -10218,7 +10199,7 @@ Monthly Active Users apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -10226,7 +10207,7 @@ As seen in apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -10234,7 +10215,7 @@ Protect your assets. Refine your personal investment strategy. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -10242,7 +10223,7 @@ Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -10250,7 +10231,7 @@ 360° View apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -10258,7 +10239,7 @@ Web3 Ready apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -10266,7 +10247,7 @@ Use Ghostfolio anonymously and own your financial data. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -10274,7 +10255,7 @@ Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -10282,7 +10263,7 @@ Benefit from continuous improvements through a strong community. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -10290,7 +10271,7 @@ Why Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -10298,7 +10279,7 @@ Ghostfolio is for you if you are... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -10306,7 +10287,7 @@ trading stocks, ETFs or cryptocurrencies on multiple platforms apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -10314,7 +10295,7 @@ pursuing a buy & hold strategy apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -10322,7 +10303,7 @@ interested in getting insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -10330,7 +10311,7 @@ valuing privacy and data ownership apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -10338,7 +10319,7 @@ into minimalism apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -10346,7 +10327,7 @@ caring about diversifying your financial resources apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -10354,7 +10335,7 @@ interested in financial independence apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -10362,7 +10343,7 @@ saying no to spreadsheets in apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -10370,7 +10351,7 @@ still reading this list apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -10378,7 +10359,7 @@ Learn more about Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -10386,7 +10367,7 @@ What our users are saying apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -10394,7 +10375,7 @@ Members from around the globe are using Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -10402,7 +10383,7 @@ How does Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -10410,7 +10391,7 @@ Sign up anonymously* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -10418,7 +10399,7 @@ * no e-mail address nor credit card required apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -10426,7 +10407,7 @@ Add any of your historical transactions apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -10434,7 +10415,7 @@ Get valuable insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -10442,7 +10423,7 @@ Are you ready? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -10450,7 +10431,7 @@ Join now or check out the example account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -10458,11 +10439,11 @@ Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -10470,7 +10451,7 @@ Get the full picture of your personal finances across multiple platforms. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -10478,7 +10459,7 @@ Get started in only 3 steps apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -11150,7 +11131,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -11186,7 +11167,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -13193,14 +13174,6 @@ 127 - - New - New - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Choose or drop a file here Choose or drop a file here @@ -13238,7 +13211,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13246,7 +13219,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13254,7 +13227,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -13286,7 +13259,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13294,7 +13267,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13434,7 +13407,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13738,7 +13711,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13762,7 +13735,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13770,7 +13743,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13778,7 +13751,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13786,7 +13759,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14634,7 +14607,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14658,7 +14631,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14706,7 +14679,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14734,7 +14707,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14802,7 +14775,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14810,7 +14783,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14818,7 +14791,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14826,7 +14799,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14834,7 +14807,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14878,7 +14851,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14886,7 +14859,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14970,7 +14943,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14985,7 +14958,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14993,7 +14966,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15001,16 +14974,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15018,7 +14991,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index 3a241feda..198523c74 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -117,12 +117,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -150,7 +150,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -158,7 +158,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -166,7 +166,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -206,7 +206,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -246,35 +246,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -350,7 +350,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -385,8 +385,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -402,7 +402,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -410,7 +410,7 @@ Tentatives apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -418,7 +418,7 @@ Créé apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -426,7 +426,7 @@ Terminé apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -434,7 +434,7 @@ Statut apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -442,7 +442,7 @@ Supprimer Tâches apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -466,7 +466,7 @@ Voir Données apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -474,7 +474,7 @@ Voir la Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -482,7 +482,7 @@ Supprimer Tâche apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -502,11 +502,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -521,8 +521,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -542,11 +542,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -562,7 +562,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -586,11 +586,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -602,7 +602,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -629,12 +629,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -653,12 +653,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -673,8 +673,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -761,8 +761,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -777,8 +777,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -793,8 +793,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -813,8 +813,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -838,7 +838,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -929,12 +929,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -988,6 +988,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -1049,8 +1053,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -1085,12 +1089,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -1110,7 +1114,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -1530,10 +1534,6 @@ Gérer les Activités apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -1546,7 +1546,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -1558,7 +1558,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -1578,7 +1578,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -1590,7 +1590,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -1638,7 +1638,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1690,7 +1690,7 @@ Achat apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -1698,7 +1698,7 @@ Vente apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -1706,11 +1706,11 @@ Investissement apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -1718,7 +1718,7 @@ Performance Absolue Brute apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -1726,26 +1726,7 @@ Performance Brute apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - Frais pour - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transaction} autres {transactions}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -1753,7 +1734,7 @@ Performance Absolue Nette apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -1761,7 +1742,7 @@ Performance nette apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -1769,7 +1750,7 @@ Actifs Totaux apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -1777,7 +1758,7 @@ Biens apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -1785,7 +1766,7 @@ Fonds d'Urgence apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -1801,7 +1782,7 @@ Pouvoir d'Achat apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -1809,7 +1790,7 @@ Exclus de l'Analyse apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -1817,7 +1798,7 @@ Fortune apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -1825,7 +1806,7 @@ Performance annualisée apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -1833,11 +1814,11 @@ Dividende apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -1845,11 +1826,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -1857,51 +1838,55 @@ Veuillez entrer le montant de votre fonds d'urgence : apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 Change Différence - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price Prix Unitaire Moyen - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price Prix Minimum - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price Prix Maximum - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 Quantity Quantité - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1912,8 +1897,8 @@ Report Data Glitch Signaler une Erreur de Données - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -1925,7 +1910,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -1937,7 +1922,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -1949,7 +1934,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -1961,7 +1946,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -1973,7 +1958,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -1993,7 +1978,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2005,7 +1990,7 @@ Oups! Quelque chose s'est mal passé. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2017,7 +2002,7 @@ D'accord apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2401,7 +2386,7 @@ Cash apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -2576,16 +2561,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -2597,11 +2578,11 @@ Résumé apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -2609,11 +2590,11 @@ Marchés apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -2629,7 +2610,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -2657,7 +2638,7 @@ Vente libs/ui/src/lib/i18n.ts - 36 + 37 @@ -2669,7 +2650,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 @@ -2677,11 +2658,11 @@ Prix Unitaire apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2693,11 +2674,11 @@ Frais apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2773,7 +2754,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -2917,7 +2898,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -2925,7 +2906,7 @@ Dépôt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -2957,7 +2938,7 @@ Bas apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -2965,7 +2946,7 @@ Évolution du Portefeuille apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -2973,7 +2954,7 @@ Historique des Investissements apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -2981,7 +2962,7 @@ Historique des Dividendes apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -3024,7 +3005,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -3193,7 +3174,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -3265,7 +3246,7 @@ Voulez-vous vraiment supprimer cette activité ? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -3305,7 +3286,7 @@ Montant Total Prévu libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -3313,11 +3294,11 @@ Intérêt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -3325,7 +3306,7 @@ Épargne libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -3341,7 +3322,7 @@ Montrer tout libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -3373,7 +3354,7 @@ Fonds d'Urgence libs/ui/src/lib/i18n.ts - 12 + 13 @@ -3381,11 +3362,11 @@ Autre libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -3393,7 +3374,7 @@ Symbole libs/ui/src/lib/i18n.ts - 24 + 25 @@ -3401,7 +3382,7 @@ Étiquette libs/ui/src/lib/i18n.ts - 25 + 26 @@ -3409,7 +3390,7 @@ Cash libs/ui/src/lib/i18n.ts - 39 + 40 @@ -3417,7 +3398,7 @@ Marchandise libs/ui/src/lib/i18n.ts - 40 + 41 @@ -3425,7 +3406,7 @@ Capital libs/ui/src/lib/i18n.ts - 41 + 42 @@ -3433,7 +3414,7 @@ Revenu Fixe libs/ui/src/lib/i18n.ts - 42 + 43 @@ -3441,7 +3422,7 @@ Immobilier libs/ui/src/lib/i18n.ts - 43 + 45 @@ -3449,7 +3430,7 @@ Obligation libs/ui/src/lib/i18n.ts - 46 + 48 @@ -3457,7 +3438,7 @@ Cryptomonnaie libs/ui/src/lib/i18n.ts - 47 + 49 @@ -3465,7 +3446,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -3473,7 +3454,7 @@ SICAV libs/ui/src/lib/i18n.ts - 49 + 51 @@ -3481,7 +3462,7 @@ Métal Précieux libs/ui/src/lib/i18n.ts - 50 + 52 @@ -3489,7 +3470,7 @@ Capital Propre libs/ui/src/lib/i18n.ts - 51 + 53 @@ -3497,7 +3478,7 @@ Action libs/ui/src/lib/i18n.ts - 52 + 54 @@ -3505,7 +3486,7 @@ Afrique libs/ui/src/lib/i18n.ts - 59 + 61 @@ -3513,7 +3494,7 @@ Asie libs/ui/src/lib/i18n.ts - 60 + 62 @@ -3521,7 +3502,7 @@ Europe libs/ui/src/lib/i18n.ts - 61 + 63 @@ -3529,7 +3510,7 @@ Amérique du Nord libs/ui/src/lib/i18n.ts - 62 + 64 @@ -3537,7 +3518,7 @@ Océanie libs/ui/src/lib/i18n.ts - 63 + 65 @@ -3545,7 +3526,7 @@ Amérique du Sud libs/ui/src/lib/i18n.ts - 64 + 66 @@ -3561,11 +3542,11 @@ Pas de données disponibles libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -3613,7 +3594,7 @@ Core libs/ui/src/lib/i18n.ts - 8 + 9 @@ -3621,7 +3602,7 @@ Donner libs/ui/src/lib/i18n.ts - 13 + 14 @@ -3629,7 +3610,7 @@ Risque élevé libs/ui/src/lib/i18n.ts - 14 + 15 @@ -3637,7 +3618,7 @@ Risque faible libs/ui/src/lib/i18n.ts - 17 + 18 @@ -3645,7 +3626,7 @@ Réserve pour retraite libs/ui/src/lib/i18n.ts - 22 + 23 @@ -3653,7 +3634,7 @@ Satellite libs/ui/src/lib/i18n.ts - 23 + 24 @@ -3913,11 +3894,11 @@ Frais apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3973,7 +3954,7 @@ Passez à Ghostfolio Premium facilement libs/ui/src/lib/i18n.ts - 10 + 11 @@ -3997,7 +3978,7 @@ Passez à Ghostfolio Premium ou Ghostfolio Open Source facilement libs/ui/src/lib/i18n.ts - 9 + 10 @@ -4005,7 +3986,7 @@ Passez à Ghostfolio Open Source ou Ghostfolio Basic facilement libs/ui/src/lib/i18n.ts - 11 + 12 @@ -4021,7 +4002,7 @@ Oups ! Nous n'avons pas pu obtenir le taux de change historique à partir de apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4105,7 +4086,7 @@ Voulez-vous vraiment supprimer toutes vos activités ? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4129,7 +4110,7 @@ Mettre à jour la Plateforme apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -4137,7 +4118,7 @@ Ajouter une Plateforme apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -4153,7 +4134,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -4177,7 +4158,7 @@ Mettre à jour le Solde apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4245,7 +4226,7 @@ Cette activité existe déjà. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -4337,7 +4318,7 @@ Série en cours apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4345,7 +4326,7 @@ Série la plus longue apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4353,7 +4334,7 @@ Mois libs/ui/src/lib/i18n.ts - 19 + 20 @@ -4361,7 +4342,7 @@ Années libs/ui/src/lib/i18n.ts - 27 + 28 @@ -4369,7 +4350,7 @@ Mois libs/ui/src/lib/i18n.ts - 18 + 19 @@ -4377,7 +4358,7 @@ Année libs/ui/src/lib/i18n.ts - 26 + 27 @@ -4385,7 +4366,7 @@ Dettes apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -4525,7 +4506,7 @@ Dette libs/ui/src/lib/i18n.ts - 35 + 36 @@ -9861,7 +9842,7 @@ Buy libs/ui/src/lib/i18n.ts - 30 + 31 @@ -9869,7 +9850,7 @@ Valuable libs/ui/src/lib/i18n.ts - 34 + 35 @@ -9893,7 +9874,7 @@ Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -9901,7 +9882,7 @@ Preset libs/ui/src/lib/i18n.ts - 21 + 22 @@ -9925,7 +9906,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -10069,7 +10050,7 @@ Stars on GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -10081,7 +10062,7 @@ Pulls on Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -10181,7 +10162,7 @@ Manage your wealth like a boss apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -10189,7 +10170,7 @@ Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -10197,11 +10178,11 @@ Get Started apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -10209,7 +10190,7 @@ or apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -10217,7 +10198,7 @@ Monthly Active Users apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -10225,7 +10206,7 @@ As seen in apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -10233,7 +10214,7 @@ Protect your assets. Refine your personal investment strategy. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -10241,7 +10222,7 @@ Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -10249,7 +10230,7 @@ 360° View apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -10257,7 +10238,7 @@ Web3 Ready apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -10265,7 +10246,7 @@ Use Ghostfolio anonymously and own your financial data. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -10273,7 +10254,7 @@ Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -10281,7 +10262,7 @@ Benefit from continuous improvements through a strong community. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -10289,7 +10270,7 @@ Why Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -10297,7 +10278,7 @@ Ghostfolio is for you if you are... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -10305,7 +10286,7 @@ trading stocks, ETFs or cryptocurrencies on multiple platforms apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -10313,7 +10294,7 @@ pursuing a buy & hold strategy apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -10321,7 +10302,7 @@ interested in getting insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -10329,7 +10310,7 @@ valuing privacy and data ownership apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -10337,7 +10318,7 @@ into minimalism apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -10345,7 +10326,7 @@ caring about diversifying your financial resources apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -10353,7 +10334,7 @@ interested in financial independence apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -10361,7 +10342,7 @@ saying no to spreadsheets in apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -10369,7 +10350,7 @@ still reading this list apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -10377,7 +10358,7 @@ Learn more about Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -10385,7 +10366,7 @@ What our users are saying apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -10393,7 +10374,7 @@ Members from around the globe are using Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -10401,7 +10382,7 @@ How does Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -10409,7 +10390,7 @@ Sign up anonymously* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -10417,7 +10398,7 @@ * no e-mail address nor credit card required apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -10425,7 +10406,7 @@ Add any of your historical transactions apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -10433,7 +10414,7 @@ Get valuable insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -10441,7 +10422,7 @@ Are you ready? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -10449,7 +10430,7 @@ Join now or check out the example account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -10457,11 +10438,11 @@ Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -10469,7 +10450,7 @@ Get the full picture of your personal finances across multiple platforms. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -10477,7 +10458,7 @@ Get started in only 3 steps apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -11149,7 +11130,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -11185,7 +11166,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -13192,14 +13173,6 @@ 127 - - New - New - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Choose or drop a file here Choose or drop a file here @@ -13237,7 +13210,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13245,7 +13218,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13253,7 +13226,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -13285,7 +13258,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13293,7 +13266,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13433,7 +13406,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13737,7 +13710,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13761,7 +13734,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13769,7 +13742,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13777,7 +13750,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13785,7 +13758,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14633,7 +14606,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14657,7 +14630,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14705,7 +14678,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14733,7 +14706,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14801,7 +14774,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14809,7 +14782,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14817,7 +14790,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14825,7 +14798,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14833,7 +14806,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14877,7 +14850,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14885,7 +14858,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14969,7 +14942,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14984,7 +14957,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14992,7 +14965,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15000,16 +14973,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15017,7 +14990,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 99f669151..2589c8146 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -106,12 +106,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -139,7 +139,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -147,7 +147,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -155,7 +155,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -191,35 +191,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -295,7 +295,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -315,7 +315,7 @@ Elimina i lavori apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -338,8 +338,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -355,7 +355,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -363,7 +363,7 @@ Tentativi apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -371,7 +371,7 @@ Creato apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -379,7 +379,7 @@ Finito apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -387,7 +387,7 @@ Stato apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -411,7 +411,7 @@ Visualizza i dati apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -419,7 +419,7 @@ Visualizza Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -427,7 +427,7 @@ Elimina il lavoro apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -447,11 +447,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -466,8 +466,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -487,11 +487,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -507,7 +507,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -531,11 +531,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -547,7 +547,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -562,8 +562,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -729,6 +729,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -838,8 +842,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -1219,10 +1223,6 @@ Gestione delle attività apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -1263,7 +1263,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1327,7 +1327,7 @@ Compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -1335,7 +1335,7 @@ Vendi apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -1343,11 +1343,11 @@ Investimento apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -1355,7 +1355,7 @@ Prestazioni lorde assolute apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -1363,26 +1363,7 @@ Prestazioni lorde apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - Commissioni per - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transazione} other {transazioni}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -1390,7 +1371,7 @@ Prestazioni nette assolute apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -1398,7 +1379,7 @@ Prestazioni nette apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -1406,7 +1387,7 @@ Asset totali apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -1414,7 +1395,7 @@ Oggetti di valore apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -1422,7 +1403,7 @@ Fondo di emergenza apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -1438,7 +1419,7 @@ Potere d'acquisto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -1446,7 +1427,7 @@ Patrimonio netto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -1454,7 +1435,7 @@ Prestazioni annualizzate apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -1462,11 +1443,11 @@ Dividendo apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -1474,11 +1455,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -1486,7 +1467,7 @@ Inserisci l'importo del tuo fondo di emergenza: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 @@ -1501,8 +1482,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -1521,8 +1502,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -1533,12 +1514,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -1549,8 +1530,8 @@ Report Data Glitch Segnala un'anomalia dei dati - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -1569,12 +1550,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -1582,7 +1563,7 @@ Mostra tutti libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -1594,7 +1575,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -1606,7 +1587,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -1618,7 +1599,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -1630,7 +1611,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -1642,7 +1623,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -1654,7 +1635,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -1666,7 +1647,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -1674,7 +1655,7 @@ Bene apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2046,7 +2027,7 @@ Contanti apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -2070,7 +2051,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2170,7 +2151,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -2186,11 +2167,11 @@ Mercati apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -2206,7 +2187,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -2310,7 +2291,7 @@ Cronologia degli investimenti apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -2326,7 +2307,7 @@ In basso apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -2369,16 +2350,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -2393,7 +2370,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -2430,7 +2407,7 @@ Vendi libs/ui/src/lib/i18n.ts - 36 + 37 @@ -2442,19 +2419,19 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 Quantity Quantità - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2466,11 +2443,11 @@ Prezzo unitario apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2482,11 +2459,11 @@ Commissione apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2506,7 +2483,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2525,12 +2502,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2542,7 +2519,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -2578,7 +2555,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -2746,7 +2723,7 @@ Vuoi davvero eliminare questa attività? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -2818,7 +2795,7 @@ Ops! Qualcosa è andato storto. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2834,7 +2811,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2845,8 +2822,12 @@ Change Modifica - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 @@ -2877,28 +2858,28 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 Average Unit Price Prezzo unitario medio - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Maximum Price Prezzo massimo - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 @@ -2933,8 +2914,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2949,16 +2930,16 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 Minimum Price Prezzo minimo - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 @@ -2966,7 +2947,7 @@ Importo totale previsto libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -2974,7 +2955,7 @@ Risparmio libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -2982,11 +2963,11 @@ Interesse libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -2994,7 +2975,7 @@ Deposito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -3030,7 +3011,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3042,7 +3023,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -3110,7 +3091,7 @@ Escluso dall'analisi apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3166,7 +3147,7 @@ Evoluzione del portafoglio apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -3198,7 +3179,7 @@ Simbolo libs/ui/src/lib/i18n.ts - 24 + 25 @@ -3206,7 +3187,7 @@ Etichetta libs/ui/src/lib/i18n.ts - 25 + 26 @@ -3214,7 +3195,7 @@ Contanti libs/ui/src/lib/i18n.ts - 39 + 40 @@ -3222,7 +3203,7 @@ Materia prima libs/ui/src/lib/i18n.ts - 40 + 41 @@ -3230,7 +3211,7 @@ Azione ordinaria libs/ui/src/lib/i18n.ts - 41 + 42 @@ -3238,7 +3219,7 @@ Reddito fisso libs/ui/src/lib/i18n.ts - 42 + 43 @@ -3246,7 +3227,7 @@ Immobiliare libs/ui/src/lib/i18n.ts - 43 + 45 @@ -3254,7 +3235,7 @@ Obbligazioni libs/ui/src/lib/i18n.ts - 46 + 48 @@ -3262,7 +3243,7 @@ Criptovaluta libs/ui/src/lib/i18n.ts - 47 + 49 @@ -3270,7 +3251,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -3278,7 +3259,7 @@ Fondo comune di investimento libs/ui/src/lib/i18n.ts - 49 + 51 @@ -3286,7 +3267,7 @@ Metalli preziosi libs/ui/src/lib/i18n.ts - 50 + 52 @@ -3294,7 +3275,7 @@ Azione ordinaria privata libs/ui/src/lib/i18n.ts - 51 + 53 @@ -3302,7 +3283,7 @@ Azione libs/ui/src/lib/i18n.ts - 52 + 54 @@ -3310,7 +3291,7 @@ Fondo di emergenza libs/ui/src/lib/i18n.ts - 12 + 13 @@ -3318,11 +3299,11 @@ Altro libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -3330,11 +3311,11 @@ Nessun dato disponibile libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -3342,7 +3323,7 @@ Nord America libs/ui/src/lib/i18n.ts - 62 + 64 @@ -3350,7 +3331,7 @@ Africa libs/ui/src/lib/i18n.ts - 59 + 61 @@ -3358,7 +3339,7 @@ Asia libs/ui/src/lib/i18n.ts - 60 + 62 @@ -3366,7 +3347,7 @@ Europa libs/ui/src/lib/i18n.ts - 61 + 63 @@ -3374,7 +3355,7 @@ Oceania libs/ui/src/lib/i18n.ts - 63 + 65 @@ -3382,7 +3363,7 @@ Sud America libs/ui/src/lib/i18n.ts - 64 + 66 @@ -3482,7 +3463,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -3490,7 +3471,7 @@ Cronologia dei dividendi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -3562,11 +3543,11 @@ Summario apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -3614,7 +3595,7 @@ Nucleo libs/ui/src/lib/i18n.ts - 8 + 9 @@ -3622,7 +3603,7 @@ Sovvenzione libs/ui/src/lib/i18n.ts - 13 + 14 @@ -3630,7 +3611,7 @@ Rischio più elevato libs/ui/src/lib/i18n.ts - 14 + 15 @@ -3638,7 +3619,7 @@ Rischio inferiore libs/ui/src/lib/i18n.ts - 17 + 18 @@ -3646,7 +3627,7 @@ Fondo pensione libs/ui/src/lib/i18n.ts - 22 + 23 @@ -3654,7 +3635,7 @@ Satellite libs/ui/src/lib/i18n.ts - 23 + 24 @@ -3914,11 +3895,11 @@ Commissioni apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3974,7 +3955,7 @@ Passa facilmente a Ghostfolio Premium libs/ui/src/lib/i18n.ts - 10 + 11 @@ -3998,7 +3979,7 @@ Passa facilmente a Ghostfolio Premium o Ghostfolio Open Source libs/ui/src/lib/i18n.ts - 9 + 10 @@ -4006,7 +3987,7 @@ Passa facilmente a Ghostfolio Open Source o a Ghostfolio Basic libs/ui/src/lib/i18n.ts - 11 + 12 @@ -4022,7 +4003,7 @@ Ops! Impossibile ottenere il tasso di cambio storico da apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4106,7 +4087,7 @@ Vuoi davvero eliminare tutte le tue attività? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4130,7 +4111,7 @@ Aggiorna la piattaforma apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -4138,7 +4119,7 @@ Aggiungi la piattaforma apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -4154,7 +4135,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -4178,7 +4159,7 @@ Aggiornamento del saldo di cassa apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4246,7 +4227,7 @@ Questa attività esiste già. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -4338,7 +4319,7 @@ Serie attuale apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4346,7 +4327,7 @@ Serie più lunga apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4354,7 +4335,7 @@ Mesi libs/ui/src/lib/i18n.ts - 19 + 20 @@ -4362,7 +4343,7 @@ Anni libs/ui/src/lib/i18n.ts - 27 + 28 @@ -4370,7 +4351,7 @@ Mese libs/ui/src/lib/i18n.ts - 18 + 19 @@ -4378,7 +4359,7 @@ Anno libs/ui/src/lib/i18n.ts - 26 + 27 @@ -4386,7 +4367,7 @@ Passività apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -4526,7 +4507,7 @@ Passività libs/ui/src/lib/i18n.ts - 35 + 36 @@ -9862,7 +9843,7 @@ Compra libs/ui/src/lib/i18n.ts - 30 + 31 @@ -9870,7 +9851,7 @@ Prezioso libs/ui/src/lib/i18n.ts - 34 + 35 @@ -9894,7 +9875,7 @@ Asset apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -9902,7 +9883,7 @@ Preimpostato libs/ui/src/lib/i18n.ts - 21 + 22 @@ -9926,7 +9907,7 @@ Giappone libs/ui/src/lib/i18n.ts - 16 + 17 @@ -10070,7 +10051,7 @@ Stelle su GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -10082,7 +10063,7 @@ Estrazioni su Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -10182,7 +10163,7 @@ Gestisci la tua ricchezza come un capo apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -10190,7 +10171,7 @@ Ghostfolio è uno strumento open source e rispettoso della privacy per la gestione delle tue finanze personali. Analizza la tua allocazione degli asset, conosci il tuo patrimonio netto e prendi decisioni di investimento solide e basate sui dati. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -10198,11 +10179,11 @@ Inizia apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -10210,7 +10191,7 @@ o apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -10218,7 +10199,7 @@ Utenti attivi mensili apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -10226,7 +10207,7 @@ Come si vede su apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -10234,7 +10215,7 @@ Proteggi i tuoi asset. Perfeziona la tua strategia di investimento personale. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -10242,7 +10223,7 @@ Ghostfolio permette alle persone impegnate di tenere traccia di azioni, ETF o criptovalute senza essere tracciate. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -10250,7 +10231,7 @@ Vista a 360° apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -10258,7 +10239,7 @@ Pronto per il Web3 apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -10266,7 +10247,7 @@ Usa Ghostfolio in modo anonimo e possiedi i tuoi dati finanziari. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -10274,7 +10255,7 @@ Open source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -10282,7 +10263,7 @@ Beneficia dei continui miglioramenti grazie a una forte comunità. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -10290,7 +10271,7 @@ Perché Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -10298,7 +10279,7 @@ Ghostfolio è per te se... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -10306,7 +10287,7 @@ fai trading di azioni, ETF o criptovalute su più piattaforme apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -10314,7 +10295,7 @@ persegui una strategia buy & hold apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -10322,7 +10303,7 @@ sei interessato a conoscere la composizione del tuo portafoglio apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -10330,7 +10311,7 @@ valorizzi la privacy e la proprietà dei dati apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -10338,7 +10319,7 @@ sei per il minimalismo apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -10346,7 +10327,7 @@ ti interessa diversificare le tue risorse finanziarie apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -10354,7 +10335,7 @@ sei interessato all'indipendenza finanziaria apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -10362,7 +10343,7 @@ non vuoi utilizzare il foglio elettronico nel apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -10370,7 +10351,7 @@ stai ancora leggendo questo elenco apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -10378,7 +10359,7 @@ Ulteriori informazioni su Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -10386,7 +10367,7 @@ Cosa dicono i nostri utenti apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -10394,7 +10375,7 @@ Membri da tutto il mondo utilizzano Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -10402,7 +10383,7 @@ Come funziona Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -10410,7 +10391,7 @@ Iscriviti in modo anonimo* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -10418,7 +10399,7 @@ * non è richiesto alcun indirizzo email né la carta di credito apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -10426,7 +10407,7 @@ Aggiungi le tue transazioni storiche apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -10434,7 +10415,7 @@ Ottieni informazioni preziose sulla composizione del tuo portafoglio apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -10442,7 +10423,7 @@ Seipronto? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -10450,7 +10431,7 @@ Iscriviti adesso o consulta l'account di esempio apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -10458,11 +10439,11 @@ Demo in tempo reale apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -10470,7 +10451,7 @@ Ottieni un quadro completo delle tue finanze personali su più piattaforme. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -10478,7 +10459,7 @@ Inizia in soli 3 passi apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -11150,7 +11131,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -11186,7 +11167,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -13193,14 +13174,6 @@ 127 - - New - Nuovo - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Choose or drop a file here Choose or drop a file here @@ -13238,7 +13211,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13246,7 +13219,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13254,7 +13227,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -13286,7 +13259,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13294,7 +13267,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13434,7 +13407,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13738,7 +13711,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13762,7 +13735,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13770,7 +13743,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13778,7 +13751,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13786,7 +13759,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14634,7 +14607,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14658,7 +14631,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14706,7 +14679,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14734,7 +14707,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14802,7 +14775,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14810,7 +14783,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14818,7 +14791,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14826,7 +14799,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14834,7 +14807,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14878,7 +14851,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14886,7 +14859,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14970,7 +14943,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14985,7 +14958,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14993,7 +14966,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15001,16 +14974,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15018,7 +14991,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 9116a411a..620200f74 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -105,12 +105,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -138,7 +138,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -146,7 +146,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -154,7 +154,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -190,35 +190,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -294,7 +294,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -314,7 +314,7 @@ Taken verwijderen apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -337,8 +337,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -354,7 +354,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -362,7 +362,7 @@ Pogingen apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -370,7 +370,7 @@ Aangemaakt apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -378,7 +378,7 @@ Voltooid apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -386,7 +386,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -410,7 +410,7 @@ Bekijk gegevens apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -418,7 +418,7 @@ Bekijk Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -426,7 +426,7 @@ Taak verwijderen apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -446,11 +446,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -465,8 +465,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -486,11 +486,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -506,7 +506,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -530,11 +530,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -546,7 +546,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -561,8 +561,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -728,6 +728,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -837,8 +841,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -1218,10 +1222,6 @@ Activiteiten beheren apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -1262,7 +1262,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1326,7 +1326,7 @@ Kopen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -1334,7 +1334,7 @@ Verkopen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -1342,11 +1342,11 @@ Belegging apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -1354,7 +1354,7 @@ Absoluut bruto rendement apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -1362,26 +1362,7 @@ Bruto rendement apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - Transactiekosten voor - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -1389,7 +1370,7 @@ Absoluut netto rendement apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -1397,7 +1378,7 @@ Netto rendement apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -1405,7 +1386,7 @@ Totaal Activa apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -1413,7 +1394,7 @@ Kostbaarheden apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -1421,7 +1402,7 @@ Noodfonds apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -1437,7 +1418,7 @@ Koopkracht apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -1445,7 +1426,7 @@ Netto waarde apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -1453,7 +1434,7 @@ Rendement per jaar apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -1461,11 +1442,11 @@ Dividend apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -1473,11 +1454,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -1485,7 +1466,7 @@ Voer het bedrag van je noodfonds in: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 @@ -1500,8 +1481,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -1520,8 +1501,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -1532,12 +1513,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -1548,8 +1529,8 @@ Report Data Glitch Gegevensstoring melden - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -1568,12 +1549,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -1581,7 +1562,7 @@ Toon alle libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -1593,7 +1574,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -1605,7 +1586,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -1617,7 +1598,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -1629,7 +1610,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -1641,7 +1622,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -1653,7 +1634,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -1665,7 +1646,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -1673,7 +1654,7 @@ Oké apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2045,7 +2026,7 @@ Contant geld apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -2069,7 +2050,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2169,7 +2150,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -2185,11 +2166,11 @@ Markten apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -2205,7 +2186,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -2309,7 +2290,7 @@ Tijdlijn investeringen apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -2325,7 +2306,7 @@ Verliezers apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -2368,16 +2349,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -2392,7 +2369,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -2429,7 +2406,7 @@ Verkopen libs/ui/src/lib/i18n.ts - 36 + 37 @@ -2441,19 +2418,19 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 Quantity Hoeveelheid - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2465,11 +2442,11 @@ Prijs per eenheid apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2481,11 +2458,11 @@ Transactiekosten apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2505,7 +2482,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2524,12 +2501,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2541,7 +2518,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -2577,7 +2554,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -2745,7 +2722,7 @@ Wil je deze activiteit echt verwijderen? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -2817,7 +2794,7 @@ Oeps! Er ging iets mis. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2833,7 +2810,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2844,8 +2821,12 @@ Change Verandering - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 @@ -2876,28 +2857,28 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 Average Unit Price Gemiddelde prijs per eenheid - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Maximum Price Maximale prijs - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 @@ -2932,8 +2913,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2948,16 +2929,16 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 Minimum Price Minimale prijs - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 @@ -2965,7 +2946,7 @@ Verwacht totaalbedrag libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -2973,7 +2954,7 @@ Besparingen libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -2981,11 +2962,11 @@ Rente libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -2993,7 +2974,7 @@ Storting libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -3029,7 +3010,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3041,7 +3022,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -3109,7 +3090,7 @@ Uitgesloten van analyse apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3165,7 +3146,7 @@ Waardeontwikkeling van portefeuille apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -3197,7 +3178,7 @@ Symbool libs/ui/src/lib/i18n.ts - 24 + 25 @@ -3205,7 +3186,7 @@ Label libs/ui/src/lib/i18n.ts - 25 + 26 @@ -3213,7 +3194,7 @@ Contant geld libs/ui/src/lib/i18n.ts - 39 + 40 @@ -3221,7 +3202,7 @@ Grondstof libs/ui/src/lib/i18n.ts - 40 + 41 @@ -3229,7 +3210,7 @@ Equity libs/ui/src/lib/i18n.ts - 41 + 42 @@ -3237,7 +3218,7 @@ Vast inkomen libs/ui/src/lib/i18n.ts - 42 + 43 @@ -3245,7 +3226,7 @@ Vastgoed libs/ui/src/lib/i18n.ts - 43 + 45 @@ -3253,7 +3234,7 @@ Obligatie libs/ui/src/lib/i18n.ts - 46 + 48 @@ -3261,7 +3242,7 @@ Cryptovaluta libs/ui/src/lib/i18n.ts - 47 + 49 @@ -3269,7 +3250,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -3277,7 +3258,7 @@ Beleggingsfonds libs/ui/src/lib/i18n.ts - 49 + 51 @@ -3285,7 +3266,7 @@ Edelmetaal libs/ui/src/lib/i18n.ts - 50 + 52 @@ -3293,7 +3274,7 @@ Private equity libs/ui/src/lib/i18n.ts - 51 + 53 @@ -3301,7 +3282,7 @@ Aandeel libs/ui/src/lib/i18n.ts - 52 + 54 @@ -3309,7 +3290,7 @@ Noodfonds libs/ui/src/lib/i18n.ts - 12 + 13 @@ -3317,11 +3298,11 @@ Anders libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -3329,11 +3310,11 @@ Geen gegevens beschikbaar libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -3341,7 +3322,7 @@ Noord-Amerika libs/ui/src/lib/i18n.ts - 62 + 64 @@ -3349,7 +3330,7 @@ Afrika libs/ui/src/lib/i18n.ts - 59 + 61 @@ -3357,7 +3338,7 @@ Azië libs/ui/src/lib/i18n.ts - 60 + 62 @@ -3365,7 +3346,7 @@ Europa libs/ui/src/lib/i18n.ts - 61 + 63 @@ -3373,7 +3354,7 @@ Oceanië libs/ui/src/lib/i18n.ts - 63 + 65 @@ -3381,7 +3362,7 @@ Zuid-Amerika libs/ui/src/lib/i18n.ts - 64 + 66 @@ -3481,7 +3462,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -3489,7 +3470,7 @@ Tijdlijn dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -3561,11 +3542,11 @@ Samenvatting apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -3613,7 +3594,7 @@ Kern libs/ui/src/lib/i18n.ts - 8 + 9 @@ -3621,7 +3602,7 @@ Toelage libs/ui/src/lib/i18n.ts - 13 + 14 @@ -3629,7 +3610,7 @@ Hoger risico libs/ui/src/lib/i18n.ts - 14 + 15 @@ -3637,7 +3618,7 @@ Lager risico libs/ui/src/lib/i18n.ts - 17 + 18 @@ -3645,7 +3626,7 @@ Pensioen libs/ui/src/lib/i18n.ts - 22 + 23 @@ -3653,7 +3634,7 @@ Satelliet libs/ui/src/lib/i18n.ts - 23 + 24 @@ -3913,11 +3894,11 @@ Kosten apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3973,7 +3954,7 @@ Eenvoudig overstappen naar Ghostfolio Premium libs/ui/src/lib/i18n.ts - 10 + 11 @@ -3997,7 +3978,7 @@ Eenvoudig overstappen naar Ghostfolio Premium of Ghostfolio Open Source libs/ui/src/lib/i18n.ts - 9 + 10 @@ -4005,7 +3986,7 @@ Eenvoudig overstappen naar Ghostfolio Open Source of Ghostfolio Basic libs/ui/src/lib/i18n.ts - 11 + 12 @@ -4021,7 +4002,7 @@ Oeps! Kon de historische wisselkoers niet krijgen van apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4105,7 +4086,7 @@ Wil je echt al je activiteiten verwijderen? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4129,7 +4110,7 @@ Platform bijwerken apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -4137,7 +4118,7 @@ Platform toevoegen apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -4153,7 +4134,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -4177,7 +4158,7 @@ Saldo bijwerken apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4245,7 +4226,7 @@ Deze activiteit bestaat al. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -4337,7 +4318,7 @@ Huidige reeks apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4345,7 +4326,7 @@ Langste reeks apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4353,7 +4334,7 @@ Maanden libs/ui/src/lib/i18n.ts - 19 + 20 @@ -4361,7 +4342,7 @@ Jaren libs/ui/src/lib/i18n.ts - 27 + 28 @@ -4369,7 +4350,7 @@ Maand libs/ui/src/lib/i18n.ts - 18 + 19 @@ -4377,7 +4358,7 @@ Jaar libs/ui/src/lib/i18n.ts - 26 + 27 @@ -4385,7 +4366,7 @@ Verplichtingen apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -4525,7 +4506,7 @@ Verplichtingen libs/ui/src/lib/i18n.ts - 35 + 36 @@ -9861,7 +9842,7 @@ Koop libs/ui/src/lib/i18n.ts - 30 + 31 @@ -9869,7 +9850,7 @@ Waardevol libs/ui/src/lib/i18n.ts - 34 + 35 @@ -9893,7 +9874,7 @@ Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -9901,7 +9882,7 @@ Voorinstelling libs/ui/src/lib/i18n.ts - 21 + 22 @@ -9925,7 +9906,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -10069,7 +10050,7 @@ Sterren op GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -10081,7 +10062,7 @@ Pulls op Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -10181,7 +10162,7 @@ Beheer je vermogen als een baas apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -10189,7 +10170,7 @@ Ghostfolio is een privacygericht, open source dashboard voor je persoonlijke financiën. Analyseer je asset-allocatie, ken je nettowaarde en neem gefundeerde, datagedreven investeringsbeslissingen. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -10197,11 +10178,11 @@ Aan de slag apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -10209,7 +10190,7 @@ of apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -10217,7 +10198,7 @@ Maandelijkse actieve gebruikers apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -10225,7 +10206,7 @@ Zoals te zien in apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -10233,7 +10214,7 @@ Bescherm je financiële bezittingen. Verfijn je persoonlijke investeringsstrategie. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -10241,7 +10222,7 @@ Ghostfolio stelt drukbezette mensen in staat om aandelen, ETF's of cryptocurrencies bij te houden zonder gevolgd te worden. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -10249,7 +10230,7 @@ 360°-overzicht apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -10257,7 +10238,7 @@ Klaar voor Web3 apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -10265,7 +10246,7 @@ Gebruik Ghostfolio anoniem en bezit je financiële gegevens. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -10273,7 +10254,7 @@ Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -10281,7 +10262,7 @@ Profiteer van voortdurende verbeteringen door een sterke gemeenschap. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -10289,7 +10270,7 @@ Waarom Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -10297,7 +10278,7 @@ Ghostfolio is iets voor je als je... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -10305,7 +10286,7 @@ handelt in aandelen, ETF's of cryptocurrencies op meerdere platforms apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -10313,7 +10294,7 @@ streeft naar een buy & hold strategie apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -10321,7 +10302,7 @@ geïnteresseerd bent in het krijgen van inzicht in je portefeuillesamenstelling apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -10329,7 +10310,7 @@ privacy en eigendom van gegevens waardeert apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -10337,7 +10318,7 @@ houdt van een minimalistisch ontwerp apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -10345,7 +10326,7 @@ zorgdraagt voor het diversifiëren van je financiële middelen apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -10353,7 +10334,7 @@ geïnteresseerd bent in financiële onafhankelijkheid apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -10361,7 +10342,7 @@ "nee" zegt tegen spreadsheets in apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -10369,7 +10350,7 @@ nog steeds deze lijst aan het lezen bent apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -10377,7 +10358,7 @@ Leer meer over Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -10385,7 +10366,7 @@ Wat onze gebruikers zeggen apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -10393,7 +10374,7 @@ Leden van over de hele wereld gebruikenGhostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -10401,7 +10382,7 @@ Hoe Ghostfolio werkt? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -10409,7 +10390,7 @@ Anoniem aanmelden* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -10417,7 +10398,7 @@ * geen e-mailadres of creditcard nodig apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -10425,7 +10406,7 @@ Voeg al je historische transacties toe apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -10433,7 +10414,7 @@ Krijg waardevolle inzichten in de samenstelling van je portefeuille apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -10441,7 +10422,7 @@ Ben je er klaar voor? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -10449,7 +10430,7 @@ Nu lid worden of bekijk het voorbeeld account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -10457,11 +10438,11 @@ Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -10469,7 +10450,7 @@ Krijg een volledig beeld van je persoonlijke financiën op meerdere platforms. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -10477,7 +10458,7 @@ Aan de slag in slechts 3 stappen apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -11149,7 +11130,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -11185,7 +11166,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -13192,14 +13173,6 @@ 127 - - New - New - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Choose or drop a file here Choose or drop a file here @@ -13237,7 +13210,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13245,7 +13218,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13253,7 +13226,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -13285,7 +13258,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13293,7 +13266,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13433,7 +13406,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13737,7 +13710,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13761,7 +13734,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13769,7 +13742,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13777,7 +13750,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13785,7 +13758,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14633,7 +14606,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14657,7 +14630,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14705,7 +14678,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14733,7 +14706,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14801,7 +14774,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14809,7 +14782,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14817,7 +14790,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14825,7 +14798,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14833,7 +14806,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14877,7 +14850,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14885,7 +14858,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14969,7 +14942,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14984,7 +14957,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14992,7 +14965,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15000,16 +14973,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15017,7 +14990,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index c02f78aee..4ea586194 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -654,7 +654,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -690,7 +690,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -1621,12 +1621,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -1682,7 +1682,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -1690,7 +1690,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1698,7 +1698,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1738,7 +1738,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1762,35 +1762,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1866,7 +1866,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1917,8 +1917,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -1934,7 +1934,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -1942,7 +1942,7 @@ Attempts apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -1950,7 +1950,7 @@ Created apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -1958,7 +1958,7 @@ Finished apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -1966,7 +1966,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -1974,7 +1974,7 @@ Delete Jobs apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -1982,7 +1982,7 @@ View Data apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -1990,7 +1990,7 @@ View Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -1998,7 +1998,7 @@ Delete Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -2018,11 +2018,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2037,8 +2037,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -2058,11 +2058,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2078,7 +2078,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -2102,11 +2102,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2118,7 +2118,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -2177,12 +2177,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2201,12 +2201,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -2221,8 +2221,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -2298,7 +2298,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -2341,8 +2341,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2357,8 +2357,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -2373,8 +2373,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -2393,8 +2393,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -2434,7 +2434,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2470,7 +2470,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 @@ -2616,6 +2616,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -2654,7 +2658,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -2677,8 +2681,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -2702,7 +2706,7 @@ Update platform apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -2710,7 +2714,7 @@ Add platform apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -2729,12 +2733,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -2762,7 +2766,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -2770,7 +2774,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -2837,12 +2841,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -2870,7 +2874,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -3006,10 +3010,6 @@ Manage Activities apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -3022,7 +3022,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3034,7 +3034,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -3138,7 +3138,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -3150,7 +3150,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -3198,7 +3198,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -3245,34 +3245,12 @@ 3 - - - - - - - - - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 - - Buy Buy apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -3280,7 +3258,7 @@ Sell apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -3288,11 +3266,11 @@ Investment apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -3300,7 +3278,7 @@ Absolute Gross Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -3308,7 +3286,7 @@ Gross Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 + 85 @@ -3316,11 +3294,11 @@ Fees apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3332,7 +3310,7 @@ Absolute Net Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -3340,7 +3318,7 @@ Net Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -3348,7 +3326,7 @@ Total Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -3356,7 +3334,7 @@ Valuables apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -3364,7 +3342,7 @@ Emergency Fund apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -3380,7 +3358,7 @@ Cash apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -3388,7 +3366,7 @@ Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -3396,7 +3374,7 @@ Buying Power apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -3404,7 +3382,7 @@ Excluded from Analysis apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3412,7 +3390,7 @@ Liabilities apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -3424,7 +3402,7 @@ Net Worth apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -3432,7 +3410,7 @@ Annualized Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -3440,7 +3418,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -3448,11 +3426,11 @@ Dividend apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -3460,11 +3438,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -3472,51 +3450,55 @@ Please enter the amount of your emergency fund: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 Change Change - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price Average Unit Price - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price Minimum Price - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price Maximum Price - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 Quantity Quantity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3527,8 +3509,8 @@ Report Data Glitch Report Data Glitch - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -3688,7 +3670,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -3700,7 +3682,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -3712,7 +3694,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -3724,7 +3706,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -3736,7 +3718,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -4016,7 +3998,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -4028,7 +4010,7 @@ Oops! Something went wrong. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -4040,7 +4022,7 @@ Okay apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -4136,7 +4118,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -4248,7 +4230,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -4451,16 +4433,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -4472,11 +4450,11 @@ Summary apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -4484,11 +4462,11 @@ Markets apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -4519,20 +4497,12 @@ 14 - - New - New - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Manage your wealth like a boss Manage your wealth like a boss apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -4540,7 +4510,7 @@ Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -4548,11 +4518,11 @@ Get Started apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -4560,7 +4530,7 @@ or apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -4568,11 +4538,11 @@ Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -4580,7 +4550,7 @@ Monthly Active Users apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -4588,7 +4558,7 @@ Stars on GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -4600,7 +4570,7 @@ Pulls on Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -4612,7 +4582,7 @@ As seen in apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -4620,7 +4590,7 @@ Protect your assets. Refine your personal investment strategy. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -4628,7 +4598,7 @@ Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -4636,7 +4606,7 @@ 360° View apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -4644,7 +4614,7 @@ Get the full picture of your personal finances across multiple platforms. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -4652,7 +4622,7 @@ Web3 Ready apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -4660,7 +4630,7 @@ Use Ghostfolio anonymously and own your financial data. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -4668,7 +4638,7 @@ Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -4676,7 +4646,7 @@ Benefit from continuous improvements through a strong community. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -4684,7 +4654,7 @@ Why Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -4692,7 +4662,7 @@ Ghostfolio is for you if you are... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -4700,7 +4670,7 @@ trading stocks, ETFs or cryptocurrencies on multiple platforms apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -4708,7 +4678,7 @@ pursuing a buy & hold strategy apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -4716,7 +4686,7 @@ interested in getting insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -4724,7 +4694,7 @@ valuing privacy and data ownership apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -4732,7 +4702,7 @@ into minimalism apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -4740,7 +4710,7 @@ caring about diversifying your financial resources apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -4748,7 +4718,7 @@ interested in financial independence apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -4756,7 +4726,7 @@ saying no to spreadsheets in apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -4764,7 +4734,7 @@ still reading this list apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -4772,7 +4742,7 @@ Learn more about Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -4780,7 +4750,7 @@ What our users are saying apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -4788,7 +4758,7 @@ Members from around the globe are using Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -4796,7 +4766,7 @@ How does Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -4804,7 +4774,7 @@ Get started in only 3 steps apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -4812,7 +4782,7 @@ Sign up anonymously* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -4820,7 +4790,7 @@ * no e-mail address nor credit card required apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -4828,7 +4798,7 @@ Add any of your historical transactions apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -4836,7 +4806,7 @@ Get valuable insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -4844,7 +4814,7 @@ Are you ready? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -4852,7 +4822,7 @@ Join now or check out the example account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -4944,7 +4914,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -4952,7 +4922,7 @@ Do you really want to delete all your activities? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -5032,7 +5002,7 @@ Update Cash Balance apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -5040,11 +5010,11 @@ Unit Price apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -5056,7 +5026,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -5064,11 +5034,11 @@ Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -5080,7 +5050,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -5208,7 +5178,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -5388,7 +5358,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -5396,7 +5366,7 @@ Deposit libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -5436,7 +5406,7 @@ Bottom apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -5444,7 +5414,7 @@ Portfolio Evolution apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -5452,7 +5422,7 @@ Investment Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -5460,7 +5430,7 @@ Current Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -5468,7 +5438,7 @@ Longest Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -5476,7 +5446,7 @@ Dividend Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -5543,7 +5513,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -13220,7 +13190,7 @@ Do you really want to delete this activity? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -13228,7 +13198,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13320,7 +13290,7 @@ Projected Total Amount libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -13328,11 +13298,11 @@ Interest libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -13340,7 +13310,7 @@ Savings libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -13356,7 +13326,7 @@ Show all libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -13396,7 +13366,7 @@ Core libs/ui/src/lib/i18n.ts - 8 + 9 @@ -13404,7 +13374,7 @@ Switch to Ghostfolio Premium or Ghostfolio Open Source easily libs/ui/src/lib/i18n.ts - 9 + 10 @@ -13412,7 +13382,7 @@ Switch to Ghostfolio Premium easily libs/ui/src/lib/i18n.ts - 10 + 11 @@ -13420,7 +13390,7 @@ Switch to Ghostfolio Open Source or Ghostfolio Basic easily libs/ui/src/lib/i18n.ts - 11 + 12 @@ -13428,7 +13398,7 @@ Emergency Fund libs/ui/src/lib/i18n.ts - 12 + 13 @@ -13436,7 +13406,7 @@ Grant libs/ui/src/lib/i18n.ts - 13 + 14 @@ -13444,7 +13414,7 @@ Higher Risk libs/ui/src/lib/i18n.ts - 14 + 15 @@ -13452,7 +13422,7 @@ This activity already exists. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -13460,7 +13430,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -13468,7 +13438,7 @@ Lower Risk libs/ui/src/lib/i18n.ts - 17 + 18 @@ -13476,7 +13446,7 @@ Month libs/ui/src/lib/i18n.ts - 18 + 19 @@ -13484,7 +13454,7 @@ Months libs/ui/src/lib/i18n.ts - 19 + 20 @@ -13492,11 +13462,11 @@ Other libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -13504,7 +13474,7 @@ Preset libs/ui/src/lib/i18n.ts - 21 + 22 @@ -13512,7 +13482,7 @@ Retirement Provision libs/ui/src/lib/i18n.ts - 22 + 23 @@ -13520,7 +13490,7 @@ Satellite libs/ui/src/lib/i18n.ts - 23 + 24 @@ -13528,7 +13498,7 @@ Symbol libs/ui/src/lib/i18n.ts - 24 + 25 @@ -13536,7 +13506,7 @@ Tag libs/ui/src/lib/i18n.ts - 25 + 26 @@ -13544,7 +13514,7 @@ Year libs/ui/src/lib/i18n.ts - 26 + 27 @@ -13552,7 +13522,7 @@ Years libs/ui/src/lib/i18n.ts - 27 + 28 @@ -13560,7 +13530,7 @@ Buy libs/ui/src/lib/i18n.ts - 30 + 31 @@ -13568,7 +13538,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13576,7 +13546,7 @@ Valuable libs/ui/src/lib/i18n.ts - 34 + 35 @@ -13584,7 +13554,7 @@ Liability libs/ui/src/lib/i18n.ts - 35 + 36 @@ -13592,7 +13562,7 @@ Sell libs/ui/src/lib/i18n.ts - 36 + 37 @@ -13600,7 +13570,7 @@ Cash libs/ui/src/lib/i18n.ts - 39 + 40 @@ -13608,7 +13578,7 @@ Commodity libs/ui/src/lib/i18n.ts - 40 + 41 @@ -13616,7 +13586,7 @@ Equity libs/ui/src/lib/i18n.ts - 41 + 42 @@ -13624,7 +13594,7 @@ Fixed Income libs/ui/src/lib/i18n.ts - 42 + 43 @@ -13632,7 +13602,7 @@ Real Estate libs/ui/src/lib/i18n.ts - 43 + 45 @@ -13640,7 +13610,7 @@ Bond libs/ui/src/lib/i18n.ts - 46 + 48 @@ -13648,7 +13618,7 @@ Cryptocurrency libs/ui/src/lib/i18n.ts - 47 + 49 @@ -13656,7 +13626,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -13664,7 +13634,7 @@ Mutual Fund libs/ui/src/lib/i18n.ts - 49 + 51 @@ -13672,7 +13642,7 @@ Precious Metal libs/ui/src/lib/i18n.ts - 50 + 52 @@ -13680,7 +13650,7 @@ Private Equity libs/ui/src/lib/i18n.ts - 51 + 53 @@ -13688,7 +13658,7 @@ Stock libs/ui/src/lib/i18n.ts - 52 + 54 @@ -13696,7 +13666,7 @@ Africa libs/ui/src/lib/i18n.ts - 59 + 61 @@ -13704,7 +13674,7 @@ Asia libs/ui/src/lib/i18n.ts - 60 + 62 @@ -13712,7 +13682,7 @@ Europe libs/ui/src/lib/i18n.ts - 61 + 63 @@ -13720,7 +13690,7 @@ North America libs/ui/src/lib/i18n.ts - 62 + 64 @@ -13728,7 +13698,7 @@ Oceania libs/ui/src/lib/i18n.ts - 63 + 65 @@ -13736,7 +13706,7 @@ South America libs/ui/src/lib/i18n.ts - 64 + 66 @@ -13744,7 +13714,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13752,7 +13722,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13760,7 +13730,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13792,11 +13762,11 @@ No data available libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -14636,7 +14606,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14660,7 +14630,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14708,7 +14678,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14736,7 +14706,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14804,7 +14774,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14812,7 +14782,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14820,7 +14790,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14828,7 +14798,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14836,7 +14806,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14880,7 +14850,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14888,7 +14858,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14972,7 +14942,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14987,7 +14957,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14995,7 +14965,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15003,16 +14973,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15020,7 +14990,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 6ebacade4..1709130f0 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -117,12 +117,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -150,7 +150,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -158,7 +158,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -166,7 +166,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -206,7 +206,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -246,35 +246,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -350,7 +350,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -385,8 +385,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -402,7 +402,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -410,7 +410,7 @@ Tentativas apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -418,7 +418,7 @@ Criado apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -426,7 +426,7 @@ Terminado apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -434,7 +434,7 @@ Estado apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -442,7 +442,7 @@ Eliminar Tarefas apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -466,7 +466,7 @@ Visualizar dados apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -474,7 +474,7 @@ Ver Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -482,7 +482,7 @@ Apagar Tarefa apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -502,11 +502,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -521,8 +521,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -542,11 +542,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -562,7 +562,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -586,11 +586,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -602,7 +602,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -629,12 +629,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -653,12 +653,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -673,8 +673,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -856,6 +856,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -917,8 +921,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -953,12 +957,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -978,7 +982,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -1398,10 +1402,6 @@ Gerir Atividades apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -1414,7 +1414,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -1426,7 +1426,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -1446,7 +1446,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -1458,7 +1458,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -1474,7 +1474,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -1514,7 +1514,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -1566,7 +1566,7 @@ Compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -1574,7 +1574,7 @@ Venda apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -1582,11 +1582,11 @@ Investimento apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -1594,7 +1594,7 @@ Desempenho Bruto Absoluto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -1602,26 +1602,7 @@ Desempenho Bruto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - Taxas para - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transação} other {transações}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -1629,7 +1610,7 @@ Desempenho Líquido Absoluto apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -1637,7 +1618,7 @@ Desempenho Líquido apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -1645,7 +1626,7 @@ Ativos Totais apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -1653,7 +1634,7 @@ Bens de valor apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -1661,7 +1642,7 @@ Fundo de Emergência apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -1677,7 +1658,7 @@ Poder de Compra apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -1685,7 +1666,7 @@ Excluído da Análise apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -1693,7 +1674,7 @@ Valor Líquido apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -1701,7 +1682,7 @@ Desempenho Anual apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -1709,11 +1690,11 @@ Dividendo apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -1721,11 +1702,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -1733,51 +1714,55 @@ Por favor, insira o valor do seu fundo de emergência: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 Change Alterar - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price Preço Médio por Unidade - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price Preço Mínimo - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price Preço Máximo - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 Quantity Quantidade - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1792,8 +1777,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -1808,8 +1793,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -1824,8 +1809,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -1844,8 +1829,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -1856,12 +1841,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -1872,8 +1857,8 @@ Report Data Glitch Dados do Relatório com Problema - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -1889,7 +1874,7 @@ Mostrar tudo libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -1901,7 +1886,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -1913,7 +1898,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -1925,7 +1910,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -1937,7 +1922,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -1949,7 +1934,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -1969,7 +1954,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -1981,7 +1966,7 @@ Oops! Ocorreu um erro. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -1993,7 +1978,7 @@ OK apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -2345,7 +2330,7 @@ Dinheiro apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -2497,7 +2482,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -2513,11 +2498,11 @@ Mercados apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -2533,7 +2518,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -2561,7 +2546,7 @@ Venda libs/ui/src/lib/i18n.ts - 36 + 37 @@ -2573,7 +2558,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 @@ -2581,11 +2566,11 @@ Preço por Unidade apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2597,11 +2582,11 @@ Comissão apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2621,7 +2606,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2669,7 +2654,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -2833,7 +2818,7 @@ Fundo apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -2841,7 +2826,7 @@ Evolução do Portefólio apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -2849,7 +2834,7 @@ Cronograma de Investimento apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -2892,16 +2877,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -2916,7 +2897,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -3137,7 +3118,7 @@ Deseja realmente eliminar esta atividade? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -3177,7 +3158,7 @@ Montante Total Projetado libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -3185,11 +3166,11 @@ Juros libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -3197,7 +3178,7 @@ Poupanças libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -3221,7 +3202,7 @@ Fundo de Emergência libs/ui/src/lib/i18n.ts - 12 + 13 @@ -3229,11 +3210,11 @@ Outro libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -3241,7 +3222,7 @@ Símbolo libs/ui/src/lib/i18n.ts - 24 + 25 @@ -3249,7 +3230,7 @@ Marcador libs/ui/src/lib/i18n.ts - 25 + 26 @@ -3257,7 +3238,7 @@ Dinheiro libs/ui/src/lib/i18n.ts - 39 + 40 @@ -3265,7 +3246,7 @@ Matéria-prima libs/ui/src/lib/i18n.ts - 40 + 41 @@ -3273,7 +3254,7 @@ Ações libs/ui/src/lib/i18n.ts - 41 + 42 @@ -3281,7 +3262,7 @@ Rendimento Fixo libs/ui/src/lib/i18n.ts - 42 + 43 @@ -3289,7 +3270,7 @@ Imobiliário libs/ui/src/lib/i18n.ts - 43 + 45 @@ -3297,7 +3278,7 @@ Obrigação libs/ui/src/lib/i18n.ts - 46 + 48 @@ -3305,7 +3286,7 @@ Criptomoedas libs/ui/src/lib/i18n.ts - 47 + 49 @@ -3313,7 +3294,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -3321,7 +3302,7 @@ Fundo de Investimento libs/ui/src/lib/i18n.ts - 49 + 51 @@ -3329,7 +3310,7 @@ Metal Precioso libs/ui/src/lib/i18n.ts - 50 + 52 @@ -3337,7 +3318,7 @@ Private Equity libs/ui/src/lib/i18n.ts - 51 + 53 @@ -3345,7 +3326,7 @@ Ação libs/ui/src/lib/i18n.ts - 52 + 54 @@ -3353,7 +3334,7 @@ África libs/ui/src/lib/i18n.ts - 59 + 61 @@ -3361,7 +3342,7 @@ Ásia libs/ui/src/lib/i18n.ts - 60 + 62 @@ -3369,7 +3350,7 @@ Europa libs/ui/src/lib/i18n.ts - 61 + 63 @@ -3377,7 +3358,7 @@ América do Norte libs/ui/src/lib/i18n.ts - 62 + 64 @@ -3385,7 +3366,7 @@ Oceânia libs/ui/src/lib/i18n.ts - 63 + 65 @@ -3393,7 +3374,7 @@ América do Sul libs/ui/src/lib/i18n.ts - 64 + 66 @@ -3409,11 +3390,11 @@ Sem dados disponíveis libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -3509,11 +3490,11 @@ Sumário apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -3549,7 +3530,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -3557,7 +3538,7 @@ Cronograma de Dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -3613,7 +3594,7 @@ Núcleo libs/ui/src/lib/i18n.ts - 8 + 9 @@ -3621,7 +3602,7 @@ Conceder libs/ui/src/lib/i18n.ts - 13 + 14 @@ -3629,7 +3610,7 @@ Risco mais Elevado libs/ui/src/lib/i18n.ts - 14 + 15 @@ -3637,7 +3618,7 @@ Risco menos Elevado libs/ui/src/lib/i18n.ts - 17 + 18 @@ -3645,7 +3626,7 @@ Provisão de Reforma libs/ui/src/lib/i18n.ts - 22 + 23 @@ -3653,7 +3634,7 @@ Satélite libs/ui/src/lib/i18n.ts - 23 + 24 @@ -3913,11 +3894,11 @@ Taxas apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3973,7 +3954,7 @@ Mude para o Ghostfolio Premium facilmente libs/ui/src/lib/i18n.ts - 10 + 11 @@ -3997,7 +3978,7 @@ Mude para o Ghostfolio Premium ou Ghostfolio Open Source facilmente libs/ui/src/lib/i18n.ts - 9 + 10 @@ -4005,7 +3986,7 @@ Mude para o Ghostfolio Open Source ou Ghostfolio Basic facilmente libs/ui/src/lib/i18n.ts - 11 + 12 @@ -4021,7 +4002,7 @@ Oops! Não foi possível obter a taxa de câmbio histórica de apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4105,7 +4086,7 @@ Deseja mesmo eliminar todas as suas atividades? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4129,7 +4110,7 @@ Atualizar plataforma apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -4137,7 +4118,7 @@ Adicionar plataforma apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -4153,7 +4134,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -4177,7 +4158,7 @@ Atualizar saldo em Dinheiro apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4245,7 +4226,7 @@ Essa atividade já existe. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -4337,7 +4318,7 @@ Série Atual apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4345,7 +4326,7 @@ Série mais Longa apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4353,7 +4334,7 @@ Meses libs/ui/src/lib/i18n.ts - 19 + 20 @@ -4361,7 +4342,7 @@ Anos libs/ui/src/lib/i18n.ts - 27 + 28 @@ -4369,7 +4350,7 @@ Mês libs/ui/src/lib/i18n.ts - 18 + 19 @@ -4377,7 +4358,7 @@ Ano libs/ui/src/lib/i18n.ts - 26 + 27 @@ -4385,7 +4366,7 @@ Liabilities apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -4525,7 +4506,7 @@ Liability libs/ui/src/lib/i18n.ts - 35 + 36 @@ -9861,7 +9842,7 @@ Buy libs/ui/src/lib/i18n.ts - 30 + 31 @@ -9869,7 +9850,7 @@ Valuable libs/ui/src/lib/i18n.ts - 34 + 35 @@ -9893,7 +9874,7 @@ Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -9901,7 +9882,7 @@ Preset libs/ui/src/lib/i18n.ts - 21 + 22 @@ -9925,7 +9906,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -10069,7 +10050,7 @@ Stars on GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -10081,7 +10062,7 @@ Pulls on Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -10181,7 +10162,7 @@ Manage your wealth like a boss apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -10189,7 +10170,7 @@ Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -10197,11 +10178,11 @@ Get Started apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -10209,7 +10190,7 @@ or apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -10217,7 +10198,7 @@ Monthly Active Users apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -10225,7 +10206,7 @@ As seen in apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -10233,7 +10214,7 @@ Protect your assets. Refine your personal investment strategy. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -10241,7 +10222,7 @@ Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -10249,7 +10230,7 @@ 360° View apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -10257,7 +10238,7 @@ Web3 Ready apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -10265,7 +10246,7 @@ Use Ghostfolio anonymously and own your financial data. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -10273,7 +10254,7 @@ Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -10281,7 +10262,7 @@ Benefit from continuous improvements through a strong community. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -10289,7 +10270,7 @@ Why Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -10297,7 +10278,7 @@ Ghostfolio is for you if you are... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -10305,7 +10286,7 @@ trading stocks, ETFs or cryptocurrencies on multiple platforms apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -10313,7 +10294,7 @@ pursuing a buy & hold strategy apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -10321,7 +10302,7 @@ interested in getting insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -10329,7 +10310,7 @@ valuing privacy and data ownership apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -10337,7 +10318,7 @@ into minimalism apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -10345,7 +10326,7 @@ caring about diversifying your financial resources apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -10353,7 +10334,7 @@ interested in financial independence apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -10361,7 +10342,7 @@ saying no to spreadsheets in apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -10369,7 +10350,7 @@ still reading this list apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -10377,7 +10358,7 @@ Learn more about Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -10385,7 +10366,7 @@ What our users are saying apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -10393,7 +10374,7 @@ Members from around the globe are using Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -10401,7 +10382,7 @@ How does Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -10409,7 +10390,7 @@ Sign up anonymously* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -10417,7 +10398,7 @@ * no e-mail address nor credit card required apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -10425,7 +10406,7 @@ Add any of your historical transactions apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -10433,7 +10414,7 @@ Get valuable insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -10441,7 +10422,7 @@ Are you ready? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -10449,7 +10430,7 @@ Join now or check out the example account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -10457,11 +10438,11 @@ Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -10469,7 +10450,7 @@ Get the full picture of your personal finances across multiple platforms. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -10477,7 +10458,7 @@ Get started in only 3 steps apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -11149,7 +11130,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -11185,7 +11166,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -13192,14 +13173,6 @@ 127 - - New - New - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Choose or drop a file here Choose or drop a file here @@ -13237,7 +13210,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13245,7 +13218,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13253,7 +13226,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -13285,7 +13258,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13293,7 +13266,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13433,7 +13406,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13737,7 +13710,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13761,7 +13734,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13769,7 +13742,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13777,7 +13750,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13785,7 +13758,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14633,7 +14606,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14657,7 +14630,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14705,7 +14678,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14733,7 +14706,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14801,7 +14774,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14809,7 +14782,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14817,7 +14790,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14825,7 +14798,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14833,7 +14806,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14877,7 +14850,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14885,7 +14858,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14969,7 +14942,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14984,7 +14957,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14992,7 +14965,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15000,16 +14973,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15017,7 +14990,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 39f5817ce..95fba4c70 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -654,7 +654,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -690,7 +690,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -1613,12 +1613,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -1646,7 +1646,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -1654,7 +1654,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1662,7 +1662,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1702,7 +1702,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1726,35 +1726,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1830,7 +1830,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1865,8 +1865,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -1882,7 +1882,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -1890,7 +1890,7 @@ Deneme apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -1898,7 +1898,7 @@ Oluşturuldu apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -1906,7 +1906,7 @@ Tamamlandı apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -1914,7 +1914,7 @@ Durum apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -1922,7 +1922,7 @@ İşleri Sil apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -1946,7 +1946,7 @@ Veri Gör apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -1954,7 +1954,7 @@ Hata İzini Görüntüle apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -1962,7 +1962,7 @@ İşleri Sil apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -1982,11 +1982,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2001,8 +2001,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -2022,11 +2022,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2042,7 +2042,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -2066,11 +2066,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2082,7 +2082,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -2133,12 +2133,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2157,12 +2157,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -2177,8 +2177,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -2273,8 +2273,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2289,8 +2289,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -2305,8 +2305,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -2325,8 +2325,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -2358,7 +2358,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2378,7 +2378,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 @@ -2469,12 +2469,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -2528,6 +2528,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -2566,7 +2570,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -2589,8 +2593,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -2614,7 +2618,7 @@ Platformu Güncelle apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -2622,7 +2626,7 @@ Platform Ekle apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -2697,12 +2701,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -2730,7 +2734,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -2858,10 +2862,6 @@ İşlemleri Yönet apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -2874,7 +2874,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -2886,7 +2886,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -2990,7 +2990,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -3002,7 +3002,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -3050,7 +3050,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -3102,7 +3102,7 @@ Al apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -3110,7 +3110,7 @@ Sat apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -3118,11 +3118,11 @@ Yatırım apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -3130,7 +3130,7 @@ Toplam Brüt Performans apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -3138,26 +3138,7 @@ Brüt Performans apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 - - - - - - - - için komisyon tutarı - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 + 85 @@ -3165,7 +3146,7 @@ Toplam Net Performans apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -3173,7 +3154,7 @@ Net Performans apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -3181,7 +3162,7 @@ Toplam Varlıklar apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -3189,7 +3170,7 @@ Yatırım Varlıkları apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -3197,7 +3178,7 @@ Acil Durum Yedeği apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -3213,7 +3194,7 @@ Nakit apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -3221,7 +3202,7 @@ Varlıklar apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -3229,7 +3210,7 @@ Alım Limiti apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -3237,7 +3218,7 @@ Analize Dahil Edilmemiştir. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3245,7 +3226,7 @@ Yükümlülükler apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -3257,7 +3238,7 @@ Toplam Varlık apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -3265,7 +3246,7 @@ Yıllıklandırılmış Performans apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -3273,11 +3254,11 @@ Temettü apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -3285,11 +3266,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -3297,51 +3278,55 @@ Lütfen acil durum yedeği meblağını giriniz: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 Change Para Birimi - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price Ortalama Birim Fiyat - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price Asgari Fiyat - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price Azami Fiyat - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 Quantity Miktar - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3353,11 +3338,11 @@ Komisyon apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3368,8 +3353,8 @@ Report Data Glitch Rapor Veri Sorunu - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -3529,7 +3514,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -3541,7 +3526,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -3553,7 +3538,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -3565,7 +3550,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -3577,7 +3562,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -3597,7 +3582,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -3609,7 +3594,7 @@ Hay Allah! Bir şeyler yanlış gitti. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -3621,7 +3606,7 @@ Tamam apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -3797,7 +3782,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -4012,16 +3997,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -4033,11 +4014,11 @@ Özet apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -4045,11 +4026,11 @@ Piyasalar apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -4061,7 +4042,7 @@ Servetinizi bir patron gibi yönetin apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -4069,7 +4050,7 @@ Ghostfolio, mali durumunuz için gizlilik odaklı, açık kaynaklı bir kontrol panelidi. Varlık dağılımınızı analiz edin, net değerinizi öğrenin ve sağlam, veriye dayalı yatırım kararları alın. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -4077,11 +4058,11 @@ Başla apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -4089,7 +4070,7 @@ veya apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -4097,11 +4078,11 @@ Canlı Deneme apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -4109,7 +4090,7 @@ Aylık Aktif Kullanıcılar apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -4117,7 +4098,7 @@ GitHub'daki Beğeniler apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -4129,7 +4110,7 @@ Docker Hub'ta Çekmeler apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -4141,7 +4122,7 @@ Şurada görüldüğü gibi apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -4149,7 +4130,7 @@ varlıklarınızı koruyun. Kişisel yatırım stratejinizi geliştirin. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -4157,7 +4138,7 @@ Ghostfolio, takip edilmeden hisse senetleri, ETF'ler veya kripto paraları izlemek isteyen yoğun insanlara güç verir. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -4165,7 +4146,7 @@ 360° Görünüm apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -4173,7 +4154,7 @@ Kişisel finansınızın tam resmini birden fazla platformda edinin. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -4181,7 +4162,7 @@ Web3 Hazır apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -4189,7 +4170,7 @@ Ghostfolio'yu anonim olarak kullanın ve finansal verilerinize sahip çıkın. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -4197,7 +4178,7 @@ Açık Kaynak apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -4205,7 +4186,7 @@ Güçlü bir topluluk aracılığıyla sürekli gelişmelerden faydalanın. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -4213,7 +4194,7 @@ Why Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -4221,7 +4202,7 @@ Ghostfolio tam size göre, apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -4229,7 +4210,7 @@ Birden fazla platformda hisse senedi, ETF veya kripto para ticareti yapıyorsanız, apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -4237,7 +4218,7 @@ al ve tut stratejisi izliyorsanız, apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -4245,7 +4226,7 @@ Portföy bileşimine dair içgörüleri edinmek istiyorsanız, apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -4253,7 +4234,7 @@ Gizliliğe ve verilerinize sahip çıkmayı önemsiyorsanız apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -4261,7 +4242,7 @@ minimalizme ilgi duyuyorsanız apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -4269,7 +4250,7 @@ finansal kaynaklarınızı çeşitlendirmeye önem veriyorsanız apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -4277,7 +4258,7 @@ finansal özgürlük peşindeyseniz apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -4285,7 +4266,7 @@ elektronik tablo uygulamalarına hayır diyorsanız apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -4293,7 +4274,7 @@ bu listeyi hala okuyorsanız apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -4301,7 +4282,7 @@ Ghostfolio hakkında daha fazla bilgi edinin apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -4309,7 +4290,7 @@ What our users are saying apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -4317,7 +4298,7 @@ Members from around the globe are using Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -4325,7 +4306,7 @@ How does Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -4333,7 +4314,7 @@ Sadece 3 adımda başlayın apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -4341,7 +4322,7 @@ Anonim olarak kaydolun* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -4349,7 +4330,7 @@ * e-posta adresi veya kredi kartı gerekmez apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -4357,7 +4338,7 @@ Herhangi bir geçmiş işleminizi ekleyin apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -4365,7 +4346,7 @@ Portföy bileşiminizle ilgili değerli bilgiler edinin apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -4373,7 +4354,7 @@ Are you ready? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -4381,7 +4362,7 @@ Join now or check out the example account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -4445,7 +4426,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -4453,7 +4434,7 @@ Tüm işlemlerinizi silmeyi gerçekten istiyor musunuz? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4509,7 +4490,7 @@ Nakit Bakiyesini Güncelle apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -4517,11 +4498,11 @@ Birim Fiyat apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -4533,7 +4514,7 @@ Hay Allah! Geçmiş döviz kuru alınamadı: apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4541,11 +4522,11 @@ Komisyon apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -4685,7 +4666,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -4865,7 +4846,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -4873,7 +4854,7 @@ Para Yatırma libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -4913,7 +4894,7 @@ Alt apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -4921,7 +4902,7 @@ Portföyün Gelişimi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -4929,7 +4910,7 @@ Yatırım Zaman Çizelgesi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -4937,7 +4918,7 @@ Güncel Seri apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -4945,7 +4926,7 @@ En Uzun Seri apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -4953,7 +4934,7 @@ Temettü Zaman Çizelgesi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -4996,7 +4977,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -12669,7 +12650,7 @@ TBu işlemi silmeyi gerçekten istiyor musunuz? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -12733,7 +12714,7 @@ Hesaplanan Toplam Tutar libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -12741,11 +12722,11 @@ Faiz libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -12753,7 +12734,7 @@ Tasarruflar libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -12769,7 +12750,7 @@ Tümünü göster libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -12809,7 +12790,7 @@ Core libs/ui/src/lib/i18n.ts - 8 + 9 @@ -12817,7 +12798,7 @@ Switch to Ghostfolio Premium or Ghostfolio Open Source easily libs/ui/src/lib/i18n.ts - 9 + 10 @@ -12825,7 +12806,7 @@ Switch to Ghostfolio Premium easily libs/ui/src/lib/i18n.ts - 10 + 11 @@ -12833,7 +12814,7 @@ Switch to Ghostfolio Open Source or Ghostfolio Basic easily libs/ui/src/lib/i18n.ts - 11 + 12 @@ -12841,7 +12822,7 @@ Emergency Fund libs/ui/src/lib/i18n.ts - 12 + 13 @@ -12849,7 +12830,7 @@ Grant libs/ui/src/lib/i18n.ts - 13 + 14 @@ -12857,7 +12838,7 @@ Higher Risk libs/ui/src/lib/i18n.ts - 14 + 15 @@ -12865,7 +12846,7 @@ This activity already exists. libs/ui/src/lib/i18n.ts - 15 + 16 @@ -12873,7 +12854,7 @@ Japan libs/ui/src/lib/i18n.ts - 16 + 17 @@ -12881,7 +12862,7 @@ Lower Risk libs/ui/src/lib/i18n.ts - 17 + 18 @@ -12889,7 +12870,7 @@ Month libs/ui/src/lib/i18n.ts - 18 + 19 @@ -12897,7 +12878,7 @@ Months libs/ui/src/lib/i18n.ts - 19 + 20 @@ -12905,11 +12886,11 @@ Other libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -12917,7 +12898,7 @@ Preset libs/ui/src/lib/i18n.ts - 21 + 22 @@ -12925,7 +12906,7 @@ Retirement Provision libs/ui/src/lib/i18n.ts - 22 + 23 @@ -12933,7 +12914,7 @@ Satellite libs/ui/src/lib/i18n.ts - 23 + 24 @@ -12941,7 +12922,7 @@ Symbol libs/ui/src/lib/i18n.ts - 24 + 25 @@ -12949,7 +12930,7 @@ Tag libs/ui/src/lib/i18n.ts - 25 + 26 @@ -12957,7 +12938,7 @@ Yıl libs/ui/src/lib/i18n.ts - 26 + 27 @@ -12965,7 +12946,7 @@ Years libs/ui/src/lib/i18n.ts - 27 + 28 @@ -12973,7 +12954,7 @@ Buy libs/ui/src/lib/i18n.ts - 30 + 31 @@ -12981,7 +12962,7 @@ Valuable libs/ui/src/lib/i18n.ts - 34 + 35 @@ -12989,7 +12970,7 @@ Liability libs/ui/src/lib/i18n.ts - 35 + 36 @@ -12997,7 +12978,7 @@ Sell libs/ui/src/lib/i18n.ts - 36 + 37 @@ -13005,7 +12986,7 @@ Cash libs/ui/src/lib/i18n.ts - 39 + 40 @@ -13013,7 +12994,7 @@ Commodity libs/ui/src/lib/i18n.ts - 40 + 41 @@ -13021,7 +13002,7 @@ Equity libs/ui/src/lib/i18n.ts - 41 + 42 @@ -13029,7 +13010,7 @@ Fixed Income libs/ui/src/lib/i18n.ts - 42 + 43 @@ -13037,7 +13018,7 @@ Real Estate libs/ui/src/lib/i18n.ts - 43 + 45 @@ -13045,7 +13026,7 @@ Bond libs/ui/src/lib/i18n.ts - 46 + 48 @@ -13053,7 +13034,7 @@ Cryptocurrency libs/ui/src/lib/i18n.ts - 47 + 49 @@ -13061,7 +13042,7 @@ ETF libs/ui/src/lib/i18n.ts - 48 + 50 @@ -13069,7 +13050,7 @@ Mutual Fund libs/ui/src/lib/i18n.ts - 49 + 51 @@ -13077,7 +13058,7 @@ Precious Metal libs/ui/src/lib/i18n.ts - 50 + 52 @@ -13085,7 +13066,7 @@ Private Equity libs/ui/src/lib/i18n.ts - 51 + 53 @@ -13093,7 +13074,7 @@ Stock libs/ui/src/lib/i18n.ts - 52 + 54 @@ -13101,7 +13082,7 @@ Africa libs/ui/src/lib/i18n.ts - 59 + 61 @@ -13109,7 +13090,7 @@ Asia libs/ui/src/lib/i18n.ts - 60 + 62 @@ -13117,7 +13098,7 @@ Europe libs/ui/src/lib/i18n.ts - 61 + 63 @@ -13125,7 +13106,7 @@ North America libs/ui/src/lib/i18n.ts - 62 + 64 @@ -13133,7 +13114,7 @@ Oceania libs/ui/src/lib/i18n.ts - 63 + 65 @@ -13141,7 +13122,7 @@ South America libs/ui/src/lib/i18n.ts - 64 + 66 @@ -13157,11 +13138,11 @@ No data available libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -13177,15 +13158,7 @@ Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 - - - - New - New - - apps/client/src/app/pages/landing/landing-page.html - 7 + 318 @@ -13245,7 +13218,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -13261,7 +13234,7 @@ Fee libs/ui/src/lib/i18n.ts - 32 + 33 @@ -13285,7 +13258,7 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -13293,7 +13266,7 @@ Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -13433,7 +13406,7 @@ Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13737,7 +13710,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -13761,7 +13734,7 @@ Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 @@ -13769,7 +13742,7 @@ Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 @@ -13777,7 +13750,7 @@ Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -13785,7 +13758,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -14633,7 +14606,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14657,7 +14630,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14705,7 +14678,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14733,7 +14706,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14801,7 +14774,7 @@ Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14809,7 +14782,7 @@ WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14817,7 +14790,7 @@ Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14825,7 +14798,7 @@ MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14833,7 +14806,7 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14877,7 +14850,7 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14885,7 +14858,7 @@ years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14969,7 +14942,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14984,7 +14957,7 @@ Active Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -14992,7 +14965,7 @@ Closed Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -15000,16 +14973,16 @@ Activity Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15017,7 +14990,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 53ff1578b..b7eaa7131 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -649,7 +649,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -685,7 +685,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -1589,12 +1589,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -1654,7 +1654,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -1662,7 +1662,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1670,7 +1670,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1708,7 +1708,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1731,35 +1731,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1833,7 +1833,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1880,8 +1880,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -1896,63 +1896,63 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 Attempts apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 Created apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 Finished apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 Delete Jobs apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 View Data apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 View Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 Delete Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -1970,11 +1970,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1988,8 +1988,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -2008,11 +2008,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2028,7 +2028,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -2051,11 +2051,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2067,7 +2067,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -2120,12 +2120,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2143,12 +2143,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -2162,8 +2162,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -2231,7 +2231,7 @@ Oops! Could not parse historical data. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -2270,8 +2270,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2285,8 +2285,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -2300,8 +2300,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -2319,8 +2319,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -2356,7 +2356,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2388,7 +2388,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 @@ -2523,6 +2523,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -2557,7 +2561,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -2579,8 +2583,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -2602,14 +2606,14 @@ Update platform apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 Add platform apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -2626,12 +2630,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -2656,14 +2660,14 @@ Update tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 Add tag apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -2722,12 +2726,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -2752,7 +2756,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -2874,10 +2878,6 @@ Manage Activities apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -2889,7 +2889,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -2900,7 +2900,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -2992,7 +2992,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -3003,7 +3003,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -3046,7 +3046,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -3089,71 +3089,54 @@ 3 - - - - - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 - - Buy apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 Sell apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 Investment apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 Absolute Gross Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 Gross Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 + 85 Fees apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3164,35 +3147,35 @@ Absolute Net Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 Net Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 Total Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 Valuables apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 Emergency Fund apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -3207,35 +3190,35 @@ Cash apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 Assets apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 Buying Power apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 Excluded from Analysis apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 Liabilities apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -3246,32 +3229,32 @@ Net Worth apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 Annualized Performance apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 Interest apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 Dividend apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -3279,57 +3262,61 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 Please enter the amount of your emergency fund: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 Change - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 Quantity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3339,8 +3326,8 @@ Report Data Glitch - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -3488,7 +3475,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -3499,7 +3486,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -3510,7 +3497,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -3521,7 +3508,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -3532,7 +3519,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -3779,7 +3766,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -3790,7 +3777,7 @@ Oops! Something went wrong. apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -3801,7 +3788,7 @@ Okay apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -3888,7 +3875,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -3989,7 +3976,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -4170,16 +4157,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -4190,22 +4173,22 @@ Summary apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 Markets apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -4233,68 +4216,61 @@ 14 - - New - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Manage your wealth like a boss apps/client/src/app/pages/landing/landing-page.html - 11 + 5 Ghostfolio is a privacy-first, open source dashboard for your personal finances. Break down your asset allocation, know your net worth and make solid, data-driven investment decisions. apps/client/src/app/pages/landing/landing-page.html - 15 + 9 Get Started apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 or apps/client/src/app/pages/landing/landing-page.html - 52 + 46 Live Demo apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 Monthly Active Users apps/client/src/app/pages/landing/landing-page.html - 75 + 69 Stars on GitHub apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -4305,7 +4281,7 @@ Pulls on Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -4316,217 +4292,217 @@ As seen in apps/client/src/app/pages/landing/landing-page.html - 119 + 113 Protect your assets. Refine your personal investment strategy. apps/client/src/app/pages/landing/landing-page.html - 221 + 215 Ghostfolio empowers busy people to keep track of stocks, ETFs or cryptocurrencies without being tracked. apps/client/src/app/pages/landing/landing-page.html - 225 + 219 360° View apps/client/src/app/pages/landing/landing-page.html - 236 + 230 Get the full picture of your personal finances across multiple platforms. apps/client/src/app/pages/landing/landing-page.html - 238 + 232 Web3 Ready apps/client/src/app/pages/landing/landing-page.html - 247 + 241 Use Ghostfolio anonymously and own your financial data. apps/client/src/app/pages/landing/landing-page.html - 249 + 243 Open Source apps/client/src/app/pages/landing/landing-page.html - 257 + 251 Benefit from continuous improvements through a strong community. apps/client/src/app/pages/landing/landing-page.html - 259 + 253 Why Ghostfolio? apps/client/src/app/pages/landing/landing-page.html - 268 + 262 Ghostfolio is for you if you are... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 trading stocks, ETFs or cryptocurrencies on multiple platforms apps/client/src/app/pages/landing/landing-page.html - 276 + 270 pursuing a buy & hold strategy apps/client/src/app/pages/landing/landing-page.html - 282 + 276 interested in getting insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 287 + 281 valuing privacy and data ownership apps/client/src/app/pages/landing/landing-page.html - 292 + 286 into minimalism apps/client/src/app/pages/landing/landing-page.html - 295 + 289 caring about diversifying your financial resources apps/client/src/app/pages/landing/landing-page.html - 299 + 293 interested in financial independence apps/client/src/app/pages/landing/landing-page.html - 303 + 297 saying no to spreadsheets in apps/client/src/app/pages/landing/landing-page.html - 307 + 301 still reading this list apps/client/src/app/pages/landing/landing-page.html - 310 + 304 Learn more about Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 315 + 309 What our users are saying apps/client/src/app/pages/landing/landing-page.html - 323 + 317 Members from around the globe are using Ghostfolio Premium apps/client/src/app/pages/landing/landing-page.html - 355 + 349 How does Ghostfolio work? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 Get started in only 3 steps apps/client/src/app/pages/landing/landing-page.html - 370 + 364 Sign up anonymously* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 * no e-mail address nor credit card required apps/client/src/app/pages/landing/landing-page.html - 378 + 372 Add any of your historical transactions apps/client/src/app/pages/landing/landing-page.html - 389 + 383 Get valuable insights of your portfolio composition apps/client/src/app/pages/landing/landing-page.html - 401 + 395 Are you ready? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 Join now or check out the example account apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -4608,14 +4584,14 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 Do you really want to delete all your activities? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -4686,18 +4662,18 @@ Update Cash Balance apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 Unit Price apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -4708,18 +4684,18 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -4730,7 +4706,7 @@ Oops! Could not get the historical exchange rate from apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -4843,7 +4819,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -5004,14 +4980,14 @@ libs/ui/src/lib/i18n.ts - 31 + 32 Deposit libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -5046,42 +5022,42 @@ Bottom apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 Portfolio Evolution apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 Investment Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 Current Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 Longest Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 Dividend Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -5140,7 +5116,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -13459,7 +13435,7 @@ Do you really want to delete this account balance? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -13538,14 +13514,14 @@ Do you really want to delete this activity? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 Find holding... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -13640,25 +13616,25 @@ Projected Total Amount libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 Interest libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 Savings libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -13672,7 +13648,7 @@ Show all libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -13707,326 +13683,326 @@ Core libs/ui/src/lib/i18n.ts - 8 + 9 Switch to Ghostfolio Premium or Ghostfolio Open Source easily libs/ui/src/lib/i18n.ts - 9 + 10 Switch to Ghostfolio Premium easily libs/ui/src/lib/i18n.ts - 10 + 11 Switch to Ghostfolio Open Source or Ghostfolio Basic easily libs/ui/src/lib/i18n.ts - 11 + 12 Emergency Fund libs/ui/src/lib/i18n.ts - 12 + 13 Grant libs/ui/src/lib/i18n.ts - 13 + 14 Higher Risk libs/ui/src/lib/i18n.ts - 14 + 15 This activity already exists. libs/ui/src/lib/i18n.ts - 15 + 16 Japan libs/ui/src/lib/i18n.ts - 16 + 17 Lower Risk libs/ui/src/lib/i18n.ts - 17 + 18 Month libs/ui/src/lib/i18n.ts - 18 + 19 Months libs/ui/src/lib/i18n.ts - 19 + 20 Other libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 Preset libs/ui/src/lib/i18n.ts - 21 + 22 Retirement Provision libs/ui/src/lib/i18n.ts - 22 + 23 Satellite libs/ui/src/lib/i18n.ts - 23 + 24 Symbol libs/ui/src/lib/i18n.ts - 24 + 25 Tag libs/ui/src/lib/i18n.ts - 25 + 26 Year libs/ui/src/lib/i18n.ts - 26 + 27 Years libs/ui/src/lib/i18n.ts - 27 + 28 Buy libs/ui/src/lib/i18n.ts - 30 + 31 Fee libs/ui/src/lib/i18n.ts - 32 + 33 Valuable libs/ui/src/lib/i18n.ts - 34 + 35 Liability libs/ui/src/lib/i18n.ts - 35 + 36 Sell libs/ui/src/lib/i18n.ts - 36 + 37 Cash libs/ui/src/lib/i18n.ts - 39 + 40 Commodity libs/ui/src/lib/i18n.ts - 40 + 41 Equity libs/ui/src/lib/i18n.ts - 41 + 42 Fixed Income libs/ui/src/lib/i18n.ts - 42 + 43 Real Estate libs/ui/src/lib/i18n.ts - 43 + 45 Bond libs/ui/src/lib/i18n.ts - 46 + 48 Cryptocurrency libs/ui/src/lib/i18n.ts - 47 + 49 ETF libs/ui/src/lib/i18n.ts - 48 + 50 Mutual Fund libs/ui/src/lib/i18n.ts - 49 + 51 Precious Metal libs/ui/src/lib/i18n.ts - 50 + 52 Private Equity libs/ui/src/lib/i18n.ts - 51 + 53 Stock libs/ui/src/lib/i18n.ts - 52 + 54 Africa libs/ui/src/lib/i18n.ts - 59 + 61 Asia libs/ui/src/lib/i18n.ts - 60 + 62 Europe libs/ui/src/lib/i18n.ts - 61 + 63 North America libs/ui/src/lib/i18n.ts - 62 + 64 Oceania libs/ui/src/lib/i18n.ts - 63 + 65 South America libs/ui/src/lib/i18n.ts - 64 + 66 Extreme Fear libs/ui/src/lib/i18n.ts - 67 + 69 Extreme Greed libs/ui/src/lib/i18n.ts - 68 + 70 Neutral libs/ui/src/lib/i18n.ts - 71 + 73 @@ -14054,11 +14030,11 @@ No data available libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -14079,7 +14055,7 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14093,7 +14069,7 @@ Oops! Could not grant access. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14140,7 +14116,7 @@ Market data is delayed for apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14200,35 +14176,35 @@ Year to date libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 Week to date libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 Month to date libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 MTD libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 WTD libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14267,14 +14243,14 @@ year libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 years libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14349,7 +14325,7 @@ Oops! It looks like you’re making too many requests. Please slow down a bit. apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14362,36 +14338,85 @@ Closed - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 Active - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 Activity - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index fa47da7e0..3f792b054 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -655,7 +655,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 81 + 83 apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts @@ -691,7 +691,7 @@ libs/ui/src/lib/membership-card/membership-card.component.ts - 13 + 25 @@ -1622,12 +1622,12 @@ 134 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 190 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 221 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 300 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 331 apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -1691,7 +1691,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 7 + 12 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -1699,7 +1699,7 @@ apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 7 + 12 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1707,7 +1707,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 138 + 134 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1747,7 +1747,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 144 + 140 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1771,35 +1771,35 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 198 + 194 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 199 + 195 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 201 + 197 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 263 + 257 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 264 + 258 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 265 + 259 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 266 + 260 libs/ui/src/lib/account-balances/account-balances.component.html - 20 + 34 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1875,7 +1875,7 @@ libs/ui/src/lib/account-balances/account-balances.component.html - 51 + 80 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1926,8 +1926,8 @@ 34 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 270 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 301 @@ -1943,7 +1943,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 154 + 150 @@ -1951,7 +1951,7 @@ 尝试 apps/client/src/app/components/admin-jobs/admin-jobs.html - 63 + 82 @@ -1959,7 +1959,7 @@ 创建 apps/client/src/app/components/admin-jobs/admin-jobs.html - 72 + 91 @@ -1967,7 +1967,7 @@ 完成的 apps/client/src/app/components/admin-jobs/admin-jobs.html - 81 + 100 @@ -1975,7 +1975,7 @@ 状况 apps/client/src/app/components/admin-jobs/admin-jobs.html - 90 + 109 @@ -1983,7 +1983,7 @@ 删除作业 apps/client/src/app/components/admin-jobs/admin-jobs.html - 126 + 158 @@ -1991,7 +1991,7 @@ 查看数据 apps/client/src/app/components/admin-jobs/admin-jobs.html - 141 + 173 @@ -1999,7 +1999,7 @@ 查看堆栈跟踪 apps/client/src/app/components/admin-jobs/admin-jobs.html - 148 + 180 @@ -2007,7 +2007,7 @@ 删除作业 apps/client/src/app/components/admin-jobs/admin-jobs.html - 154 + 186 @@ -2027,11 +2027,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 160 + 156 libs/ui/src/lib/account-balances/account-balances.component.html - 11 + 12 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2046,8 +2046,8 @@ 26 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 81 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 112 @@ -2067,11 +2067,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 26 + 39 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 13 + 22 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2087,7 +2087,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 408 + 399 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -2111,11 +2111,11 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 33 + 46 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 20 + 29 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -2127,7 +2127,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 415 + 406 @@ -2186,12 +2186,12 @@ 232 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 197 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 228 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 334 + 326 @@ -2210,12 +2210,12 @@ 245 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 206 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 237 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 350 + 342 @@ -2230,8 +2230,8 @@ 130 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 178 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 209 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -2307,7 +2307,7 @@ 哎呀!无法解析历史数据。 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 235 + 236 @@ -2350,8 +2350,8 @@ 174 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 223 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 254 @@ -2366,8 +2366,8 @@ 77 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 233 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 264 @@ -2382,8 +2382,8 @@ 316 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 239 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 270 apps/client/src/app/pages/public/public-page.html @@ -2402,8 +2402,8 @@ 327 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 251 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 282 @@ -2443,7 +2443,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 319 + 311 @@ -2479,7 +2479,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 122 + 120 @@ -2633,6 +2633,10 @@ apps/client/src/app/components/admin-overview/admin-overview.html 231 + + libs/ui/src/lib/account-balances/account-balances.component.html + 93 + Housekeeping @@ -2671,7 +2675,7 @@ apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 13 + 22 @@ -2694,8 +2698,8 @@ 257 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 325 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 356 apps/client/src/app/pages/accounts/accounts-page.html @@ -2719,7 +2723,7 @@ 更新平台 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 2 + 7 @@ -2727,7 +2731,7 @@ 添加平台 apps/client/src/app/components/admin-platform/create-or-update-platform-dialog/create-or-update-platform-dialog.html - 3 + 8 @@ -2746,12 +2750,12 @@ 10 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 345 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 376 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 363 + 355 libs/ui/src/lib/assistant/assistant.html @@ -2779,7 +2783,7 @@ 更新标签 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 2 + 7 @@ -2787,7 +2791,7 @@ 添加标签 apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/create-or-update-tag-dialog.html - 3 + 8 @@ -2854,12 +2858,12 @@ 6 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 59 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 89 libs/ui/src/lib/holdings-table/holdings-table.component.html - 119 + 142 @@ -2887,7 +2891,7 @@ apps/client/src/app/pages/portfolio/portfolio-page-routing.module.ts - 48 + 41 @@ -3023,10 +3027,6 @@ 管理活动 apps/client/src/app/components/home-holdings/home-holdings.html - 22 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page.html 32 @@ -3039,7 +3039,7 @@ libs/ui/src/lib/i18n.ts - 69 + 71 @@ -3051,7 +3051,7 @@ libs/ui/src/lib/i18n.ts - 70 + 72 @@ -3155,7 +3155,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 68 + 69 @@ -3167,7 +3167,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 70 + 72 @@ -3215,7 +3215,7 @@ apps/client/src/app/pages/landing/landing-page.html - 429 + 423 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html @@ -3262,34 +3262,12 @@ 3 - - - - - - - - - - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 12 - - - - {VAR_PLURAL, plural, =1 {transaction} other {transactions}} - {VAR_PLURAL,复数,=1 {交易} 其他{交易}} - - apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 14 - - Buy apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 21 + 31 @@ -3297,7 +3275,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 33 + 43 @@ -3305,11 +3283,11 @@ 投资 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 48 + 58 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 134 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 165 @@ -3317,7 +3295,7 @@ 绝对总业绩 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 60 + 70 @@ -3325,7 +3303,7 @@ 总表现 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 77 + 85 @@ -3333,11 +3311,11 @@ 费用 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 100 + 108 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 168 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 199 apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -3349,7 +3327,7 @@ 绝对净绩效 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 116 + 124 @@ -3357,7 +3335,7 @@ 净绩效 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 133 + 139 @@ -3365,7 +3343,7 @@ 总资产 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 159 + 165 @@ -3373,7 +3351,7 @@ 贵重物品 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 172 + 178 @@ -3381,7 +3359,7 @@ 应急基金 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 184 + 190 apps/client/src/app/pages/features/features-page.html @@ -3397,7 +3375,7 @@ 现金 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 205 + 211 @@ -3405,7 +3383,7 @@ 资产 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 218 + 224 @@ -3413,7 +3391,7 @@ 购买力 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 231 + 237 @@ -3421,7 +3399,7 @@ 从分析中排除 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 243 + 249 @@ -3429,7 +3407,7 @@ 负债 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 258 + 264 apps/client/src/app/pages/features/features-page.html @@ -3441,7 +3419,7 @@ 净值 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 278 + 284 @@ -3449,7 +3427,7 @@ 年化业绩 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 290 + 296 @@ -3457,7 +3435,7 @@ 利息 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 312 + 318 @@ -3465,11 +3443,11 @@ 股息 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html - 324 + 330 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 146 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 177 apps/client/src/app/pages/features/features-page.html @@ -3477,11 +3455,11 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 196 + 192 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 261 + 255 @@ -3489,51 +3467,55 @@ 请输入您的应急基金金额: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 53 + 57 Change 修改 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 48 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 63 + + + libs/ui/src/lib/holdings-table/holdings-table.component.html + 119 Average Unit Price 平均单价 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 70 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 101 Minimum Price 最低价格 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 97 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 128 Maximum Price 最高价格 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 113 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 144 Quantity 数量 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 123 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 154 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 183 + 179 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3544,8 +3526,8 @@ Report Data Glitch 报告数据故障 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 363 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 394 @@ -3705,7 +3687,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 188 + 215 @@ -3717,7 +3699,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -3729,7 +3711,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -3741,7 +3723,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -3753,7 +3735,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 209 + 236 @@ -4033,7 +4015,7 @@ apps/client/src/app/core/http-response.interceptor.ts - 89 + 91 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -4045,7 +4027,7 @@ 哎呀!出了些问题。 apps/client/src/app/core/http-response.interceptor.ts - 87 + 89 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -4057,7 +4039,7 @@ 好的 apps/client/src/app/core/http-response.interceptor.ts - 90 + 92 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -4153,7 +4135,7 @@ 糟糕,现金余额转账失败。 apps/client/src/app/pages/accounts/accounts-page.component.ts - 306 + 304 @@ -4265,7 +4247,7 @@ apps/client/src/app/pages/home/home-page.component.ts - 34 + 61 apps/client/src/app/pages/zen/zen-page-routing.module.ts @@ -4468,16 +4450,12 @@ 23 - apps/client/src/app/pages/home/home-page.component.ts - 39 - - - apps/client/src/app/pages/portfolio/holdings/holdings-page-routing.module.ts - 13 + apps/client/src/app/pages/home/home-page-routing.module.ts + 28 - apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 39 + apps/client/src/app/pages/home/home-page.component.ts + 66 apps/client/src/app/pages/zen/zen-page.component.ts @@ -4489,11 +4467,11 @@ 概括 apps/client/src/app/pages/home/home-page-routing.module.ts - 28 + 33 apps/client/src/app/pages/home/home-page.component.ts - 44 + 71 @@ -4501,11 +4479,11 @@ 市场 apps/client/src/app/pages/home/home-page-routing.module.ts - 33 + 38 apps/client/src/app/pages/home/home-page.component.ts - 49 + 76 apps/client/src/app/pages/markets/markets-page-routing.module.ts @@ -4536,20 +4514,12 @@ 14 - - New - 新的 - - apps/client/src/app/pages/landing/landing-page.html - 7 - - Manage your wealth like a boss 像老板一样管理您的财富 apps/client/src/app/pages/landing/landing-page.html - 11 + 5 @@ -4557,7 +4527,7 @@ Ghostfolio 是一个隐私优先、开源的个人财务仪表板。分解您的资产配置,了解您的净资产并做出可靠的、数据驱动的投资决策。 apps/client/src/app/pages/landing/landing-page.html - 15 + 9 @@ -4565,11 +4535,11 @@ 开始使用 apps/client/src/app/pages/landing/landing-page.html - 47 + 41 apps/client/src/app/pages/landing/landing-page.html - 425 + 419 @@ -4577,7 +4547,7 @@ apps/client/src/app/pages/landing/landing-page.html - 52 + 46 @@ -4585,11 +4555,11 @@ 现场演示 apps/client/src/app/pages/landing/landing-page.html - 55 + 49 apps/client/src/app/pages/landing/landing-page.html - 430 + 424 @@ -4597,7 +4567,7 @@ 每月活跃用户数 apps/client/src/app/pages/landing/landing-page.html - 75 + 69 @@ -4605,7 +4575,7 @@ GitHub 上的星星 apps/client/src/app/pages/landing/landing-page.html - 93 + 87 apps/client/src/app/pages/open/open-page.html @@ -4617,7 +4587,7 @@ 拉动 Docker Hub apps/client/src/app/pages/landing/landing-page.html - 111 + 105 apps/client/src/app/pages/open/open-page.html @@ -4629,7 +4599,7 @@ 如图所示 apps/client/src/app/pages/landing/landing-page.html - 119 + 113 @@ -4637,7 +4607,7 @@ 保护你的资产。完善你的个人投资策略 apps/client/src/app/pages/landing/landing-page.html - 221 + 215 @@ -4645,7 +4615,7 @@ Ghostfolio 使忙碌的人们能够在不被追踪的情况下跟踪股票、ETF 或加密货币。 apps/client/src/app/pages/landing/landing-page.html - 225 + 219 @@ -4653,7 +4623,7 @@ 360° 视角 apps/client/src/app/pages/landing/landing-page.html - 236 + 230 @@ -4661,7 +4631,7 @@ 跨多个平台全面了解您的个人财务状况。 apps/client/src/app/pages/landing/landing-page.html - 238 + 232 @@ -4669,7 +4639,7 @@ Web3 就绪 apps/client/src/app/pages/landing/landing-page.html - 247 + 241 @@ -4677,7 +4647,7 @@ 匿名使用 Ghostfolio 并拥有您的财务数据。 apps/client/src/app/pages/landing/landing-page.html - 249 + 243 @@ -4685,7 +4655,7 @@ 开源 apps/client/src/app/pages/landing/landing-page.html - 257 + 251 @@ -4693,7 +4663,7 @@ 通过强大的社区不断改进,从中受益。 apps/client/src/app/pages/landing/landing-page.html - 259 + 253 @@ -4701,7 +4671,7 @@ 为什么使用Ghostfolio apps/client/src/app/pages/landing/landing-page.html - 268 + 262 @@ -4709,7 +4679,7 @@ 如果您符合以下条件,那么 Ghostfolio 适合您... apps/client/src/app/pages/landing/landing-page.html - 269 + 263 @@ -4717,7 +4687,7 @@ 在多个平台上交易股票、ETF 或加密货币 apps/client/src/app/pages/landing/landing-page.html - 276 + 270 @@ -4725,7 +4695,7 @@ 采取买入并持有策略 apps/client/src/app/pages/landing/landing-page.html - 282 + 276 @@ -4733,7 +4703,7 @@ 有兴趣深入了解您的投资组合构成 apps/client/src/app/pages/landing/landing-page.html - 287 + 281 @@ -4741,7 +4711,7 @@ 重视隐私和数据所有权 apps/client/src/app/pages/landing/landing-page.html - 292 + 286 @@ -4749,7 +4719,7 @@ 进入极简主义 apps/client/src/app/pages/landing/landing-page.html - 295 + 289 @@ -4757,7 +4727,7 @@ 关心您的财务资源多元化 apps/client/src/app/pages/landing/landing-page.html - 299 + 293 @@ -4765,7 +4735,7 @@ 对财务独立感兴趣 apps/client/src/app/pages/landing/landing-page.html - 303 + 297 @@ -4773,7 +4743,7 @@ 对电子表格说不 apps/client/src/app/pages/landing/landing-page.html - 307 + 301 @@ -4781,7 +4751,7 @@ 仍在阅读此列表 apps/client/src/app/pages/landing/landing-page.html - 310 + 304 @@ -4789,7 +4759,7 @@ 了解有关 Ghostfolio 的更多信息 apps/client/src/app/pages/landing/landing-page.html - 315 + 309 @@ -4797,7 +4767,7 @@ 我们的什么用户正在说 apps/client/src/app/pages/landing/landing-page.html - 323 + 317 @@ -4805,7 +4775,7 @@ 来自世界各地的会员正在使用Ghostfolio 高级版 apps/client/src/app/pages/landing/landing-page.html - 355 + 349 @@ -4813,7 +4783,7 @@ 如何幽灵作品集工作? apps/client/src/app/pages/landing/landing-page.html - 367 + 361 @@ -4821,7 +4791,7 @@ 只需 3 步即可开始 apps/client/src/app/pages/landing/landing-page.html - 370 + 364 @@ -4829,7 +4799,7 @@ 匿名注册* apps/client/src/app/pages/landing/landing-page.html - 376 + 370 @@ -4837,7 +4807,7 @@ * 无需电子邮件地址或信用卡 apps/client/src/app/pages/landing/landing-page.html - 378 + 372 @@ -4845,7 +4815,7 @@ 添加您的任何历史交易 apps/client/src/app/pages/landing/landing-page.html - 389 + 383 @@ -4853,7 +4823,7 @@ 获取有关您的投资组合构成的宝贵见解 apps/client/src/app/pages/landing/landing-page.html - 401 + 395 @@ -4861,7 +4831,7 @@ 准备好? apps/client/src/app/pages/landing/landing-page.html - 413 + 407 @@ -4869,7 +4839,7 @@ 立即加入或查看示例帐户 apps/client/src/app/pages/landing/landing-page.html - 414 + 408 @@ -4961,7 +4931,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 44 + 39 @@ -4969,7 +4939,7 @@ 您真的要删除所有活动吗? apps/client/src/app/pages/portfolio/activities/activities-page.component.ts - 171 + 168 @@ -5049,7 +5019,7 @@ 更新现金余额 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 110 + 108 @@ -5057,11 +5027,11 @@ 单价 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 203 + 199 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 267 + 261 libs/ui/src/lib/activities-table/activities-table.component.html @@ -5073,7 +5043,7 @@ 哎呀!无法从以下来源获取历史汇率 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 232 + 226 @@ -5081,11 +5051,11 @@ 费用 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 + 280 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 310 + 302 libs/ui/src/lib/activities-table/activities-table.component.html @@ -5097,7 +5067,7 @@ 哎呀!无法获取历史汇率 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 300 + 292 @@ -5225,7 +5195,7 @@ apps/client/src/app/pages/portfolio/portfolio-page.component.ts - 49 + 44 @@ -5405,7 +5375,7 @@ libs/ui/src/lib/i18n.ts - 31 + 32 @@ -5413,7 +5383,7 @@ 订金 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 332 + 357 @@ -5453,7 +5423,7 @@ 底部 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 216 + 214 @@ -5461,7 +5431,7 @@ 投资组合演变 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 268 + 264 @@ -5469,7 +5439,7 @@ 投资时间表 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 298 + 294 @@ -5477,7 +5447,7 @@ 当前连胜 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 319 + 315 @@ -5485,7 +5455,7 @@ 最长连续纪录 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 328 + 324 @@ -5493,7 +5463,7 @@ 股息时间表 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 356 + 352 @@ -5560,7 +5530,7 @@ 77 - apps/client/src/app/pages/portfolio/holdings/holdings-page.html + apps/client/src/app/components/home-holdings/home-holdings.html 4 @@ -13965,7 +13935,7 @@ 您确实要删除该帐户余额吗? libs/ui/src/lib/account-balances/account-balances.component.ts - 58 + 102 @@ -14053,7 +14023,7 @@ 您确实要删除此活动吗? libs/ui/src/lib/activities-table/activities-table.component.ts - 175 + 215 @@ -14061,7 +14031,7 @@ 查找持有... libs/ui/src/lib/assistant/assistant.component.ts - 111 + 138 @@ -14169,7 +14139,7 @@ 预计总额 libs/ui/src/lib/fire-calculator/fire-calculator.component.html - 60 + 57 @@ -14177,11 +14147,11 @@ 利息 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 342 + 367 libs/ui/src/lib/i18n.ts - 33 + 34 @@ -14189,7 +14159,7 @@ 储蓄 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 352 + 377 @@ -14205,7 +14175,7 @@ 显示所有 libs/ui/src/lib/holdings-table/holdings-table.component.html - 174 + 197 @@ -14245,7 +14215,7 @@ 核心 libs/ui/src/lib/i18n.ts - 8 + 9 @@ -14253,7 +14223,7 @@ 轻松切换到 Ghostfolio Premium 或 Ghostfolio Open Source libs/ui/src/lib/i18n.ts - 9 + 10 @@ -14261,7 +14231,7 @@ 轻松切换到 Ghostfolio Premium libs/ui/src/lib/i18n.ts - 10 + 11 @@ -14269,7 +14239,7 @@ 轻松切换到 Ghostfolio Open Source 或 Ghostfolio Basic libs/ui/src/lib/i18n.ts - 11 + 12 @@ -14277,7 +14247,7 @@ 应急基金 libs/ui/src/lib/i18n.ts - 12 + 13 @@ -14285,7 +14255,7 @@ 授予 libs/ui/src/lib/i18n.ts - 13 + 14 @@ -14293,7 +14263,7 @@ 风险较高 libs/ui/src/lib/i18n.ts - 14 + 15 @@ -14301,7 +14271,7 @@ 这项活动已经存在。 libs/ui/src/lib/i18n.ts - 15 + 16 @@ -14309,7 +14279,7 @@ 日本 libs/ui/src/lib/i18n.ts - 16 + 17 @@ -14317,7 +14287,7 @@ 降低风险 libs/ui/src/lib/i18n.ts - 17 + 18 @@ -14325,7 +14295,7 @@ libs/ui/src/lib/i18n.ts - 18 + 19 @@ -14333,7 +14303,7 @@ 几个月 libs/ui/src/lib/i18n.ts - 19 + 20 @@ -14341,11 +14311,11 @@ 其他 libs/ui/src/lib/i18n.ts - 20 + 21 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 385 + 389 @@ -14353,7 +14323,7 @@ 预设 libs/ui/src/lib/i18n.ts - 21 + 22 @@ -14361,7 +14331,7 @@ 退休金 libs/ui/src/lib/i18n.ts - 22 + 23 @@ -14369,7 +14339,7 @@ 卫星 libs/ui/src/lib/i18n.ts - 23 + 24 @@ -14377,7 +14347,7 @@ 符号 libs/ui/src/lib/i18n.ts - 24 + 25 @@ -14385,7 +14355,7 @@ 标签 libs/ui/src/lib/i18n.ts - 25 + 26 @@ -14393,7 +14363,7 @@ libs/ui/src/lib/i18n.ts - 26 + 27 @@ -14401,7 +14371,7 @@ libs/ui/src/lib/i18n.ts - 27 + 28 @@ -14409,7 +14379,7 @@ libs/ui/src/lib/i18n.ts - 30 + 31 @@ -14417,7 +14387,7 @@ 费用 libs/ui/src/lib/i18n.ts - 32 + 33 @@ -14425,7 +14395,7 @@ 有价值的 libs/ui/src/lib/i18n.ts - 34 + 35 @@ -14433,7 +14403,7 @@ 责任 libs/ui/src/lib/i18n.ts - 35 + 36 @@ -14441,7 +14411,7 @@ libs/ui/src/lib/i18n.ts - 36 + 37 @@ -14449,7 +14419,7 @@ 现金 libs/ui/src/lib/i18n.ts - 39 + 40 @@ -14457,7 +14427,7 @@ 商品 libs/ui/src/lib/i18n.ts - 40 + 41 @@ -14465,7 +14435,7 @@ 公平 libs/ui/src/lib/i18n.ts - 41 + 42 @@ -14473,7 +14443,7 @@ 固定收入 libs/ui/src/lib/i18n.ts - 42 + 43 @@ -14481,7 +14451,7 @@ 房地产 libs/ui/src/lib/i18n.ts - 43 + 45 @@ -14489,7 +14459,7 @@ 纽带 libs/ui/src/lib/i18n.ts - 46 + 48 @@ -14497,7 +14467,7 @@ 加密货币 libs/ui/src/lib/i18n.ts - 47 + 49 @@ -14505,7 +14475,7 @@ 交易所交易基金 libs/ui/src/lib/i18n.ts - 48 + 50 @@ -14513,7 +14483,7 @@ 共同基金 libs/ui/src/lib/i18n.ts - 49 + 51 @@ -14521,7 +14491,7 @@ 贵金属 libs/ui/src/lib/i18n.ts - 50 + 52 @@ -14529,7 +14499,7 @@ 私人产权 libs/ui/src/lib/i18n.ts - 51 + 53 @@ -14537,7 +14507,7 @@ 库存 libs/ui/src/lib/i18n.ts - 52 + 54 @@ -14545,7 +14515,7 @@ 非洲 libs/ui/src/lib/i18n.ts - 59 + 61 @@ -14553,7 +14523,7 @@ 亚洲 libs/ui/src/lib/i18n.ts - 60 + 62 @@ -14561,7 +14531,7 @@ 欧洲 libs/ui/src/lib/i18n.ts - 61 + 63 @@ -14569,7 +14539,7 @@ 北美 libs/ui/src/lib/i18n.ts - 62 + 64 @@ -14577,7 +14547,7 @@ 大洋洲 libs/ui/src/lib/i18n.ts - 63 + 65 @@ -14585,7 +14555,7 @@ 南美洲 libs/ui/src/lib/i18n.ts - 64 + 66 @@ -14593,7 +14563,7 @@ 极度恐惧 libs/ui/src/lib/i18n.ts - 67 + 69 @@ -14601,7 +14571,7 @@ 极度贪婪 libs/ui/src/lib/i18n.ts - 68 + 70 @@ -14609,7 +14579,7 @@ 中性的 libs/ui/src/lib/i18n.ts - 71 + 73 @@ -14641,11 +14611,11 @@ 无可用数据 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 387 + 391 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 400 + 404 @@ -14669,7 +14639,7 @@ 当前市场价格为 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 330 + 342 @@ -14685,7 +14655,7 @@ 哎呀!无法授予访问权限。 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts - 80 + 88 @@ -14737,7 +14707,7 @@ 市场数据延迟 apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts - 82 + 81 @@ -14805,7 +14775,7 @@ 今年迄今为止 libs/ui/src/lib/assistant/assistant.component.ts - 198 + 225 @@ -14813,7 +14783,7 @@ 本周至今 libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14821,7 +14791,7 @@ 本月至今 libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14829,7 +14799,7 @@ 最大输运量 libs/ui/src/lib/assistant/assistant.component.ts - 194 + 221 @@ -14837,7 +14807,7 @@ 世界贸易组织 libs/ui/src/lib/assistant/assistant.component.ts - 190 + 217 @@ -14881,7 +14851,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 202 + 229 @@ -14889,7 +14859,7 @@ libs/ui/src/lib/assistant/assistant.component.ts - 206 + 233 @@ -14973,7 +14943,7 @@ 哎呀!看来您提出了太多要求。请慢一点。 apps/client/src/app/core/http-response.interceptor.ts - 105 + 107 @@ -14988,7 +14958,7 @@ Closed 关闭 - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 31 @@ -14996,7 +14966,7 @@ Active 积极的 - apps/client/src/app/pages/portfolio/holdings/holdings-page.component.ts + apps/client/src/app/components/home-holdings/home-holdings.component.ts 30 @@ -15004,16 +14974,16 @@ Activity 活动 - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 188 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 219 Dividend Yield Dividend Yield - apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html - 156 + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 187 @@ -15021,7 +14991,63 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 183 + + + + Priority + Priority + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 63 + + + + This action is not allowed. + This action is not allowed. + + apps/client/src/app/core/http-response.interceptor.ts + 70 + + + + Liquidity + Liquidity + + libs/ui/src/lib/i18n.ts + 44 + + + + Change with currency effect + Change with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 52 + + + + Performance with currency effect + Performance with currency effect + + apps/client/src/app/components/position-detail-dialog/position-detail-dialog.html + 79 + + + + {VAR_PLURAL, plural, =1 {activity} other {activities}} + {VAR_PLURAL, plural, =1 {activity} other {activities}} + + apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html + 14 + + + + Buy and sell + Buy and sell + + libs/ui/src/lib/i18n.ts + 8 diff --git a/apps/client/src/styles.scss b/apps/client/src/styles.scss index 6d3cffff2..ce18789b2 100644 --- a/apps/client/src/styles.scss +++ b/apps/client/src/styles.scss @@ -387,6 +387,10 @@ ngx-skeleton-loader { @include gf-table; } +.has-fab { + padding-bottom: 3rem !important; +} + .has-info-message { .page.has-tabs { height: calc(100svh - 2 * var(--mat-toolbar-standard-height)); @@ -543,6 +547,10 @@ ngx-skeleton-loader { --mdc-tab-indicator-active-indicator-color: transparent; } + .mat-mdc-tab-nav-panel { + padding: 2rem 0; + } + @media (max-width: 575.98px) { .mat-mdc-tab-link { --mdc-secondary-navigation-tab-container-height: 3rem; @@ -567,10 +575,6 @@ ngx-skeleton-loader { } } } - - .mat-mdc-tab-nav-panel { - padding: 2rem 0; - } } } } diff --git a/git-hooks/pre-commit b/git-hooks/pre-commit old mode 100644 new mode 100755 diff --git a/libs/common/src/lib/class-transformer.ts b/libs/common/src/lib/class-transformer.ts new file mode 100644 index 000000000..bd9db22da --- /dev/null +++ b/libs/common/src/lib/class-transformer.ts @@ -0,0 +1,9 @@ +import { Big } from 'big.js'; + +export function transformToBig({ value }: { value: string }): Big { + if (value === null) { + return null; + } + + return new Big(value); +} diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 5e1366ce2..c89143d9d 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -4,7 +4,6 @@ import ms from 'ms'; export const ghostfolioPrefix = 'GF'; export const ghostfolioScraperApiSymbolPrefix = `_${ghostfolioPrefix}_`; -export const ghostfolioCashSymbol = `${ghostfolioScraperApiSymbolPrefix}CASH`; export const ghostfolioFearAndGreedIndexDataSource = DataSource.RAPID_API; export const ghostfolioFearAndGreedIndexSymbol = `${ghostfolioScraperApiSymbolPrefix}FEAR_AND_GREED_INDEX`; @@ -67,7 +66,7 @@ export const EMERGENCY_FUND_TAG_ID = '4452656d-9fa4-4bd0-ba38-70492e31d180'; export const GATHER_ASSET_PROFILE_PROCESS = 'GATHER_ASSET_PROFILE'; export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = { - attempts: 10, + attempts: 12, backoff: { delay: ms('1 minute'), type: 'exponential' @@ -77,7 +76,7 @@ export const GATHER_ASSET_PROFILE_PROCESS_OPTIONS: JobOptions = { export const GATHER_HISTORICAL_MARKET_DATA_PROCESS = 'GATHER_HISTORICAL_MARKET_DATA'; export const GATHER_HISTORICAL_MARKET_DATA_PROCESS_OPTIONS: JobOptions = { - attempts: 10, + attempts: 12, backoff: { delay: ms('1 minute'), type: 'exponential' diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index dba1ac79a..c2c9ce619 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -48,7 +48,6 @@ import type { Subscription } from './subscription.interface'; import type { SymbolMetrics } from './symbol-metrics.interface'; import type { SystemMessage } from './system-message.interface'; import type { TabConfiguration } from './tab-configuration.interface'; -import type { TimelinePosition } from './timeline-position.interface'; import type { UniqueAsset } from './unique-asset.interface'; import type { UserSettings } from './user-settings.interface'; import type { User } from './user.interface'; @@ -102,7 +101,6 @@ export { Subscription, SymbolMetrics, TabConfiguration, - TimelinePosition, UniqueAsset, User, UserSettings diff --git a/libs/common/src/lib/interfaces/portfolio-performance.interface.ts b/libs/common/src/lib/interfaces/portfolio-performance.interface.ts index 1c6f50b30..9d4ac5fab 100644 --- a/libs/common/src/lib/interfaces/portfolio-performance.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-performance.interface.ts @@ -1,14 +1,14 @@ export interface PortfolioPerformance { annualizedPerformancePercent?: number; - currentGrossPerformance: number; - currentGrossPerformancePercent: number; - currentGrossPerformancePercentWithCurrencyEffect: number; - currentGrossPerformanceWithCurrencyEffect: number; - currentNetPerformance: number; - currentNetPerformancePercent: number; - currentNetPerformancePercentWithCurrencyEffect: number; - currentNetPerformanceWithCurrencyEffect: number; - currentNetWorth: number; - currentValue: number; + currentNetWorth?: number; + currentValueInBaseCurrency: number; + grossPerformance: number; + grossPerformancePercentage: number; + grossPerformancePercentageWithCurrencyEffect: number; + grossPerformanceWithCurrencyEffect: number; + netPerformance: number; + netPerformancePercentage: number; + netPerformancePercentageWithCurrencyEffect: number; + netPerformanceWithCurrencyEffect: number; totalInvestment: number; } diff --git a/libs/common/src/lib/interfaces/portfolio-position.interface.ts b/libs/common/src/lib/interfaces/portfolio-position.interface.ts index 2e5772ef7..a47a1ebc7 100644 --- a/libs/common/src/lib/interfaces/portfolio-position.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-position.interface.ts @@ -8,7 +8,7 @@ export interface PortfolioPosition { allocationInPercentage: number; assetClass?: AssetClass; assetClassLabel?: string; - assetSubClass?: AssetSubClass | 'CASH'; + assetSubClass?: AssetSubClass; assetSubClassLabel?: string; countries: Country[]; currency: string; diff --git a/libs/common/src/lib/interfaces/symbol-metrics.interface.ts b/libs/common/src/lib/interfaces/symbol-metrics.interface.ts index 57eed9212..6b78f273a 100644 --- a/libs/common/src/lib/interfaces/symbol-metrics.interface.ts +++ b/libs/common/src/lib/interfaces/symbol-metrics.interface.ts @@ -40,6 +40,7 @@ export interface SymbolMetrics { [date: string]: Big; }; timeWeightedInvestmentWithCurrencyEffect: Big; + totalAccountBalanceInBaseCurrency: Big; totalDividend: Big; totalDividendInBaseCurrency: Big; totalInterest: Big; diff --git a/libs/common/src/lib/interfaces/timeline-position.interface.ts b/libs/common/src/lib/interfaces/timeline-position.interface.ts deleted file mode 100644 index 539f887ce..000000000 --- a/libs/common/src/lib/interfaces/timeline-position.interface.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { DataSource, Tag } from '@prisma/client'; -import { Big } from 'big.js'; - -export interface TimelinePosition { - averagePrice: Big; - currency: string; - dataSource: DataSource; - dividend: Big; - dividendInBaseCurrency: Big; - fee: Big; - firstBuyDate: string; - grossPerformance: Big; - grossPerformancePercentage: Big; - grossPerformancePercentageWithCurrencyEffect: Big; - grossPerformanceWithCurrencyEffect: Big; - investment: Big; - investmentWithCurrencyEffect: Big; - marketPrice: number; - marketPriceInBaseCurrency: number; - netPerformance: Big; - netPerformancePercentage: Big; - netPerformancePercentageWithCurrencyEffect: Big; - netPerformanceWithCurrencyEffect: Big; - quantity: Big; - symbol: string; - tags?: Tag[]; - timeWeightedInvestment: Big; - timeWeightedInvestmentWithCurrencyEffect: Big; - transactionCount: number; - valueInBaseCurrency: Big; -} diff --git a/libs/common/src/lib/models/index.ts b/libs/common/src/lib/models/index.ts new file mode 100644 index 000000000..0dd601a0e --- /dev/null +++ b/libs/common/src/lib/models/index.ts @@ -0,0 +1,4 @@ +import { PortfolioSnapshot } from './portfolio-snapshot'; +import { TimelinePosition } from './timeline-position'; + +export { PortfolioSnapshot, TimelinePosition }; diff --git a/libs/common/src/lib/models/portfolio-snapshot.ts b/libs/common/src/lib/models/portfolio-snapshot.ts new file mode 100644 index 000000000..909f44f2a --- /dev/null +++ b/libs/common/src/lib/models/portfolio-snapshot.ts @@ -0,0 +1,82 @@ +import { transformToBig } from '@ghostfolio/common/class-transformer'; +import { UniqueAsset } from '@ghostfolio/common/interfaces'; +import { TimelinePosition } from '@ghostfolio/common/models'; + +import { Big } from 'big.js'; +import { Transform, Type } from 'class-transformer'; + +export class PortfolioSnapshot { + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + currentValueInBaseCurrency: Big; + errors?: UniqueAsset[]; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformance: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformanceWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformancePercentage: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformancePercentageWithCurrencyEffect: Big; + + hasErrors: boolean; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netAnnualizedPerformance?: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netAnnualizedPerformanceWithCurrencyEffect?: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformance: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformanceWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformancePercentage: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformancePercentageWithCurrencyEffect: Big; + + @Type(() => TimelinePosition) + positions: TimelinePosition[]; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + totalFeesWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + totalInterestWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + totalInvestment: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + totalInvestmentWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + totalLiabilitiesWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + totalValuablesWithCurrencyEffect: Big; +} diff --git a/libs/common/src/lib/models/timeline-position.ts b/libs/common/src/lib/models/timeline-position.ts new file mode 100644 index 000000000..412449590 --- /dev/null +++ b/libs/common/src/lib/models/timeline-position.ts @@ -0,0 +1,92 @@ +import { transformToBig } from '@ghostfolio/common/class-transformer'; + +import { DataSource, Tag } from '@prisma/client'; +import { Big } from 'big.js'; +import { Transform, Type } from 'class-transformer'; + +export class TimelinePosition { + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + averagePrice: Big; + + currency: string; + dataSource: DataSource; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + dividend: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + dividendInBaseCurrency: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + fee: Big; + + firstBuyDate: string; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformance: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformancePercentage: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformancePercentageWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + grossPerformanceWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + investment: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + investmentWithCurrencyEffect: Big; + + marketPrice: number; + marketPriceInBaseCurrency: number; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformance: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformancePercentage: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformancePercentageWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + netPerformanceWithCurrencyEffect: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + quantity: Big; + + symbol: string; + tags?: Tag[]; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + timeWeightedInvestment: Big; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + timeWeightedInvestmentWithCurrencyEffect: Big; + + transactionCount: number; + + @Transform(transformToBig, { toClassOnly: true }) + @Type(() => Big) + valueInBaseCurrency: Big; +} diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index 09bbfa1bd..890cb8b63 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -7,6 +7,7 @@ export const permissions = { accessAssistant: 'accessAssistant', createAccess: 'createAccess', createAccount: 'createAccount', + createAccountBalance: 'createAccountBalance', createOrder: 'createOrder', createPlatform: 'createPlatform', createTag: 'createTag', @@ -47,6 +48,7 @@ export function getPermissions(aRole: Role): string[] { permissions.accessAssistant, permissions.createAccess, permissions.createAccount, + permissions.createAccountBalance, permissions.deleteAccountBalance, permissions.createOrder, permissions.createPlatform, @@ -75,6 +77,7 @@ export function getPermissions(aRole: Role): string[] { permissions.accessAssistant, permissions.createAccess, permissions.createAccount, + permissions.createAccountBalance, permissions.createOrder, permissions.deleteAccess, permissions.deleteAccount, diff --git a/libs/ui/src/lib/account-balances/account-balances.component.html b/libs/ui/src/lib/account-balances/account-balances.component.html index 0d1a79f41..0cfa4a5da 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.html +++ b/libs/ui/src/lib/account-balances/account-balances.component.html @@ -1,60 +1,106 @@ - - - - - + +
      - Date - - -
      + + + + + - - - - + + + + + - - - + + - + + - - -
      + Date + + + + + + + + + + + - Value - -
      - -
      -
      + Value + +
      + +
      +
      +
      + + +
      + {{ accountCurrency }} +
      +
      +
      +
      - @if (showActions) { + + + @if (showActions) { + + } + + + + - } - - - -
      + + + + + diff --git a/libs/ui/src/lib/account-balances/account-balances.component.ts b/libs/ui/src/lib/account-balances/account-balances.component.ts index 65f2547b9..996b513e6 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.ts +++ b/libs/ui/src/lib/account-balances/account-balances.component.ts @@ -2,6 +2,7 @@ import { getLocale } from '@ghostfolio/common/helper'; import { AccountBalancesResponse } from '@ghostfolio/common/interfaces'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, EventEmitter, @@ -12,37 +13,80 @@ import { Output, ViewChild } from '@angular/core'; -import { MatSort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; +import { + FormGroup, + FormControl, + Validators, + ReactiveFormsModule +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { DateAdapter } from '@angular/material/core'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSort, MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { get } from 'lodash'; import { Subject } from 'rxjs'; +import { GfValueComponent } from '../value'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + GfValueComponent, + MatButtonModule, + MatDatepickerModule, + MatFormFieldModule, + MatInputModule, + MatMenuModule, + MatSortModule, + MatTableModule, + ReactiveFormsModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-account-balances', + standalone: true, styleUrls: ['./account-balances.component.scss'], templateUrl: './account-balances.component.html' }) -export class AccountBalancesComponent implements OnChanges, OnDestroy, OnInit { +export class GfAccountBalancesComponent + implements OnChanges, OnDestroy, OnInit +{ @Input() accountBalances: AccountBalancesResponse['balances']; + @Input() accountCurrency: string; @Input() accountId: string; @Input() locale = getLocale(); @Input() showActions = true; + @Output() accountBalanceCreated = new EventEmitter<{ + balance: number; + date: Date; + }>(); @Output() accountBalanceDeleted = new EventEmitter(); @ViewChild(MatSort) sort: MatSort; + public accountBalanceForm = new FormGroup({ + balance: new FormControl(0, Validators.required), + date: new FormControl(new Date(), Validators.required) + }); + public dataSource: MatTableDataSource< AccountBalancesResponse['balances'][0] > = new MatTableDataSource(); + public displayedColumns: string[] = ['date', 'value', 'actions']; + public Validators = Validators; private unsubscribeSubject = new Subject(); - public constructor() {} + public constructor(private dateAdapter: DateAdapter) {} - public ngOnInit() {} + public ngOnInit() { + this.dateAdapter.setLocale(this.locale); + } public ngOnChanges() { if (this.accountBalances) { @@ -63,6 +107,10 @@ export class AccountBalancesComponent implements OnChanges, OnDestroy, OnInit { } } + public onSubmitAccountBalance() { + this.accountBalanceCreated.emit(this.accountBalanceForm.getRawValue()); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); diff --git a/libs/ui/src/lib/account-balances/account-balances.module.ts b/libs/ui/src/lib/account-balances/account-balances.module.ts deleted file mode 100644 index a789dcc39..000000000 --- a/libs/ui/src/lib/account-balances/account-balances.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { GfValueModule } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSortModule } from '@angular/material/sort'; -import { MatTableModule } from '@angular/material/table'; - -import { AccountBalancesComponent } from './account-balances.component'; - -@NgModule({ - declarations: [AccountBalancesComponent], - exports: [AccountBalancesComponent], - imports: [ - CommonModule, - GfValueModule, - MatButtonModule, - MatMenuModule, - MatSortModule, - MatTableModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAccountBalancesModule {} diff --git a/libs/ui/src/lib/account-balances/index.ts b/libs/ui/src/lib/account-balances/index.ts new file mode 100644 index 000000000..b32ba9a0f --- /dev/null +++ b/libs/ui/src/lib/account-balances/index.ts @@ -0,0 +1 @@ +export * from './account-balances.component'; diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.ts b/libs/ui/src/lib/activities-filter/activities-filter.component.ts index db4cc2d31..6244fa5fc 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.ts +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.ts @@ -1,8 +1,11 @@ +import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { Filter, FilterGroup } from '@ghostfolio/common/interfaces'; import { translate } from '@ghostfolio/ui/i18n'; import { COMMA, ENTER } from '@angular/cdk/keycodes'; +import { CommonModule } from '@angular/common'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, ElementRef, @@ -14,23 +17,39 @@ import { SimpleChanges, ViewChild } from '@angular/core'; -import { FormControl } from '@angular/forms'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { MatAutocomplete, + MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; -import { MatChipInputEvent } from '@angular/material/chips'; +import { MatButtonModule } from '@angular/material/button'; +import { MatChipInputEvent, MatChipsModule } from '@angular/material/chips'; +import { MatInputModule } from '@angular/material/input'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { groupBy } from 'lodash'; import { BehaviorSubject, Observable, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + GfSymbolModule, + MatAutocompleteModule, + MatButtonModule, + MatChipsModule, + MatInputModule, + MatProgressSpinnerModule, + ReactiveFormsModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-activities-filter', + standalone: true, styleUrls: ['./activities-filter.component.scss'], templateUrl: './activities-filter.component.html' }) -export class ActivitiesFilterComponent implements OnChanges, OnDestroy { +export class GfActivitiesFilterComponent implements OnChanges, OnDestroy { @Input() allFilters: Filter[]; @Input() isLoading: boolean; @Input() placeholder: string; diff --git a/libs/ui/src/lib/activities-filter/activities-filter.module.ts b/libs/ui/src/lib/activities-filter/activities-filter.module.ts deleted file mode 100644 index 56f082e7b..000000000 --- a/libs/ui/src/lib/activities-filter/activities-filter.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { ReactiveFormsModule } from '@angular/forms'; -import { MatAutocompleteModule } from '@angular/material/autocomplete'; -import { MatButtonModule } from '@angular/material/button'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; - -import { ActivitiesFilterComponent } from './activities-filter.component'; - -@NgModule({ - declarations: [ActivitiesFilterComponent], - exports: [ActivitiesFilterComponent], - imports: [ - CommonModule, - GfSymbolModule, - MatAutocompleteModule, - MatButtonModule, - MatChipsModule, - MatInputModule, - MatProgressSpinnerModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfActivitiesFilterModule {} diff --git a/libs/ui/src/lib/activities-filter/index.ts b/libs/ui/src/lib/activities-filter/index.ts new file mode 100644 index 000000000..ef776e130 --- /dev/null +++ b/libs/ui/src/lib/activities-filter/index.ts @@ -0,0 +1 @@ +export * from './activities-filter.component'; diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html index 4a1b1004d..dfa17a28c 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -119,7 +119,7 @@ - +
      {{ item?.symbol | gfSymbol }} · {{ item?.currency - }} - · {{ item?.assetSubClassString }}{{ item?.symbol | gfSymbol }} · {{ item?.currency }} + @if (item?.assetSubClassString) { + · {{ item.assetSubClassString }} + } + diff --git a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.module.ts b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.module.ts deleted file mode 100644 index fb512ee5e..000000000 --- a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; - -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { AssistantListItemComponent } from './assistant-list-item.component'; - -@NgModule({ - declarations: [AssistantListItemComponent], - exports: [AssistantListItemComponent], - imports: [CommonModule, GfSymbolModule, RouterModule] -}) -export class GfAssistantListItemModule {} diff --git a/libs/ui/src/lib/assistant/assistant.component.ts b/libs/ui/src/lib/assistant/assistant.component.ts index 310bede05..101872a86 100644 --- a/libs/ui/src/lib/assistant/assistant.component.ts +++ b/libs/ui/src/lib/assistant/assistant.component.ts @@ -1,3 +1,4 @@ +import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { Filter, User } from '@ghostfolio/common/interfaces'; @@ -5,7 +6,9 @@ import { DateRange } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { FocusKeyManager } from '@angular/cdk/a11y'; +import { CommonModule } from '@angular/common'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, @@ -21,10 +24,20 @@ import { ViewChild, ViewChildren } from '@angular/core'; -import { FormBuilder, FormControl } from '@angular/forms'; +import { + FormBuilder, + FormControl, + FormsModule, + ReactiveFormsModule +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; import { MatMenuTrigger } from '@angular/material/menu'; +import { MatSelectModule } from '@angular/material/select'; +import { RouterModule } from '@angular/router'; import { Account, AssetClass } from '@prisma/client'; import { eachYearOfInterval, format } from 'date-fns'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { EMPTY, Observable, Subject, lastValueFrom } from 'rxjs'; import { catchError, @@ -35,7 +48,7 @@ import { takeUntil } from 'rxjs/operators'; -import { AssistantListItemComponent } from './assistant-list-item/assistant-list-item.component'; +import { GfAssistantListItemComponent } from './assistant-list-item/assistant-list-item.component'; import { IDateRangeOption, ISearchResultItem, @@ -44,11 +57,25 @@ import { @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + FormsModule, + GfAssetProfileIconComponent, + GfAssistantListItemComponent, + MatButtonModule, + MatFormFieldModule, + MatSelectModule, + NgxSkeletonLoaderModule, + ReactiveFormsModule, + RouterModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-assistant', + standalone: true, styleUrls: ['./assistant.scss'], templateUrl: './assistant.html' }) -export class AssistantComponent implements OnChanges, OnDestroy, OnInit { +export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { @HostListener('document:keydown', ['$event']) onKeydown( event: KeyboardEvent ) { @@ -92,8 +119,8 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { @ViewChild('menuTrigger') menuTriggerElement: MatMenuTrigger; @ViewChild('search', { static: true }) searchElement: ElementRef; - @ViewChildren(AssistantListItemComponent) - assistantListItems: QueryList; + @ViewChildren(GfAssistantListItemComponent) + assistantListItems: QueryList; public static readonly SEARCH_RESULTS_DEFAULT_LIMIT = 5; @@ -117,7 +144,7 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { public tags: Filter[] = []; private filterTypes: Filter['type'][] = ['ACCOUNT', 'ASSET_CLASS', 'TAG']; - private keyManager: FocusKeyManager; + private keyManager: FocusKeyManager; private unsubscribeSubject = new Subject(); public constructor( @@ -334,7 +361,7 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { ); assetProfiles = assetProfiles.slice( 0, - AssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT + GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT ); } catch {} } @@ -343,7 +370,7 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { holdings = await lastValueFrom(this.searchHoldings(aSearchTerm)); holdings = holdings.slice( 0, - AssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT + GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT ); } catch {} @@ -364,7 +391,7 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { type: 'SEARCH_QUERY' } ], - take: AssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT + take: GfAssistantComponent.SEARCH_RESULTS_DEFAULT_LIMIT }) .pipe( catchError(() => { @@ -389,7 +416,7 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { private searchHoldings(aSearchTerm: string): Observable { return this.dataService - .fetchPositions({ + .fetchPortfolioHoldings({ filters: [ { id: aSearchTerm, @@ -402,8 +429,8 @@ export class AssistantComponent implements OnChanges, OnDestroy, OnInit { catchError(() => { return EMPTY; }), - map(({ positions }) => { - return positions.map( + map(({ holdings }) => { + return holdings.map( ({ assetSubClass, currency, dataSource, name, symbol }) => { return { currency, diff --git a/libs/ui/src/lib/assistant/assistant.module.ts b/libs/ui/src/lib/assistant/assistant.module.ts deleted file mode 100644 index 031f57f46..000000000 --- a/libs/ui/src/lib/assistant/assistant.module.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatSelectModule } from '@angular/material/select'; -import { RouterModule } from '@angular/router'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { GfAssistantListItemModule } from './assistant-list-item/assistant-list-item.module'; -import { AssistantComponent } from './assistant.component'; - -@NgModule({ - declarations: [AssistantComponent], - exports: [AssistantComponent], - imports: [ - CommonModule, - FormsModule, - GfAssetProfileIconComponent, - GfAssistantListItemModule, - MatButtonModule, - MatFormFieldModule, - MatSelectModule, - NgxSkeletonLoaderModule, - ReactiveFormsModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfAssistantModule {} diff --git a/libs/ui/src/lib/assistant/index.ts b/libs/ui/src/lib/assistant/index.ts index f58d1b2f3..aded19f26 100644 --- a/libs/ui/src/lib/assistant/index.ts +++ b/libs/ui/src/lib/assistant/index.ts @@ -1 +1 @@ -export * from './assistant.module'; +export * from './assistant.component'; diff --git a/libs/ui/src/lib/benchmark/benchmark.component.ts b/libs/ui/src/lib/benchmark/benchmark.component.ts index 032c131bf..07e70c2fd 100644 --- a/libs/ui/src/lib/benchmark/benchmark.component.ts +++ b/libs/ui/src/lib/benchmark/benchmark.component.ts @@ -2,20 +2,36 @@ import { getLocale, resolveMarketCondition } from '@ghostfolio/common/helper'; import { Benchmark, User } from '@ghostfolio/common/interfaces'; import { translate } from '@ghostfolio/ui/i18n'; +import { CommonModule } from '@angular/common'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; +import { MatTableModule } from '@angular/material/table'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; + +import { GfTrendIndicatorComponent } from '../trend-indicator'; +import { GfValueComponent } from '../value'; @Component({ - selector: 'gf-benchmark', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './benchmark.component.html', - styleUrls: ['./benchmark.component.scss'] + imports: [ + CommonModule, + GfTrendIndicatorComponent, + GfValueComponent, + MatTableModule, + NgxSkeletonLoaderModule + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-benchmark', + standalone: true, + styleUrls: ['./benchmark.component.scss'], + templateUrl: './benchmark.component.html' }) -export class BenchmarkComponent implements OnChanges { +export class GfBenchmarkComponent implements OnChanges { @Input() benchmarks: Benchmark[]; @Input() locale = getLocale(); @Input() user: User; diff --git a/libs/ui/src/lib/benchmark/benchmark.module.ts b/libs/ui/src/lib/benchmark/benchmark.module.ts deleted file mode 100644 index 5b3e00209..000000000 --- a/libs/ui/src/lib/benchmark/benchmark.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatTableModule } from '@angular/material/table'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { GfTrendIndicatorModule } from '../trend-indicator'; -import { GfValueModule } from '../value'; -import { BenchmarkComponent } from './benchmark.component'; - -@NgModule({ - declarations: [BenchmarkComponent], - exports: [BenchmarkComponent], - imports: [ - CommonModule, - GfTrendIndicatorModule, - GfValueModule, - MatTableModule, - NgxSkeletonLoaderModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfBenchmarkModule {} diff --git a/libs/ui/src/lib/benchmark/index.ts b/libs/ui/src/lib/benchmark/index.ts index b8cd0c1a8..87fdc713c 100644 --- a/libs/ui/src/lib/benchmark/index.ts +++ b/libs/ui/src/lib/benchmark/index.ts @@ -1 +1 @@ -export * from './benchmark.module'; +export * from './benchmark.component'; diff --git a/libs/ui/src/lib/carousel/carousel.component.ts b/libs/ui/src/lib/carousel/carousel.component.ts index a0eb0f8a1..7f93297dd 100644 --- a/libs/ui/src/lib/carousel/carousel.component.ts +++ b/libs/ui/src/lib/carousel/carousel.component.ts @@ -2,6 +2,7 @@ import { FocusKeyManager } from '@angular/cdk/a11y'; import { LEFT_ARROW, RIGHT_ARROW, TAB } from '@angular/cdk/keycodes'; import { AfterContentInit, + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, ContentChildren, @@ -13,17 +14,21 @@ import { QueryList, ViewChild } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations'; import { CarouselItem } from './carousel-item.directive'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [MatButtonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-carousel', + standalone: true, styleUrls: ['./carousel.component.scss'], templateUrl: './carousel.component.html' }) -export class CarouselComponent implements AfterContentInit { +export class GfCarouselComponent implements AfterContentInit { @ContentChildren(CarouselItem) public items!: QueryList; @HostBinding('class.animations-disabled') diff --git a/libs/ui/src/lib/carousel/carousel.module.ts b/libs/ui/src/lib/carousel/carousel.module.ts deleted file mode 100644 index 4e43f23b0..000000000 --- a/libs/ui/src/lib/carousel/carousel.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; - -import { CarouselItem } from './carousel-item.directive'; -import { CarouselComponent } from './carousel.component'; - -@NgModule({ - declarations: [CarouselComponent, CarouselItem], - exports: [CarouselComponent, CarouselItem], - imports: [CommonModule, MatButtonModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfCarouselModule {} diff --git a/libs/ui/src/lib/carousel/index.ts b/libs/ui/src/lib/carousel/index.ts index 2e039a80b..3cd42148e 100644 --- a/libs/ui/src/lib/carousel/index.ts +++ b/libs/ui/src/lib/carousel/index.ts @@ -1 +1 @@ -export * from './carousel.module'; +export * from './carousel.component'; diff --git a/libs/ui/src/lib/currency-selector/currency-selector.component.ts b/libs/ui/src/lib/currency-selector/currency-selector.component.ts index 8c9415689..046af1cf8 100644 --- a/libs/ui/src/lib/currency-selector/currency-selector.component.ts +++ b/libs/ui/src/lib/currency-selector/currency-selector.component.ts @@ -3,6 +3,7 @@ import { AbstractMatFormField } from '@ghostfolio/ui/shared/abstract-mat-form-fi import { FocusMonitor } from '@angular/cdk/a11y'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, @@ -12,13 +13,23 @@ import { OnInit, ViewChild } from '@angular/core'; -import { FormControl, FormGroupDirective, NgControl } from '@angular/forms'; +import { + FormControl, + FormGroupDirective, + FormsModule, + NgControl, + ReactiveFormsModule +} from '@angular/forms'; import { MatAutocomplete, + MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; -import { MatFormFieldControl } from '@angular/material/form-field'; -import { MatInput } from '@angular/material/input'; +import { + MatFormFieldControl, + MatFormFieldModule +} from '@angular/material/form-field'; +import { MatInput, MatInputModule } from '@angular/material/input'; import { Subject } from 'rxjs'; import { map, startWith, takeUntil } from 'rxjs/operators'; @@ -28,17 +39,26 @@ import { map, startWith, takeUntil } from 'rxjs/operators'; '[attr.aria-describedBy]': 'describedBy', '[id]': 'id' }, + imports: [ + FormsModule, + MatAutocompleteModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule + ], providers: [ { provide: MatFormFieldControl, - useExisting: CurrencySelectorComponent + useExisting: GfCurrencySelectorComponent } ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-currency-selector', + standalone: true, styleUrls: ['./currency-selector.component.scss'], templateUrl: 'currency-selector.component.html' }) -export class CurrencySelectorComponent +export class GfCurrencySelectorComponent extends AbstractMatFormField implements OnInit, OnDestroy { diff --git a/libs/ui/src/lib/currency-selector/currency-selector.module.ts b/libs/ui/src/lib/currency-selector/currency-selector.module.ts deleted file mode 100644 index ac4d12096..000000000 --- a/libs/ui/src/lib/currency-selector/currency-selector.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatAutocompleteModule } from '@angular/material/autocomplete'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { CurrencySelectorComponent } from './currency-selector.component'; - -@NgModule({ - declarations: [CurrencySelectorComponent], - exports: [CurrencySelectorComponent], - imports: [ - CommonModule, - FormsModule, - MatAutocompleteModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfCurrencySelectorModule {} diff --git a/libs/ui/src/lib/currency-selector/index.ts b/libs/ui/src/lib/currency-selector/index.ts new file mode 100644 index 000000000..2faa42b80 --- /dev/null +++ b/libs/ui/src/lib/currency-selector/index.ts @@ -0,0 +1 @@ +export * from './currency-selector.component'; diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts index afdcb969a..bfab714f9 100644 --- a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts +++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts @@ -1,14 +1,23 @@ import { DataProviderInfo } from '@ghostfolio/common/interfaces'; -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + CUSTOM_ELEMENTS_SCHEMA, + ChangeDetectionStrategy, + Component, + Input +} from '@angular/core'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-data-provider-credits', + standalone: true, styleUrls: ['./data-provider-credits.component.scss'], templateUrl: './data-provider-credits.component.html' }) -export class DataProviderCreditsComponent { +export class GfDataProviderCreditsComponent { @Input() dataProviderInfos: DataProviderInfo[]; public constructor() {} diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts b/libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts deleted file mode 100644 index e5dd9d3b9..000000000 --- a/libs/ui/src/lib/data-provider-credits/data-provider-credits.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; - -import { DataProviderCreditsComponent } from './data-provider-credits.component'; - -@NgModule({ - declarations: [DataProviderCreditsComponent], - exports: [DataProviderCreditsComponent], - imports: [CommonModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfDataProviderCreditsModule {} diff --git a/libs/ui/src/lib/data-provider-credits/index.ts b/libs/ui/src/lib/data-provider-credits/index.ts index 5d3759577..44db13ea5 100644 --- a/libs/ui/src/lib/data-provider-credits/index.ts +++ b/libs/ui/src/lib/data-provider-credits/index.ts @@ -1 +1 @@ -export * from './data-provider-credits.module'; +export * from './data-provider-credits.component'; diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html index 46cd0999f..31c7b334d 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html @@ -31,10 +31,7 @@ Retirement Date
      - {{ - calculatorForm.controls['retirementDate'].value - | date: 'MMMM YYYY' - }} + {{ calculatorForm.get('retirementDate').value | date: 'MMMM YYYY' }}
      - + + + Change + + +
      + +
      + +
      + + = new MatTableDataSource(); public displayedColumns = []; - public ignoreAssetSubClasses = [AssetClass.CASH]; + public ignoreAssetSubClasses = [AssetSubClass.CASH]; public isLoading = true; public routeQueryParams: Subscription; @@ -57,7 +84,12 @@ export class HoldingsTableComponent implements OnChanges, OnDestroy, OnInit { } this.displayedColumns.push('allocationInPercentage'); - this.displayedColumns.push('performance'); + + if (this.hasPermissionToShowValues) { + this.displayedColumns.push('performance'); + } + + this.displayedColumns.push('performanceInPercentage'); this.isLoading = true; diff --git a/libs/ui/src/lib/holdings-table/holdings-table.module.ts b/libs/ui/src/lib/holdings-table/holdings-table.module.ts deleted file mode 100644 index a944bc1c1..000000000 --- a/libs/ui/src/lib/holdings-table/holdings-table.module.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { GfAssetProfileIconComponent } from '@ghostfolio/client/components/asset-profile-icon/asset-profile-icon.component'; -import { GfPositionDetailDialogModule } from '@ghostfolio/client/components/position/position-detail-dialog/position-detail-dialog.module'; -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; -import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info'; -import { GfValueModule } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatPaginatorModule } from '@angular/material/paginator'; -import { MatSortModule } from '@angular/material/sort'; -import { MatTableModule } from '@angular/material/table'; -import { RouterModule } from '@angular/router'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { HoldingsTableComponent } from './holdings-table.component'; - -@NgModule({ - declarations: [HoldingsTableComponent], - exports: [HoldingsTableComponent], - imports: [ - CommonModule, - GfAssetProfileIconComponent, - GfNoTransactionsInfoModule, - GfPositionDetailDialogModule, - GfSymbolModule, - GfValueModule, - MatButtonModule, - MatDialogModule, - MatPaginatorModule, - MatSortModule, - MatTableModule, - NgxSkeletonLoaderModule, - RouterModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfHoldingsTableModule {} diff --git a/libs/ui/src/lib/holdings-table/index.ts b/libs/ui/src/lib/holdings-table/index.ts new file mode 100644 index 000000000..f2dd696ce --- /dev/null +++ b/libs/ui/src/lib/holdings-table/index.ts @@ -0,0 +1 @@ +export * from './holdings-table.component'; diff --git a/libs/ui/src/lib/i18n.ts b/libs/ui/src/lib/i18n.ts index 9687f461c..51b3cab69 100644 --- a/libs/ui/src/lib/i18n.ts +++ b/libs/ui/src/lib/i18n.ts @@ -5,6 +5,7 @@ const locales = { 'Asia-Pacific': $localize`Asia-Pacific`, ASSET_CLASS: $localize`Asset Class`, ASSET_SUB_CLASS: $localize`Asset Sub Class`, + BUY_AND_SELL_ACTIVITIES_TOOLTIP: $localize`Buy and sell`, CORE: $localize`Core`, DATA_IMPORT_AND_EXPORT_TOOLTIP_BASIC: $localize`Switch to Ghostfolio Premium or Ghostfolio Open Source easily`, DATA_IMPORT_AND_EXPORT_TOOLTIP_OSS: $localize`Switch to Ghostfolio Premium easily`, @@ -40,6 +41,7 @@ const locales = { COMMODITY: $localize`Commodity`, EQUITY: $localize`Equity`, FIXED_INCOME: $localize`Fixed Income`, + LIQUIDITY: $localize`Liquidity`, REAL_ESTATE: $localize`Real Estate`, // AssetSubClass (enum) diff --git a/libs/ui/src/lib/line-chart/index.ts b/libs/ui/src/lib/line-chart/index.ts new file mode 100644 index 000000000..fca368497 --- /dev/null +++ b/libs/ui/src/lib/line-chart/index.ts @@ -0,0 +1 @@ +export * from './line-chart.component'; diff --git a/libs/ui/src/lib/line-chart/line-chart.component.ts b/libs/ui/src/lib/line-chart/line-chart.component.ts index bad5e2f3f..4098e1d5b 100644 --- a/libs/ui/src/lib/line-chart/line-chart.component.ts +++ b/libs/ui/src/lib/line-chart/line-chart.component.ts @@ -13,6 +13,7 @@ import { import { LineChartItem } from '@ghostfolio/common/interfaces'; import { ColorScheme } from '@ghostfolio/common/types'; +import { CommonModule } from '@angular/common'; import { AfterViewInit, ChangeDetectionStrategy, @@ -34,14 +35,19 @@ import { Tooltip } from 'chart.js'; import 'chartjs-adapter-date-fns'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ - selector: 'gf-line-chart', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './line-chart.component.html', - styleUrls: ['./line-chart.component.scss'] + imports: [CommonModule, NgxSkeletonLoaderModule], + selector: 'gf-line-chart', + standalone: true, + styleUrls: ['./line-chart.component.scss'], + templateUrl: './line-chart.component.html' }) -export class LineChartComponent implements AfterViewInit, OnChanges, OnDestroy { +export class GfLineChartComponent + implements AfterViewInit, OnChanges, OnDestroy +{ @Input() benchmarkDataItems: LineChartItem[] = []; @Input() benchmarkLabel = ''; @Input() colorScheme: ColorScheme; diff --git a/libs/ui/src/lib/line-chart/line-chart.module.ts b/libs/ui/src/lib/line-chart/line-chart.module.ts deleted file mode 100644 index 0483fc996..000000000 --- a/libs/ui/src/lib/line-chart/line-chart.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { LineChartComponent } from './line-chart.component'; - -@NgModule({ - declarations: [LineChartComponent], - exports: [LineChartComponent], - imports: [CommonModule, NgxSkeletonLoaderModule] -}) -export class GfLineChartModule {} diff --git a/libs/ui/src/lib/logo/index.ts b/libs/ui/src/lib/logo/index.ts index a02a37ec8..9a94f8985 100644 --- a/libs/ui/src/lib/logo/index.ts +++ b/libs/ui/src/lib/logo/index.ts @@ -1 +1 @@ -export * from './logo.module'; +export * from './logo.component'; diff --git a/libs/ui/src/lib/logo/logo.component.ts b/libs/ui/src/lib/logo/logo.component.ts index ecb3885dc..d9edd546e 100644 --- a/libs/ui/src/lib/logo/logo.component.ts +++ b/libs/ui/src/lib/logo/logo.component.ts @@ -1,4 +1,6 @@ +import { CommonModule } from '@angular/common'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, HostBinding, @@ -6,12 +8,15 @@ import { } from '@angular/core'; @Component({ - selector: 'gf-logo', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './logo.component.html', - styleUrls: ['./logo.component.scss'] + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-logo', + standalone: true, + styleUrls: ['./logo.component.scss'], + templateUrl: './logo.component.html' }) -export class LogoComponent { +export class GfLogoComponent { @HostBinding('class') @Input() size: 'large' | 'medium' = 'medium'; @Input() label: string; @Input() showLabel = true; diff --git a/libs/ui/src/lib/logo/logo.module.ts b/libs/ui/src/lib/logo/logo.module.ts deleted file mode 100644 index ced9bae30..000000000 --- a/libs/ui/src/lib/logo/logo.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; - -import { LogoComponent } from './logo.component'; - -@NgModule({ - declarations: [LogoComponent], - exports: [LogoComponent], - imports: [CommonModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfLogoModule {} diff --git a/libs/ui/src/lib/membership-card/index.ts b/libs/ui/src/lib/membership-card/index.ts index eccd8c4fd..1a0b5cac1 100644 --- a/libs/ui/src/lib/membership-card/index.ts +++ b/libs/ui/src/lib/membership-card/index.ts @@ -1 +1 @@ -export * from './membership-card.module'; +export * from './membership-card.component'; diff --git a/libs/ui/src/lib/membership-card/membership-card.component.ts b/libs/ui/src/lib/membership-card/membership-card.component.ts index 0ae760aba..f82dee3f1 100644 --- a/libs/ui/src/lib/membership-card/membership-card.component.ts +++ b/libs/ui/src/lib/membership-card/membership-card.component.ts @@ -1,12 +1,24 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + CUSTOM_ELEMENTS_SCHEMA, + ChangeDetectionStrategy, + Component, + Input +} from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { GfLogoComponent } from '../logo'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CommonModule, GfLogoComponent, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-membership-card', + standalone: true, styleUrls: ['./membership-card.component.scss'], templateUrl: './membership-card.component.html' }) -export class MembershipCardComponent { +export class GfMembershipCardComponent { @Input() public expiresAt: string; @Input() public name: string; diff --git a/libs/ui/src/lib/membership-card/membership-card.module.ts b/libs/ui/src/lib/membership-card/membership-card.module.ts deleted file mode 100644 index 564308e29..000000000 --- a/libs/ui/src/lib/membership-card/membership-card.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GfLogoModule } from '@ghostfolio/ui/logo'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { MembershipCardComponent } from './membership-card.component'; - -@NgModule({ - declarations: [MembershipCardComponent], - exports: [MembershipCardComponent], - imports: [CommonModule, GfLogoModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfMembershipCardModule {} diff --git a/libs/ui/src/lib/no-transactions-info/index.ts b/libs/ui/src/lib/no-transactions-info/index.ts index 8a907c9ec..956d0304d 100644 --- a/libs/ui/src/lib/no-transactions-info/index.ts +++ b/libs/ui/src/lib/no-transactions-info/index.ts @@ -1 +1 @@ -export * from './no-transactions-info.module'; +export * from './no-transactions-info.component'; diff --git a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts index 8910943b0..7fc8830a8 100644 --- a/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts +++ b/libs/ui/src/lib/no-transactions-info/no-transactions-info.component.ts @@ -1,17 +1,25 @@ import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, HostBinding, Input } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { RouterModule } from '@angular/router'; + +import { GfLogoComponent } from '../logo'; @Component({ - selector: 'gf-no-transactions-info-indicator', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './no-transactions-info.component.html', - styleUrls: ['./no-transactions-info.component.scss'] + imports: [GfLogoComponent, MatButtonModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-no-transactions-info-indicator', + standalone: true, + styleUrls: ['./no-transactions-info.component.scss'], + templateUrl: './no-transactions-info.component.html' }) -export class NoTransactionsInfoComponent { +export class GfNoTransactionsInfoComponent { @HostBinding('class.has-border') @Input() hasBorder = true; public constructor() {} diff --git a/libs/ui/src/lib/no-transactions-info/no-transactions-info.module.ts b/libs/ui/src/lib/no-transactions-info/no-transactions-info.module.ts deleted file mode 100644 index 03363abc8..000000000 --- a/libs/ui/src/lib/no-transactions-info/no-transactions-info.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GfLogoModule } from '@ghostfolio/ui/logo'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { RouterModule } from '@angular/router'; - -import { NoTransactionsInfoComponent } from './no-transactions-info.component'; - -@NgModule({ - declarations: [NoTransactionsInfoComponent], - exports: [NoTransactionsInfoComponent], - imports: [CommonModule, GfLogoModule, MatButtonModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfNoTransactionsInfoModule {} diff --git a/libs/ui/src/lib/portfolio-proportion-chart/index.ts b/libs/ui/src/lib/portfolio-proportion-chart/index.ts new file mode 100644 index 000000000..edf1fa198 --- /dev/null +++ b/libs/ui/src/lib/portfolio-proportion-chart/index.ts @@ -0,0 +1 @@ +export * from './portfolio-proportion-chart.component'; diff --git a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts index 620cb2066..f243f888a 100644 --- a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts +++ b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts @@ -5,6 +5,7 @@ import { PortfolioPosition, UniqueAsset } from '@ghostfolio/common/interfaces'; import { ColorScheme } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; +import { CommonModule } from '@angular/common'; import { AfterViewInit, ChangeDetectionStrategy, @@ -26,14 +27,17 @@ import { DoughnutController } from 'chart.js'; import { Chart } from 'chart.js'; import ChartDataLabels from 'chartjs-plugin-datalabels'; import * as Color from 'color'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ - selector: 'gf-portfolio-proportion-chart', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './portfolio-proportion-chart.component.html', - styleUrls: ['./portfolio-proportion-chart.component.scss'] + imports: [CommonModule, NgxSkeletonLoaderModule], + selector: 'gf-portfolio-proportion-chart', + standalone: true, + styleUrls: ['./portfolio-proportion-chart.component.scss'], + templateUrl: './portfolio-proportion-chart.component.html' }) -export class PortfolioProportionChartComponent +export class GfPortfolioProportionChartComponent implements AfterViewInit, OnChanges, OnDestroy { @Input() baseCurrency: string; diff --git a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.module.ts b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.module.ts deleted file mode 100644 index 587c19072..000000000 --- a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { PortfolioProportionChartComponent } from './portfolio-proportion-chart.component'; - -@NgModule({ - declarations: [PortfolioProportionChartComponent], - exports: [PortfolioProportionChartComponent], - imports: [CommonModule, NgxSkeletonLoaderModule] -}) -export class GfPortfolioProportionChartModule {} diff --git a/libs/ui/src/lib/premium-indicator/index.ts b/libs/ui/src/lib/premium-indicator/index.ts index 593823bbd..a61db2559 100644 --- a/libs/ui/src/lib/premium-indicator/index.ts +++ b/libs/ui/src/lib/premium-indicator/index.ts @@ -1 +1 @@ -export * from './premium-indicator.module'; +export * from './premium-indicator.component'; diff --git a/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts b/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts index 3711a28dd..ff2b158b5 100644 --- a/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts +++ b/libs/ui/src/lib/premium-indicator/premium-indicator.component.ts @@ -1,12 +1,22 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + CUSTOM_ELEMENTS_SCHEMA, + ChangeDetectionStrategy, + Component, + Input +} from '@angular/core'; +import { RouterModule } from '@angular/router'; @Component({ - selector: 'gf-premium-indicator', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './premium-indicator.component.html', - styleUrls: ['./premium-indicator.component.scss'] + imports: [CommonModule, RouterModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-premium-indicator', + standalone: true, + styleUrls: ['./premium-indicator.component.scss'], + templateUrl: './premium-indicator.component.html' }) -export class PremiumIndicatorComponent { +export class GfPremiumIndicatorComponent { @Input() enableLink = true; public constructor() {} diff --git a/libs/ui/src/lib/premium-indicator/premium-indicator.module.ts b/libs/ui/src/lib/premium-indicator/premium-indicator.module.ts deleted file mode 100644 index f79dc2f60..000000000 --- a/libs/ui/src/lib/premium-indicator/premium-indicator.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { PremiumIndicatorComponent } from './premium-indicator.component'; - -@NgModule({ - declarations: [PremiumIndicatorComponent], - exports: [PremiumIndicatorComponent], - imports: [CommonModule, RouterModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfPremiumIndicatorModule {} diff --git a/libs/ui/src/lib/symbol-autocomplete/index.ts b/libs/ui/src/lib/symbol-autocomplete/index.ts index 7271d1ca9..2964effa0 100644 --- a/libs/ui/src/lib/symbol-autocomplete/index.ts +++ b/libs/ui/src/lib/symbol-autocomplete/index.ts @@ -1 +1 @@ -export * from './symbol-autocomplete.module'; +export * from './symbol-autocomplete.component'; diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts index d25a15a28..8e07ed674 100644 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts +++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts @@ -1,10 +1,12 @@ import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; +import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { DataService } from '@ghostfolio/client/services/data.service'; import { translate } from '@ghostfolio/ui/i18n'; import { AbstractMatFormField } from '@ghostfolio/ui/shared/abstract-mat-form-field'; import { FocusMonitor } from '@angular/cdk/a11y'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, @@ -14,13 +16,23 @@ import { OnInit, ViewChild } from '@angular/core'; -import { FormControl, NgControl } from '@angular/forms'; +import { + FormControl, + FormsModule, + NgControl, + ReactiveFormsModule +} from '@angular/forms'; import { MatAutocomplete, + MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; -import { MatFormFieldControl } from '@angular/material/form-field'; -import { MatInput } from '@angular/material/input'; +import { + MatFormFieldControl, + MatFormFieldModule +} from '@angular/material/form-field'; +import { MatInput, MatInputModule } from '@angular/material/input'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { isString } from 'lodash'; import { Subject, tap } from 'rxjs'; import { @@ -31,23 +43,37 @@ import { takeUntil } from 'rxjs/operators'; +import { GfPremiumIndicatorComponent } from '../premium-indicator'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, host: { '[attr.aria-describedBy]': 'describedBy', '[id]': 'id' }, - selector: 'gf-symbol-autocomplete', - styleUrls: ['./symbol-autocomplete.component.scss'], - templateUrl: 'symbol-autocomplete.component.html', + imports: [ + FormsModule, + GfPremiumIndicatorComponent, + GfSymbolModule, + MatAutocompleteModule, + MatFormFieldModule, + MatInputModule, + MatProgressSpinnerModule, + ReactiveFormsModule + ], providers: [ { provide: MatFormFieldControl, - useExisting: SymbolAutocompleteComponent + useExisting: GfSymbolAutocompleteComponent } - ] + ], + selector: 'gf-symbol-autocomplete', + schemas: [CUSTOM_ELEMENTS_SCHEMA], + standalone: true, + styleUrls: ['./symbol-autocomplete.component.scss'], + templateUrl: 'symbol-autocomplete.component.html' }) -export class SymbolAutocompleteComponent +export class GfSymbolAutocompleteComponent extends AbstractMatFormField implements OnInit, OnDestroy { diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.module.ts b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.module.ts deleted file mode 100644 index cdb6cc97a..000000000 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; -import { GfPremiumIndicatorModule } from '@ghostfolio/ui/premium-indicator'; -import { SymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete/symbol-autocomplete.component'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatAutocompleteModule } from '@angular/material/autocomplete'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; - -@NgModule({ - declarations: [SymbolAutocompleteComponent], - exports: [SymbolAutocompleteComponent], - imports: [ - CommonModule, - FormsModule, - GfPremiumIndicatorModule, - GfSymbolModule, - MatAutocompleteModule, - MatFormFieldModule, - MatInputModule, - MatProgressSpinnerModule, - ReactiveFormsModule - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfSymbolAutocompleteModule {} diff --git a/libs/ui/src/lib/trend-indicator/index.ts b/libs/ui/src/lib/trend-indicator/index.ts index 5d9fc1d42..3e5ebf36e 100644 --- a/libs/ui/src/lib/trend-indicator/index.ts +++ b/libs/ui/src/lib/trend-indicator/index.ts @@ -1 +1 @@ -export * from './trend-indicator.module'; +export * from './trend-indicator.component'; diff --git a/libs/ui/src/lib/trend-indicator/trend-indicator.component.html b/libs/ui/src/lib/trend-indicator/trend-indicator.component.html index 81ce57bfc..761b3f232 100644 --- a/libs/ui/src/lib/trend-indicator/trend-indicator.component.html +++ b/libs/ui/src/lib/trend-indicator/trend-indicator.component.html @@ -1,50 +1,36 @@ - - - - - +} @else { + @if (marketState === 'closed' && range === '1d') { + + } @else if (marketState === 'delayed' && range === '1d') { + + } @else if (value <= -0.0005) { + + } @else if (value > -0.0005 && value < 0.0005) { + } @else { + - - - - - - - - - + } +} diff --git a/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts b/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts index fafe6e0f3..d03ee8cf4 100644 --- a/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts +++ b/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts @@ -1,14 +1,24 @@ import { DateRange, MarketState } from '@ghostfolio/common/types'; -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + CUSTOM_ELEMENTS_SCHEMA, + ChangeDetectionStrategy, + Component, + Input +} from '@angular/core'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ - selector: 'gf-trend-indicator', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './trend-indicator.component.html', - styleUrls: ['./trend-indicator.component.scss'] + imports: [CommonModule, NgxSkeletonLoaderModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-trend-indicator', + standalone: true, + styleUrls: ['./trend-indicator.component.scss'], + templateUrl: './trend-indicator.component.html' }) -export class TrendIndicatorComponent { +export class GfTrendIndicatorComponent { @Input() isLoading = false; @Input() marketState: MarketState = 'open'; @Input() range: DateRange = 'max'; diff --git a/libs/ui/src/lib/trend-indicator/trend-indicator.module.ts b/libs/ui/src/lib/trend-indicator/trend-indicator.module.ts deleted file mode 100644 index dc84a3baa..000000000 --- a/libs/ui/src/lib/trend-indicator/trend-indicator.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { TrendIndicatorComponent } from './trend-indicator.component'; - -@NgModule({ - declarations: [TrendIndicatorComponent], - exports: [TrendIndicatorComponent], - imports: [CommonModule, NgxSkeletonLoaderModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfTrendIndicatorModule {} diff --git a/libs/ui/src/lib/value/index.ts b/libs/ui/src/lib/value/index.ts index 1e8ac4def..9dc866865 100644 --- a/libs/ui/src/lib/value/index.ts +++ b/libs/ui/src/lib/value/index.ts @@ -1 +1 @@ -export * from './value.module'; +export * from './value.component'; diff --git a/libs/ui/src/lib/value/value.component.html b/libs/ui/src/lib/value/value.component.html index 4bdaf06a5..d1e498bcc 100644 --- a/libs/ui/src/lib/value/value.component.html +++ b/libs/ui/src/lib/value/value.component.html @@ -1,7 +1,7 @@
      -
      +
      -
      +
      {{ subLabel }}
      - + diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts index 13675403f..28cb3c90a 100644 --- a/libs/ui/src/lib/value/value.component.ts +++ b/libs/ui/src/lib/value/value.component.ts @@ -1,20 +1,26 @@ import { getLocale } from '@ghostfolio/common/helper'; +import { CommonModule } from '@angular/common'; import { + CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { isNumber } from 'lodash'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ - selector: 'gf-value', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './value.component.html', - styleUrls: ['./value.component.scss'] + imports: [CommonModule, NgxSkeletonLoaderModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + selector: 'gf-value', + standalone: true, + styleUrls: ['./value.component.scss'], + templateUrl: './value.component.html' }) -export class ValueComponent implements OnChanges { +export class GfValueComponent implements OnChanges { @Input() colorizeSign = false; @Input() icon = ''; @Input() isAbsolute = false; diff --git a/libs/ui/src/lib/value/value.module.ts b/libs/ui/src/lib/value/value.module.ts deleted file mode 100644 index 1cb91050e..000000000 --- a/libs/ui/src/lib/value/value.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { ValueComponent } from './value.component'; - -@NgModule({ - declarations: [ValueComponent], - exports: [ValueComponent], - imports: [CommonModule, NgxSkeletonLoaderModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfValueModule {} diff --git a/package.json b/package.json index 146c99274..dd7355bd5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.72.0", + "version": "2.80.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", @@ -54,17 +54,17 @@ "workspace-generator": "nx workspace-generator" }, "dependencies": { - "@angular/animations": "17.3.3", - "@angular/cdk": "17.3.3", - "@angular/common": "17.3.3", - "@angular/compiler": "17.3.3", - "@angular/core": "17.3.3", - "@angular/forms": "17.3.3", - "@angular/material": "17.3.3", - "@angular/platform-browser": "17.3.3", - "@angular/platform-browser-dynamic": "17.3.3", - "@angular/router": "17.3.3", - "@angular/service-worker": "17.3.3", + "@angular/animations": "17.3.5", + "@angular/cdk": "17.3.5", + "@angular/common": "17.3.5", + "@angular/compiler": "17.3.5", + "@angular/core": "17.3.5", + "@angular/forms": "17.3.5", + "@angular/material": "17.3.5", + "@angular/platform-browser": "17.3.5", + "@angular/platform-browser-dynamic": "17.3.5", + "@angular/router": "17.3.5", + "@angular/service-worker": "17.3.5", "@codewithdan/observable-store": "2.2.15", "@dfinity/agent": "0.15.7", "@dfinity/auth-client": "0.15.7", @@ -78,12 +78,13 @@ "@nestjs/common": "10.1.3", "@nestjs/config": "3.0.0", "@nestjs/core": "10.1.3", + "@nestjs/event-emitter": "2.0.4", "@nestjs/jwt": "10.1.0", "@nestjs/passport": "10.0.0", "@nestjs/platform-express": "10.1.3", "@nestjs/schedule": "3.0.2", "@nestjs/serve-static": "4.0.0", - "@prisma/client": "5.12.1", + "@prisma/client": "5.13.0", "@simplewebauthn/browser": "9.0.1", "@simplewebauthn/server": "9.0.3", "@stripe/stripe-js": "1.47.0", @@ -111,7 +112,7 @@ "got": "11.8.6", "helmet": "7.0.0", "http-status-codes": "2.3.0", - "ionicons": "7.3.0", + "ionicons": "7.4.0", "jsonpath": "1.1.1", "lodash": "4.17.21", "marked": "9.1.6", @@ -125,40 +126,40 @@ "passport": "0.6.0", "passport-google-oauth20": "2.0.0", "passport-jwt": "4.0.0", - "prisma": "5.12.1", + "prisma": "5.13.0", "reflect-metadata": "0.1.13", "rxjs": "7.5.6", "stripe": "11.12.0", "svgmap": "2.6.0", "twitter-api-v2": "1.14.2", "uuid": "9.0.1", - "yahoo-finance2": "2.11.1", + "yahoo-finance2": "2.11.2", "zone.js": "0.14.4" }, "devDependencies": { - "@angular-devkit/build-angular": "17.3.3", - "@angular-devkit/core": "17.3.3", - "@angular-devkit/schematics": "17.3.3", + "@angular-devkit/build-angular": "17.3.5", + "@angular-devkit/core": "17.3.5", + "@angular-devkit/schematics": "17.3.5", "@angular-eslint/eslint-plugin": "17.3.0", "@angular-eslint/eslint-plugin-template": "17.3.0", "@angular-eslint/template-parser": "17.3.0", - "@angular/cli": "17.3.3", - "@angular/compiler-cli": "17.3.3", - "@angular/language-service": "17.3.3", - "@angular/localize": "17.3.3", - "@angular/pwa": "17.3.3", + "@angular/cli": "17.3.5", + "@angular/compiler-cli": "17.3.5", + "@angular/language-service": "17.3.5", + "@angular/localize": "17.3.5", + "@angular/pwa": "17.3.5", "@nestjs/schematics": "10.0.1", "@nestjs/testing": "10.1.3", - "@nx/angular": "18.2.3", - "@nx/cypress": "18.2.3", - "@nx/eslint-plugin": "18.2.3", - "@nx/jest": "18.2.3", - "@nx/js": "18.2.3", - "@nx/nest": "18.2.3", - "@nx/node": "18.2.3", - "@nx/storybook": "18.2.3", - "@nx/web": "18.2.3", - "@nx/workspace": "18.2.3", + "@nx/angular": "18.3.3", + "@nx/cypress": "18.3.3", + "@nx/eslint-plugin": "18.3.3", + "@nx/jest": "18.3.3", + "@nx/js": "18.3.3", + "@nx/nest": "18.3.3", + "@nx/node": "18.3.3", + "@nx/storybook": "18.3.3", + "@nx/web": "18.3.3", + "@nx/workspace": "18.3.3", "@schematics/angular": "17.3.3", "@simplewebauthn/types": "9.0.1", "@storybook/addon-essentials": "7.6.5", @@ -187,7 +188,7 @@ "jest": "29.4.3", "jest-environment-jsdom": "29.4.3", "jest-preset-angular": "14.0.3", - "nx": "18.2.3", + "nx": "18.3.3", "prettier": "3.2.5", "prettier-plugin-organize-attributes": "1.0.0", "react": "18.2.0", diff --git a/prisma/migrations/20240421080039_added_account_id_and_date_to_account_balance_as_unique_constraint/migration.sql b/prisma/migrations/20240421080039_added_account_id_and_date_to_account_balance_as_unique_constraint/migration.sql new file mode 100644 index 000000000..96521bbfa --- /dev/null +++ b/prisma/migrations/20240421080039_added_account_id_and_date_to_account_balance_as_unique_constraint/migration.sql @@ -0,0 +1,29 @@ +-- Only keep the newest AccountBalance entry for each account / day +WITH entries_to_keep AS ( + SELECT + id, + "accountId", + date, + ROW_NUMBER() OVER (PARTITION BY "accountId", DATE(date) ORDER BY date DESC) AS row_num + FROM + "AccountBalance" +), +entries_to_delete AS ( + SELECT + id + FROM + entries_to_keep + WHERE + row_num > 1 +) +DELETE FROM + "AccountBalance" +WHERE + id IN (SELECT id FROM entries_to_delete); + +-- Reset time part of the date +UPDATE "AccountBalance" +SET date = DATE_TRUNC('day', date); + +-- CreateIndex +CREATE UNIQUE INDEX "AccountBalance_accountId_date_key" ON "AccountBalance"("accountId", "date"); diff --git a/prisma/migrations/20240422181320_added_liquidity_to_asset_class/migration.sql b/prisma/migrations/20240422181320_added_liquidity_to_asset_class/migration.sql new file mode 100644 index 000000000..685cae6bb --- /dev/null +++ b/prisma/migrations/20240422181320_added_liquidity_to_asset_class/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AssetClass" ADD VALUE 'LIQUIDITY'; diff --git a/prisma/migrations/20240422181356_added_cash_to_asset_sub_class/migration.sql b/prisma/migrations/20240422181356_added_cash_to_asset_sub_class/migration.sql new file mode 100644 index 000000000..7aeaf5abd --- /dev/null +++ b/prisma/migrations/20240422181356_added_cash_to_asset_sub_class/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AssetSubClass" ADD VALUE 'CASH'; diff --git a/prisma/migrations/20240422181835_changed_cash_to_liquidity_in_asset_sub_class/migration.sql b/prisma/migrations/20240422181835_changed_cash_to_liquidity_in_asset_sub_class/migration.sql new file mode 100644 index 000000000..f0b260a09 --- /dev/null +++ b/prisma/migrations/20240422181835_changed_cash_to_liquidity_in_asset_sub_class/migration.sql @@ -0,0 +1,7 @@ +UPDATE "SymbolProfile" +SET "assetClass" = 'LIQUIDITY' +WHERE "assetClass" = 'CASH'; + +UPDATE "SymbolProfileOverrides" +SET "assetClass" = 'LIQUIDITY' +WHERE "assetClass" = 'CASH'; diff --git a/prisma/migrations/20240422182643_removed_cash_from_asset_class/migration.sql b/prisma/migrations/20240422182643_removed_cash_from_asset_class/migration.sql new file mode 100644 index 000000000..6a08aee78 --- /dev/null +++ b/prisma/migrations/20240422182643_removed_cash_from_asset_class/migration.sql @@ -0,0 +1,9 @@ +-- AlterEnum +BEGIN; +CREATE TYPE "AssetClass_new" AS ENUM ('COMMODITY', 'EQUITY', 'FIXED_INCOME', 'LIQUIDITY', 'REAL_ESTATE'); +ALTER TABLE "SymbolProfile" ALTER COLUMN "assetClass" TYPE "AssetClass_new" USING ("assetClass"::text::"AssetClass_new"); +ALTER TABLE "SymbolProfileOverrides" ALTER COLUMN "assetClass" TYPE "AssetClass_new" USING ("assetClass"::text::"AssetClass_new"); +ALTER TYPE "AssetClass" RENAME TO "AssetClass_old"; +ALTER TYPE "AssetClass_new" RENAME TO "AssetClass"; +DROP TYPE "AssetClass_old"; +COMMIT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f9a17d114..43052de11 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -59,6 +59,7 @@ model AccountBalance { value Float Account Account @relation(fields: [accountId, userId], onDelete: Cascade, references: [id, userId]) + @@unique([accountId, date]) @@index([accountId]) @@index([date]) } @@ -247,15 +248,16 @@ enum AccessPermission { } enum AssetClass { - CASH COMMODITY EQUITY FIXED_INCOME + LIQUIDITY REAL_ESTATE } enum AssetSubClass { BOND + CASH COMMODITY CRYPTOCURRENCY ETF diff --git a/yarn.lock b/yarn.lock index b821e4c08..48f07b9e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,12 +28,12 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@angular-devkit/architect@0.1703.3": - version "0.1703.3" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1703.3.tgz#d60cdc2d2ad3b204d8b353124a8defa92c40db69" - integrity sha512-BKbdigCjmspqxOxSIQuWgPZzpyuKqZoTBDh0jDeLcAmvPsuxCgIWbsExI4OQ0CyusnQ+XT0IT39q8B9rvF56cg== +"@angular-devkit/architect@0.1703.5": + version "0.1703.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1703.5.tgz#2e6e534c99fd99d53034237d64de6317f24af52a" + integrity sha512-j3+9QeXIafuRMtk7N5Cmm/IiMSS/TOaybzfCv/LK+DP3hjEd8f8Az7hPmevUuOArvWNzUvoUeu30GmR3wABydA== dependencies: - "@angular-devkit/core" "17.3.3" + "@angular-devkit/core" "17.3.5" rxjs "7.8.1" "@angular-devkit/architect@^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0": @@ -44,15 +44,15 @@ "@angular-devkit/core" "17.0.0" rxjs "7.8.1" -"@angular-devkit/build-angular@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-17.3.3.tgz#94b610596300a8acba22f5c30dcb03220cbd96da" - integrity sha512-E/6Z1MIMhEB1I2sN+Pw4/zinwAFj4vLDh6dEuj856WWEPndgPiUB6fGX4EbCTsyIUzboXI5ysdNyt2Eq56bllA== +"@angular-devkit/build-angular@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-17.3.5.tgz#a1b1fdfe906a0132191c0fee56c2a1dc0a1d5f8f" + integrity sha512-Ju2MkMidJglJq/iWgM9CNbhK7A/2n0LNYPZx+ucb+aOFWvurCQrU4Mt/es6xCsxOEs5OPhjqdva8mxE5FHwzTQ== dependencies: "@ampproject/remapping" "2.3.0" - "@angular-devkit/architect" "0.1703.3" - "@angular-devkit/build-webpack" "0.1703.3" - "@angular-devkit/core" "17.3.3" + "@angular-devkit/architect" "0.1703.5" + "@angular-devkit/build-webpack" "0.1703.5" + "@angular-devkit/core" "17.3.5" "@babel/core" "7.24.0" "@babel/generator" "7.23.6" "@babel/helper-annotate-as-pure" "7.22.5" @@ -63,7 +63,7 @@ "@babel/preset-env" "7.24.0" "@babel/runtime" "7.24.0" "@discoveryjs/json-ext" "0.5.7" - "@ngtools/webpack" "17.3.3" + "@ngtools/webpack" "17.3.5" "@vitejs/plugin-basic-ssl" "1.1.0" ansi-colors "4.1.3" autoprefixer "10.4.18" @@ -104,8 +104,8 @@ terser "5.29.1" tree-kill "1.2.2" tslib "2.6.2" - undici "6.7.1" - vite "5.1.5" + undici "6.11.1" + vite "5.1.7" watchpack "2.4.0" webpack "5.90.3" webpack-dev-middleware "6.1.2" @@ -115,12 +115,12 @@ optionalDependencies: esbuild "0.20.1" -"@angular-devkit/build-webpack@0.1703.3": - version "0.1703.3" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1703.3.tgz#b7fcc2fa2c0c6ba4cc1dcdd8d108c8f536d03a60" - integrity sha512-d0JjE8MaGVNphlJfeP1OZKhNT4wCXkEZKdSdwE0+W+vDHNUuZiUBB1czO48sb7T4xBrdjRWlV/9CzMNJ7n3ydA== +"@angular-devkit/build-webpack@0.1703.5": + version "0.1703.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1703.5.tgz#3f8912aacb5b0d986e1f86756a40e4d21b3d7855" + integrity sha512-KcoKlWhDP6+2q3laQ6elXLt2QrVxWJFdCPUC9dIm0Tnc997Tal/UVhlDKaZgITYDgDvRFqG+tzNm2uFd8l7h+A== dependencies: - "@angular-devkit/architect" "0.1703.3" + "@angular-devkit/architect" "0.1703.5" rxjs "7.8.1" "@angular-devkit/core@16.0.1": @@ -169,6 +169,18 @@ rxjs "7.8.1" source-map "0.7.4" +"@angular-devkit/core@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-17.3.5.tgz#5af01de95b4945587aea1feaa1011f87485ffee5" + integrity sha512-iqGv45HVI+yRROoTqQTY0QChYlRCZkFUfIjdfJLegjc6xq9sLtxDr03CWM45BKGG5lSxDOy+qu/pdRvtL3V2eg== + dependencies: + ajv "8.12.0" + ajv-formats "2.1.1" + jsonc-parser "3.2.1" + picomatch "4.0.1" + rxjs "7.8.1" + source-map "0.7.4" + "@angular-devkit/schematics@16.0.1": version "16.0.1" resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-16.0.1.tgz#d49387e9e41c9cce98b155da51b0e193333dd178" @@ -213,6 +225,17 @@ ora "5.4.1" rxjs "7.8.1" +"@angular-devkit/schematics@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-17.3.5.tgz#5ea31a3e5d7dc5eb11f786b796d0536f0a9b05bd" + integrity sha512-oh/mvpMKxGfk5v9QIB7LfGsDC/iVpmsIAvbb4+1ddCx86EJXdz3xWnVDbUehOd6n7HJXnQrNirWjWvWquM2GhQ== + dependencies: + "@angular-devkit/core" "17.3.5" + jsonc-parser "3.2.1" + magic-string "0.30.8" + ora "5.4.1" + rxjs "7.8.1" + "@angular-eslint/bundled-angular-compiler@17.3.0": version "17.3.0" resolved "https://registry.yarnpkg.com/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-17.3.0.tgz#08b8b1bebbb677a1f208b56516fc9177a289d212" @@ -254,31 +277,31 @@ "@angular-eslint/bundled-angular-compiler" "17.3.0" "@typescript-eslint/utils" "7.2.0" -"@angular/animations@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-17.3.3.tgz#b6487fbaa970cfd1f998d72a61e74c7e3deb14be" - integrity sha512-poLW3FHe5wkxmTIsQ3em2vq4obgQHyZJz6biF+4hCqQSNMbMBS0e5ZycAiJLkUD/WLc88lQZ20muRO7qjVuMLA== +"@angular/animations@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-17.3.5.tgz#68f1f209137b3e7148143b66ab3a2b444ac9b546" + integrity sha512-hbfCnBxwhYQMKB+9tDcmfvckUtB8LdY1gPST6TZ7CzrWCSPddsnXxqxBZSBjBI6zXvE4FOV3kUzaUXM/Bq5sRw== dependencies: tslib "^2.3.0" -"@angular/cdk@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-17.3.3.tgz#a266eb76a91ee2ce8f1e2df4bdc9a40b8dab29eb" - integrity sha512-hfS9pwaNE6CTZqP3FBh9tZPbuf//bDqZ5IpMzscfDFrwX8ycxBiI3znH/rFSf9l1rL0OQGoqWWNVfJCT+RrukA== +"@angular/cdk@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-17.3.5.tgz#a610ec34fe7adb4ebd30798664a421ce204c653d" + integrity sha512-6y8+yIPWG0wTdPwHIPxKrEFCX1JxxBh4aXcmQnrNTDIvtoEPGaea9SU9XKaU8ahiZMlcpUXqKLG0BVbEhA1Oow== dependencies: tslib "^2.3.0" optionalDependencies: parse5 "^7.1.2" -"@angular/cli@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-17.3.3.tgz#66880fb12b0d4e536222ec7a256431795fe344c9" - integrity sha512-veIGK2sRm0SfiLHeftx0W0xC3N8uxoqxXiSG57V6W2wIFN/fKm3aRq3sa8phz7vxUzoKGqyZh6hsT7ybkjgkGA== +"@angular/cli@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-17.3.5.tgz#f668db09d283d669e42f166b7c9cfc0a8298b0a3" + integrity sha512-6MHJzPKy4uB9qlJO1eKs4rtDlRuCe0lOiz1f3kHFZ/GQQm5xA1xsmZJMN4ASsnu4yU3oZs6vJ/vt8i2/jvdPbA== dependencies: - "@angular-devkit/architect" "0.1703.3" - "@angular-devkit/core" "17.3.3" - "@angular-devkit/schematics" "17.3.3" - "@schematics/angular" "17.3.3" + "@angular-devkit/architect" "0.1703.5" + "@angular-devkit/core" "17.3.5" + "@angular-devkit/schematics" "17.3.5" + "@schematics/angular" "17.3.5" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.3" ini "4.1.2" @@ -294,17 +317,17 @@ symbol-observable "4.0.0" yargs "17.7.2" -"@angular/common@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-17.3.3.tgz#6bbd0c033446010ada04511b6955d048259cf9d7" - integrity sha512-GwlKetNpfWKiG2j4S6bYTi6PA2iT4+eln7o8owo44xZWdQnWQjfxnH39vQuCyhi6OOQL1dozmae+fVXgQsV6jQ== +"@angular/common@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-17.3.5.tgz#901f5d85b78f5e28f36156064961d58732e73a7b" + integrity sha512-Ox91WxSnOSrQ6I21cHi69EfT2Pxtd5Knb5AsdwpxqE57V2E7EnWMhb+LP+holCtFUhK529EGXCk788M+Elyw6g== dependencies: tslib "^2.3.0" -"@angular/compiler-cli@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-17.3.3.tgz#e2505b95b0d56118ea0950eae18bb0fa2c2e7515" - integrity sha512-vM0lqwuXQZ912HbLnIuvUblvIz2WEUsU7a5Z2ieNey6famH4zxPH12vCbVwXgicB6GLHorhOfcWC5443wD2mJw== +"@angular/compiler-cli@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-17.3.5.tgz#d24cb2039d130b03a898ec3bedf7cbabb573ba03" + integrity sha512-R53JNbbVDHWSGdL0e2vGQ5iJCrILOWZ1oemKjekOFB93fUBlEyi+nZmm4uTO7RU8PgjB0UpxI6ok5ZE3Amkt6A== dependencies: "@babel/core" "7.23.9" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -315,10 +338,10 @@ tslib "^2.3.0" yargs "^17.2.1" -"@angular/compiler@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-17.3.3.tgz#ac6aefbb01f031b5834477aff46aa267719f7156" - integrity sha512-ZNMRfagMxMjk1KW5H3ssCg5QL0J6ZW1JAZ1mrTXixqS7gbdwl60bTGE+EfuEwbjvovEYaj4l9cga47eMaxZTbQ== +"@angular/compiler@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-17.3.5.tgz#308ac763c2a95fb6cea764d1ec3e8bd5f2384b89" + integrity sha512-lTubBFNlpH9zK46+yeVI7VJQNUELLAB8W1ucndYLCA9Rr9Jop+rYIXijmr42AGokOYr7yLc8HRiSQ5e+X2pUQg== dependencies: tslib "^2.3.0" @@ -327,10 +350,10 @@ resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0.tgz#87e0bef4c369b6cadae07e3a4295778fc93799d5" integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== -"@angular/core@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-17.3.3.tgz#e0fd86eccd0106a5b8602c56eb4449cbb4538219" - integrity sha512-O/jr3aFJMCxF6Jmymjx4jIigRHJfqM/ALIi60y2LVznBVFkk9xyMTsAjgWQIEHX+2muEIzgfKuXzpL0y30y+wA== +"@angular/core@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-17.3.5.tgz#5445e5dad4dc713b032dde10dc048169afe998db" + integrity sha512-y6P27lcrKy3yMx/rtMuGsAnDyVEsS3BdyArTXcD0TOImVGHhVIaB0L95DUCam3ajTe2f2x39eozJZDh7QSpJaw== dependencies: tslib "^2.3.0" @@ -339,32 +362,32 @@ resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0.tgz#227dc53e1ac81824f998c6e76000b7efc522641e" integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== -"@angular/forms@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-17.3.3.tgz#ff00da4f7ab1f6fefda7b3c323ddb07c2a4b23ac" - integrity sha512-wqn+eAggbOZY91hr7oDjv5qdflszVOC9SZMcWJUoZTGn+8eoV6v6728GDFuDDwYkKQ9G9eQbX4IZmYoVw3TVjQ== +"@angular/forms@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-17.3.5.tgz#68a1511c1c2b147d704f2579563840c3f94cb714" + integrity sha512-Rf/8XWHdFYZQaOVTJ0QVwxQm9fDqQqIJc0yfPcH/DYL5pT7R0U2z98I5McZawzUBJUo1Zt1gijzDlzNUGf6jiA== dependencies: tslib "^2.3.0" -"@angular/language-service@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-17.3.3.tgz#99b26aabc10b210e1cedf4b8cca1cac64ccf4183" - integrity sha512-OtdWNY0Syg4UvA8j2IhQJeq/UjWHYbRiyUcZjGKPRzuqIPjUhsmMyuW3zpi7Pwx2CpBzZXcik1Ra2WZ0gbwigg== +"@angular/language-service@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-17.3.5.tgz#64d31f5948f24bc2217047be1899b34c177c8cc6" + integrity sha512-s3W5o+pRPU3jNWeeyO4XEdc28+s4MPhew+k0meQfZ11VMdmShzwFu5nPgOMmLB3fBhQqlSBrHUh1P9SB7Hu3FQ== -"@angular/localize@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-17.3.3.tgz#3f9c3c66eb02648edc9c8d348124d7170bab1946" - integrity sha512-gahGKy0VBZ+KP6MUULGQMoi5SN3REwslaPvtomizzz9fdmqHfR8PPd1vOJSNm2IEVlvm1hv1dDRjPcR4DJwvaQ== +"@angular/localize@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-17.3.5.tgz#2af9f4f5db3c0b99d55534ef14058c6831a2fb4d" + integrity sha512-/5iKRvnleA2vsf8zqNZaXeOBjFFq3FLrbot+ygfmk3uYqz949X0nXrXBKk9kpakw/WC6kgzK+tmiEHKQY6cLiQ== dependencies: "@babel/core" "7.23.9" "@types/babel__core" "7.20.5" fast-glob "3.3.2" yargs "^17.2.1" -"@angular/material@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-17.3.3.tgz#33f7ca38d3c0ff909bde4e8ae490ea2da49ecd3f" - integrity sha512-cb3PYY+Lf3FvXxXIRmOBcTn5QS9Ghr5Eq0aiJiiYV6YVohr0YGWsndMCZ/5a2j8fxpboDo9THeTnOuuAOJv7AA== +"@angular/material@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-17.3.5.tgz#66e5479ba342277b0549cc301f0578ef51c40c3c" + integrity sha512-1+QqBQ8HVOwxOkx/v2n53JA9ALOee55yVDbnAv7TkseNN4JEDxOcE5TO5HGmdV2A4tcsXQ00MIdy04jiB4sCng== dependencies: "@material/animation" "15.0.0-canary.7f224ddd4.0" "@material/auto-init" "15.0.0-canary.7f224ddd4.0" @@ -415,40 +438,40 @@ "@material/typography" "15.0.0-canary.7f224ddd4.0" tslib "^2.3.0" -"@angular/platform-browser-dynamic@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.3.tgz#0e747cecb51ebaec53c11ebfef289972b793484d" - integrity sha512-jSgSNHRTXCIat20I+4tLm/e8qOvrIE3Zv7S/DtYZEiAth84uoznvo1kXnN+KREse2vP/WoNgSDKQ2JLzkwYXSQ== +"@angular/platform-browser-dynamic@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.5.tgz#39cedb2144e093a7b6127a694565c6b1afb8b872" + integrity sha512-KuS4j3Gh1h/CEj+bIOc/IcZIdiCB/DNbtUvz1eNp1o23aM8QutqelI3A4WBnQuR4yq8Z/8M3FH9F1OVwwhn2QQ== dependencies: tslib "^2.3.0" -"@angular/platform-browser@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-17.3.3.tgz#b00a68526e2f39e9797ad4696f9dd8b42451f268" - integrity sha512-XFWjquD+Pr9VszRzrDlT6uaf57TsY9XhL9iHCNok6Op5DpVQpIAuw1vFt2t5ZoQ0gv+lY8mVWnxgqe3CgTdYxw== +"@angular/platform-browser@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-17.3.5.tgz#f1b3832163a7bfccb8e7c3cafa0246226f03a6aa" + integrity sha512-ITlu/GTD64Sr0FMaFCJiHoTJrEZw8qRFXjPjv3BKhAp5dQKcwnCm02o1NOaj5d8oIItIh5fbI2zP0CSU2qNZkQ== dependencies: tslib "^2.3.0" -"@angular/pwa@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/pwa/-/pwa-17.3.3.tgz#28851976b5763b2e6608dafc6fdd86af1416d42a" - integrity sha512-my2EHZ+ld9L+r2BUfL1Mq9ozUvE+1BY3bav5o4ZkwwtQOZ3XTqYIK2v3Z5O/Mot3XAIAeUR9rksoHGtCZcagMg== +"@angular/pwa@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/pwa/-/pwa-17.3.5.tgz#c0f9fb156a4dcd8961de191638728f18bd431854" + integrity sha512-qa1w36x/oRErS9eMTUkmVolA7G/d6lEshAs4RprGxh/2cZ5WkrOxdzb2u1KAEZr0X/C6118laFvr6KRyPCsxpw== dependencies: - "@angular-devkit/schematics" "17.3.3" - "@schematics/angular" "17.3.3" + "@angular-devkit/schematics" "17.3.5" + "@schematics/angular" "17.3.5" parse5-html-rewriting-stream "7.0.0" -"@angular/router@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-17.3.3.tgz#29859efaeaf9e70ff098011679d1407b68de5997" - integrity sha512-kj42+TtwvET7MFqxB3pkKyob0VNmspASlv8Y29vSpzzaOHn8J1fDf6H+8opoIC+Gmvo5NqXUDwq7nxI5aQ0mUQ== +"@angular/router@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-17.3.5.tgz#6498d91560296424a2e2bc8a09cd0d9d81058a85" + integrity sha512-KsIIs3t9IpxsdMSrJDZzO5WgIWkVE6Ep5WWiSyPIgEfA+ndGpJLmyv0d/r1yKKlYUJxz7Hde55o4thgT2n2x/A== dependencies: tslib "^2.3.0" -"@angular/service-worker@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-17.3.3.tgz#cd8c83793771e93e0a98192428d956d92e9cb487" - integrity sha512-ZS7MPNPdvIoNKuPfK2pukKiyn+OXVMUALBjSH6k2ayiKxhMiNBCybA4KkQf6DZ9NIlKiGoBc46wf7FZybWAYbQ== +"@angular/service-worker@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-17.3.5.tgz#7e297ef8a654b517cbb93cb6ac702df815068e21" + integrity sha512-YJBSxlrLDUINHjy1GTrbfmUJOUf2ArLN2y/nM4OOsIev7w0d6PIqruKX7wnT6tl6jJZwFRcEGulo/bSd68P63A== dependencies: tslib "^2.3.0" @@ -4791,6 +4814,13 @@ path-to-regexp "3.2.0" tslib "2.6.1" +"@nestjs/event-emitter@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@nestjs/event-emitter/-/event-emitter-2.0.4.tgz#de7d3986cfeb82639bb95181fab4fe5525437c74" + integrity sha512-quMiw8yOwoSul0pp3mOonGz8EyXWHSBTqBy8B0TbYYgpnG1Ix2wGUnuTksLWaaBiiOTDhciaZ41Y5fJZsSJE1Q== + dependencies: + eventemitter2 "6.4.9" + "@nestjs/jwt@10.1.0": version "10.1.0" resolved "https://registry.yarnpkg.com/@nestjs/jwt/-/jwt-10.1.0.tgz#7899b68d68b998cc140bc0af392c63fc00755236" @@ -4858,10 +4888,10 @@ dependencies: tslib "2.6.1" -"@ngtools/webpack@17.3.3": - version "17.3.3" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-17.3.3.tgz#da62af790e2d7280fe8b03f5dbff343580ffc0f0" - integrity sha512-053KMbg1Tb+Mmg4Htsv8yTpI7ABghguoxhwosQXKB0CjO6M0oexuvdaxbRDQ1vd5xYNOW9LcOfxOMPIwyU4BBA== +"@ngtools/webpack@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-17.3.5.tgz#5f1a8d6e59e8fb37b8f1a4fe69116d9f46f2102f" + integrity sha512-0heI0yHUckdGI8uywu/wkp24KR/tdYMKYJOaYIU+9JydyN1zJRpbR7x0thddl7+k/zu2ZGbfFdv1779Ecw/xdA== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -4947,98 +4977,98 @@ read-package-json-fast "^3.0.0" which "^4.0.0" -"@nrwl/angular@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/angular/-/angular-18.2.3.tgz#eb65c229726c50f00d78e679d5696b0494548a24" - integrity sha512-F0RtvSIH/Qs0ju7VcdfBpDeBZvwio2g4KdNpRog9ZBlgJjEmRWu7aA733A2xng96IkJkIrO0DiJaFbNdm8Yelw== +"@nrwl/angular@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/angular/-/angular-18.3.3.tgz#63d7b65e4d96637d7361d018ec56d061595cb0d4" + integrity sha512-pQsxy58DZBVna3qeJH+osdiRBpx+FCAnCz5kogO6EmRsM17zP4zGpgijVHorAI4EjCNhl2vWa3X/bZ8yQIFBpg== dependencies: - "@nx/angular" "18.2.3" + "@nx/angular" "18.3.3" tslib "^2.3.0" -"@nrwl/cypress@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/cypress/-/cypress-18.2.3.tgz#934f7615f347ece85025a925de2e132a9a924164" - integrity sha512-P44e3hmhXWK6jALoHK8bAVUvIqGP8SCX/GM/e6jVAZIjvAC+L69WTkAXVLgZkiD8WpZegSho47AtaL1D256a/g== +"@nrwl/cypress@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/cypress/-/cypress-18.3.3.tgz#3b85e45169c3aff23ea46e19835956a355111b22" + integrity sha512-CsoPFX+iLwvc/+Im/zZsk3FP8c8epBMmI8GNvZFnDZe8J9bdBmtlxp8/Yh3LdUw8ycmPGPvW7eggv31yNZmT+Q== dependencies: - "@nx/cypress" "18.2.3" + "@nx/cypress" "18.3.3" -"@nrwl/devkit@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-18.2.3.tgz#4de5589b99c6e5a15da334630079d027a59fdd4c" - integrity sha512-BJQdPmXFze7g4zsHhwSTssAcm/hvl0rXbIzZYQxncsVU4d+Fx0GS3JYBZ+9EcfnCeAEb10jGvn7Rfk+0okMmOw== +"@nrwl/devkit@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-18.3.3.tgz#9ec5575afe6d14b17acd5e8da4e98a0de27704c6" + integrity sha512-3zZLE1vfwsNie7qjVUt9lqaM1slU0RTr/dW+Yt/2lxe8Peu6f8bnCM1Pf3kSlzoxQroctfocRtVHFXJsAuAt4g== dependencies: - "@nx/devkit" "18.2.3" + "@nx/devkit" "18.3.3" -"@nrwl/eslint-plugin-nx@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-18.2.3.tgz#f66513f8a2bbb63f3555129f8d8236a0936d7573" - integrity sha512-hwIqxp2A0G250tFzEDmVbhwhtldoB7858848AME99Nt9Ij27ThzYaLIG+TYicmb+Rq2FqG9G/6wS89eg1aAg2Q== +"@nrwl/eslint-plugin-nx@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-18.3.3.tgz#b41316daa9ac7f55379cb4510767f7a865c920a6" + integrity sha512-ARqwcA2n2NN+8ATrooZtPbaW5fb9WSjDFZaI8RdphMXFnPrEkZnMpbrjFpLTj+wc1R6hIgTcYbli6fv4Gfbo3Q== dependencies: - "@nx/eslint-plugin" "18.2.3" + "@nx/eslint-plugin" "18.3.3" -"@nrwl/jest@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-18.2.3.tgz#f603d310729b216788d00d70ad0c00193f8bc430" - integrity sha512-64Ebl6GYOQ8AWp/MpPx8qXwKla3x0wnVGjJK4gUGOJ9ShMQnzd4hgYLpVuB4Des7QSxXoict3YVOVocY0joNow== +"@nrwl/jest@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-18.3.3.tgz#6d75e59c47be007cbe4b78c23fd3e08fe954ed68" + integrity sha512-BPI0mIbmjTHFb0/qtMND59ECld7gorV+SEVLwf4BLl7SWumVB2gLAA2+yx71cvF1jO4R5Ndi2FrBwBC9E2Va5Q== dependencies: - "@nx/jest" "18.2.3" + "@nx/jest" "18.3.3" -"@nrwl/js@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/js/-/js-18.2.3.tgz#f7aa58ae957403215ca2507c6740245796a27d3e" - integrity sha512-fOpKQg7CvzOmcow9fbBc5l96Pbv8gTe9qba4jiw3Z+EH776qraNBL9pRpff653V+obVh//gkq84BUeoJgk8vzQ== +"@nrwl/js@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/js/-/js-18.3.3.tgz#e1a83fb43541cd06752aced6dd7ad932d0c1afa1" + integrity sha512-7Wtv5kpeMWUDBUFu5go49HM/S8vDrtMOvZf9xnUcnjsFDReWe8XIEkTWudZDbzID3X4T6WQAftzj2Ov6k566lQ== dependencies: - "@nx/js" "18.2.3" + "@nx/js" "18.3.3" -"@nrwl/nest@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/nest/-/nest-18.2.3.tgz#c4544725ab375f1189e719b50410d38c36bcec95" - integrity sha512-hQqh3kGZ6Ky7zHzyRDNnzZ57Egn7w96IEfABsT2nnpej0LPWebryPefGSAI4Afgy2q8jSUFj9Bgjf6j93Ogiqg== +"@nrwl/nest@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/nest/-/nest-18.3.3.tgz#28709e32ef4cef6db06a9e219de46ae9b9f40378" + integrity sha512-LIyCiS73O58n7NRWT/SnuA8xHWDu4ANLd9fvguyAzXk1TcPekFvTo6zpY+iu0lkxJ7RfvZHVDGC90bIFSyV9YA== dependencies: - "@nx/nest" "18.2.3" + "@nx/nest" "18.3.3" -"@nrwl/node@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/node/-/node-18.2.3.tgz#fff8c16005c41c8c7d3fe6b7ee4a1b4446e44461" - integrity sha512-cQWAAtG+AexiWsU+5DRfEvbHhU0vkcvhdD3yUG8HjcMjc7eHS82PPxWUk/EzEI/3+3fYcHhSw5F/WyqaVkYJaw== +"@nrwl/node@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/node/-/node-18.3.3.tgz#eb0850a8e7877332550d7e06e7c959d0842b25e2" + integrity sha512-87PXppPqI/jOl6swYVdQi8RBveOF7Oqmqw9m9eEbts6U2bazPipKTwBO4E9afkz3GMqaxe+d2H794JqH05Mr8w== dependencies: - "@nx/node" "18.2.3" + "@nx/node" "18.3.3" -"@nrwl/storybook@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/storybook/-/storybook-18.2.3.tgz#340b10b845dfa373c0513fba40213631e6d0bf51" - integrity sha512-+kZYFSKtZp4+qDav2Z9+xGtRoCiYFE7toKSWNO+7qBmuEm+noCppgxyJ4dv92gc2DR8FSWPrHKp5x+Km0dwJYQ== +"@nrwl/storybook@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/storybook/-/storybook-18.3.3.tgz#80c60ef3975150127a9b09e2d7b79900cd962af0" + integrity sha512-i8mZoJz9CTT7hmXJxgqlz8u4nm48S4XTZLH5nARXcArjoiojUQTQnRr8iDZlJsZxa3+kHTMCJVyQ5WQUC6+Uog== dependencies: - "@nx/storybook" "18.2.3" + "@nx/storybook" "18.3.3" -"@nrwl/tao@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-18.2.3.tgz#c29abf614c23b404d30340326fb52d33822815c0" - integrity sha512-vmteqzGcKPbexaAVPb/7VfXI5dXxzZwSm3rem3z20QlDOmNh1545VLO9YEfT5xzmZT2CC7F0etR4KcrJLtoT5g== +"@nrwl/tao@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-18.3.3.tgz#2d0c60d233f2cc07c85ba08126dd46f21dda1ef0" + integrity sha512-f/PUDLpSMEObiLQ5sIDySJM+5DxSCNunkxxbY1R9rmQ1cFcgrHaXIHQqbSj91mMa3mmtbKACk8u1LbI+oQV0Tg== dependencies: - nx "18.2.3" + nx "18.3.3" tslib "^2.3.0" -"@nrwl/web@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/web/-/web-18.2.3.tgz#15e43dd727ba06df111edf16c7f74f915600e41d" - integrity sha512-nlucIDaMUOAG5xOJTCzvKHhCAxergYUrfi2XgPYjg4mu+ApqJxI7HO6FVXZazdivEwNy++BLErjmOjMb52iaVw== +"@nrwl/web@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/web/-/web-18.3.3.tgz#3e31d086fef5aa1e68ac5af9d5c27592ef2fe39d" + integrity sha512-EuEht/tk9VHLKxjVMEh96wu8WNkRFRabpmLBc++pp2bEaoxz8Qm2xDO+sOU3Wp4zGNx/qQVxA1kKMZCjVjk75g== dependencies: - "@nx/web" "18.2.3" + "@nx/web" "18.3.3" -"@nrwl/webpack@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/webpack/-/webpack-18.2.3.tgz#d3443ed4478e87defb5be209a335d71b91ccce27" - integrity sha512-ygkYzE+ihhFBuMmOuOkGse0Aas0CSbJ8uLth8UumnapU1euBTP5blhp+y6HRCRT8SzfGzc0qJ+M8YLb6E/DvMQ== +"@nrwl/webpack@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/webpack/-/webpack-18.3.3.tgz#0c29dc1561c9b8e613313fd02f805be72515dfa6" + integrity sha512-E/8vr1qAFSan1FnewvLBRBHYIaPG9dxZeYKRcQvcDx+Jf2oPyJNYI+9kkoNxEZg9FeFJMShK2x8YBgwB+ivH5A== dependencies: - "@nx/webpack" "18.2.3" + "@nx/webpack" "18.3.3" -"@nrwl/workspace@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nrwl/workspace/-/workspace-18.2.3.tgz#811b3778b3222be835248eb366de0b9a98f3843e" - integrity sha512-5tVtui/iy+VZTk3x/eFj21Zm0ICPUre9CfB5jlJ2MwH8w+96+186Yt2XGJATkFfnVnjqnszOcjk5BLlra8fdLA== +"@nrwl/workspace@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nrwl/workspace/-/workspace-18.3.3.tgz#291ecda3c4fddcb534f0cc6b7c7796a21483ae49" + integrity sha512-9Giuec9l3PpS8mekD00W9kBIKmWRpQSkp+/RvYmc+7kKtVC+Uj/kc68exBOanVgq6zKzYrn+FqHWHGWnHxp+ww== dependencies: - "@nx/workspace" "18.2.3" + "@nx/workspace" "18.3.3" "@nuxtjs/opencollective@0.3.2": version "0.3.2" @@ -5049,18 +5079,18 @@ consola "^2.15.0" node-fetch "^2.6.1" -"@nx/angular@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/angular/-/angular-18.2.3.tgz#564c304c253a268c87d2cb751655691f471e98f7" - integrity sha512-oSp4cNlyCUd03SNoa+x5zjrnqBjxANInB0+vsGD5VlOewpfkVNWPb7TIRa+JyOFXWSWblF0LNEiLxWnxY+27gw== - dependencies: - "@nrwl/angular" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/eslint" "18.2.3" - "@nx/js" "18.2.3" - "@nx/web" "18.2.3" - "@nx/webpack" "18.2.3" - "@nx/workspace" "18.2.3" +"@nx/angular@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/angular/-/angular-18.3.3.tgz#3648480ddec56e2ca54caed7482eb941b60df3e4" + integrity sha512-KAWpIxd+cNAjSNaArHzJGavES6hBJApE6KVgg3lJwSThkjgTy6loEC4mw8VAQaSlHVx/OEQcbebC1LPkJadG9w== + dependencies: + "@nrwl/angular" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/eslint" "18.3.3" + "@nx/js" "18.3.3" + "@nx/web" "18.3.3" + "@nx/webpack" "18.3.3" + "@nx/workspace" "18.3.3" "@phenomnomnominal/tsquery" "~5.0.1" "@typescript-eslint/type-utils" "^7.3.0" chalk "^4.1.0" @@ -5074,26 +5104,26 @@ webpack "^5.80.0" webpack-merge "^5.8.0" -"@nx/cypress@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/cypress/-/cypress-18.2.3.tgz#fe32cbb21d592fbe0c62f1ee47abc5ffc232bd23" - integrity sha512-TY5LC4cXFAMq3hrIQDTKYwGgNVDWCTF6i22gaaMlTayowfSWcEug5FHfBGXzpvYR4Q5Snci988krI1yN/6Fbfw== +"@nx/cypress@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/cypress/-/cypress-18.3.3.tgz#d0af052f421312018b0d0ddc3476cd4a31ca748f" + integrity sha512-ou7Q6XXM9zIiWFVojZwnnFFJxx4iKACWvusfCOIwJ3zcel1vtamWHffRp2Z9WjdBDxy26Ax/DM+lZj4t6hQRmA== dependencies: - "@nrwl/cypress" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/eslint" "18.2.3" - "@nx/js" "18.2.3" + "@nrwl/cypress" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/eslint" "18.3.3" + "@nx/js" "18.3.3" "@phenomnomnominal/tsquery" "~5.0.1" detect-port "^1.5.1" semver "^7.5.3" tslib "^2.3.0" -"@nx/devkit@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/devkit/-/devkit-18.2.3.tgz#81788e9d018772414ddad0f1aba7ce007da570a3" - integrity sha512-dugw9Jm3Og28uwGee94P3KYkqiUV7J8RgibOQjQG4J2Vt3DPBNEGSgBD72qKkzpioEo+XSVUkn9h3GrdmnRU+Q== +"@nx/devkit@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/devkit/-/devkit-18.3.3.tgz#2ec37855020da74ad1e77b51711b057b3cb12fec" + integrity sha512-FtkZ6mA5//vEA5lcbT80m080ROVacHYV5F1peztTRA+IY2JZGJoqx425kn5ylDO8aCSAIAwcn2qIdhI8BnpG3Q== dependencies: - "@nrwl/devkit" "18.2.3" + "@nrwl/devkit" "18.3.3" ejs "^3.1.7" enquirer "~2.3.6" ignore "^5.0.4" @@ -5102,14 +5132,14 @@ tslib "^2.3.0" yargs-parser "21.1.1" -"@nx/eslint-plugin@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/eslint-plugin/-/eslint-plugin-18.2.3.tgz#99e7e46d8bc32966bdb9c0be7783b7e7bc84a795" - integrity sha512-vOHkzHNpDLLd5RMrL/8/sAdqBqMcf2FrSJWug6W4cC0x8hzUpNwnfEn+i4ZCV/QxduQH4/UP96AbOm7rzwoAdg== +"@nx/eslint-plugin@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/eslint-plugin/-/eslint-plugin-18.3.3.tgz#0410261cf7f1a227eefbe2a979c9482ad9c19894" + integrity sha512-ww3r8VRlzJXOBRG+qCTd+VXHRKxiIrOH+cIokTtuzGrnCXWEMSPO5Ts6z/Jsbb0xAcfZ39WUnxuDZdKbp4aHqA== dependencies: - "@nrwl/eslint-plugin-nx" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/js" "18.2.3" + "@nrwl/eslint-plugin-nx" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/js" "18.3.3" "@typescript-eslint/type-utils" "^7.3.0" "@typescript-eslint/utils" "^7.3.0" chalk "^4.1.0" @@ -5118,28 +5148,28 @@ semver "^7.5.3" tslib "^2.3.0" -"@nx/eslint@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/eslint/-/eslint-18.2.3.tgz#714106ffb0e9a7dd35e3248640a073e811eb9c66" - integrity sha512-qr1A3on5tPR3Rxsrg1wlPLVB/L6iFDp+II1xBb/3PBAsddKvPCzPASsogAm0Q3RdqK2JkJrwo/rX3YxwrjZ5cQ== +"@nx/eslint@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/eslint/-/eslint-18.3.3.tgz#ce28b4240e0558333dee08c824d8f82d72a11159" + integrity sha512-cvJjyykTEtQN08b5wQFelD/cbye7Nl5zFVESs+mn9/ezCukjAgP9seOk39nchKykRBAm7zzA1xZOB9thNqw9aA== dependencies: - "@nx/devkit" "18.2.3" - "@nx/js" "18.2.3" - "@nx/linter" "18.2.3" + "@nx/devkit" "18.3.3" + "@nx/js" "18.3.3" + "@nx/linter" "18.3.3" eslint "^8.0.0" tslib "^2.3.0" typescript "~5.4.2" -"@nx/jest@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/jest/-/jest-18.2.3.tgz#f36a0671bb64e45961dad4a97c835873a5e297cf" - integrity sha512-AMI/RuTlNz5d0JiBdraCkZ1ABfEyuJkdCvVjo/RDu1NAw1Xv4hI4+5UG7sb/bJoX6n+lK1SS51z+Zb/ab8lQoQ== +"@nx/jest@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/jest/-/jest-18.3.3.tgz#4a25f77169d0e630cb9b5f49bd0cde1faf0aae31" + integrity sha512-AwkwYSJqu0vrDFMxKAc3lb0yHZFhsD8rX6rMMwe/fZMlAYml9FvGCp/ixWpcRWIo/1t3pxiF3Vejk9+oq/Avfw== dependencies: "@jest/reporters" "^29.4.1" "@jest/test-result" "^29.4.1" - "@nrwl/jest" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/js" "18.2.3" + "@nrwl/jest" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/js" "18.3.3" "@phenomnomnominal/tsquery" "~5.0.1" chalk "^4.1.0" identity-obj-proxy "3.0.0" @@ -5151,10 +5181,10 @@ tslib "^2.3.0" yargs-parser "21.1.1" -"@nx/js@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/js/-/js-18.2.3.tgz#fd9a1be56fd674f80563a20d90feffc6ab9b830a" - integrity sha512-hFSmgyaMVIlN/SyFwOwn/IveHsGxxJOv7qhewACg9NlKOa6+eEJYlEbOik9LjvcosDOh5icrngjsFgFJoC1sWA== +"@nx/js@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/js/-/js-18.3.3.tgz#977968160d6edc11f320bc0f654b52d36a9101ac" + integrity sha512-e8u56oG0mlTVz48EeH0C7txX0GeLYN0o4mK1LDAMIHQa4tKefNfwrdqHaZBiVqFOPopeFtqi8s0kqce5prwCaw== dependencies: "@babel/core" "^7.23.2" "@babel/plugin-proposal-decorators" "^7.22.7" @@ -5163,9 +5193,9 @@ "@babel/preset-env" "^7.23.2" "@babel/preset-typescript" "^7.22.5" "@babel/runtime" "^7.22.6" - "@nrwl/js" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/workspace" "18.2.3" + "@nrwl/js" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/workspace" "18.3.3" "@phenomnomnominal/tsquery" "~5.0.1" babel-plugin-const-enum "^1.0.1" babel-plugin-macros "^2.8.0" @@ -5187,125 +5217,125 @@ tsconfig-paths "^4.1.2" tslib "^2.3.0" -"@nx/linter@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/linter/-/linter-18.2.3.tgz#a2b9bd388955f7872c42b5dfcabb7f308344039b" - integrity sha512-buxqe0N/d5iVWA4zE/jX8xrkCJLyGG2h1bSTrz1oyPvM3SdcWr69JpL8j1wtBvnKo/brDzLbNWsnrUwO9cgSAQ== +"@nx/linter@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/linter/-/linter-18.3.3.tgz#ae861fb7d10c4f1dcdb4389f5b9f25aecab6fee0" + integrity sha512-5HmAN/8jZ2scrA0OiJSUdBPhIjwIHecK8AK7TxYX4fg1VJ3VcpknV8pWcETuNoBW8WlgF1RX2RW7Gog7vjf+Ww== dependencies: - "@nx/eslint" "18.2.3" + "@nx/eslint" "18.3.3" -"@nx/nest@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nest/-/nest-18.2.3.tgz#24a01ba16207768e80ff42004fa6552b2605f609" - integrity sha512-kBIKF08iB8V4k9RaPsSzawaVIZo/czx+SEaQmS7+fSsVerLji5ZJoFKqSxnDz6ksW1lfkmRpymSdWWHRc/UDKA== +"@nx/nest@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nest/-/nest-18.3.3.tgz#16fe7ba6d1f8634ffae58b8e6dda4132ef112c5e" + integrity sha512-e2uPVBsewdLkgf9ncAxN/UEln3ygc1lyy8LTfR5X0Gzx3CUPiayDfd9OxZaxnDFi7Jpu89dpckMO8NhAIBvheA== dependencies: "@nestjs/schematics" "^9.1.0" - "@nrwl/nest" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/eslint" "18.2.3" - "@nx/js" "18.2.3" - "@nx/node" "18.2.3" + "@nrwl/nest" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/eslint" "18.3.3" + "@nx/js" "18.3.3" + "@nx/node" "18.3.3" "@phenomnomnominal/tsquery" "~5.0.1" tslib "^2.3.0" -"@nx/node@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/node/-/node-18.2.3.tgz#5ba965f8163dadb802bd43c9706807efaea750be" - integrity sha512-ryI+xzFLBNlRqLNH5UkHO2ZYIs1u1dUbkf7HTyJ4AOrzH2kuBd7tKfFI/IcDzmhjMOfhDYPC0RV7osOSS5Vdiw== +"@nx/node@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/node/-/node-18.3.3.tgz#a000284eb88dc58cbb4dad9909c1e0a930560c61" + integrity sha512-OoeRuuvqrdEH8AsFKrJ91lnDVL9mlqvLzUy9D5PZCYspjCesc7Tmt7Xmbu3VEGzhQPilqZz4hVfXH6MLE7TvqA== dependencies: - "@nrwl/node" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/eslint" "18.2.3" - "@nx/jest" "18.2.3" - "@nx/js" "18.2.3" + "@nrwl/node" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/eslint" "18.3.3" + "@nx/jest" "18.3.3" + "@nx/js" "18.3.3" tslib "^2.3.0" -"@nx/nx-darwin-arm64@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-darwin-arm64/-/nx-darwin-arm64-18.2.3.tgz#4b3f14437e6f5a7233594f63a8d36097e8872af1" - integrity sha512-TEks/vXHE87rNvVqhcIzQOM/+aZvNCf/70PhGG4RBEb+qV0C1kw7nygzdoLI4inFC76Qxhyya/K3J2OnU5ATiw== - -"@nx/nx-darwin-x64@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-darwin-x64/-/nx-darwin-x64-18.2.3.tgz#bc546836bcce2293181a315666d4a0ea7b42642a" - integrity sha512-UsBbNbNXj+L2OzPyQYotyzmZF4h+ryaZ8quYDfdnlYwvFeqkdb2QJ3vJRd6in0kMWGrdk/ria/wZMCxR7U1ggg== - -"@nx/nx-freebsd-x64@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-freebsd-x64/-/nx-freebsd-x64-18.2.3.tgz#afe920b26385fffb77cbad5435ff97607481c01c" - integrity sha512-f9BXGOeRPhrsNm99TCnOqZZeZUqN1BUOEzWa12eo3u+vQG6Qba3qKn7T92SeEzxOx/mUP/Csv3pFYoY6TE26jA== - -"@nx/nx-linux-arm-gnueabihf@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-18.2.3.tgz#d438dddcfb0fd255b8903214118c304eb89f33ef" - integrity sha512-ekqr5jZhD6PxGM5IbI/RtlERDJ+8HR04OIdfo6HkbwxwCHxZlzZq+ApEZYum4AbjP6cuc3Zd/us1uuDqfQbeHw== - -"@nx/nx-linux-arm64-gnu@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-18.2.3.tgz#a496666a70499d22589dfe0df3d46e738921250b" - integrity sha512-iAW2J8NBFU4zDn5nqRgUq4t7gYC8ALyALzznr97ZvMTQorWfmHYgPUAj/opNqUcr10fjxcmXT0Ux2SX3DgUDmw== - -"@nx/nx-linux-arm64-musl@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-18.2.3.tgz#90744f03377959bdc90cf5a8a2f00afb5b084b70" - integrity sha512-AJjGVHGGew0QVKUL30mjFjafowrSDYSQ1GgkJCLuWef5jl4rFvm9ruZswVja1KfZTFaImTCU01tZjPBr3zhmAA== - -"@nx/nx-linux-x64-gnu@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-18.2.3.tgz#0c0fac195dcf5eaf58a89bbd4764e06c5e338f14" - integrity sha512-nk5Xg8vmbBRoL0fOgZNBl1paC7hmjACLaSBmU7U2X+Y+QPGQzSw2b+Zn1MKVUWDmc4E6VnQfZ8n0L27+r9NgRw== - -"@nx/nx-linux-x64-musl@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-18.2.3.tgz#ba2e290ae3e7e0b43669546591e576c3f7ff2c50" - integrity sha512-bOlhul/eov58k9fX8lltopUDOIBEohZq2qc4ag91W2r4jdp6suAiqfXRxQwNZ2iHd8nAXuCDIHCbUuojs6OZnA== - -"@nx/nx-win32-arm64-msvc@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-18.2.3.tgz#5fc56f77ae98e273b1abb9eaf91492f1a40f2dc6" - integrity sha512-olXer0LnCvJrdV5ynd19fZHvvarRK/p1JnkoOUZDPVV+A3jGQQ8+paz+/5iLQBKA+5VcgWyqAaGFJnpyEFmnoQ== - -"@nx/nx-win32-x64-msvc@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.2.3.tgz#91083c549d4cdbaa0098cf1158edce98f1b440d6" - integrity sha512-BgzPjF/wqi7zIFcspcKzN37BX1wgGo0OTLncK2PN5nyzSQ+XeNbR5laDswxzOGdB4CRLPqak2+YMhYnoiXeRCg== - -"@nx/storybook@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/storybook/-/storybook-18.2.3.tgz#38a9d6a541113304abf5d918411bf8696ccdb51e" - integrity sha512-6XvgLD2L4+cbEwPneey+mxB7nGUi4l0K+R1AWjijGg14X2IzyCTgs5up56vIAKVuwuXxGWUTuXgSXwfKXINLIg== - dependencies: - "@nrwl/storybook" "18.2.3" - "@nx/cypress" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/eslint" "18.2.3" - "@nx/js" "18.2.3" +"@nx/nx-darwin-arm64@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-arm64/-/nx-darwin-arm64-18.3.3.tgz#dcdbcfe2796bbe3f1dfd61bce81389b05a50e69b" + integrity sha512-NpA2/7o1uUuaocMYopX9muxKif9HlGfWaXo2UeiR918usF6xri4aUqweZbaXVc9iqCAEbVMWUsjaLYGKPXHAjw== + +"@nx/nx-darwin-x64@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-x64/-/nx-darwin-x64-18.3.3.tgz#aa7bdd1a3ea0bb81682422b805914efccab3b179" + integrity sha512-aydPLbc7DeceJ6szRf6DLT4ERoPvwfWyFiGXdAlEZYWhjEuNZLeG8K6jA3yHeWltKfX/qJqhnyKbnubBNzBKlQ== + +"@nx/nx-freebsd-x64@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-freebsd-x64/-/nx-freebsd-x64-18.3.3.tgz#331f5dbb56c90b08e99c1ce9ff51e0c5b956f030" + integrity sha512-sEYEWsK/fwC1l7wzls7RNOjhmrooH0lK0mpgj1vDXesLBSZ7k+pddAqaHFECN4QXBSbHZI2PWOEhbnIH+Errsg== + +"@nx/nx-linux-arm-gnueabihf@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-18.3.3.tgz#d66d4787f5cfc56b5a7aa9a0453174b96b4729a8" + integrity sha512-B9GGMkrrzwiAfvew22x85ITO9TiNxbgRbKJQWQaoopNpXrnSWpY8WTNxpDT24fwV1qdQfsPKcY3F4O0NOUgPRA== + +"@nx/nx-linux-arm64-gnu@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-18.3.3.tgz#2ab08df1d052a55d4a52ba910fe41c25701d5361" + integrity sha512-1EucHf5/0JeqZmhritqkpEdOcdo9Dl32gpFvhNfS6kCAYmaDlEl4zqedz3VIoj4C7+C0pV3mcRO9qB9H7GM5bQ== + +"@nx/nx-linux-arm64-musl@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-18.3.3.tgz#69376454bb9759c376d0a90aa876dfff6bbf4d15" + integrity sha512-HPgOgnYYLPVCBEaAkSEGPGzZqTDCiyCAF/qtvx5z0f1U/hZYb1ubgxw70ogY82Cafr7X4gQBz5k4/ZCnoCXlOQ== + +"@nx/nx-linux-x64-gnu@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-18.3.3.tgz#0b8ba8ec0c2371f0df462742460d52d63b1cc715" + integrity sha512-FgYTQ3VEE6EUOGtJT9riRK8IBwPGFjKS+N2mudQJn2bB/9IumUvVRYQUIX08gqGLlqZPO6uUUhUjwZY8SnjRLQ== + +"@nx/nx-linux-x64-musl@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-18.3.3.tgz#c96d6f8d2d94b99ac8da723077ebbc92f833beea" + integrity sha512-QnWjGViR1Wj9gJXa1RJ9mXyy2/JzQ7NF2C4ulTYSH5St1HoxhkfnLsV0+uNLFEV9PSZq+2BfxmQuT8Appefv1A== + +"@nx/nx-win32-arm64-msvc@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-18.3.3.tgz#0d2c7396e7a063849edbd6e3d34ea81445c389b5" + integrity sha512-Xn3LUaPsF8QkEYUVV3lc693NTCMWrfZBFXTy1cQpvLzQ+idsXQ/EGWoq93cIM3Nc2YWyblT2hHHelb8dHCZAlw== + +"@nx/nx-win32-x64-msvc@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.3.3.tgz#ea1a60ae1ffe805529d5cb95e7b28e6b8ae24621" + integrity sha512-t8HvOnQEiaaoTFOOIrql30NPhIwDFO7jg0Jtz3Tbneulh7ceswJp71yFHsRGGrYZ23Tgg+Sna6M9qLRGzlRGkg== + +"@nx/storybook@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/storybook/-/storybook-18.3.3.tgz#4fa01568e3189984d14bae217281f16e2cea5f4e" + integrity sha512-wqca3J20F9HakmPBzq9fwmcZ25LFNb9iWnSngXMgDXjRizbjZrXrCkpyiZe3qlYzhoCNN9oYlUsbas3dec/lwA== + dependencies: + "@nrwl/storybook" "18.3.3" + "@nx/cypress" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/eslint" "18.3.3" + "@nx/js" "18.3.3" "@phenomnomnominal/tsquery" "~5.0.1" semver "^7.5.3" tslib "^2.3.0" -"@nx/web@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/web/-/web-18.2.3.tgz#c1d1bf7a77d16fd9281453c1c9e68dea853f0fc0" - integrity sha512-nDiCHinZGfkGWuTL2HLk6tUcKILMYtrtd6c/cE8T+5TnTXNaMrOQFt1GvDa60HGh8xgRgpjzTsGfJFrf90GJcA== +"@nx/web@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/web/-/web-18.3.3.tgz#99e6952942b3e43bc52ba444f6933dd279f49a6a" + integrity sha512-/NfQirVd2Ncq2if+1n8DaxNQF0OLaFaDag7qm5pDWJnjXFNh8N7NGZQRry2k/bTSfSc8gN+KJjqSMLAUNNtKgQ== dependencies: - "@nrwl/web" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/js" "18.2.3" + "@nrwl/web" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/js" "18.3.3" chalk "^4.1.0" detect-port "^1.5.1" http-server "^14.1.0" tslib "^2.3.0" -"@nx/webpack@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/webpack/-/webpack-18.2.3.tgz#15b3c4be376f2313abdd64c3b67e04f11fbde1fc" - integrity sha512-0X7HXrF/VP9BrbbYD4Ewr4KnMT85eSaIBr/TvTrUM4v2BXqPgP4NVQhkd6jLlEkWuDlYtAgwFjcx4NGWRqnwbw== +"@nx/webpack@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/webpack/-/webpack-18.3.3.tgz#2b13c08c99821a413edd4ff7749936871ae6ae32" + integrity sha512-DPs8wfmYe/mEZCQ/TQgUqb/zgXY8hevR23d8bDkYjB3Akjk4OOF3QpQ2OXQ4c+Jf0ckGnQYOg6XAkE682UZqzg== dependencies: "@babel/core" "^7.23.2" - "@nrwl/webpack" "18.2.3" - "@nx/devkit" "18.2.3" - "@nx/js" "18.2.3" + "@nrwl/webpack" "18.3.3" + "@nx/devkit" "18.3.3" + "@nx/js" "18.3.3" ajv "^8.12.0" autoprefixer "^10.4.9" babel-loader "^9.1.2" @@ -5340,16 +5370,16 @@ webpack-node-externals "^3.0.0" webpack-subresource-integrity "^5.1.0" -"@nx/workspace@18.2.3": - version "18.2.3" - resolved "https://registry.yarnpkg.com/@nx/workspace/-/workspace-18.2.3.tgz#797b2aef3613ddb30ea4dbef0bd1bde37b3c60e2" - integrity sha512-en3lSArMrHZ75SqMHnnZjXiMunc6QFDMcglNPQwIE8TuXnV8UWQ1e4hkzRo6hY/YOoY7HcFvMEJ5KyP8OWCmQg== +"@nx/workspace@18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@nx/workspace/-/workspace-18.3.3.tgz#bae369fe9d6c8aca425222ec53f797bcacd715e6" + integrity sha512-SUJJKzOUuNnclpHHde6f6nlF+pQwMjeF026jFpWDFaNzdsADhhRulkz0GLRXB9kKszvzz2JKde9WBWnKrFZ2IQ== dependencies: - "@nrwl/workspace" "18.2.3" - "@nx/devkit" "18.2.3" + "@nrwl/workspace" "18.3.3" + "@nx/devkit" "18.3.3" chalk "^4.1.0" enquirer "~2.3.6" - nx "18.2.3" + nx "18.3.3" tslib "^2.3.0" yargs-parser "21.1.1" @@ -5419,46 +5449,46 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== -"@prisma/client@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.12.1.tgz#c26a674fea76754b3a9e8b90a11e617f90212f76" - integrity sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA== +"@prisma/client@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.13.0.tgz#b9f1d0983d714e982675201d8222a9ecb4bdad4a" + integrity sha512-uYdfpPncbZ/syJyiYBwGZS8Gt1PTNoErNYMuqHDa2r30rNSFtgTA/LXsSk55R7pdRTMi5pHkeP9B14K6nHmwkg== -"@prisma/debug@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.12.1.tgz#007c8ad2e466d565bcd0671b8846c27f8700c722" - integrity sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A== +"@prisma/debug@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.13.0.tgz#d88b0f6fafa0c216e20e284ed9fc30f1cbe45786" + integrity sha512-699iqlEvzyCj9ETrXhs8o8wQc/eVW+FigSsHpiskSFydhjVuwTJEfj/nIYqTaWFYuxiWQRfm3r01meuW97SZaQ== -"@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab": - version "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab.tgz#c78d099a3fe86d446db7442e64e56987e39e7f32" - integrity sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g== +"@prisma/engines-version@5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b": + version "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b.tgz#a72a4fb83ba1fd01ad45f795aa55168f60d34723" + integrity sha512-AyUuhahTINGn8auyqYdmxsN+qn0mw3eg+uhkp8zwknXYIqoT3bChG4RqNY/nfDkPvzWAPBa9mrDyBeOnWSgO6A== -"@prisma/engines@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.12.1.tgz#a50649427d627a9af962a188a84c65d61c6e2b3f" - integrity sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA== +"@prisma/engines@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.13.0.tgz#8994ebf7b4e35aee7746a8465ec22738379bcab6" + integrity sha512-hIFLm4H1boj6CBZx55P4xKby9jgDTeDG0Jj3iXtwaaHmlD5JmiDkZhh8+DYWkTGchu+rRF36AVROLnk0oaqhHw== dependencies: - "@prisma/debug" "5.12.1" - "@prisma/engines-version" "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab" - "@prisma/fetch-engine" "5.12.1" - "@prisma/get-platform" "5.12.1" + "@prisma/debug" "5.13.0" + "@prisma/engines-version" "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b" + "@prisma/fetch-engine" "5.13.0" + "@prisma/get-platform" "5.13.0" -"@prisma/fetch-engine@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.12.1.tgz#c38e9fa17fdc535b4c83cbb7645569ad0a511fa9" - integrity sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA== +"@prisma/fetch-engine@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.13.0.tgz#9b6945c7b38bb59e840f8905b20ea7a3d059ca55" + integrity sha512-Yh4W+t6YKyqgcSEB3odBXt7QyVSm0OQlBSldQF2SNXtmOgMX8D7PF/fvH6E6qBCpjB/yeJLy/FfwfFijoHI6sA== dependencies: - "@prisma/debug" "5.12.1" - "@prisma/engines-version" "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab" - "@prisma/get-platform" "5.12.1" + "@prisma/debug" "5.13.0" + "@prisma/engines-version" "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b" + "@prisma/get-platform" "5.13.0" -"@prisma/get-platform@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.12.1.tgz#33f427f6d744dee62a9e06858889691d78b50804" - integrity sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ== +"@prisma/get-platform@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.13.0.tgz#99ef909a52b9d79b64d72d2d3d8210c4892b6572" + integrity sha512-B/WrQwYTzwr7qCLifQzYOmQhZcFmIFhR81xC45gweInSUn2hTEbfKUPd2keAog+y5WI5xLAFNJ3wkXplvSVkSw== dependencies: - "@prisma/debug" "5.12.1" + "@prisma/debug" "5.13.0" "@radix-ui/number@1.0.1": version "1.0.1" @@ -5831,6 +5861,15 @@ "@angular-devkit/schematics" "17.3.3" jsonc-parser "3.2.1" +"@schematics/angular@17.3.5": + version "17.3.5" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-17.3.5.tgz#c58a6afef977e9280cc7a5e24e70b058f68fdc5e" + integrity sha512-SWCK16Eob0K86hpZ3NHmrTS6LSzTlhvnIdf3BXC6nzoiyDhcAS0oJ2Tjdq1opW/PaL1hB7MulcbIhxYln5du0w== + dependencies: + "@angular-devkit/core" "17.3.5" + "@angular-devkit/schematics" "17.3.5" + jsonc-parser "3.2.1" + "@schematics/angular@^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0": version "17.0.0" resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-17.0.0.tgz#63ddf8bfbb3b117fe7a355bd22b43d2c9ff7f0ee" @@ -9248,20 +9287,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541: - version "1.0.30001554" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz#ba80d88dff9acbc0cd4b7535fc30e0191c5e2e2a" - integrity sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ== - -caniuse-lite@^1.0.30001565: - version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== - -caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001591: - version "1.0.30001606" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz#b4d5f67ab0746a3b8b5b6d1f06e39c51beb39a9e" - integrity sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541, caniuse-lite@^1.0.30001565, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001591: + version "1.0.30001610" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001610.tgz" + integrity sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA== case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" @@ -11621,7 +11650,7 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -eventemitter2@^6.4.2: +eventemitter2@6.4.9, eventemitter2@^6.4.2: version "6.4.9" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125" integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg== @@ -13075,10 +13104,10 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -ionicons@7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-7.3.0.tgz#d2385e87dbe6a8c79fd44fb2e7c87b0de4a2cbcb" - integrity sha512-l9quySYi+o4T6mFzhKRyU/1nKc2Zs0zxs7jWcq9iVRhRPQondV11jYqLTed0lVVXHfGrBCfnedKl9D6BCnA1UQ== +ionicons@7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-7.4.0.tgz#9c285aaa8089befbd6c5a89ae13292d364cd9ace" + integrity sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ== dependencies: "@stencil/core" "^4.0.3" @@ -15633,12 +15662,12 @@ nwsapi@^2.2.2: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== -nx@18.2.3: - version "18.2.3" - resolved "https://registry.yarnpkg.com/nx/-/nx-18.2.3.tgz#40d4c18a3b7143e10b3645b5bd47a65c5b9d5e6f" - integrity sha512-4XGvvIzXeeeSj1hObiBL7E7aXX6rbiB1F856AqUdGoysYfkhcxOFyeAv5XsXeukl9gYwh/LH84paXjEOkGaJlA== +nx@18.3.3: + version "18.3.3" + resolved "https://registry.yarnpkg.com/nx/-/nx-18.3.3.tgz#ab96811961b631efd4f0c83550e92f7b0a625e83" + integrity sha512-GqC5ANfTWV6SFbgquZwuRMI2Z2nO0c0Yx4JzM3x32aJOgXsmRml3WcV0a5648bIXSen34gylHYl2EHaxVWkzNQ== dependencies: - "@nrwl/tao" "18.2.3" + "@nrwl/tao" "18.3.3" "@yarnpkg/lockfile" "^1.1.0" "@yarnpkg/parsers" "3.0.0-rc.46" "@zkochan/js-yaml" "0.0.6" @@ -15673,16 +15702,16 @@ nx@18.2.3: yargs "^17.6.2" yargs-parser "21.1.1" optionalDependencies: - "@nx/nx-darwin-arm64" "18.2.3" - "@nx/nx-darwin-x64" "18.2.3" - "@nx/nx-freebsd-x64" "18.2.3" - "@nx/nx-linux-arm-gnueabihf" "18.2.3" - "@nx/nx-linux-arm64-gnu" "18.2.3" - "@nx/nx-linux-arm64-musl" "18.2.3" - "@nx/nx-linux-x64-gnu" "18.2.3" - "@nx/nx-linux-x64-musl" "18.2.3" - "@nx/nx-win32-arm64-msvc" "18.2.3" - "@nx/nx-win32-x64-msvc" "18.2.3" + "@nx/nx-darwin-arm64" "18.3.3" + "@nx/nx-darwin-x64" "18.3.3" + "@nx/nx-freebsd-x64" "18.3.3" + "@nx/nx-linux-arm-gnueabihf" "18.3.3" + "@nx/nx-linux-arm64-gnu" "18.3.3" + "@nx/nx-linux-arm64-musl" "18.3.3" + "@nx/nx-linux-x64-gnu" "18.3.3" + "@nx/nx-linux-x64-musl" "18.3.3" + "@nx/nx-win32-arm64-msvc" "18.3.3" + "@nx/nx-win32-x64-msvc" "18.3.3" oauth@0.9.x: version "0.9.15" @@ -16674,12 +16703,12 @@ pretty-hrtime@^1.0.3: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== -prisma@5.12.1: - version "5.12.1" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.12.1.tgz#db4596253bb066afc9f08744642f200a398d8d51" - integrity sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q== +prisma@5.13.0: + version "5.13.0" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.13.0.tgz#1f06e20ccfb6038ad68869e6eacd3b346f9d0851" + integrity sha512-kGtcJaElNRAdAGsCNykFSZ7dBKpL14Cbs+VaQ8cECxQlRPDjBlMHNFYeYt0SKovAVy2Y65JXQwB3A5+zIQwnTg== dependencies: - "@prisma/engines" "5.12.1" + "@prisma/engines" "5.13.0" prismjs@^1.28.0: version "1.29.0" @@ -18885,10 +18914,10 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici@6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.7.1.tgz#3cb27222fd5d72c1b2058f4e18bf9b53dd933af8" - integrity sha512-+Wtb9bAQw6HYWzCnxrPTMVEV3Q1QjYanI0E4q02ehReMuquQdLTEFEYbfs7hcImVYKcQkWSwT6buEmSVIiDDtQ== +undici@6.11.1: + version "6.11.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.11.1.tgz#75ab573677885b421ca2e6f5f17ff1185b24c68d" + integrity sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw== unfetch@^4.2.0: version "4.2.0" @@ -19162,10 +19191,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vite@5.1.5: - version "5.1.5" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.5.tgz#bdbc2b15e8000d9cc5172f059201178f9c9de5fb" - integrity sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q== +vite@5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.7.tgz#9f685a2c4c70707fef6d37341b0e809c366da619" + integrity sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA== dependencies: esbuild "^0.19.3" postcss "^8.4.35" @@ -19620,10 +19649,10 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yahoo-finance2@2.11.1: - version "2.11.1" - resolved "https://registry.yarnpkg.com/yahoo-finance2/-/yahoo-finance2-2.11.1.tgz#97758d4784ef0b4efe4b370a72063929cc4c6342" - integrity sha512-YglgpjIDithq1PG8Je/gy8nzJFqkH214x2ZGfr6Y+HV4ymTDFLluq2W9Hsvvyydv1zTv9/Ykedf0J4YIpmO2Zg== +yahoo-finance2@2.11.2: + version "2.11.2" + resolved "https://registry.yarnpkg.com/yahoo-finance2/-/yahoo-finance2-2.11.2.tgz#44f35105a2500fd1da22ac4f4393106f2bfec6d1" + integrity sha512-S5lHKqneMXMKN/rxowqErEfkvXJE6s/SPuekT7UkOVbsSyRcptea/U3Mud+ikOEXEbKXPiZrU0Jy+iF51ITuSw== dependencies: "@types/tough-cookie" "^4.0.2" ajv "8.10.0"