Browse Source

Merge branch 'main' into task/improve-language-localization-by-translating-various-tooltips

pull/7190/head
Thomas Kaul 2 weeks ago
committed by GitHub
parent
commit
5fd083c59c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 12
      apps/api/src/services/benchmark/benchmark.service.spec.ts
  3. 8
      apps/api/src/services/benchmark/benchmark.service.ts
  4. 2
      apps/client/src/app/components/header/header.component.html
  5. 2
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
  6. 2
      libs/ui/src/lib/account-balances/account-balances.component.html
  7. 10
      libs/ui/src/lib/benchmark/benchmark.component.html
  8. 3
      libs/ui/src/lib/benchmark/benchmark.component.ts
  9. 19
      libs/ui/src/lib/fire-calculator/fire-calculator.component.html
  10. 6
      libs/ui/src/lib/fire-calculator/fire-calculator.component.ts
  11. 4
      libs/ui/src/lib/value/value.component.ts
  12. 4
      package-lock.json
  13. 2
      package.json

6
CHANGELOG.md

@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the language localization by translating various tooltips across the application - Improved the language localization by translating various tooltips across the application
## 3.19.0 - 2026-07-02 ## 3.19.1 - 2026-07-03
### Added ### Added
@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Harmonized the date picker styling across various components
- Updated the _Privacy Policy_ - Updated the _Privacy Policy_
- Updated the _Terms of Service_ - Updated the _Terms of Service_
- Improved the parsing of integer query parameters (`skip` and `take`) in the `GET api/v1/activities` endpoint - Improved the parsing of integer query parameters (`skip` and `take`) in the `GET api/v1/activities` endpoint
@ -30,6 +31,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Fixed an issue where values incorrectly rounded to negative zero in the value component
- Fixed the colorization of the change from all time high in the benchmark component when values round to zero
- Fixed the market condition of the benchmarks when values round to zero
- Fixed the validation of the data source field of an asset profile with market data - Fixed the validation of the data source field of an asset profile with market data
- Fixed a recurring issue where single-value fields were incorrectly validated as arrays in various endpoints - Fixed a recurring issue where single-value fields were incorrectly validated as arrays in various endpoints

12
apps/api/src/services/benchmark/benchmark.service.spec.ts

@ -12,4 +12,16 @@ describe('BenchmarkService', () => {
expect(benchmarkService.calculateChangeInPercentage(2, 2)).toEqual(0); expect(benchmarkService.calculateChangeInPercentage(2, 2)).toEqual(0);
expect(benchmarkService.calculateChangeInPercentage(2, 1)).toEqual(-0.5); expect(benchmarkService.calculateChangeInPercentage(2, 1)).toEqual(-0.5);
}); });
it('getMarketCondition', async () => {
expect(benchmarkService.getMarketCondition(0)).toEqual('ALL_TIME_HIGH');
expect(benchmarkService.getMarketCondition(-5.90736454893e-9)).toEqual(
'ALL_TIME_HIGH'
);
expect(benchmarkService.getMarketCondition(-0.1)).toEqual('NEUTRAL_MARKET');
expect(benchmarkService.getMarketCondition(-0.19996)).toEqual(
'BEAR_MARKET'
);
expect(benchmarkService.getMarketCondition(-0.2)).toEqual('BEAR_MARKET');
});
}); });

8
apps/api/src/services/benchmark/benchmark.service.ts

