diff --git a/CHANGELOG.md b/CHANGELOG.md index b202eb23f..be1fe3ee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add Average Buy Price in holdings table +- Added support for a date range query parameter in the data gathering endpoint +- Added a _Storybook_ story for the activities table component + +## 2.206.0 - 2025-10-04 + +### Changed + +- Localized the number formatting in the settings dialog to customize the rule thresholds of the _X-ray_ page +- Improved the usability of the assistant by preselecting the first search result +- Improved the usability of the _Cancel_ / _Close_ buttons in the create watchlist item dialog +- Refactored the `fireWealth` from `number` type to a structured object in the summary of the portfolio details endpoint +- Refactored the _Open Startup_ (`/open`) page to standalone +- Refactored the file drop directive to standalone +- Refactored the symbol pipe to standalone + +### Fixed + +- Handled an exception in the get asset profile functionality of the _Financial Modeling Prep_ service +- Added the missing `CommonModule` import in the import activities dialog + +## 2.205.0 - 2025-10-01 + +### Changed + +- Restricted the selection of the retirement date picker in the _FIRE_ calculator to a future date +- Improved the support for mutual funds in the _Financial Modeling Prep_ service (get asset profiles) +- Improved the language localization for German (`de`) +- Upgraded `prisma` from version `6.16.1` to `6.16.3` + +## 2.204.0 - 2025-09-30 + +### Added + +- Added the safe withdrawal rate to the user settings (experimental) + +### Changed + +- Improved the number formatting of the y-axis labels in the investment chart component +- Localized the number formatting of the y-axis labels in the line chart component +- Improved the wording of the 4% rule in the _FIRE_ section +- Improved the usability of the create asset profile dialog in the market data section of the admin control panel +- Improved the language localization for German (`de`) + +### Fixed + +- Improved the table headers’ alignment of the activities table + +## 2.203.0 - 2025-09-27 + +### Added + +- Added support for column sorting to the queue jobs table in the admin control panel - Added a blog post: _Hacktoberfest 2025_ ### Changed diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 27cc088d1..66f8483b4 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -6,6 +6,7 @@ import { ManualService } from '@ghostfolio/api/services/data-provider/manual/man import { DemoService } from '@ghostfolio/api/services/demo/demo.service'; import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; +import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH, DATA_GATHERING_QUEUE_PRIORITY_MEDIUM, @@ -22,6 +23,7 @@ import { } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; import type { + DateRange, MarketDataPreset, RequestWithUser } from '@ghostfolio/common/types'; @@ -161,9 +163,21 @@ export class AdminController { @HasPermission(permissions.accessAdminControl) public async gatherSymbol( @Param('dataSource') dataSource: DataSource, - @Param('symbol') symbol: string + @Param('symbol') symbol: string, + @Query('range') dateRange: DateRange ): Promise { - this.dataGatheringService.gatherSymbol({ dataSource, symbol }); + let date: Date; + + if (dateRange) { + const { startDate } = getIntervalFromDateRange(dateRange, new Date()); + date = startDate; + } + + this.dataGatheringService.gatherSymbol({ + dataSource, + date, + symbol + }); return; } diff --git a/apps/api/src/app/endpoints/sitemap/sitemap.service.ts b/apps/api/src/app/endpoints/sitemap/sitemap.service.ts index b8cdfc5c6..359a29531 100644 --- a/apps/api/src/app/endpoints/sitemap/sitemap.service.ts +++ b/apps/api/src/app/endpoints/sitemap/sitemap.service.ts @@ -124,7 +124,7 @@ export class SitemapService { languageCode, rootUrl, route: { - routerLink: ['blog', ...routerLink], + routerLink: [publicRoutes.blog.path, ...routerLink], path: undefined } }); diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index d703cf604..5659818a8 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -195,7 +195,6 @@ export class PortfolioController { 'excludedAccountsAndActivities', 'fees', 'filteredValueInBaseCurrency', - 'fireWealth', 'grossPerformance', 'grossPerformanceWithCurrencyEffect', 'interest', diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 2236632e1..a19ef36e3 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -2094,9 +2094,13 @@ export class PortfolioService { filteredValueInPercentage: netWorth ? filteredValueInBaseCurrency.div(netWorth).toNumber() : undefined, - fireWealth: new Big(currentValueInBaseCurrency) - .minus(emergencyFundHoldingsValueInBaseCurrency) - .toNumber(), + fireWealth: { + today: { + valueInBaseCurrency: new Big(currentValueInBaseCurrency) + .minus(emergencyFundHoldingsValueInBaseCurrency) + .toNumber() + } + }, grossPerformance: new Big(netPerformance).plus(fees).toNumber(), grossPerformanceWithCurrencyEffect: new Big( netPerformanceWithCurrencyEffect diff --git a/apps/api/src/app/user/update-user-setting.dto.ts b/apps/api/src/app/user/update-user-setting.dto.ts index b34b6fae2..3ee59f7dd 100644 --- a/apps/api/src/app/user/update-user-setting.dto.ts +++ b/apps/api/src/app/user/update-user-setting.dto.ts @@ -104,6 +104,10 @@ export class UpdateUserSettingDto { @IsOptional() retirementDate?: string; + @IsNumber() + @IsOptional() + safeWithdrawalRate?: number; + @IsNumber() @IsOptional() savingsRate?: number; diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 6512fbbc2..f797270ff 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -265,6 +265,11 @@ export class UserService { PerformanceCalculationType.ROAI; } + // Set default value for safe withdrawal rate + if (!(user.settings.settings as UserSettings)?.safeWithdrawalRate) { + (user.settings.settings as UserSettings).safeWithdrawalRate = 0.04; + } + // Set default value for view mode if (!(user.settings.settings as UserSettings).viewMode) { (user.settings.settings as UserSettings).viewMode = 'DEFAULT'; diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index 8f52fb779..8bb8f8327 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -106,7 +106,10 @@ export class FinancialModelingPrepService implements DataProviderInterface { response.assetClass = assetClass; response.assetSubClass = assetSubClass; - if (assetSubClass === AssetSubClass.ETF) { + if ( + assetSubClass === AssetSubClass.ETF || + assetSubClass === AssetSubClass.MUTUALFUND + ) { const etfCountryWeightings = await fetch( `${this.getUrl({ version: 'stable' })}/etf/country-weightings?symbol=${symbol}&apikey=${this.apiKey}`, { @@ -158,7 +161,7 @@ export class FinancialModelingPrepService implements DataProviderInterface { } ).then((res) => res.json()); - if (etfInformation.website) { + if (etfInformation?.website) { response.url = etfInformation.website; } diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts index 31edf6ffc..dd93e3e47 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts @@ -94,17 +94,21 @@ export class DataGatheringService { }); } - public async gatherSymbol({ dataSource, symbol }: AssetProfileIdentifier) { + public async gatherSymbol({ dataSource, date, symbol }: IDataGatheringItem) { await this.marketDataService.deleteMany({ dataSource, symbol }); - const dataGatheringItems = (await this.getSymbolsMax()).filter( - (dataGatheringItem) => { + const dataGatheringItems = (await this.getSymbolsMax()) + .filter((dataGatheringItem) => { return ( dataGatheringItem.dataSource === dataSource && dataGatheringItem.symbol === symbol ); - } - ); + }) + .map((item) => ({ + ...item, + date: date ?? item.date + })); + await this.gatherSymbols({ dataGatheringItems, priority: DATA_GATHERING_QUEUE_PRIORITY_HIGH diff --git a/apps/client/src/app/app-routing.module.ts b/apps/client/src/app/app-routing.module.ts index 53db1f06b..5c5eadcab 100644 --- a/apps/client/src/app/app-routing.module.ts +++ b/apps/client/src/app/app-routing.module.ts @@ -94,7 +94,7 @@ const routes: Routes = [ { path: publicRoutes.openStartup.path, loadChildren: () => - import('./pages/open/open-page.module').then((m) => m.OpenPageModule) + import('./pages/open/open-page.routes').then((m) => m.routes) }, { path: internalRoutes.portfolio.path, diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts index d28749b9c..8ed72445f 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts @@ -16,7 +16,8 @@ import { ChangeDetectorRef, Component, OnDestroy, - OnInit + OnInit, + ViewChild } from '@angular/core'; import { FormBuilder, @@ -27,6 +28,7 @@ import { import { MatButtonModule } from '@angular/material/button'; import { MatMenuModule } from '@angular/material/menu'; import { MatSelectModule } from '@angular/material/select'; +import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { IonIcon } from '@ionic/angular/standalone'; import { JobStatus } from 'bull'; @@ -44,6 +46,7 @@ import { removeCircleOutline, timeOutline } from 'ionicons/icons'; +import { get } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -57,6 +60,7 @@ import { takeUntil } from 'rxjs/operators'; MatButtonModule, MatMenuModule, MatSelectModule, + MatSortModule, MatTableModule, NgxSkeletonLoaderModule, ReactiveFormsModule @@ -66,6 +70,8 @@ import { takeUntil } from 'rxjs/operators'; templateUrl: './admin-jobs.html' }) export class GfAdminJobsComponent implements OnDestroy, OnInit { + @ViewChild(MatSort) sort: MatSort; + public DATA_GATHERING_QUEUE_PRIORITY_LOW = DATA_GATHERING_QUEUE_PRIORITY_LOW; public DATA_GATHERING_QUEUE_PRIORITY_HIGH = DATA_GATHERING_QUEUE_PRIORITY_HIGH; @@ -196,6 +202,8 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(({ jobs }) => { this.dataSource = new MatTableDataSource(jobs); + this.dataSource.sort = this.sort; + this.dataSource.sortingDataAccessor = get; this.isLoading = false; diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.html b/apps/client/src/app/components/admin-jobs/admin-jobs.html index f2bfaa931..14f1b211b 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.html +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.html @@ -16,9 +16,21 @@ - +
-
+ Job ID @@ -27,7 +39,12 @@ - + Type @@ -42,7 +59,12 @@ - + Symbol @@ -51,7 +73,12 @@ - + Data Source @@ -60,7 +87,12 @@ - + Priority @@ -79,7 +111,12 @@ - + Attempts @@ -88,7 +125,12 @@ - + Created 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 4e410c3a0..e907f4b03 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 @@ -1,4 +1,4 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; @@ -79,7 +79,7 @@ import { CreateAssetProfileDialogParams } from './create-asset-profile-dialog/in CommonModule, GfActivitiesFilterComponent, GfPremiumIndicatorComponent, - GfSymbolModule, + GfSymbolPipe, GfValueComponent, IonIcon, MatButtonModule, 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 94433e56c..18dc48c39 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 @@ -55,6 +55,7 @@ import { CreateAssetProfileDialogMode } from './interfaces/interfaces'; }) export class GfCreateAssetProfileDialogComponent implements OnInit, OnDestroy { public createAssetProfileForm: FormGroup; + public ghostfolioPrefix = `${ghostfolioPrefix}_`; public mode: CreateAssetProfileDialogMode; private customCurrencies: string[]; @@ -77,9 +78,7 @@ export class GfCreateAssetProfileDialogComponent implements OnInit, OnDestroy { addCurrency: new FormControl(null, [ this.iso4217CurrencyCodeValidator() ]), - addSymbol: new FormControl(`${ghostfolioPrefix}_`, [ - Validators.required - ]), + addSymbol: new FormControl(null, [Validators.required]), searchSymbol: new FormControl(null, [Validators.required]) }, { @@ -95,6 +94,8 @@ export class GfCreateAssetProfileDialogComponent implements OnInit, OnDestroy { } public onRadioChange(mode: CreateAssetProfileDialogMode) { + this.createAssetProfileForm.reset(); + this.mode = mode; } @@ -133,7 +134,7 @@ export class GfCreateAssetProfileDialogComponent implements OnInit, OnDestroy { } else if (this.mode === 'manual') { this.dialogRef.close({ dataSource: 'MANUAL', - symbol: this.createAssetProfileForm.get('addSymbol').value + symbol: `${this.ghostfolioPrefix}${this.createAssetProfileForm.get('addSymbol').value}` }); } } diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html index c60ca83b8..1474596aa 100644 --- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html +++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -38,6 +38,7 @@ Symbol + {{ ghostfolioPrefix }} } @else if (mode === 'currency') { @@ -53,7 +54,13 @@ }
- +
- +
-
+
Threshold Max: - @if (data.rule.configuration.threshold.unit === '%') { - {{ data.settings.thresholdMax | percent: '1.2-2' }} - } @else { - {{ data.settings.thresholdMax }} - } +
- @if (data.rule.configuration.threshold.unit === '%') { - - } @else { - - } + - @if (data.rule.configuration.threshold.unit === '%') { - - } @else { - - } +
} 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 1a4d3210a..067eb2d59 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 @@ -47,7 +47,7 @@ import { CreateOrUpdateAccessDialogParams } from './interfaces/interfaces'; styleUrls: ['./create-or-update-access-dialog.scss'], templateUrl: 'create-or-update-access-dialog.html' }) -export class GfCreateOrUpdateAccessDialog implements OnDestroy { +export class GfCreateOrUpdateAccessDialogComponent implements OnDestroy { public accessForm: FormGroup; private unsubscribeSubject = new Subject(); @@ -55,7 +55,7 @@ export class GfCreateOrUpdateAccessDialog implements OnDestroy { public constructor( private changeDetectorRef: ChangeDetectorRef, @Inject(MAT_DIALOG_DATA) private data: CreateOrUpdateAccessDialogParams, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private dataService: DataService, private formBuilder: FormBuilder, private notificationService: NotificationService diff --git a/apps/client/src/app/components/user-account-access/user-account-access.component.ts b/apps/client/src/app/components/user-account-access/user-account-access.component.ts index c7959486b..178df374d 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.component.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -30,7 +30,7 @@ import { DeviceDetectorService } from 'ngx-device-detector'; import { EMPTY, Subject } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; -import { GfCreateOrUpdateAccessDialog } from './create-or-update-access-dialog/create-or-update-access-dialog.component'; +import { GfCreateOrUpdateAccessDialogComponent } from './create-or-update-access-dialog/create-or-update-access-dialog.component'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -179,7 +179,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { } private openCreateAccessDialog() { - const dialogRef = this.dialog.open(GfCreateOrUpdateAccessDialog, { + const dialogRef = this.dialog.open(GfCreateOrUpdateAccessDialogComponent, { data: { access: { alias: '', diff --git a/apps/client/src/app/directives/file-drop/file-drop.directive.ts b/apps/client/src/app/directives/file-drop/file-drop.directive.ts index 93f444572..a7e628bc9 100644 --- a/apps/client/src/app/directives/file-drop/file-drop.directive.ts +++ b/apps/client/src/app/directives/file-drop/file-drop.directive.ts @@ -1,10 +1,9 @@ import { Directive, EventEmitter, HostListener, Output } from '@angular/core'; @Directive({ - selector: '[gfFileDrop]', - standalone: false + selector: '[gfFileDrop]' }) -export class FileDropDirective { +export class GfFileDropDirective { @Output() filesDropped = new EventEmitter(); @HostListener('dragenter', ['$event']) onDragEnter(event: DragEvent) { diff --git a/apps/client/src/app/directives/file-drop/file-drop.module.ts b/apps/client/src/app/directives/file-drop/file-drop.module.ts deleted file mode 100644 index a0148516e..000000000 --- a/apps/client/src/app/directives/file-drop/file-drop.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { NgModule } from '@angular/core'; - -import { FileDropDirective } from './file-drop.directive'; - -@NgModule({ - declarations: [FileDropDirective], - exports: [FileDropDirective] -}) -export class GfFileDropModule {} diff --git a/apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html b/apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html index 318d86aa0..bde5a2fee 100644 --- a/apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html +++ b/apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html @@ -19,10 +19,9 @@ time and we are looking forward to meeting new open-source contributors along the way. Every year in October, Hacktoberfest celebrates open source by - highlighting projects, maintainers, and contributors worldwide. Open - source maintainers around the globe dedicate extra time to support - new contributors while guiding them through their first pull - requests on + highlighting projects, maintainers, and contributors from around the + globe. Open source maintainers dedicate extra time to support new + contributors while guiding them through their first pull requests on GitHub.

@@ -50,7 +49,7 @@

With over 200 contributors, the OSS project is used daily by a growing global community. Ghostfolio counts more than - 6’600 stars on GitHub + 6’500 stars on GitHub and 1’600’000+ pulls on Docker Hub { - if (transaction) { + .subscribe((activity: UpdateOrderDto) => { + if (activity) { this.dataService - .putOrder(transaction) + .putOrder(activity) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe({ next: () => { @@ -347,23 +350,26 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { .subscribe((user) => { this.updateUser(user); - const dialogRef = this.dialog.open(GfCreateOrUpdateActivityDialog, { - data: { - accounts: this.user?.accounts, - activity: { - ...aActivity, - accountId: aActivity?.accountId, - date: new Date(), - id: null, - fee: 0, - type: aActivity?.type ?? 'BUY', - unitPrice: null + const dialogRef = this.dialog.open( + GfCreateOrUpdateActivityDialogComponent, + { + data: { + accounts: this.user?.accounts, + activity: { + ...aActivity, + accountId: aActivity?.accountId, + date: new Date(), + id: null, + fee: 0, + type: aActivity?.type ?? 'BUY', + unitPrice: null + }, + user: this.user }, - user: this.user - }, - height: this.deviceType === 'mobile' ? '98vh' : '80vh', - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - }); + height: this.deviceType === 'mobile' ? '98vh' : '80vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + } + ); dialogRef .afterClosed() 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 6454b9918..3261e9752 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 @@ -76,7 +76,7 @@ import { ActivityType } from './types/activity-type.type'; styleUrls: ['./create-or-update-activity-dialog.scss'], templateUrl: 'create-or-update-activity-dialog.html' }) -export class GfCreateOrUpdateActivityDialog implements OnDestroy { +export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy { public activityForm: FormGroup; public assetClassOptions: AssetClassSelectorOption[] = Object.keys(AssetClass) @@ -110,7 +110,7 @@ export class GfCreateOrUpdateActivityDialog implements OnDestroy { @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateActivityDialogParams, private dataService: DataService, private dateAdapter: DateAdapter, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private formBuilder: FormBuilder, @Inject(MAT_DATE_LOCALE) private locale: string, private userService: UserService 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 ea3292663..2439a4b65 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 @@ -4,8 +4,8 @@ import { CreateAssetProfileWithMarketDataDto } from '@ghostfolio/api/app/import/ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { GfDialogFooterComponent } from '@ghostfolio/client/components/dialog-footer/dialog-footer.component'; import { GfDialogHeaderComponent } from '@ghostfolio/client/components/dialog-header/dialog-header.component'; -import { GfFileDropModule } from '@ghostfolio/client/directives/file-drop/file-drop.module'; -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfFileDropDirective } from '@ghostfolio/client/directives/file-drop/file-drop.directive'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImportActivitiesService } from '@ghostfolio/client/services/import-activities.service'; import { PortfolioPosition } from '@ghostfolio/common/interfaces'; @@ -15,6 +15,7 @@ import { StepperOrientation, StepperSelectionEvent } from '@angular/cdk/stepper'; +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -59,11 +60,12 @@ import { ImportActivitiesDialogParams } from './interfaces/interfaces'; changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'd-flex flex-column h-100' }, imports: [ + CommonModule, GfActivitiesTableComponent, GfDialogFooterComponent, GfDialogHeaderComponent, - GfFileDropModule, - GfSymbolModule, + GfFileDropDirective, + GfSymbolPipe, IonIcon, MatButtonModule, MatDialogModule, @@ -78,7 +80,7 @@ import { ImportActivitiesDialogParams } from './interfaces/interfaces'; styleUrls: ['./import-activities-dialog.scss'], templateUrl: 'import-activities-dialog.html' }) -export class GfImportActivitiesDialog implements OnDestroy { +export class GfImportActivitiesDialogComponent implements OnDestroy { public accounts: CreateAccountWithBalancesDto[] = []; public activities: Activity[] = []; public assetProfileForm: FormGroup; @@ -109,7 +111,7 @@ export class GfImportActivitiesDialog implements OnDestroy { private dataService: DataService, private deviceService: DeviceDetectorService, private formBuilder: FormBuilder, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private importActivitiesService: ImportActivitiesService, private snackBar: MatSnackBar ) { diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts index 83650d9ca..c80b55c45 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts @@ -1,7 +1,7 @@ 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 { User } from '@ghostfolio/common/interfaces'; +import { FireWealth, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { GfFireCalculatorComponent } from '@ghostfolio/ui/fire-calculator'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; @@ -29,7 +29,7 @@ import { takeUntil } from 'rxjs/operators'; }) export class GfFirePageComponent implements OnDestroy, OnInit { public deviceType: string; - public fireWealth: Big; + public fireWealth: FireWealth; public hasImpersonationId: boolean; public hasPermissionToUpdateUserSettings: boolean; public isLoading = false; @@ -55,15 +55,25 @@ export class GfFirePageComponent implements OnDestroy, OnInit { .fetchPortfolioDetails() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(({ summary }) => { - this.fireWealth = summary.fireWealth - ? new Big(summary.fireWealth) - : new Big(0); - + this.fireWealth = { + today: { + valueInBaseCurrency: summary.fireWealth + ? summary.fireWealth.today.valueInBaseCurrency + : 0 + } + }; if (this.user.subscription?.type === 'Basic') { - this.fireWealth = new Big(10000); + this.fireWealth = { + today: { + valueInBaseCurrency: 10000 + } + }; } - this.withdrawalRatePerYear = this.fireWealth.mul(4).div(100); + this.withdrawalRatePerYear = Big( + this.fireWealth.today.valueInBaseCurrency + ).mul(this.user.settings.safeWithdrawalRate); + this.withdrawalRatePerMonth = this.withdrawalRatePerYear.div(12); this.isLoading = false; diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.html b/apps/client/src/app/pages/portfolio/fire/fire-page.html index 77fd1640c..d6548f761 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.html +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -14,7 +14,7 @@ [colorScheme]="user?.settings?.colorScheme" [currency]="user?.settings?.baseCurrency" [deviceType]="deviceType" - [fireWealth]="fireWealth?.toNumber()" + [fireWealth]="fireWealth?.today.valueInBaseCurrency" [hasPermissionToUpdateUserSettings]=" !hasImpersonationId && hasPermissionToUpdateUserSettings " @@ -37,7 +37,7 @@

- 4% Rule + Sustainable retirement income @if (user?.subscription?.type === 'Basic') { } @@ -61,11 +61,11 @@ />

} @else { -
- If you retire today, you would be able to withdraw +
+ If you retire today, you would be able to withdraw +   - per year  + per year - or +   + or +   - per month, based on your total assets of +   + per month, +   + based on your total assets of +   - and a withdrawal rate of 4%. +   + and a safe withdrawal rate (SWR) of +   + .
}
diff --git a/apps/client/src/app/pipes/symbol/symbol.module.ts b/apps/client/src/app/pipes/symbol/symbol.module.ts deleted file mode 100644 index 7ba1c1c73..000000000 --- a/apps/client/src/app/pipes/symbol/symbol.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { NgModule } from '@angular/core'; - -import { SymbolPipe } from './symbol.pipe'; - -@NgModule({ - declarations: [SymbolPipe], - exports: [SymbolPipe] -}) -export class GfSymbolModule {} diff --git a/apps/client/src/app/pipes/symbol/symbol.pipe.ts b/apps/client/src/app/pipes/symbol/symbol.pipe.ts index 2b30d1041..6f4981699 100644 --- a/apps/client/src/app/pipes/symbol/symbol.pipe.ts +++ b/apps/client/src/app/pipes/symbol/symbol.pipe.ts @@ -3,10 +3,9 @@ import { prettifySymbol } from '@ghostfolio/common/helper'; import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ - name: 'gfSymbol', - standalone: false + name: 'gfSymbol' }) -export class SymbolPipe implements PipeTransform { +export class GfSymbolPipe implements PipeTransform { public transform(aSymbol: string) { return prettifySymbol(aSymbol); } diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 820ad5e3c..6ab370399 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -512,48 +512,6 @@ export class DataService { ); } - public fetchSymbolItem({ - dataSource, - includeHistoricalData, - symbol - }: { - dataSource: DataSource | string; - includeHistoricalData?: number; - symbol: string; - }) { - let params = new HttpParams(); - - if (includeHistoricalData) { - params = params.append('includeHistoricalData', includeHistoricalData); - } - - return this.http.get(`/api/v1/symbol/${dataSource}/${symbol}`, { - params - }); - } - - public fetchSymbols({ - includeIndices = false, - query - }: { - includeIndices?: boolean; - query: string; - }) { - let params = new HttpParams().set('query', query); - - if (includeIndices) { - params = params.append('includeIndices', includeIndices); - } - - return this.http - .get('/api/v1/symbol/lookup', { params }) - .pipe( - map(({ items }) => { - return items; - }) - ); - } - public fetchPortfolioDetails({ filters, withMarkets = false @@ -725,6 +683,48 @@ export class DataService { ); } + public fetchSymbolItem({ + dataSource, + includeHistoricalData, + symbol + }: { + dataSource: DataSource | string; + includeHistoricalData?: number; + symbol: string; + }) { + let params = new HttpParams(); + + if (includeHistoricalData) { + params = params.append('includeHistoricalData', includeHistoricalData); + } + + return this.http.get(`/api/v1/symbol/${dataSource}/${symbol}`, { + params + }); + } + + public fetchSymbols({ + includeIndices = false, + query + }: { + includeIndices?: boolean; + query: string; + }) { + let params = new HttpParams().set('query', query); + + if (includeIndices) { + params = params.append('includeIndices', includeIndices); + } + + return this.http + .get('/api/v1/symbol/lookup', { params }) + .pipe( + map(({ items }) => { + return items; + }) + ); + } + public fetchTags() { return this.http.get('/api/v1/tags'); } diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index bd4be27a4..216704d26 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -647,7 +647,7 @@ Tipus apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -667,7 +667,7 @@ Perfil d’Actiu apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -675,7 +675,7 @@ Dades Històriques de Mercat apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -687,7 +687,7 @@ Origen de les Dades apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -711,7 +711,7 @@ Prioritat apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -719,7 +719,7 @@ Intents apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -727,7 +727,7 @@ Creat apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -735,7 +735,7 @@ Finalitzat apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -743,7 +743,7 @@ Estat apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -763,7 +763,7 @@ Aturar Processos apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -771,7 +771,7 @@ Veure les Dades apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -779,7 +779,7 @@ Veure Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -787,7 +787,7 @@ Executar Procés apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -795,7 +795,7 @@ Suprimir Procés apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1965,6 +1965,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -2405,6 +2409,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -3065,6 +3073,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -3755,6 +3767,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + New Users Usuaris nous @@ -3776,7 +3796,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -4463,22 +4483,6 @@ 7 - - 4% Rule - 4% Regla - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Pricing Preus @@ -4711,6 +4715,14 @@ 234 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio us permet fer un seguiment de la vostra riquesa. @@ -4868,6 +4880,14 @@ 44 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Taula comparativa Ghostfolio vs @@ -5328,6 +5348,14 @@ 61 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Darrer tot el temps @@ -5697,7 +5725,7 @@ Símbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5781,7 +5809,7 @@ Valuós libs/ui/src/lib/i18n.ts - 41 + 43 @@ -5789,7 +5817,7 @@ Passiu libs/ui/src/lib/i18n.ts - 42 + 41 @@ -5801,7 +5829,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -5948,6 +5976,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Oceania @@ -6380,6 +6416,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inactive @@ -6429,7 +6473,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6473,7 +6517,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6509,7 +6553,7 @@ Portfolio Snapshot apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6979,7 +7023,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 4dcc345d4..d5add9012 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -42,7 +42,7 @@ Typ apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -286,7 +286,7 @@ Jobs löschen apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -294,7 +294,7 @@ Datenquelle apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -318,7 +318,7 @@ Versuche apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -326,7 +326,7 @@ Erstellt apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -334,7 +334,7 @@ Abgeschlossen apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -342,7 +342,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -370,7 +370,7 @@ Historische Marktdaten apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -382,7 +382,7 @@ Daten anzeigen apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -390,7 +390,7 @@ Stacktrace anzeigen apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -398,7 +398,7 @@ Job löschen apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -800,6 +800,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1152,6 +1156,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -1492,6 +1500,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -1761,14 +1773,6 @@ 7 - - 4% Rule - 4% Regel - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Positionen @@ -1830,7 +1834,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -2033,6 +2037,14 @@ 132 + + Sustainable retirement income + Nachhaltiges Einkommen im Ruhestand + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio verschafft dir den Überblick über dein Vermögen. @@ -2670,7 +2682,7 @@ Symbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2897,6 +2909,14 @@ 71 + + If you retire today, you would be able to withdraw + Wenn du heute in den Ruhestand gehen würdest, könntest du + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Ozeanien @@ -4038,7 +4058,7 @@ Verbindlichkeit libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4282,7 +4302,7 @@ Wertsache libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4470,7 +4490,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -5163,6 +5183,14 @@ 59 + + and a safe withdrawal rate (SWR) of + und einer sicheren Entnahmerate (SWR) von + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Letzte 90 Tage) @@ -5328,7 +5356,7 @@ Anlageprofil apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5363,6 +5391,14 @@ 5 + + , + entnehmen, + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Letztes Allzeithoch @@ -5379,6 +5415,14 @@ 13 + + per month + pro Monat + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs Vergleichstabelle @@ -5723,14 +5767,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Wenn du heute in den Ruhestand gehen würdest, könnest du pro Jahr oder pro Monat entnehmen, bezogen auf dein Gesamtanlagevermögen von und einer Entnahmerate von 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Filter zurücksetzen @@ -5889,7 +5925,7 @@ Job ausführen apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5897,7 +5933,7 @@ Priorität apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6404,6 +6440,14 @@ 83 + + based on your total assets of + bezogen auf dein Gesamtanlagevermögen von + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inaktiv @@ -6453,7 +6497,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6497,7 +6541,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6533,7 +6577,7 @@ Portfolio Snapshot apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -7003,7 +7047,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index c23d83944..5773a95e7 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -43,7 +43,7 @@ Tipo apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -287,7 +287,7 @@ Elimina los trabajos apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -295,7 +295,7 @@ Fuente de datos apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -319,7 +319,7 @@ Intentos apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -327,7 +327,7 @@ Creado apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -335,7 +335,7 @@ Finalizado apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -343,7 +343,7 @@ Estado apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -371,7 +371,7 @@ Datos históricos del mercado apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -383,7 +383,7 @@ Visualiza los datos apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -391,7 +391,7 @@ Visualiza Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -399,7 +399,7 @@ Elimina el trabajo apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -785,6 +785,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1137,6 +1141,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -1477,6 +1485,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -1746,14 +1758,6 @@ 7 - - 4% Rule - Regla del 4% - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Participaciones @@ -1815,7 +1819,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -2018,6 +2022,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio te permite hacer un seguimiento de tu riqueza. @@ -2655,7 +2667,7 @@ Símbolo apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2882,6 +2894,14 @@ 71 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Oceanía @@ -4015,7 +4035,7 @@ Responsabilidad libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4259,7 +4279,7 @@ Valioso libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4447,7 +4467,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -5140,6 +5160,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Últimos 90 días) @@ -5305,7 +5333,7 @@ Perfil de activo apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5340,6 +5368,14 @@ 5 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Último máximo histórico @@ -5356,6 +5392,14 @@ 13 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs tabla comparativa @@ -5700,14 +5744,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Si te jubilaras hoy, podrías retirar por año o por mes, basado en tus activos totales de y una tasa de retiro del 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Reiniciar filtros @@ -5866,7 +5902,7 @@ Ejecutar Tarea apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5874,7 +5910,7 @@ Prioridad apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6381,6 +6417,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inactiva @@ -6430,7 +6474,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6474,7 +6518,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6510,7 +6554,7 @@ Instantánea de la cartera apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6980,7 +7024,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index 0e7d8ab2d..07496e53d 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -34,7 +34,7 @@ Type apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -342,7 +342,7 @@ Source Données apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -366,7 +366,7 @@ Tentatives apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -374,7 +374,7 @@ Créé apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -382,7 +382,7 @@ Terminé apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -390,7 +390,7 @@ Statut apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -410,7 +410,7 @@ Supprimer Tâches apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -426,7 +426,7 @@ Données historiques du marché apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -438,7 +438,7 @@ Voir Données apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -446,7 +446,7 @@ Voir la Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -454,7 +454,7 @@ Supprimer Tâche apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1080,6 +1080,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1444,6 +1448,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -1780,6 +1788,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -1990,7 +2002,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -2357,14 +2369,6 @@ 7 - - 4% Rule - Règle des 4% - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Positions @@ -2421,6 +2425,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio vous aide à garder un aperçu de votre patrimoine. @@ -2850,7 +2862,7 @@ Symbole apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -3021,6 +3033,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Océanie @@ -4014,7 +4034,7 @@ Dette libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4258,7 +4278,7 @@ Actifs libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4446,7 +4466,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -5139,6 +5159,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Derniers 90 jours) @@ -5304,7 +5332,7 @@ Profil d’Actif apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5339,6 +5367,14 @@ 5 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Dernier All Time High @@ -5355,6 +5391,14 @@ 13 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs tableau comparatif @@ -5699,14 +5743,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Si vous prenez votre retraite aujourd’hui, vous pourrez retirer par an ou par mois, sur la base de vos actifs totaux de et un taux de retrait de 4 %. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Réinitialiser les Filtres @@ -5865,7 +5901,7 @@ Execute la tâche apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5873,7 +5909,7 @@ Priorité apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6380,6 +6416,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inactif @@ -6429,7 +6473,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6473,7 +6517,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6509,7 +6553,7 @@ Résumé du portefeuille apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6979,7 +7023,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index e6e96a265..9c49e4939 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -43,7 +43,7 @@ Tipo apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -287,7 +287,7 @@ Elimina i lavori apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -295,7 +295,7 @@ Sorgente dei dati apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -319,7 +319,7 @@ Tentativi apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -327,7 +327,7 @@ Creato apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -335,7 +335,7 @@ Finito apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -343,7 +343,7 @@ Stato apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -371,7 +371,7 @@ Dati storici del mercato apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -383,7 +383,7 @@ Visualizza i dati apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -391,7 +391,7 @@ Visualizza Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -399,7 +399,7 @@ Elimina il lavoro apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -785,6 +785,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1137,6 +1141,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -1477,6 +1485,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -1746,14 +1758,6 @@ 7 - - 4% Rule - Regola del 4% - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Partecipazioni @@ -1815,7 +1819,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -2018,6 +2022,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio ti permette di tenere traccia della tua ricchezza. @@ -2655,7 +2667,7 @@ Simbolo apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2882,6 +2894,14 @@ 71 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Oceania @@ -4015,7 +4035,7 @@ Passività libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4259,7 +4279,7 @@ Prezioso libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4447,7 +4467,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -5140,6 +5160,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Ultimi 90 giorni) @@ -5305,7 +5333,7 @@ Profilo dell’asset apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5340,6 +5368,14 @@ 5 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Ultimo massimo storico @@ -5356,6 +5392,14 @@ 13 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs tabella di comparazione @@ -5700,14 +5744,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Se andassi in pensione oggi, saresti in grado di prelevare all’anno o al mese, calcolato sul valore totale dei tuoi asset di e un prelievo costante del 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Reset Filtri @@ -5866,7 +5902,7 @@ Esegui il lavoro apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5874,7 +5910,7 @@ Priorità apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6381,6 +6417,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inattivo @@ -6430,7 +6474,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6474,7 +6518,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6510,7 +6554,7 @@ Stato del Portfolio apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6980,7 +7024,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 140089733..e1fa9d36e 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -42,7 +42,7 @@ Type apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -286,7 +286,7 @@ Taken verwijderen apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -294,7 +294,7 @@ Gegevensbron apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -318,7 +318,7 @@ Pogingen apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -326,7 +326,7 @@ Aangemaakt apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -334,7 +334,7 @@ Voltooid apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -342,7 +342,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -370,7 +370,7 @@ Historische marktgegevens apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -382,7 +382,7 @@ Bekijk gegevens apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -390,7 +390,7 @@ Bekijk Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -398,7 +398,7 @@ Taak verwijderen apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -784,6 +784,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1136,6 +1140,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -1476,6 +1484,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -1745,14 +1757,6 @@ 7 - - 4% Rule - 4% regel - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Posities @@ -1814,7 +1818,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -2017,6 +2021,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio stelt je in staat om je vermogen bij te houden. @@ -2654,7 +2666,7 @@ Symbool apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2881,6 +2893,14 @@ 71 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Oceanië @@ -4014,7 +4034,7 @@ Verplichtingen libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4258,7 +4278,7 @@ Waardevol libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4446,7 +4466,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -5139,6 +5159,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Laatste 90 dagen) @@ -5304,7 +5332,7 @@ Bezittingen Profiel apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5339,6 +5367,14 @@ 5 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Laatste Recordhoogte @@ -5355,6 +5391,14 @@ 13 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs vergelijkingstabel @@ -5699,14 +5743,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Als u vandaag met pensioen zou gaan, kunt u per jaar or per maand opnemen, gebaseerd op uw totale vermogen van en een opnamepercentage van 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Filters Herstellen @@ -5865,7 +5901,7 @@ Opdracht Uitvoeren apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5873,7 +5909,7 @@ Prioriteit apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6380,6 +6416,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inactief @@ -6429,7 +6473,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6473,7 +6517,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6509,7 +6553,7 @@ Portfolio Momentopname apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6979,7 +7023,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index b0d8e1840..8558e883e 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -243,7 +243,7 @@ Typ apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -563,7 +563,7 @@ Profil Aktywów apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -571,7 +571,7 @@ Historyczne Dane Rynkowe apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -583,7 +583,7 @@ Źródło Danych apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -607,7 +607,7 @@ Próby apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -615,7 +615,7 @@ Utworzono apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -623,7 +623,7 @@ Zakończono apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -631,7 +631,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -651,7 +651,7 @@ Usuń Zadania apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -659,7 +659,7 @@ Zobacz Dane apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -667,7 +667,7 @@ Wyświetl Stos Wywołań apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -675,7 +675,7 @@ Usuń Zadanie apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1653,6 +1653,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -2117,6 +2121,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -2725,6 +2733,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -3374,6 +3386,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + New Users Nowi Użytkownicy @@ -3395,7 +3415,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -4010,14 +4030,6 @@ 7 - - 4% Rule - Zasada 4% - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Inwestycje @@ -4266,6 +4278,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio umożliwia śledzenie wartości swojego majątku. @@ -4399,6 +4419,14 @@ 44 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs - tabela porównawcza @@ -4743,6 +4771,14 @@ 106 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Ostatni Najwyższy Punkt w Historii @@ -5096,7 +5132,7 @@ Symbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5180,7 +5216,7 @@ Kosztowności libs/ui/src/lib/i18n.ts - 41 + 43 @@ -5188,7 +5224,7 @@ Zobowiązanie libs/ui/src/lib/i18n.ts - 42 + 41 @@ -5200,7 +5236,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -5339,6 +5375,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Oceania @@ -5699,14 +5743,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Jeśli przejdziesz na emeryturę dzisiaj, będziesz mógł wypłacić rocznie lub miesięcznie, w oparciu o Twój łączny majątek w wysokości i stopę wypłaty w wysokości 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Resetuj Filtry @@ -5865,7 +5901,7 @@ Wykonaj Zadanie apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5873,7 +5909,7 @@ Priorytet apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6380,6 +6416,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Nieaktywny @@ -6429,7 +6473,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6473,7 +6517,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6509,7 +6553,7 @@ Przegląd portfela apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6979,7 +7023,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 1fad5f3bb..45776a245 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -34,7 +34,7 @@ Tipo apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -342,7 +342,7 @@ Fonte de dados apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -366,7 +366,7 @@ Tentativas apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -374,7 +374,7 @@ Criado apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -382,7 +382,7 @@ Terminado apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -390,7 +390,7 @@ Estado apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -410,7 +410,7 @@ Eliminar Tarefas apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -426,7 +426,7 @@ Histórico de Dados de Mercado apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -438,7 +438,7 @@ Visualizar dados apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -446,7 +446,7 @@ Ver Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -454,7 +454,7 @@ Apagar Tarefa apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -960,6 +960,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1432,6 +1436,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -1756,6 +1764,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -1962,7 +1974,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -2273,14 +2285,6 @@ 7 - - 4% Rule - Regra dos 4% - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Posições @@ -2361,6 +2365,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. O Ghostfolio permite-lhe estar a par e gerir a sua riqueza. @@ -2702,7 +2714,7 @@ Símbolo apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2873,6 +2885,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Oceânia @@ -4014,7 +4034,7 @@ Responsabilidade libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4258,7 +4278,7 @@ De valor libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4446,7 +4466,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -5139,6 +5159,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Últimos 90 dias) @@ -5304,7 +5332,7 @@ Perfil de ativos apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5339,6 +5367,14 @@ 5 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Última alta de todos os tempos @@ -5355,6 +5391,14 @@ 13 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs tabela de comparação @@ -5699,14 +5743,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Se você se aposentar hoje, poderá sacar per year or per month, based on your total assets of and a withdrawal rate of 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Redefinir filtros @@ -5865,7 +5901,7 @@ Executar trabalho apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5873,7 +5909,7 @@ Prioridade apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6380,6 +6416,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Inativo @@ -6429,7 +6473,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6473,7 +6517,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6509,7 +6553,7 @@ Visão geral do portfólio apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6979,7 +7023,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 50522d41f..5b91056d1 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -215,7 +215,7 @@ Tip apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -523,7 +523,7 @@ Veri Kaynağı apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -547,7 +547,7 @@ Deneme apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -555,7 +555,7 @@ Oluşturuldu apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -563,7 +563,7 @@ Tamamlandı apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -571,7 +571,7 @@ Durum apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -591,7 +591,7 @@ İşleri Sil apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -607,7 +607,7 @@ Tarihsel Piyasa Verisi apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -619,7 +619,7 @@ Veri Gör apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -627,7 +627,7 @@ Hata İzini Görüntüle apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -635,7 +635,7 @@ İşleri Sil apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1509,6 +1509,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -2297,6 +2301,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -2927,7 +2935,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -3518,14 +3526,6 @@ 7 - - 4% Rule - %4 Kuralı - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings Varlıklar @@ -3774,6 +3774,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio, varlıklarınızı takip etmenizi sağlar. @@ -4242,6 +4250,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -4832,7 +4844,7 @@ Sembol apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -4900,7 +4912,7 @@ Kıymet libs/ui/src/lib/i18n.ts - 41 + 43 @@ -4908,7 +4920,7 @@ Yükümlülük libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4920,7 +4932,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -5059,6 +5071,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Okyanusya @@ -5147,6 +5167,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + (Last 90 days) (Son 90 gün) @@ -5304,7 +5332,7 @@ Varlık Profili apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -5339,6 +5367,14 @@ 5 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Son, ATH @@ -5355,6 +5391,14 @@ 13 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio ve karşılatırma tablosu @@ -5699,14 +5743,6 @@ 8 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Eğer bugün emekli olursanız, paranızı çekebilirsiniz yıllık veya aylık, toplam varlıklarınıza göre ve %4’lük bir çekilme oranı. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Reset Filters Filtreleri Sıfırla @@ -5865,7 +5901,7 @@ İşlemi Yürüt apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5873,7 +5909,7 @@ Öncelik apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6380,6 +6416,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Pasif @@ -6429,7 +6473,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6473,7 +6517,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6509,7 +6553,7 @@ Portföy Anlık Görüntüsü apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6979,7 +7023,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 734c29a16..3b069dd93 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -671,7 +671,7 @@ Тип apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -691,7 +691,7 @@ Профіль активу apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -699,7 +699,7 @@ Історичні ринкові дані apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -711,7 +711,7 @@ Знімок портфеля apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -719,7 +719,7 @@ Джерело даних apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -743,7 +743,7 @@ Пріоритет apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -751,7 +751,7 @@ Спроби apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -759,7 +759,7 @@ Створено apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -767,7 +767,7 @@ Завершено apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -775,7 +775,7 @@ Статус apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -795,7 +795,7 @@ Видалити завдання apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -803,7 +803,7 @@ Переглянути дані apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -811,7 +811,7 @@ Переглянути трасування apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -819,7 +819,7 @@ Виконати завдання apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -827,7 +827,7 @@ Видалити завдання apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1497,6 +1497,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -2243,7 +2247,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -2681,6 +2685,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -3341,6 +3349,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -4031,6 +4043,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + New Users Нові користувачі @@ -4052,7 +4072,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -4775,22 +4795,6 @@ 7 - - 4% Rule - Правило 4% - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - Якщо ви вийдете на пенсію сьогодні, ви зможете знімати на рік або на місяць, виходячи з вашого загального капіталу в та ставкою виведення у 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - Ghostfolio X-ray uses static analysis to uncover potential issues and risks in your portfolio. Adjust the rules below and set custom thresholds to align with your personal investment strategy. Ghostfolio X-ray використовує статичний аналіз для виявлення потенційних проблем та ризиків у вашому портфелі. Налаштуйте правила нижче та встановіть індивідуальні пороги, щоб узгодити їх з вашою особистою інвестиційною стратегією. @@ -4815,6 +4819,14 @@ 58 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive Неактивний @@ -5071,6 +5083,14 @@ 234 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio надає можливість вам стежити за вашим багатством. @@ -5462,6 +5482,14 @@ 44 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Порівняльна таблиця Ghostfolio проти @@ -6026,6 +6054,14 @@ 61 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High Останній рекордний максимум @@ -6307,7 +6343,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6359,7 +6395,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6503,7 +6539,7 @@ Символ apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -6595,7 +6631,7 @@ Цінний libs/ui/src/lib/i18n.ts - 41 + 43 @@ -6603,7 +6639,7 @@ Зобов’язання libs/ui/src/lib/i18n.ts - 42 + 41 @@ -6615,7 +6651,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -6762,6 +6798,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania Океанія diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 58da88399..7a185aa34 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -228,7 +228,7 @@ Type apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -540,14 +540,14 @@ Asset Profile apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 Historical Market Data apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -558,7 +558,7 @@ Data Source apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -581,28 +581,28 @@ Attempts apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 Created apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 Finished apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -620,28 +620,28 @@ Delete Jobs apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 View Data apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 View Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 Delete Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1548,6 +1548,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -1968,6 +1972,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -2529,6 +2537,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -3112,6 +3124,13 @@ 59 + + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + New Users @@ -3130,7 +3149,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -3684,13 +3703,6 @@ 7 - - 4% Rule - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings @@ -3917,6 +3929,13 @@ 132 + + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. @@ -4035,6 +4054,13 @@ 44 + + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table @@ -4380,6 +4406,13 @@ 61 + + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High @@ -4700,7 +4733,7 @@ Symbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -4778,14 +4811,14 @@ Valuable libs/ui/src/lib/i18n.ts - 41 + 43 Liability libs/ui/src/lib/i18n.ts - 42 + 41 @@ -4796,7 +4829,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -4919,6 +4952,13 @@ 72 + + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania @@ -5209,13 +5249,6 @@ 266 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - year @@ -5350,7 +5383,7 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5364,7 +5397,7 @@ Priority apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -5834,7 +5867,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -5856,6 +5889,13 @@ 34 + + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive @@ -5891,7 +5931,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -5937,7 +5977,7 @@ Portfolio Snapshot apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6353,7 +6393,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index b845cf7ad..f25ad787a 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -244,7 +244,7 @@ 类型 apps/client/src/app/components/admin-jobs/admin-jobs.html - 31 + 48 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -572,7 +572,7 @@ 资产概况 apps/client/src/app/components/admin-jobs/admin-jobs.html - 35 + 52 @@ -580,7 +580,7 @@ 历史市场数据 apps/client/src/app/components/admin-jobs/admin-jobs.html - 37 + 54 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -592,7 +592,7 @@ 数据源 apps/client/src/app/components/admin-jobs/admin-jobs.html - 55 + 82 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -616,7 +616,7 @@ 尝试次数 apps/client/src/app/components/admin-jobs/admin-jobs.html - 83 + 120 @@ -624,7 +624,7 @@ 创建 apps/client/src/app/components/admin-jobs/admin-jobs.html - 92 + 134 @@ -632,7 +632,7 @@ 完成 apps/client/src/app/components/admin-jobs/admin-jobs.html - 101 + 143 @@ -640,7 +640,7 @@ 状态 apps/client/src/app/components/admin-jobs/admin-jobs.html - 110 + 152 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -660,7 +660,7 @@ 删除任务 apps/client/src/app/components/admin-jobs/admin-jobs.html - 151 + 193 @@ -668,7 +668,7 @@ 查看数据 apps/client/src/app/components/admin-jobs/admin-jobs.html - 166 + 208 @@ -676,7 +676,7 @@ 查看堆栈跟踪 apps/client/src/app/components/admin-jobs/admin-jobs.html - 173 + 215 @@ -684,7 +684,7 @@ 删除任务 apps/client/src/app/components/admin-jobs/admin-jobs.html - 180 + 222 @@ -1662,6 +1662,10 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html 97 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 81 + apps/client/src/app/pages/register/register-page.html 31 @@ -2126,6 +2130,10 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html 32 + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 78 + apps/client/src/app/pages/pricing/pricing-page.html 283 @@ -2734,6 +2742,10 @@ apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.html 168 + + apps/client/src/app/pages/blog/2025/09/hacktoberfest-2025/hacktoberfest-2025-page.html + 189 + apps/client/src/app/pages/blog/blog-page.html 5 @@ -3383,6 +3395,14 @@ 59 + + and a safe withdrawal rate (SWR) of + and a safe withdrawal rate (SWR) of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 107 + + New Users 新用户 @@ -3404,7 +3424,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 22 + 34 @@ -4019,14 +4039,6 @@ 7 - - 4% Rule - 4%规则 - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 40 - - Holdings 持仓 @@ -4275,6 +4287,14 @@ 132 + + Sustainable retirement income + Sustainable retirement income + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 40 + + Ghostfolio empowers you to keep track of your wealth. Ghostfolio 使您能够跟踪您的财富。 @@ -4408,6 +4428,14 @@ 44 + + per month + per month + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 92 + + Ghostfolio vs comparison table Ghostfolio vs比较表 @@ -4788,6 +4816,14 @@ 61 + + , + , + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 93 + + Last All Time High 上次历史最高纪录 @@ -5141,7 +5177,7 @@ 代码 apps/client/src/app/components/admin-jobs/admin-jobs.html - 46 + 68 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5225,7 +5261,7 @@ 贵重物品 libs/ui/src/lib/i18n.ts - 41 + 43 @@ -5233,7 +5269,7 @@ 负债 libs/ui/src/lib/i18n.ts - 42 + 41 @@ -5245,7 +5281,7 @@ libs/ui/src/lib/i18n.ts - 43 + 42 @@ -5384,6 +5420,14 @@ 72 + + If you retire today, you would be able to withdraw + If you retire today, you would be able to withdraw + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 66 + + Oceania 大洋洲 @@ -5708,14 +5752,6 @@ 266 - - If you retire today, you would be able to withdraw per year or per month, based on your total assets of and a withdrawal rate of 4%. - 如果你今天退休,你可以领取每年或者每月,根据您的总资产提款率为4%。 - - apps/client/src/app/pages/portfolio/fire/fire-page.html - 68 - - year @@ -5866,7 +5902,7 @@ 执行作业 apps/client/src/app/components/admin-jobs/admin-jobs.html - 176 + 218 @@ -5874,7 +5910,7 @@ 优先级 apps/client/src/app/components/admin-jobs/admin-jobs.html - 64 + 96 @@ -6381,6 +6417,14 @@ 83 + + based on your total assets of + based on your total assets of + + apps/client/src/app/pages/portfolio/fire/fire-page.html + 95 + + Inactive 非活跃 @@ -6430,7 +6474,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 346 + 345 apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html @@ -6474,7 +6518,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 348 + 347 libs/ui/src/lib/i18n.ts @@ -6510,7 +6554,7 @@ 投资组合快照 apps/client/src/app/components/admin-jobs/admin-jobs.html - 39 + 56 @@ -6980,7 +7024,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 357 + 356 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html diff --git a/apps/client/src/styles/table.scss b/apps/client/src/styles/table.scss index f232cb1af..88258d48b 100644 --- a/apps/client/src/styles/table.scss +++ b/apps/client/src/styles/table.scss @@ -1,6 +1,12 @@ @mixin gf-table($darkTheme: false) { --mat-table-background-color: var(--light-background); + th { + .mat-sort-header-container { + justify-content: inherit; + } + } + .mat-footer-row, .mat-row { .mat-cell, diff --git a/libs/common/src/lib/chart-helper.ts b/libs/common/src/lib/chart-helper.ts index 4181ebbbf..697f39467 100644 --- a/libs/common/src/lib/chart-helper.ts +++ b/libs/common/src/lib/chart-helper.ts @@ -132,8 +132,10 @@ export function getVerticalHoverLinePlugin( } export function transformTickToAbbreviation(value: number) { - if (value >= -999 && value <= 999) { - return value.toString(); + if (value === 0) { + return '0'; + } else if (value >= -999 && value <= 999) { + return value.toFixed(2); } else if (value >= -999999 && value <= 999999) { return `${value / 1000}K`; } else { diff --git a/libs/common/src/lib/interfaces/fire-wealth.interface.ts b/libs/common/src/lib/interfaces/fire-wealth.interface.ts new file mode 100644 index 000000000..42fbeabd4 --- /dev/null +++ b/libs/common/src/lib/interfaces/fire-wealth.interface.ts @@ -0,0 +1,3 @@ +export interface FireWealth { + today: { valueInBaseCurrency: number }; +} diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index 6529fa3ef..1da2236e8 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -19,6 +19,7 @@ import type { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface' import type { Export } from './export.interface'; import type { FilterGroup } from './filter-group.interface'; import type { Filter } from './filter.interface'; +import type { FireWealth } from './fire-wealth.interface'; import type { HistoricalDataItem } from './historical-data-item.interface'; import type { HoldingWithParents } from './holding-with-parents.interface'; import type { Holding } from './holding.interface'; @@ -104,6 +105,7 @@ export { Export, Filter, FilterGroup, + FireWealth, HistoricalDataItem, HistoricalResponse, Holding, diff --git a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts index 419915a79..05fac0ba0 100644 --- a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts @@ -1,3 +1,4 @@ +import { FireWealth } from './fire-wealth.interface'; import { PortfolioPerformance } from './portfolio-performance.interface'; export interface PortfolioSummary extends PortfolioPerformance { @@ -16,7 +17,7 @@ export interface PortfolioSummary extends PortfolioPerformance { fees: number; filteredValueInBaseCurrency?: number; filteredValueInPercentage?: number; - fireWealth: number; + fireWealth: FireWealth; grossPerformance: number; grossPerformanceWithCurrencyEffect: number; interest: number; diff --git a/libs/common/src/lib/interfaces/user-settings.interface.ts b/libs/common/src/lib/interfaces/user-settings.interface.ts index e5c65f82d..65325a42f 100644 --- a/libs/common/src/lib/interfaces/user-settings.interface.ts +++ b/libs/common/src/lib/interfaces/user-settings.interface.ts @@ -29,6 +29,7 @@ export interface UserSettings { performanceCalculationType?: PerformanceCalculationType; projectedTotalAmount?: number; retirementDate?: string; + safeWithdrawalRate?: number; savingsRate?: number; viewMode?: ViewMode; xRayRules?: XRayRulesSettings; diff --git a/libs/ui/src/lib/accounts-table/accounts-table.component.scss b/libs/ui/src/lib/accounts-table/accounts-table.component.scss index 990b8b294..5d4e87f30 100644 --- a/libs/ui/src/lib/accounts-table/accounts-table.component.scss +++ b/libs/ui/src/lib/accounts-table/accounts-table.component.scss @@ -1,13 +1,3 @@ :host { display: block; - - .gf-table { - th { - ::ng-deep { - .mat-sort-header-container { - justify-content: inherit; - } - } - } - } } 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 c31a5fecd..cb659988a 100644 --- a/libs/ui/src/lib/activities-filter/activities-filter.component.ts +++ b/libs/ui/src/lib/activities-filter/activities-filter.component.ts @@ -1,4 +1,4 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { Filter, FilterGroup } from '@ghostfolio/common/interfaces'; import { COMMA, ENTER } from '@angular/cdk/keycodes'; @@ -39,7 +39,7 @@ import { translate } from '../i18n'; changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, - GfSymbolModule, + GfSymbolPipe, IonIcon, MatAutocompleteModule, MatButtonModule, 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 85db627d2..523020585 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -255,7 +255,7 @@
Value @@ -291,7 +291,7 @@ Value diff --git a/libs/ui/src/lib/activities-table/activities-table.component.stories.ts b/libs/ui/src/lib/activities-table/activities-table.component.stories.ts new file mode 100644 index 000000000..5e774730b --- /dev/null +++ b/libs/ui/src/lib/activities-table/activities-table.component.stories.ts @@ -0,0 +1,471 @@ +import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; + +import { CommonModule } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatSortModule } from '@angular/material/sort'; +import { MatTableDataSource, MatTableModule } from '@angular/material/table'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { RouterModule } from '@angular/router'; +import { IonIcon } from '@ionic/angular/standalone'; +import { moduleMetadata } from '@storybook/angular'; +import type { Meta, StoryObj } from '@storybook/angular'; +import { NotificationService } from 'apps/client/src/app/core/notification/notification.service'; +import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; + +import { GfActivityTypeComponent } from '../activity-type/activity-type.component'; +import { GfEntityLogoComponent } from '../entity-logo'; +import { GfNoTransactionsInfoComponent } from '../no-transactions-info/no-transactions-info.component'; +import { GfValueComponent } from '../value'; +import { GfActivitiesTableComponent } from './activities-table.component'; + +const activities: Activity[] = [ + { + accountId: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + accountUserId: '081aa387-487d-4438-83a4-3060eb2a016e', + comment: null, + createdAt: new Date('2025-04-09T13:47:33.133Z'), + currency: 'USD', + date: new Date('2025-04-09T13:45:45.504Z'), + fee: 1, + id: 'a76968ff-80a4-4453-81ed-c3627dea3919', + isDraft: false, + quantity: 115, + symbolProfileId: '21746431-d612-4298-911c-3099b2a43003', + type: 'BUY', + unitPrice: 103.543, + updatedAt: new Date('2025-05-31T18:43:01.840Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + account: { + balance: 150.2, + comment: null, + createdAt: new Date('2025-05-31T13:00:13.940Z'), + currency: 'USD', + id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + isExcluded: false, + name: 'Trading Account', + platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', + updatedAt: new Date('2025-06-01T06:53:10.569Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + platform: { + id: '9da3a8a7-4795-43e3-a6db-ccb914189737', + name: 'Interactive Brokers', + url: 'https://interactivebrokers.com' + } + }, + SymbolProfile: { + assetClass: 'EQUITY', + assetSubClass: 'ETF', + comment: null, + countries: [], + createdAt: new Date('2021-06-06T16:12:20.982Z'), + currency: 'USD', + cusip: '922042742', + dataSource: 'YAHOO', + figi: 'BBG000GM5FZ6', + figiComposite: 'BBG000GM5FZ6', + figiShareClass: 'BBG001T2YZG9', + holdings: [], + id: '21746431-d612-4298-911c-3099b2a43003', + isActive: true, + isin: 'US9220427424', + name: 'Vanguard Total World Stock Index Fund ETF Shares', + updatedAt: new Date('2025-10-01T20:09:39.500Z'), + scraperConfiguration: null, + sectors: [], + symbol: 'VT', + symbolMapping: {}, + url: 'https://www.vanguard.com', + userId: null, + activitiesCount: 267, + dateOfFirstActivity: new Date('2018-05-31T16:00:00.000Z') + }, + tags: [], + feeInAssetProfileCurrency: 1, + feeInBaseCurrency: 1, + unitPriceInAssetProfileCurrency: 103.543, + value: 11907.445, + valueInBaseCurrency: 11907.445 + }, + { + accountId: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + accountUserId: '081aa387-487d-4438-83a4-3060eb2a016e', + comment: null, + createdAt: new Date('2024-08-07T13:40:39.103Z'), + currency: 'USD', + date: new Date('2024-08-07T13:38:06.289Z'), + fee: 2.97, + id: '0c2f4fbf-6edc-4adc-8f83-abf8148500ec', + isDraft: false, + quantity: 105, + symbolProfileId: '21746431-d612-4298-911c-3099b2a43003', + type: 'BUY', + unitPrice: 110.24, + updatedAt: new Date('2025-05-31T18:46:14.175Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + account: { + balance: 150.2, + comment: null, + createdAt: new Date('2025-05-31T13:00:13.940Z'), + currency: 'USD', + id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + isExcluded: false, + name: 'Trading Account', + platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', + updatedAt: new Date('2025-06-01T06:53:10.569Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + platform: { + id: '9da3a8a7-4795-43e3-a6db-ccb914189737', + name: 'Interactive Brokers', + url: 'https://interactivebrokers.com' + } + }, + SymbolProfile: { + assetClass: 'EQUITY', + assetSubClass: 'ETF', + comment: null, + countries: [], + createdAt: new Date('2021-06-06T16:12:20.982Z'), + currency: 'USD', + cusip: '922042742', + dataSource: 'YAHOO', + figi: 'BBG000GM5FZ6', + figiComposite: 'BBG000GM5FZ6', + figiShareClass: 'BBG001T2YZG9', + holdings: [], + id: '21746431-d612-4298-911c-3099b2a43003', + isActive: true, + isin: 'US9220427424', + name: 'Vanguard Total World Stock Index Fund ETF Shares', + updatedAt: new Date('2025-10-01T20:09:39.500Z'), + scraperConfiguration: null, + sectors: [], + symbol: 'VT', + symbolMapping: {}, + url: 'https://www.vanguard.com', + userId: null, + activitiesCount: 267, + dateOfFirstActivity: new Date('2018-05-31T16:00:00.000Z') + }, + tags: [], + feeInAssetProfileCurrency: 2.97, + feeInBaseCurrency: 2.97, + unitPriceInAssetProfileCurrency: 110.24, + value: 11575.2, + valueInBaseCurrency: 11575.2 + }, + { + accountId: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + accountUserId: '081aa387-487d-4438-83a4-3060eb2a016e', + comment: null, + createdAt: new Date('2024-03-12T15:15:21.217Z'), + currency: 'USD', + date: new Date('2024-03-12T15:14:38.597Z'), + fee: 45.29, + id: 'bfc92677-faf4-4d4f-9762-e0ec056525c2', + isDraft: false, + quantity: 167, + symbolProfileId: '888d4123-db9a-42f3-9775-01b1ae6f9092', + type: 'BUY', + unitPrice: 41.0596, + updatedAt: new Date('2025-05-31T18:49:54.064Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + account: { + balance: 150.2, + comment: null, + createdAt: new Date('2025-05-31T13:00:13.940Z'), + currency: 'USD', + id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + isExcluded: false, + name: 'Trading Account', + platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', + updatedAt: new Date('2025-06-01T06:53:10.569Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + platform: { + id: '9da3a8a7-4795-43e3-a6db-ccb914189737', + name: 'Interactive Brokers', + url: 'https://interactivebrokers.com' + } + }, + SymbolProfile: { + assetClass: 'LIQUIDITY', + assetSubClass: 'CRYPTOCURRENCY', + comment: null, + countries: [], + createdAt: new Date('2024-03-12T15:15:21.217Z'), + currency: 'USD', + cusip: '463918102', + dataSource: 'YAHOO', + figi: 'BBG01KYQ6PV3', + figiComposite: 'BBG01KYQ6PV3', + figiShareClass: 'BBG01KYQ6QS5', + holdings: [], + id: '888d4123-db9a-42f3-9775-01b1ae6f9092', + isActive: true, + isin: 'CA4639181029', + name: 'iShares Bitcoin Trust', + updatedAt: new Date('2025-09-29T03:14:07.742Z'), + scraperConfiguration: null, + sectors: [], + symbol: 'IBIT', + symbolMapping: {}, + url: 'https://www.ishares.com', + userId: null, + activitiesCount: 6, + dateOfFirstActivity: new Date('2024-01-01T08:00:00.000Z') + }, + tags: [], + feeInAssetProfileCurrency: 45.29, + feeInBaseCurrency: 45.29, + unitPriceInAssetProfileCurrency: 41.0596, + value: 6856.9532, + valueInBaseCurrency: 6856.9532 + }, + { + accountId: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + accountUserId: '081aa387-487d-4438-83a4-3060eb2a016e', + comment: null, + createdAt: new Date('2024-02-23T15:53:46.907Z'), + currency: 'USD', + date: new Date('2024-02-23T15:53:15.745Z'), + fee: 3, + id: '7c9ceb54-acb1-4850-bfb1-adb41c29fd6a', + isDraft: false, + quantity: 81, + symbolProfileId: '36effe43-7cb4-4e8b-b7ac-03ff65702cb9', + type: 'BUY', + unitPrice: 67.995, + updatedAt: new Date('2025-05-31T18:48:48.209Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + account: { + balance: 150.2, + comment: null, + createdAt: new Date('2025-05-31T13:00:13.940Z'), + currency: 'USD', + id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + isExcluded: false, + name: 'Trading Account', + platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', + updatedAt: new Date('2025-06-01T06:53:10.569Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + platform: { + id: '9da3a8a7-4795-43e3-a6db-ccb914189737', + name: 'Interactive Brokers', + url: 'https://interactivebrokers.com' + } + }, + SymbolProfile: { + assetClass: 'FIXED_INCOME', + assetSubClass: 'BOND', + comment: 'No data', + countries: [], + createdAt: new Date('2022-04-13T20:05:47.301Z'), + currency: 'USD', + cusip: '92206C565', + dataSource: 'YAHOO', + figi: 'BBG00LWSF7T3', + figiComposite: 'BBG00LWSF7T3', + figiShareClass: 'BBG00LWSF8K0', + holdings: [], + id: '36effe43-7cb4-4e8b-b7ac-03ff65702cb9', + isActive: true, + isin: 'US92206C5655', + name: 'Vanguard Total World Bond ETF', + updatedAt: new Date('2025-10-02T06:02:56.314Z'), + + sectors: [], + symbol: 'BNDW', + symbolMapping: {}, + url: 'https://vanguard.com', + userId: null, + activitiesCount: 38, + dateOfFirstActivity: new Date('2022-04-13T20:05:48.742Z') + }, + tags: [], + feeInAssetProfileCurrency: 3, + feeInBaseCurrency: 3, + unitPriceInAssetProfileCurrency: 67.995, + value: 5507.595, + valueInBaseCurrency: 5507.595 + }, + { + accountId: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + accountUserId: '081aa387-487d-4438-83a4-3060eb2a016e', + comment: null, + createdAt: new Date('2023-01-11T14:35:22.325Z'), + currency: 'USD', + date: new Date('2023-01-11T14:34:55.174Z'), + fee: 7.38, + id: '3fe87b3f-78de-407a-bc02-4189b221051f', + isDraft: false, + quantity: 55, + symbolProfileId: '21746431-d612-4298-911c-3099b2a43003', + type: 'BUY', + unitPrice: 89.48, + updatedAt: new Date('2025-05-31T18:46:44.616Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + account: { + balance: 150.2, + comment: null, + createdAt: new Date('2025-05-31T13:00:13.940Z'), + currency: 'USD', + id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', + isExcluded: false, + name: 'Trading Account', + platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', + updatedAt: new Date('2025-06-01T06:53:10.569Z'), + userId: '081aa387-487d-4438-83a4-3060eb2a016e', + platform: { + id: '9da3a8a7-4795-43e3-a6db-ccb914189737', + name: 'Interactive Brokers', + url: 'https://interactivebrokers.com' + } + }, + SymbolProfile: { + assetClass: 'EQUITY', + assetSubClass: 'ETF', + comment: null, + countries: [], + createdAt: new Date('2021-06-06T16:12:20.982Z'), + currency: 'USD', + cusip: '922042742', + dataSource: 'YAHOO', + figi: 'BBG000GM5FZ6', + figiComposite: 'BBG000GM5FZ6', + figiShareClass: 'BBG001T2YZG9', + holdings: [], + id: '21746431-d612-4298-911c-3099b2a43003', + isActive: true, + isin: 'US9220427424', + name: 'Vanguard Total World Stock Index Fund ETF Shares', + updatedAt: new Date('2025-10-01T20:09:39.500Z'), + scraperConfiguration: null, + sectors: [], + symbol: 'VT', + symbolMapping: {}, + url: 'https://www.vanguard.com', + userId: null, + activitiesCount: 267, + dateOfFirstActivity: new Date('2018-05-31T16:00:00.000Z') + }, + tags: [], + feeInAssetProfileCurrency: 7.38, + feeInBaseCurrency: 7.38, + unitPriceInAssetProfileCurrency: 89.48, + value: 4921.4, + valueInBaseCurrency: 4921.4 + } +]; + +const dataSource = new MatTableDataSource(activities); + +export default { + title: 'Activities Table', + component: GfActivitiesTableComponent, + decorators: [ + moduleMetadata({ + imports: [ + CommonModule, + GfActivityTypeComponent, + GfEntityLogoComponent, + GfNoTransactionsInfoComponent, + GfSymbolPipe, + GfValueComponent, + IonIcon, + MatButtonModule, + MatCheckboxModule, + MatMenuModule, + MatPaginatorModule, + MatSortModule, + MatTableModule, + MatTooltipModule, + NgxSkeletonLoaderModule, + RouterModule.forChild([]) + ], + providers: [NotificationService] + }) + ] +} as Meta; + +type Story = StoryObj; + +export const Loading: Story = { + args: { + baseCurrency: 'USD', + dataSource: undefined, + deviceType: 'desktop', + hasActivities: true, + hasPermissionToCreateActivity: false, + hasPermissionToDeleteActivity: false, + hasPermissionToExportActivities: false, + hasPermissionToOpenDetails: false, + locale: 'en-US', + pageIndex: 0, + pageSize: 10, + showAccountColumn: true, + showActions: false, + showCheckbox: false, + showNameColumn: true, + sortColumn: 'date', + sortDirection: 'desc', + sortDisabled: false, + totalItems: 0 + } +}; + +export const Default: Story = { + args: { + baseCurrency: 'USD', + dataSource, + deviceType: 'desktop', + hasActivities: true, + hasPermissionToCreateActivity: false, + hasPermissionToDeleteActivity: false, + hasPermissionToExportActivities: false, + hasPermissionToOpenDetails: false, + locale: 'en-US', + pageIndex: 0, + pageSize: 10, + showAccountColumn: true, + showActions: false, + showCheckbox: false, + showNameColumn: true, + sortColumn: 'date', + sortDirection: 'desc', + sortDisabled: false, + totalItems: activities.length + } +}; + +export const Pagination: Story = { + args: { + baseCurrency: 'USD', + dataSource: new MatTableDataSource( + Array.from({ length: 50 }).map((_, i) => ({ + ...(activities[i % activities.length] as Activity), + date: new Date(2025, 5, (i % 28) + 1), + id: `${i}` + })) + ), + deviceType: 'desktop', + hasActivities: true, + hasPermissionToCreateActivity: false, + hasPermissionToDeleteActivity: false, + hasPermissionToExportActivities: false, + hasPermissionToOpenDetails: false, + locale: 'en-US', + pageIndex: 0, + pageSize: 10, + showAccountColumn: true, + showActions: false, + showCheckbox: false, + showNameColumn: true, + sortColumn: 'date', + sortDirection: 'desc', + sortDisabled: false, + totalItems: 50 + } +}; diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts index 4be9fbec6..ce2de1caa 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -1,7 +1,7 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { DEFAULT_PAGE_SIZE, TAG_ID_EXCLUDE_FROM_ANALYSIS @@ -73,7 +73,7 @@ import { GfValueComponent } from '../value/value.component'; GfActivityTypeComponent, GfEntityLogoComponent, GfNoTransactionsInfoComponent, - GfSymbolModule, + GfSymbolPipe, GfValueComponent, IonIcon, MatButtonModule, diff --git a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts index 1cfcfec6a..f75aaea01 100644 --- a/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts +++ b/libs/ui/src/lib/assistant/assistant-list-item/assistant-list-item.component.ts @@ -1,4 +1,4 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { FocusableOption } from '@angular/cdk/a11y'; @@ -24,7 +24,7 @@ import { @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [GfSymbolModule, RouterModule], + imports: [GfSymbolPipe, RouterModule], selector: 'gf-assistant-list-item', styleUrls: ['./assistant-list-item.scss'], templateUrl: './assistant-list-item.html' diff --git a/libs/ui/src/lib/assistant/assistant.component.ts b/libs/ui/src/lib/assistant/assistant.component.ts index e5d0dd6da..3fc1cc232 100644 --- a/libs/ui/src/lib/assistant/assistant.component.ts +++ b/libs/ui/src/lib/assistant/assistant.component.ts @@ -1,4 +1,4 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { AdminService } from '@ghostfolio/client/services/admin.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; @@ -76,7 +76,7 @@ import { FormsModule, GfAssistantListItemComponent, GfEntityLogoComponent, - GfSymbolModule, + GfSymbolPipe, IonIcon, MatButtonModule, MatFormFieldModule, @@ -169,6 +169,8 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { }; public tags: Filter[] = []; + private readonly PRESELECTION_DELAY = 100; + private filterTypes: Filter['type'][] = [ 'ACCOUNT', 'ASSET_CLASS', @@ -176,7 +178,9 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { 'SYMBOL', 'TAG' ]; + private keyManager: FocusKeyManager; + private preselectionTimeout: ReturnType; private unsubscribeSubject = new Subject(); public constructor( @@ -344,6 +348,9 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { .subscribe({ next: (searchResults) => { this.searchResults = searchResults; + + this.preselectFirstItem(); + this.changeDetectorRef.markForCheck(); }, error: (error) => { @@ -585,6 +592,10 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { } public ngOnDestroy() { + if (this.preselectionTimeout) { + clearTimeout(this.preselectionTimeout); + } + this.unsubscribeSubject.next(); this.unsubscribeSubject.complete(); } @@ -595,6 +606,58 @@ export class GfAssistantComponent implements OnChanges, OnDestroy, OnInit { }); } + private getFirstSearchResultItem() { + if (this.searchResults.quickLinks?.length > 0) { + return this.searchResults.quickLinks[0]; + } + + if (this.searchResults.accounts?.length > 0) { + return this.searchResults.accounts[0]; + } + + if (this.searchResults.holdings?.length > 0) { + return this.searchResults.holdings[0]; + } + + if (this.searchResults.assetProfiles?.length > 0) { + return this.searchResults.assetProfiles[0]; + } + + return null; + } + + private preselectFirstItem() { + if (this.preselectionTimeout) { + clearTimeout(this.preselectionTimeout); + } + + this.preselectionTimeout = setTimeout(() => { + if (!this.isOpen || !this.searchFormControl.value) { + return; + } + + const firstItem = this.getFirstSearchResultItem(); + + if (!firstItem) { + return; + } + + for (const item of this.assistantListItems) { + item.removeFocus(); + } + + this.keyManager.setFirstItemActive(); + + const currentFocusedItem = this.getCurrentAssistantListItem(); + + if (currentFocusedItem) { + currentFocusedItem.focus(); + } + + this.changeDetectorRef.markForCheck(); + }, this.PRESELECTION_DELAY); + } + private searchAccounts(aSearchTerm: string): Observable { return this.dataService .fetchAccounts({ diff --git a/libs/ui/src/lib/benchmark/benchmark.component.scss b/libs/ui/src/lib/benchmark/benchmark.component.scss index 990b8b294..5d4e87f30 100644 --- a/libs/ui/src/lib/benchmark/benchmark.component.scss +++ b/libs/ui/src/lib/benchmark/benchmark.component.scss @@ -1,13 +1,3 @@ :host { display: block; - - .gf-table { - th { - ::ng-deep { - .mat-sort-header-container { - justify-content: inherit; - } - } - } - } } 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 60d5204e1..ef4722255 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.html +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.html @@ -40,6 +40,7 @@ formControlName="retirementDate" matInput [matDatepicker]="datepicker" + [min]="minDate" /> ; public isLoading = true; + public minDate = addDays(new Date(), 1); public periodsToRetire = 0; private readonly CONTRIBUTION_PERIOD = 12; diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.scss b/libs/ui/src/lib/holdings-table/holdings-table.component.scss index 990b8b294..5d4e87f30 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.scss +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.scss @@ -1,13 +1,3 @@ :host { display: block; - - .gf-table { - th { - ::ng-deep { - .mat-sort-header-container { - justify-content: inherit; - } - } - } - } } diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.ts b/libs/ui/src/lib/holdings-table/holdings-table.component.ts index e0dae867e..10620a652 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.ts +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.ts @@ -1,4 +1,3 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; import { getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, @@ -34,7 +33,6 @@ import { GfValueComponent } from '../value/value.component'; imports: [ CommonModule, GfEntityLogoComponent, - GfSymbolModule, GfValueComponent, MatButtonModule, MatDialogModule, 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 e7f8b132e..0afef5959 100644 --- a/libs/ui/src/lib/line-chart/line-chart.component.ts +++ b/libs/ui/src/lib/line-chart/line-chart.component.ts @@ -261,7 +261,10 @@ export class GfLineChartComponent } if (typeof tickValue === 'number') { - return tickValue.toFixed(2); + return tickValue.toLocaleString(this.locale, { + maximumFractionDigits: 2, + minimumFractionDigits: 2 + }); } return tickValue; 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 f6c289b72..80315fc06 100644 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts +++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts @@ -1,4 +1,4 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { DataService } from '@ghostfolio/client/services/data.service'; import { LookupItem } from '@ghostfolio/common/interfaces'; @@ -57,7 +57,7 @@ import { AbstractMatFormField } from '../shared/abstract-mat-form-field'; imports: [ FormsModule, GfPremiumIndicatorComponent, - GfSymbolModule, + GfSymbolPipe, MatAutocompleteModule, MatFormFieldModule, MatInputModule, diff --git a/libs/ui/src/lib/top-holdings/top-holdings.component.ts b/libs/ui/src/lib/top-holdings/top-holdings.component.ts index b4ebf4c8c..c9f7e0372 100644 --- a/libs/ui/src/lib/top-holdings/top-holdings.component.ts +++ b/libs/ui/src/lib/top-holdings/top-holdings.component.ts @@ -1,4 +1,4 @@ -import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module'; +import { GfSymbolPipe } from '@ghostfolio/client/pipes/symbol/symbol.pipe'; import { getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, @@ -46,7 +46,7 @@ import { GfValueComponent } from '../value/value.component'; changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, - GfSymbolModule, + GfSymbolPipe, GfValueComponent, MatButtonModule, MatPaginatorModule, diff --git a/package-lock.json b/package-lock.json index 7b31242c0..2ed25d7c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.202.0", + "version": "2.206.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.202.0", + "version": "2.206.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { @@ -44,7 +44,7 @@ "@nestjs/schedule": "6.0.0", "@nestjs/serve-static": "5.0.3", "@openrouter/ai-sdk-provider": "0.7.2", - "@prisma/client": "6.16.1", + "@prisma/client": "6.16.3", "@simplewebauthn/browser": "13.1.0", "@simplewebauthn/server": "13.1.1", "@stripe/stripe-js": "7.9.0", @@ -130,7 +130,7 @@ "@types/big.js": "6.2.2", "@types/google-spreadsheet": "3.1.5", "@types/jest": "29.5.13", - "@types/lodash": "4.17.17", + "@types/lodash": "4.17.20", "@types/node": "22.15.17", "@types/papaparse": "5.3.7", "@types/passport-google-oauth20": "2.0.16", @@ -149,7 +149,7 @@ "nx": "21.5.1", "prettier": "3.6.2", "prettier-plugin-organize-attributes": "1.0.0", - "prisma": "6.16.1", + "prisma": "6.16.3", "react": "18.2.0", "react-dom": "18.2.0", "replace-in-file": "8.3.0", @@ -11960,9 +11960,9 @@ "license": "MIT" }, "node_modules/@prisma/client": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.1.tgz", - "integrity": "sha512-QaBCOY29lLAxEFFJgBPyW3WInCW52fJeQTmWx/h6YsP5u0bwuqP51aP0uhqFvhK9DaZPwvai/M4tSDYLVE9vRg==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.3.tgz", + "integrity": "sha512-JfNfAtXG+/lIopsvoZlZiH2k5yNx87mcTS4t9/S5oufM1nKdXYxOvpDC1XoTCFBa5cQh7uXnbMPsmZrwZY80xw==", "hasInstallScript": true, "license": "Apache-2.0", "engines": { @@ -11982,9 +11982,9 @@ } }, "node_modules/@prisma/config": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.1.tgz", - "integrity": "sha512-sz3uxRPNL62QrJ0EYiujCFkIGZ3hg+9hgC1Ae1HjoYuj0BxCqHua4JNijYvYCrh9LlofZDZcRBX3tHBfLvAngA==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.3.tgz", + "integrity": "sha512-VlsLnG4oOuKGGMToEeVaRhoTBZu5H3q51jTQXb/diRags3WV0+BQK5MolJTtP6G7COlzoXmWeS11rNBtvg+qFQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -11995,53 +11995,53 @@ } }, "node_modules/@prisma/debug": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.1.tgz", - "integrity": "sha512-RWv/VisW5vJE4cDRTuAHeVedtGoItXTnhuLHsSlJ9202QKz60uiXWywBlVcqXVq8bFeIZoCoWH+R1duZJPwqLw==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.3.tgz", + "integrity": "sha512-89DdqWtdKd7qoc9/qJCKLTazj3W3zPEiz0hc7HfZdpjzm21c7orOUB5oHWJsG+4KbV4cWU5pefq3CuDVYF9vgA==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.1.tgz", - "integrity": "sha512-EOnEM5HlosPudBqbI+jipmaW/vQEaF0bKBo4gVkGabasINHR6RpC6h44fKZEqx4GD8CvH+einD2+b49DQrwrAg==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.3.tgz", + "integrity": "sha512-b+Rl4nzQDcoqe6RIpSHv8f5lLnwdDGvXhHjGDiokObguAAv/O1KaX1Oc69mBW/GFWKQpCkOraobLjU6s1h8HGg==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.16.1", - "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", - "@prisma/fetch-engine": "6.16.1", - "@prisma/get-platform": "6.16.1" + "@prisma/debug": "6.16.3", + "@prisma/engines-version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", + "@prisma/fetch-engine": "6.16.3", + "@prisma/get-platform": "6.16.3" } }, "node_modules/@prisma/engines-version": { - "version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43.tgz", - "integrity": "sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA==", + "version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a.tgz", + "integrity": "sha512-fftRmosBex48Ph1v2ll1FrPpirwtPZpNkE5CDCY1Lw2SD2ctyrLlVlHiuxDAAlALwWBOkPbAll4+EaqdGuMhJw==", "devOptional": true, "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.1.tgz", - "integrity": "sha512-fl/PKQ8da5YTayw86WD3O9OmKJEM43gD3vANy2hS5S1CnfW2oPXk+Q03+gUWqcKK306QqhjjIHRFuTZ31WaosQ==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.3.tgz", + "integrity": "sha512-bUoRIkVaI+CCaVGrSfcKev0/Mk4ateubqWqGZvQ9uCqFv2ENwWIR3OeNuGin96nZn5+SkebcD7RGgKr/+mJelw==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.16.1", - "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", - "@prisma/get-platform": "6.16.1" + "@prisma/debug": "6.16.3", + "@prisma/engines-version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", + "@prisma/get-platform": "6.16.3" } }, "node_modules/@prisma/get-platform": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.1.tgz", - "integrity": "sha512-kUfg4vagBG7dnaGRcGd1c0ytQFcDj2SUABiuveIpL3bthFdTLI6PJeLEia6Q8Dgh+WhPdo0N2q0Fzjk63XTyaA==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.3.tgz", + "integrity": "sha512-X1LxiFXinJ4iQehrodGp0f66Dv6cDL0GbRlcCoLtSu6f4Wi+hgo7eND/afIs5029GQLgNWKZ46vn8hjyXTsHLA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.16.1" + "@prisma/debug": "6.16.3" } }, "node_modules/@redis/client": { @@ -14435,9 +14435,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", "dev": true, "license": "MIT" }, @@ -17285,9 +17285,9 @@ } }, "node_modules/c12/node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "devOptional": true, "license": "MIT", "bin": { @@ -33713,16 +33713,16 @@ } }, "node_modules/nypm": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", - "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", + "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", "devOptional": true, "license": "MIT", "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", - "pkg-types": "^2.2.0", + "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { @@ -34903,9 +34903,9 @@ } }, "node_modules/pkg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", - "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", "devOptional": true, "license": "MIT", "dependencies": { @@ -35747,15 +35747,15 @@ } }, "node_modules/prisma": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.1.tgz", - "integrity": "sha512-MFkMU0eaDDKAT4R/By2IA9oQmwLTxokqv2wegAErr9Rf+oIe7W2sYpE/Uxq0H2DliIR7vnV63PkC1bEwUtl98w==", + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.3.tgz", + "integrity": "sha512-4tJq3KB9WRshH5+QmzOLV54YMkNlKOtLKaSdvraI5kC/axF47HuOw6zDM8xrxJ6s9o2WodY654On4XKkrobQdQ==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/config": "6.16.1", - "@prisma/engines": "6.16.1" + "@prisma/config": "6.16.3", + "@prisma/engines": "6.16.3" }, "bin": { "prisma": "build/index.js" diff --git a/package.json b/package.json index 463310c60..8717f58df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.202.0", + "version": "2.206.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", @@ -90,7 +90,7 @@ "@nestjs/schedule": "6.0.0", "@nestjs/serve-static": "5.0.3", "@openrouter/ai-sdk-provider": "0.7.2", - "@prisma/client": "6.16.1", + "@prisma/client": "6.16.3", "@simplewebauthn/browser": "13.1.0", "@simplewebauthn/server": "13.1.1", "@stripe/stripe-js": "7.9.0", @@ -176,7 +176,7 @@ "@types/big.js": "6.2.2", "@types/google-spreadsheet": "3.1.5", "@types/jest": "29.5.13", - "@types/lodash": "4.17.17", + "@types/lodash": "4.17.20", "@types/node": "22.15.17", "@types/papaparse": "5.3.7", "@types/passport-google-oauth20": "2.0.16", @@ -195,7 +195,7 @@ "nx": "21.5.1", "prettier": "3.6.2", "prettier-plugin-organize-attributes": "1.0.0", - "prisma": "6.16.1", + "prisma": "6.16.3", "react": "18.2.0", "react-dom": "18.2.0", "replace-in-file": "8.3.0",