diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b50de07..936975ffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added the interest and dividend values to the account detail dialog + ### Changed +- Moved the chart of the account detail dialog from experimental to general availability - Improved the dynamic numerical precision for various values in the account detail dialog +- Improved the usability of the _Cancel_ / _Close_ and _Save_ buttons in various dialogs - Extended the accounts endpoint by allocations - Extended the accounts endpoint by dividend and interest +- Refactored the portfolio performance component to standalone - Improved the language localization for Portuguese (`pt`) - Improved the language localization for Spanish (`es`) diff --git a/README.md b/README.md index 02f17fe49..82d5710d1 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ Are you building your own project? Add the `ghostfolio` topic to your _GitHub_ r Ghostfolio is **100% free** and **open source**. We encourage and support an active and healthy community that accepts contributions from the public - including 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), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). 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, get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio). 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 c718df686..2886910c4 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 @@ -55,11 +55,15 @@ export class AccountDetailDialog implements OnDestroy, OnInit { public balancePrecision = 2; public currency: string; public dataSource: MatTableDataSource; + public dividendInBaseCurrency: number; + public dividendInBaseCurrencyPrecision = 2; public equity: number; public equityPrecision = 2; public hasPermissionToDeleteAccountBalance: boolean; public historicalDataItems: HistoricalDataItem[]; public holdings: PortfolioPosition[]; + public interestInBaseCurrency: number; + public interestInBaseCurrencyPrecision = 2; public isLoadingActivities: boolean; public isLoadingChart: boolean; public name: string; @@ -184,6 +188,8 @@ export class AccountDetailDialog implements OnDestroy, OnInit { ({ balance, currency, + dividendInBaseCurrency, + interestInBaseCurrency, name, platform, transactionCount, @@ -200,6 +206,15 @@ export class AccountDetailDialog implements OnDestroy, OnInit { } this.currency = currency; + this.dividendInBaseCurrency = dividendInBaseCurrency; + + if ( + this.data.deviceType === 'mobile' && + this.dividendInBaseCurrency >= + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.dividendInBaseCurrencyPrecision = 0; + } if (isNumber(balance) && isNumber(value)) { this.equity = new Big(value).minus(balance).toNumber(); @@ -214,6 +229,16 @@ export class AccountDetailDialog implements OnDestroy, OnInit { this.equity = null; } + this.interestInBaseCurrency = interestInBaseCurrency; + + if ( + this.data.deviceType === 'mobile' && + this.interestInBaseCurrency >= + NUMERICAL_PRECISION_THRESHOLD_6_FIGURES + ) { + this.interestInBaseCurrencyPrecision = 0; + } + this.name = name; this.platformName = platform?.name ?? '-'; this.transactionCount = transactionCount; 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 4e86ef5ea..c43c5cb68 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 @@ -20,20 +20,18 @@ - @if (user?.settings?.isExperimentalFeatures) { -
- -
- } +
+ +
@@ -60,6 +58,30 @@ >Equity
+
+ Interest +
+
+ Dividend +
ActivitiesData Gathering
- +
- + 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 0efb9d307..d2fdad30e 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 @@ -22,12 +22,18 @@
- + diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index acb253935..6c9694a19 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -1,4 +1,4 @@ -import { GfPortfolioPerformanceModule } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.module'; +import { GfPortfolioPerformanceComponent } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.component'; import { LayoutService } from '@ghostfolio/client/core/layout.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; @@ -32,7 +32,7 @@ import { takeUntil } from 'rxjs/operators'; imports: [ CommonModule, GfLineChartComponent, - GfPortfolioPerformanceModule, + GfPortfolioPerformanceComponent, MatButtonModule, RouterModule ], 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 caef1082f..c98a26831 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 @@ -8,7 +8,9 @@ import { PortfolioPerformance, ResponseError } from '@ghostfolio/common/interfaces'; +import { GfValueComponent } from '@ghostfolio/ui/value'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, @@ -17,19 +19,21 @@ import { OnChanges, ViewChild } from '@angular/core'; +import { IonIcon } from '@ionic/angular/standalone'; import { CountUp } from 'countup.js'; import { addIcons } from 'ionicons'; import { timeOutline } from 'ionicons/icons'; import { isNumber } from 'lodash'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ - selector: 'gf-portfolio-performance', changeDetection: ChangeDetectionStrategy.OnPush, - templateUrl: './portfolio-performance.component.html', + imports: [CommonModule, GfValueComponent, IonIcon, NgxSkeletonLoaderModule], + selector: 'gf-portfolio-performance', styleUrls: ['./portfolio-performance.component.scss'], - standalone: false + templateUrl: './portfolio-performance.component.html' }) -export class PortfolioPerformanceComponent implements OnChanges { +export class GfPortfolioPerformanceComponent implements OnChanges { @Input() deviceType: string; @Input() errors: ResponseError['errors']; @Input() isAllTimeHigh: boolean; 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 deleted file mode 100644 index e5b606255..000000000 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GfValueComponent } from '@ghostfolio/ui/value'; - -import { CommonModule } from '@angular/common'; -import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; -import { IonIcon } from '@ionic/angular/standalone'; -import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; - -import { PortfolioPerformanceComponent } from './portfolio-performance.component'; - -@NgModule({ - declarations: [PortfolioPerformanceComponent], - exports: [PortfolioPerformanceComponent], - imports: [CommonModule, GfValueComponent, IonIcon, NgxSkeletonLoaderModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] -}) -export class GfPortfolioPerformanceModule {} 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 b903c64d5..210933d61 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 @@ -55,12 +55,18 @@ }
- + 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 e87876c45..9a9d89624 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 @@ -100,12 +100,18 @@ }
- + 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 b0185dc72..acd128786 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 @@ -335,12 +335,18 @@ [value]="total" />
- + diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index ecf7d9223..e814ac415 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -57,7 +57,7 @@ export const personalFinanceTools: Product[] = [ founded: 2016, key: 'atominvest', name: 'Atominvest', - origin: 'London', + origin: 'United Kingdom', slogan: 'Portfolio Management' }, { @@ -139,6 +139,7 @@ export const personalFinanceTools: Product[] = [ founded: 2011, key: 'cobalt', name: 'Cobalt', + origin: 'United States', slogan: 'Next-Level Portfolio Monitoring' }, { @@ -683,6 +684,16 @@ export const personalFinanceTools: Product[] = [ origin: 'Italy', slogan: 'Your Personal Finance Hub' }, + { + founded: 2015, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'pocketguard', + name: 'PocketGuard', + origin: 'United States', + pricingPerYear: '$74.99', + slogan: 'Budgeting App & Finance Planner' + }, { founded: 2008, hasFreePlan: true,