@ -16,6 +16,121 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Breaking Change**: The `sslmode=prefer` parameter in `DATABASE_URL` is no longer supported. Please update your environment variables (see `.env`) to use `sslmode=require` if _SSL_ is enabled or remove the `sslmode` parameter entirely if _SSL_ is not used.
- **Breaking Change**: The `sslmode=prefer` parameter in `DATABASE_URL` is no longer supported. Please update your environment variables (see `.env`) to use `sslmode=require` if _SSL_ is enabled or remove the `sslmode` parameter entirely if _SSL_ is not used.
## Unreleased
### Added
- Added support for filtering by activity type on the activities page (experimental)
## 2.252.0 - 2026-03-02
### Added
- Added support for a copy-to-clipboard functionality in the value component
- Extended the holding detail dialog by adding a copy-to-clipboard button for the ISIN number (experimental)
- Extended the holding detail dialog by adding a copy-to-clipboard button for the symbol (experimental)
- Extended the user detail dialog of the admin control panel’s users section by adding a copy-to-clipboard button for the user id
### Changed
- Refreshed the cryptocurrencies list
- Improved the language localization for German (`de`)
- Improved the language localization for Spanish (`es`)
- Upgraded `countries-list` from version `3.2.2` to `3.3.0`
- Upgraded `ng-extract-i18n-merge` from `3.2.1` to `3.3.0`
- Upgraded `stripe` from version `20.3.0` to `20.4.1`
## 2.251.0 - 2026-03-24
### Added
- Added the quantity column to the holdings table of the portfolio holdings page
### Changed
- Hardened the endpoint `DELETE /api/v1/auth-device/:id` by improving the user validation
- Improved the allocations by ETF holding on the allocations page by refining the grouping of the same assets with diverging names (experimental)
- Improved the language localization for Polish (`pl`)
- Upgraded `@trivago/prettier-plugin-sort-imports` from version `5.2.2` to `6.0.2`
### Fixed
- Fixed an issue by adding a missing guard in the public access for portfolio sharing
## 2.250.0 - 2026-03-17
### Added
- Added support for specific calendar year date ranges (`2025`, `2024`, `2023`, etc.) on the portfolio activities page
### Changed
- Consolidated the sign-out logic within the user service to unify cookie, state and token clearance
- Improved the language localization for Polish (`pl`)
- Upgraded `@ionic/angular` from version `8.7.3` to `8.8.1`
- Upgraded `replace-in-file` from version `8.3.0` to `8.4.0`
- Upgraded `svgmap` from version `2.14.0` to `2.19.2`
- Pinned the _Node.js_ version in the _Build code__GitHub Action_ to ensure environment consistency for tests
### Fixed
- Fixed an issue with the detection of the thousand separator for the `de-CH` locale
- Fixed an issue in the _Storybook_ stories of the symbol autocomplete component caused by a circular dependency
## 2.249.0 - 2026-03-10
### Added
- Integrated _Bull Dashboard_ for a detailed jobs queue view in the admin control panel (experimental)
- Added a debounce to the `PortfolioChangedListener` and `AssetProfileChangedListener` to minimize redundant _Redis_ and database operations
### Changed
- Improved the _Storybook_ stories of the value component
- Improved the language localization for Dutch (`nl`)
- Improved the language localization for German (`de`)
- Upgraded `class-validator` from version `0.14.3` to `0.15.1`
### Fixed
- Fixed false _Redis_ health check failures by using unique keys and increasing the timeout to 5s
## 2.248.0 - 2026-03-07
### Added
- Added support for column sorting to the data providers management of the admin control panel
### Changed
- Included asset profile data in the endpoint `GET api/v1/portfolio/holdings`
- Included asset profile data in the holdings of the public page
- Reused the value component in the platform management of the admin control panel
- Reused the value component in the tag management of the admin control panel
- Deprecated the `api/v1/order` endpoints in favor of the `api/v1/activities` endpoints
- Upgraded `jsonpath` from version `1.1.1` to `1.2.1`
### Fixed
- Fixed an issue in the _FIRE_ calculator to correctly calculate the projected total amount
## 2.247.0 - 2026-03-04
### Changed
- Upgraded `yahoo-finance2` from version `3.13.0` to `3.13.2`
## 2.246.0 - 2026-03-03
### Changed
- Removed the deprecated `committedFunds` from the summary of the portfolio details endpoint
- Upgraded `Nx` from version `22.4.5` to `22.5.3`
### Fixed
- Fixed an issue where the apply and reset filter buttons remained disabled in the assistant
@ -313,10 +313,12 @@ Ghostfolio is **100% free** and **open source**. We encourage and support an act
Not sure what to work on? We have [some ideas](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22%20no%3Aassignee), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22%20no%3Aassignee). Please join the Ghostfolio [Slack](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) channel or post to [@ghostfolio\_](https://x.com/ghostfolio_) on _X_. We would love to hear from you.
Not sure what to work on? We have [some ideas](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22%20no%3Aassignee), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22%20no%3Aassignee). Please join the Ghostfolio [Slack](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) channel or post to [@ghostfolio\_](https://x.com/ghostfolio_) on _X_. We would love to hear from you.
If you like to support this project, become a [**Sponsor**](https://github.com/sponsors/ghostfolio), get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio).
## Sponsors
## Sponsors
If you like to support this project, get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing), become a [**Sponsor**](https://github.com/sponsors/ghostfolio) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio).
<br/>
<divalign="center">
<divalign="center">
<ahref="https://www.testmuai.com?utm_medium=sponsor&utm_source=ghostfolio"target="_blank"title="TestMu AI - AI Powered Testing Tool">
<ahref="https://www.testmuai.com?utm_medium=sponsor&utm_source=ghostfolio"target="_blank"title="TestMu AI - AI Powered Testing Tool">
<imgalt="TestMu AI Logo"height="45"src="https://assets.testmuai.com/resources/images/logos/logo.svg"/>
<imgalt="TestMu AI Logo"height="45"src="https://assets.testmuai.com/resources/images/logos/logo.svg"/>
@ -54,11 +55,10 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
'mailto:hi@ghostfol.io?Subject=Ghostfolio Premium Trial&body=Hello%0D%0DI am interested in Ghostfolio Premium. Can you please send me a coupon code to try it for some time?%0D%0DKind regards';
'mailto:hi@ghostfol.io?Subject=Ghostfolio Premium Trial&body=Hello%0D%0DI am interested in Ghostfolio Premium. Can you please send me a coupon code to try it for some time?%0D%0DKind regards';
publicuser: User;
publicuser: User;
privateunsubscribeSubject=newSubject<void>();
publicconstructor(
publicconstructor(
privatechangeDetectorRef: ChangeDetectorRef,
privatechangeDetectorRef: ChangeDetectorRef,
privatedataService: DataService,
privatedataService: DataService,
privatedestroyRef: DestroyRef,
privatenotificationService: NotificationService,
privatenotificationService: NotificationService,
privatesnackBar: MatSnackBar,
privatesnackBar: MatSnackBar,
privateuserService: UserService
privateuserService: UserService
@ -73,7 +73,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
);
);
this.userService.stateChanged
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((state)=>{
.subscribe((state)=>{
if(state?.user){
if(state?.user){
this.user=state.user;
this.user=state.user;
@ -118,7 +118,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
returnEMPTY;
returnEMPTY;
}),
}),
takeUntil(this.unsubscribeSubject)
takeUntilDestroyed(this.destroyRef)
)
)
.subscribe(({sessionUrl})=>{
.subscribe(({sessionUrl})=>{
window.location.href=sessionUrl;
window.location.href=sessionUrl;
@ -142,7 +142,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
returnEMPTY;
returnEMPTY;
}),
}),
takeUntil(this.unsubscribeSubject)
takeUntilDestroyed(this.destroyRef)
)
)
.subscribe(({apiKey})=>{
.subscribe(({apiKey})=>{
this.notificationService.alert({
this.notificationService.alert({
@ -180,7 +180,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
returnEMPTY;
returnEMPTY;
}),
}),
takeUntil(this.unsubscribeSubject)
takeUntilDestroyed(this.destroyRef)
)
)
.subscribe(()=>{
.subscribe(()=>{
constsnackBarRef=this.snackBar.open(
constsnackBarRef=this.snackBar.open(
@ -193,14 +193,14 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
snackBarRef
snackBarRef
.afterDismissed()
.afterDismissed()
.pipe(takeUntil(this.unsubscribeSubject))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(()=>{
.subscribe(()=>{
window.location.reload();
window.location.reload();
});
});
snackBarRef
snackBarRef
.onAction()
.onAction()
.pipe(takeUntil(this.unsubscribeSubject))
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(()=>{
.subscribe(()=>{
window.location.reload();
window.location.reload();
});
});
@ -210,9 +210,4 @@ export class GfUserAccountMembershipComponent implements OnDestroy {