diff --git a/.vscode/extensions.json b/.vscode/extensions.json index fde9874a2..68abade5f 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,8 +1,8 @@ { "recommendations": [ "angular.ng-template", + "esbenp.prettier-vscode", "firsttris.vscode-jest-runner", - "nrwl.angular-console", - "prettier.prettier-vscode" + "nrwl.angular-console" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 36091af85..9bf4d12b5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { - "editor.defaultFormatter": "prettier.prettier-vscode", + "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index cab8393e3..67541f050 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,63 @@ 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 +## Next + +### Changed + +- Migrated from _Material Design_ 2 to _Material Design_ 3 + +## 2.233.0 - 2026-01-23 + +### Changed + +- Deprecated `firstBuyDate` in favor of `dateOfFirstActivity` in the portfolio calculator +- Deprecated `transactionCount` in favor of `activitiesCount` in the portfolio calculator and service +- Removed the deprecated `firstBuyDate` from the endpoint `GET api/v1/portfolio/holding/:dataSource/:symbol` +- Refreshed the cryptocurrencies list +- Upgraded `prettier` from version `3.7.4` to `3.8.0` + +## 2.232.0 - 2026-01-19 + +### Added + +- Extended the analysis page to include the total amount, change and performance with currency effects (experimental) + +### Changed + +- Deprecated `firstBuyDate` in favor of `dateOfFirstActivity` in the endpoint `GET api/v1/portfolio/holding/:dataSource/:symbol` +- Improved the language localization for German (`de`) +- Upgraded `countries-list` from version `3.2.0` to `3.2.2` + +## 2.231.0 - 2026-01-17 + +### Changed + +- Removed the deprecated platforms from the info service +- Removed the deprecated activities from the endpoint `GET api/v1/portfolio/holding/:dataSource/:symbol` + +### Fixed + +- Fixed a numeric parsing error related to cash positions on the _X-ray_ page +- Fixed the total fee calculation in the holding detail dialog related to activities in a custom currency +- Fixed the total fee calculation in the summary related to activities in a custom currency + +## 2.230.0 - 2026-01-14 + +### Added + +- Set up the language localization for Korean (`ko`) + +### Changed + +- Restored the support for specific calendar year date ranges (`2024`, `2023`, `2022`, etc.) in the holdings table (experimental) + +### Fixed + +- Fixed the total fee calculation in the holding detail dialog related to activities in a custom currency +- Fixed the total fee calculation in the summary related to activities in a custom currency + +## 2.229.0 - 2026-01-11 ### Changed @@ -19,7 +75,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed the net worth calculation to prevent the double counting of cash positions - Fixed the filtering by asset class in the endpoint `GET api/v1/portfolio/holdings` +- Fixed the case-insensitive sorting in the accounts table component +- Fixed the case-insensitive sorting in the benchmark component +- Fixed the case-insensitive sorting in the holdings table component ## 2.228.0 - 2026-01-03 diff --git a/README.md b/README.md index 35276b232..03566b2dd 100644 --- a/README.md +++ b/README.md @@ -85,31 +85,32 @@ We provide official container images hosted on [Docker Hub](https://hub.docker.c ### Supported Environment Variables -| 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 key | -| `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) | -| `LOG_LEVELS` | `string[]` (optional) | | The logging levels for the Ghostfolio application, e.g. `["debug","error","log","warn"]` | -| `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 | -| `ROOT_URL` | `string` (optional) | `http://0.0.0.0:3333` | The root URL of the Ghostfolio application, used for generating callback URLs and external links. | +| 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 key | +| `DATABASE_URL` | `string` | | The database connection URL, e.g. `postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?sslmode=prefer` | +| `ENABLE_FEATURE_AUTH_TOKEN` | `boolean` (optional) | `true` | Enables authentication via security token | +| `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) | +| `LOG_LEVELS` | `string[]` (optional) | | The logging levels for the Ghostfolio application, e.g. `["debug","error","log","warn"]` | +| `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 | +| `ROOT_URL` | `string` (optional) | `http://0.0.0.0:3333` | The root URL of the Ghostfolio application, used for generating callback URLs and external links. | #### OpenID Connect OIDC (Experimental) | Name | Type | Default Value | Description | | -------------------------- | --------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------- | -| `ENABLE_FEATURE_AUTH_OIDC` | `boolean` (optional) | `false` | Enables _OpenID Connect_ authentication | +| `ENABLE_FEATURE_AUTH_OIDC` | `boolean` (optional) | `false` | Enables authentication via _OpenID Connect_ | | `OIDC_AUTHORIZATION_URL` | `string` (optional) | | Manual override for the OIDC authorization endpoint (falls back to the discovery from the issuer) | | `OIDC_CALLBACK_URL` | `string` (optional) | `${ROOT_URL}/api/auth/oidc/callback` | The OIDC callback URL | | `OIDC_CLIENT_ID` | `string` | | The OIDC client ID | @@ -317,12 +318,9 @@ If you like to support this project, become a [**Sponsor**](https://github.com/s ## Sponsors
## Analytics diff --git a/apps/api/src/app/endpoints/platforms/platforms.controller.ts b/apps/api/src/app/endpoints/platforms/platforms.controller.ts index 46303a3f8..92ba77297 100644 --- a/apps/api/src/app/endpoints/platforms/platforms.controller.ts +++ b/apps/api/src/app/endpoints/platforms/platforms.controller.ts @@ -15,7 +15,9 @@ export class PlatformsController { @HasPermission(permissions.readPlatforms) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async getPlatforms(): PromiseUse Ghostfolio in multiple languages: English, - Chinese, Dutch, French, German, Italian, Polish, Portuguese, - Spanish and Turkish + Chinese, Dutch, French, German, Italian, + + Polish, Portuguese, Spanish and Turkish are currently supported.
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 ec872c770..5cd24777c 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 @@ -2,6 +2,7 @@ import { GfBenchmarkComparatorComponent } from '@ghostfolio/client/components/be import { GfInvestmentChartComponent } from '@ghostfolio/client/components/investment-chart/investment-chart.component'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { NUMERICAL_PRECISION_THRESHOLD_6_FIGURES } from '@ghostfolio/common/config'; import { HistoricalDataItem, InvestmentItem, @@ -94,6 +95,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { public performanceDataItems: HistoricalDataItem[]; public performanceDataItemsInPercentage: HistoricalDataItem[]; public portfolioEvolutionDataLabel = $localize`Investment`; + public precision = 2; public streaks: PortfolioInvestmentsResponse['streaks']; public top3: PortfolioPosition[]; public unitCurrentStreak: string; @@ -317,12 +319,21 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { : valueInPercentage }); } + this.performanceDataItemsInPercentage.push({ date, value: netPerformanceInPercentageWithCurrencyEffect }); } + if ( + this.deviceType === 'mobile' && + this.performance.currentValueInBaseCurrency >= + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.precision = 0; + } + this.isLoadingInvestmentChart = false; this.updateBenchmarkDataItems(); 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 150caa7d8..517ad7101 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -74,6 +74,72 @@