Browse Source

Merge remote-tracking branch 'origin/main' into task/upgrade-to-nx-21-3

pull/5292/head
KenTandrian 3 weeks ago
parent
commit
543f6a2f7b
  1. 5
      CHANGELOG.md
  2. 2
      apps/client/src/app/components/admin-users/admin-users.component.ts
  3. 17
      apps/client/src/app/components/admin-users/admin-users.html
  4. 25
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  5. 10
      apps/client/src/app/pages/portfolio/analysis/analysis-page.html
  6. 32
      apps/client/src/locales/messages.es.xlf
  7. 4
      package-lock.json
  8. 2
      package.json

5
CHANGELOG.md

@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased ## 2.186.0 - 2025-07-30
### Added ### Added
@ -13,7 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Improved the _Top 3_ and _Bottom 3_ performers on the analysis page by removing items without performance
- Improved the usability of the toggle component - Improved the usability of the toggle component
- Simplified the users table of the admin control panel
- Restructured the response of the portfolio report endpoint (_X-ray_) - Restructured the response of the portfolio report endpoint (_X-ray_)
- Refreshed the cryptocurrencies list - Refreshed the cryptocurrencies list
- Improved the language localization for Catalan (`ca`) - Improved the language localization for Catalan (`ca`)
@ -27,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Fixed the links of the _Top 3_ and _Bottom 3_ performers on the analysis page
- Excluded the holdings originated of `FEE`, `INTEREST` and `LIABILITY` activities from the closed holdings on the portfolio holdings page - Excluded the holdings originated of `FEE`, `INTEREST` and `LIABILITY` activities from the closed holdings on the portfolio holdings page
- Fixed an issue with serving _Storybook_ related to missing styles - Fixed an issue with serving _Storybook_ related to missing styles

2
apps/client/src/app/components/admin-users/admin-users.component.ts

@ -101,7 +101,6 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
if (this.hasPermissionForSubscription) { if (this.hasPermissionForSubscription) {
this.displayedColumns = [ this.displayedColumns = [
'index',
'user', 'user',
'country', 'country',
'registration', 'registration',
@ -114,7 +113,6 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
]; ];
} else { } else {
this.displayedColumns = [ this.displayedColumns = [
'index',
'user', 'user',
'registration', 'registration',
'accounts', 'accounts',

17
apps/client/src/app/components/admin-users/admin-users.html

@ -3,23 +3,6 @@
<div class="col"> <div class="col">
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="gf-table" mat-table [dataSource]="dataSource"> <table class="gf-table" mat-table [dataSource]="dataSource">
<ng-container matColumnDef="index">
<th
*matHeaderCellDef
class="mat-mdc-header-cell px-1 py-2 text-right"
mat-header-cell
>
#
</th>
<td
*matCellDef="let element; let i = index"
class="mat-mdc-cell px-1 py-2 text-right"
mat-cell
>
{{ i + 1 }}
</td>
</ng-container>
<ng-container matColumnDef="user"> <ng-container matColumnDef="user">
<th <th
*matHeaderCellDef *matHeaderCellDef

25
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -32,6 +32,7 @@ import { MatCardModule } from '@angular/material/card';
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu'; import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone'; import { IonIcon } from '@ionic/angular/standalone';
import { SymbolProfile } from '@prisma/client'; import { SymbolProfile } from '@prisma/client';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
@ -55,7 +56,8 @@ import { takeUntil } from 'rxjs/operators';
MatCardModule, MatCardModule,
MatMenuModule, MatMenuModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
NgxSkeletonLoaderModule NgxSkeletonLoaderModule,
RouterModule
], ],
selector: 'gf-analysis-page', selector: 'gf-analysis-page',
styleUrls: ['./analysis-page.scss'], styleUrls: ['./analysis-page.scss'],
@ -342,13 +344,20 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit {
'netPerformancePercentWithCurrencyEffect' 'netPerformancePercentWithCurrencyEffect'
).reverse(); ).reverse();
this.top3 = holdingsSorted.slice(0, 3); this.top3 = holdingsSorted
.filter(
if (holdings?.length > 3) { ({ netPerformancePercentWithCurrencyEffect }) =>
this.bottom3 = holdingsSorted.slice(-3).reverse(); netPerformancePercentWithCurrencyEffect > 0
} else { )
this.bottom3 = []; .slice(0, 3);
}
this.bottom3 = holdingsSorted
.filter(
({ netPerformancePercentWithCurrencyEffect }) =>
netPerformancePercentWithCurrencyEffect < 0
)
.slice(-3)
.reverse();
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
}); });