@ -24,7 +24,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client'; import { SymbolProfile } from '@prisma/client';
import { Big } from 'big.js'; import { Big } from 'big.js';
import { addHours, isAfter, subDays } from 'date-fns'; import { addHours, isAfter, subDays } from 'date-fns';
import { uniqBy } from 'lodash'; import { round, uniqBy } from 'lodash';
import ms from 'ms'; import ms from 'ms';
import { BenchmarkValue } from './interfaces/benchmark-value.interface'; import { BenchmarkValue } from './interfaces/benchmark-value.interface';
@ -220,9 +220,11 @@ export class BenchmarkService {
public getMarketCondition( public getMarketCondition(
aPerformanceInPercent: number aPerformanceInPercent: number
): Benchmark['marketCondition'] { ): Benchmark['marketCondition'] {
if (aPerformanceInPercent >= 0) { const performanceInPercent = round(aPerformanceInPercent, 4);
if (performanceInPercent >= 0) {
return 'ALL_TIME_HIGH'; return 'ALL_TIME_HIGH';
} else if (aPerformanceInPercent <= -0.2) { } else if (performanceInPercent <= -0.2) {
return 'BEAR_MARKET'; return 'BEAR_MARKET';
} else { } else {
return 'NEUTRAL_MARKET'; return 'NEUTRAL_MARKET';

2
apps/client/src/app/components/header/header.component.html

@ -332,7 +332,7 @@
</li> </li>
</ul> </ul>
} }
@if (user() === null) { @if (!user()) {
<div class="d-flex h-100 logo-container" [class.filled]="hasTabs()"> <div class="d-flex h-100 logo-container" [class.filled]="hasTabs()">
<a <a
class="align-items-center h-100 justify-content-start px-2 px-sm-3 rounded-0" class="align-items-center h-100 justify-content-start px-2 px-sm-3 rounded-0"

2
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html

@ -167,7 +167,7 @@
name="calendar-clear-outline" name="calendar-clear-outline"
/> />
</mat-datepicker-toggle> </mat-datepicker-toggle>
<mat-datepicker #date disabled="false" /> <mat-datepicker #date />
</mat-form-field> </mat-form-field>
</div> </div>
<div <div

2
libs/ui/src/lib/account-balances/account-balances.component.html

@ -22,7 +22,7 @@
[matDatepicker]="date" [matDatepicker]="date"
[max]="maxDate" [max]="maxDate"
/> />
<mat-datepicker-toggle matSuffix [for]="date"> <mat-datepicker-toggle class="mr-2" matSuffix [for]="date">
<ion-icon <ion-icon
class="text-muted" class="text-muted"
matDatepickerToggleIcon matDatepickerToggleIcon

10
libs/ui/src/lib/benchmark/benchmark.component.html

@ -135,9 +135,15 @@
class="d-inline-block justify-content-end" class="d-inline-block justify-content-end"
[class]="{ [class]="{
'text-danger': 'text-danger':
element?.performances?.allTimeHigh?.performancePercent < 0, round(
element?.performances?.allTimeHigh?.performancePercent,
4
) < 0,
'text-success': 'text-success':
element?.performances?.allTimeHigh?.performancePercent === 0 round(
element?.performances?.allTimeHigh?.performancePercent,
4
) === 0
}" }"
[isPercent]="true" [isPercent]="true"
[locale]="locale()" [locale]="locale()"

3
libs/ui/src/lib/benchmark/benchmark.component.ts

@ -33,7 +33,7 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone'; import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons'; import { addIcons } from 'ionicons';
import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; import { ellipsisHorizontal, trashOutline } from 'ionicons/icons';
import { isNumber } from 'lodash'; import { isNumber, round } from 'lodash';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component'; import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component';
@ -92,6 +92,7 @@ export class GfBenchmarkComponent {
protected isLoading = true; protected isLoading = true;
protected readonly isNumber = isNumber; protected readonly isNumber = isNumber;
protected readonly resolveMarketCondition = resolveMarketCondition; protected readonly resolveMarketCondition = resolveMarketCondition;
protected readonly round = round;
protected readonly translate = translate; protected readonly translate = translate;
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);

19
libs/ui/src/lib/fire-calculator/fire-calculator.component.html

@ -39,19 +39,26 @@
class="d-none" class="d-none"
formControlName="retirementDate" formControlName="retirementDate"
matInput matInput
[matDatepicker]="datepicker" [matDatepicker]="date"
[min]="minDate" [min]="minDate"
/> />
<mat-datepicker-toggle <mat-datepicker-toggle
matIconSuffix class="mr-2"
matSuffix
[disabled]="hasPermissionToUpdateUserSettings !== true" [disabled]="hasPermissionToUpdateUserSettings !== true"
[for]="datepicker" [for]="date"
/> >
<ion-icon
class="text-muted"
matDatepickerToggleIcon
name="calendar-clear-outline"
/>
</mat-datepicker-toggle>
<mat-datepicker <mat-datepicker
#datepicker #date
startView="multi-year" startView="multi-year"
[disabled]="hasPermissionToUpdateUserSettings !== true" [disabled]="hasPermissionToUpdateUserSettings !== true"
(monthSelected)="setMonthAndYear($event, datepicker)" (monthSelected)="setMonthAndYear($event, date)"
/> />
</mat-form-field> </mat-form-field>

6
libs/ui/src/lib/fire-calculator/fire-calculator.component.ts

@ -34,6 +34,7 @@ import {
} from '@angular/material/datepicker'; } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { IonIcon } from '@ionic/angular/standalone';
import { import {
BarController, BarController,
BarElement, BarElement,
@ -56,6 +57,8 @@ import {
startOfMonth, startOfMonth,
sub sub
} from 'date-fns'; } from 'date-fns';
import { addIcons } from 'ionicons';
import { calendarClearOutline } from 'ionicons/icons';
import { isNumber } from 'lodash'; import { isNumber } from 'lodash';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { debounceTime } from 'rxjs'; import { debounceTime } from 'rxjs';
@ -67,6 +70,7 @@ import { FireCalculatorService } from './fire-calculator.service';
imports: [ imports: [
CommonModule, CommonModule,
FormsModule, FormsModule,
IonIcon,
MatButtonModule, MatButtonModule,
MatDatepickerModule, MatDatepickerModule,
MatFormFieldModule, MatFormFieldModule,
@ -136,6 +140,8 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy {
Tooltip Tooltip
); );
addIcons({ calendarClearOutline });
this.calculatorForm.valueChanges this.calculatorForm.valueChanges
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => { .subscribe(() => {

4
libs/ui/src/lib/value/value.component.ts

@ -168,7 +168,9 @@ export class GfValueComponent implements AfterViewInit, OnChanges {
} }
} }
if (this.formattedValue === '0.00') { if (/^-?0([.,]0*)?$/.test(this.formattedValue)) {
// Remove algebraic sign of values rounding to zero
this.formattedValue = this.formattedValue.replace(/^-/, '');
this.useAbsoluteValue = true; this.useAbsoluteValue = true;
} }
} }

4
package-lock.json

@ -1,12 +1,12 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "3.19.0", "version": "3.19.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ghostfolio", "name": "ghostfolio",
"version": "3.19.0", "version": "3.19.1",
"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": "3.19.0", "version": "3.19.1",
"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