10
apps/client/src/app/pages/portfolio/analysis/analysis-page.html

@ -93,7 +93,7 @@
<div class="mb-5 row"> <div class="mb-5 row">
<div class="col"> <div class="col">
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined">
<mat-card-content> <mat-card-content>
<div class="d-flex py-1"> <div class="d-flex py-1">
<div <div
@ -232,8 +232,8 @@
</div> </div>
<div class="mb-5 row"> <div class="mb-5 row">
<div class="col-md-6"> <div class="col-md-6 mb-3">
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="h-100">
<mat-card-header> <mat-card-header>
<mat-card-title class="align-items-center d-flex" i18n <mat-card-title class="align-items-center d-flex" i18n
>Top</mat-card-title >Top</mat-card-title
@ -281,8 +281,8 @@
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div> </div>
<div class="col-md-6"> <div class="col-md-6 mb-3">
<mat-card appearance="outlined" class="mb-3"> <mat-card appearance="outlined" class="h-100">
<mat-card-header> <mat-card-header>
<mat-card-title class="align-items-center d-flex" i18n <mat-card-title class="align-items-center d-flex" i18n
>Bottom</mat-card-title >Bottom</mat-card-title

32
apps/client/src/locales/messages.es.xlf

@ -3544,7 +3544,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6962217007874959362" datatype="html"> <trans-unit id="6962217007874959362" datatype="html">
<source> Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. </source> <source> Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover operational costs for the hosting infrastructure and professional data providers, and to fund ongoing development. </source>
<target state="new"> Nuestra oferta oficial en la nube de Ghostfolio Premium es la forma más sencilla de comenzar. Debido al tiempo que ahorra, esta será la mejor opción para la mayoría de las personas. Los ingresos se utilizan para cubrir los costos de la infraestructura de alojamiento y para financiar el desarrollo continuo.</target> <target state="translated"> Nuestra oferta oficial en la nube Ghostfolio Premium es la forma más fácil de comenzar. Debido al tiempo que ahorra, esta será la mejor opción para la mayoría de las personas. Los ingresos se utilizan para cubrir los costos operativos de la infraestructura de alojamiento y los proveedores de datos profesionales, y para financiar el desarrollo continuo.</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/pricing/pricing-page.html</context>
<context context-type="linenumber">7</context> <context context-type="linenumber">7</context>
@ -8010,7 +8010,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskJapan" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskJapan" datatype="html">
<source>Japan</source> <source>Japan</source>
<target state="new">Japan</target> <target state="translated">Japón</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">196</context> <context context-type="linenumber">196</context>
@ -8018,7 +8018,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskJapan.false.max" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskJapan.false.max" datatype="html">
<source> The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% </source> <source> The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% </source>
<target state="new"> The Japan market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% </target> <target state="translated"> La contribución al mercado japonés de su inversión actual (${valueRatio}%) supera el ${thresholdMax}% </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">198</context> <context context-type="linenumber">198</context>
@ -8026,7 +8026,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskJapan.false.min" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskJapan.false.min" datatype="html">
<source> The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% </source> <source> The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% </source>
<target state="new"> The Japan market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% </target> <target state="translated"> La contribución al mercado japonés de su inversión actual (${valueRatio}%) es inferior a ${thresholdMin}% </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">202</context> <context context-type="linenumber">202</context>
@ -8034,7 +8034,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskJapan.true" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskJapan.true" datatype="html">
<source> The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% </source> <source> The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% </source>
<target state="new"> The Japan market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% </target> <target state="translated"> La contribución al mercado japonés de su inversión actual (${valueRatio}%) está dentro del rango de ${thresholdMin}% y ${thresholdMax}% </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">206</context> <context context-type="linenumber">206</context>
@ -8042,7 +8042,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskNorthAmerica" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskNorthAmerica" datatype="html">
<source>North America</source> <source>North America</source>
<target state="new">North America</target> <target state="translated">Norteamérica</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">210</context> <context context-type="linenumber">210</context>
@ -8050,7 +8050,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskNorthAmerica.false.max" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskNorthAmerica.false.max" datatype="html">
<source> The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% </source> <source> The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% </source>
<target state="new"> The North America market contribution of your current investment (${valueRatio}%) exceeds ${thresholdMax}% </target> <target state="translated"> La contribución del mercado de América del Norte de su inversión actual (${valueRatio}%) supera el ${thresholdMax}% </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">212</context> <context context-type="linenumber">212</context>
@ -8058,7 +8058,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskNorthAmerica.false.min" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskNorthAmerica.false.min" datatype="html">
<source> The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% </source> <source> The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% </source>
<target state="new"> The North America market contribution of your current investment (${valueRatio}%) is below ${thresholdMin}% </target> <target state="translated"> La contribución al mercado de América del Norte de su inversión actual (${valueRatio}%) es inferior a ${thresholdMin}% </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">216</context> <context context-type="linenumber">216</context>
@ -8066,7 +8066,7 @@
</trans-unit> </trans-unit>
<trans-unit id="rule.regionalMarketClusterRiskNorthAmerica.true" datatype="html"> <trans-unit id="rule.regionalMarketClusterRiskNorthAmerica.true" datatype="html">
<source> The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% </source> <source> The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% </source>
<target state="new"> The North America market contribution of your current investment (${valueRatio}%) is within the range of ${thresholdMin}% and ${thresholdMax}% </target> <target state="translated"> La contribución al mercado de América del Norte de su inversión actual (${valueRatio}%) está dentro del rango de ${thresholdMin}% y ${thresholdMax}% </target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">220</context> <context context-type="linenumber">220</context>
@ -8074,7 +8074,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2305116864852661861" datatype="html"> <trans-unit id="2305116864852661861" datatype="html">
<source>Find Ghostfolio on GitHub</source> <source>Find Ghostfolio on GitHub</source>
<target state="new">Find Ghostfolio on GitHub</target> <target state="translated">Encuentra Ghostfolio en GitHub</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">74</context> <context context-type="linenumber">74</context>
@ -8086,7 +8086,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5606994816647505945" datatype="html"> <trans-unit id="5606994816647505945" datatype="html">
<source>Join the Ghostfolio Slack community</source> <source>Join the Ghostfolio Slack community</source>
<target state="new">Join the Ghostfolio Slack community</target> <target state="translated">Únete a la comunidad de Ghostfolio Slack</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">84</context> <context context-type="linenumber">84</context>
@ -8094,7 +8094,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2555424753565986929" datatype="html"> <trans-unit id="2555424753565986929" datatype="html">
<source>Follow Ghostfolio on X (formerly Twitter)</source> <source>Follow Ghostfolio on X (formerly Twitter)</source>
<target state="new">Follow Ghostfolio on X (formerly Twitter)</target> <target state="translated">Siga a Ghostfolio en X (anteriormente Twitter)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">93</context> <context context-type="linenumber">93</context>
@ -8102,7 +8102,7 @@
</trans-unit> </trans-unit>
<trans-unit id="3375362149606316745" datatype="html"> <trans-unit id="3375362149606316745" datatype="html">
<source>Send an e-mail</source> <source>Send an e-mail</source>
<target state="new">Send an e-mail</target> <target state="translated">Enviar un correo electrónico</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">103</context> <context context-type="linenumber">103</context>
@ -8110,7 +8110,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5162138648470294706" datatype="html"> <trans-unit id="5162138648470294706" datatype="html">
<source>Follow Ghostfolio on LinkedIn</source> <source>Follow Ghostfolio on LinkedIn</source>
<target state="new">Follow Ghostfolio on LinkedIn</target> <target state="translated">Siga a Ghostfolio en LinkedIn</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">122</context> <context context-type="linenumber">122</context>
@ -8118,7 +8118,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4170353658096790081" datatype="html"> <trans-unit id="4170353658096790081" datatype="html">
<source>Ghostfolio is an independent &amp; bootstrapped business</source> <source>Ghostfolio is an independent &amp; bootstrapped business</source>
<target state="new">Ghostfolio is an independent &amp; bootstrapped business</target> <target state="translated">Ghostfolio es una empresa independiente y autónoma</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">132</context> <context context-type="linenumber">132</context>
@ -8126,7 +8126,7 @@
</trans-unit> </trans-unit>
<trans-unit id="1184917049575486230" datatype="html"> <trans-unit id="1184917049575486230" datatype="html">
<source>Support Ghostfolio</source> <source>Support Ghostfolio</source>
<target state="new">Support Ghostfolio</target> <target state="translated">Soporte Ghostfolio</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context> <context context-type="sourcefile">apps/client/src/app/pages/about/overview/about-overview-page.html</context>
<context context-type="linenumber">141</context> <context context-type="linenumber">141</context>

4
package-lock.json

@ -1,12 +1,12 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.185.0", "version": "2.186.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.185.0", "version": "2.186.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.185.0", "version": "2.186.0",
"homepage": "https://ghostfol.io", "homepage": "https://ghostfol.io",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio", "repository": "https://github.com/ghostfolio/ghostfolio",

Loading…
Cancel
Save