Browse Source

Merge branch 'main' into feature/holdings-in-matching-of-assets-with-ghostfolio-ai

pull/8190/head
Thomas Kaul 13 hours ago
committed by GitHub
parent
commit
d5fc143b8e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 4
      apps/api/src/app/account-balance/account-balance.service.ts
  3. 2
      apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts
  4. 2
      apps/client/src/app/components/user-account-membership/user-account-membership.html
  5. 2
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  6. 10
      apps/client/src/app/services/user/user.service.ts
  7. 7
      libs/common/src/lib/config.ts
  8. 1
      libs/common/src/lib/interfaces/user.interface.ts
  9. 1
      libs/ui/src/lib/investment-chart/index.ts
  10. 0
      libs/ui/src/lib/investment-chart/investment-chart.component.html
  11. 0
      libs/ui/src/lib/investment-chart/investment-chart.component.scss
  12. 75
      libs/ui/src/lib/investment-chart/investment-chart.component.stories.ts
  13. 11
      libs/ui/src/lib/investment-chart/investment-chart.component.ts
  14. 5
      prisma/migrations/20261014000000_added_user_id_to_unique_constraint_of_account_balance/migration.sql
  15. 2
      prisma/schema.prisma

6
CHANGELOG.md

@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- Added a _Storybook_ story for the investment chart component
### Changed
- Moved the investment chart component to `@ghostfolio/ui`
- Improved the matching of assets in the import of activities with _Ghostfolio AI_ to prefer the holdings of the user (experimental)
- Extended the holdings table by the ISIN in the _Copy AI prompt to clipboard_ actions on the analysis page and in the tool to get the portfolio of the server of the Model Context Protocol (MCP) (experimental)
- Hardened the validation of the date in the endpoint to create an account balance
@ -18,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed an exception in the authentication interceptor when the time zone of the browser is not available
- Fixed the missing `userId` in the unique constraint of the `AccountBalance` database schema
## 3.86.0 - 2026-10-13

4
apps/api/src/app/account-balance/account-balance.service.ts

@ -68,9 +68,9 @@ export class AccountBalanceService {
value: balance
},
where: {
userId,
accountId_date: {
accountId_userId_date: {
accountId,
userId,
date: resetHours(parseISO(date))
}
}

2
apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts

@ -1,4 +1,3 @@
import { GfInvestmentChartComponent } from '@ghostfolio/client/components/investment-chart/investment-chart.component';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import {
DEFAULT_DATE_RANGE,
@ -23,6 +22,7 @@ import { GfDialogFooterComponent } from '@ghostfolio/ui/dialog-footer';
import { GfDialogHeaderComponent } from '@ghostfolio/ui/dialog-header';
import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table';
import { translate } from '@ghostfolio/ui/i18n';
import { GfInvestmentChartComponent } from '@ghostfolio/ui/investment-chart';
import { DataService } from '@ghostfolio/ui/services';
import { GfTagsSelectorComponent } from '@ghostfolio/ui/tags-selector';
import { GfValueComponent } from '@ghostfolio/ui/value';

2
apps/client/src/app/components/user-account-membership/user-account-membership.html

@ -50,7 +50,7 @@
}
}
<div class="align-items-center d-flex justify-content-center mt-4">
@if (!user?.subscription?.expiresAt) {
@if (!user?.subscription?.subscribedAt) {
<a
class="mx-1"
mat-stroked-button

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

@ -1,5 +1,4 @@
import { GfBenchmarkComparatorComponent } from '@ghostfolio/client/components/benchmark-comparator/benchmark-comparator.component';
import { GfInvestmentChartComponent } from '@ghostfolio/client/components/investment-chart/investment-chart.component';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import {
DEFAULT_DATE_RANGE,
@ -25,6 +24,7 @@ import type {
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
import type { SymbolProfile } from '@ghostfolio/prisma/browser';
import { translate } from '@ghostfolio/ui/i18n';
import { GfInvestmentChartComponent } from '@ghostfolio/ui/investment-chart';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { DataService } from '@ghostfolio/ui/services';
import { GfToggleComponent } from '@ghostfolio/ui/toggle';

10
apps/client/src/app/services/user/user.service.ts

@ -151,6 +151,16 @@ export class UserService extends ObservableStore<UserStoreState> {
user.settings.retirementDate = parseISO(user.settings.retirementDate);
}
if (user.subscription?.expiresAt) {
user.subscription.expiresAt = parseISO(user.subscription.expiresAt);
}
if (user.subscription?.subscribedAt) {
user.subscription.subscribedAt = parseISO(
user.subscription.subscribedAt
);
}
this.setState({ user }, UserStoreActions.GetUser);
if (

7
libs/common/src/lib/config.ts

@ -31,13 +31,6 @@ export const secondaryColorRgb = {
b: 207
};
export const warnColorHex = '#dc3545';
export const warnColorRgb = {
r: 220,
g: 53,
b: 69
};
export const AI_ACTIVITIES_FILE_MAXIMUM_SIZE = 10 * 1024 * 1024;
export const AI_ACTIVITIES_TIMEOUT = ms('2 minutes');
export const AI_MAX_ACTIVITIES = 25;

1
libs/common/src/lib/interfaces/user.interface.ts

@ -27,6 +27,7 @@ export interface User {
subscription: {
expiresAt?: Date;
offer: SubscriptionOffer;
subscribedAt?: Date;
type: SubscriptionType;
};
tags: (Tag & { isUsed: boolean })[];

1
libs/ui/src/lib/investment-chart/index.ts

@ -0,0 +1 @@
export * from './investment-chart.component';

0
apps/client/src/app/components/investment-chart/investment-chart.component.html → libs/ui/src/lib/investment-chart/investment-chart.component.html

0
apps/client/src/app/components/investment-chart/investment-chart.component.scss → libs/ui/src/lib/investment-chart/investment-chart.component.scss

75
libs/ui/src/lib/investment-chart/investment-chart.component.stories.ts

@ -0,0 +1,75 @@
import { moduleMetadata } from '@storybook/angular';
import type { Meta, StoryObj } from '@storybook/angular';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfInvestmentChartComponent } from './investment-chart.component';
export default {
title: 'Investment Chart',
component: GfInvestmentChartComponent,
decorators: [
moduleMetadata({
imports: [NgxSkeletonLoaderModule]
})
]
} as Meta<GfInvestmentChartComponent>;
type Story = StoryObj<GfInvestmentChartComponent>;
export const PerformanceByYear: Story = {
args: {
benchmarkDataItems: [
{
date: '2015-01-01',
investment: -0.02783300898051616
},
{
date: '2016-01-01',
investment: 0.2955008663975502
},
{
date: '2017-01-01',
investment: 0.5581973009289353
},
{
date: '2018-01-01',
investment: -0.27056776062551113
},
{
date: '2019-01-01',
investment: 0.27802802888773426
},
{
date: '2020-01-01',
investment: 0.11264960377555408
},
{
date: '2021-01-01',
investment: 0.31365756351078433
},
{
date: '2022-01-01',
investment: -0.23865494728984496
},
{
date: '2023-01-01',
investment: 0.07752911954819477
},
{
date: '2024-01-01',
investment: 0.24854314905668837
},
{
date: '2025-01-01',
investment: 0.05351048565996891
},
{
date: '2026-01-01',
investment: 0.1037188655512382
}
],
benchmarkDataLabel: 'Net Performance',
groupBy: 'year',
isInPercentage: true
}
};

11
apps/client/src/app/components/investment-chart/investment-chart.component.ts → libs/ui/src/lib/investment-chart/investment-chart.component.ts

@ -12,11 +12,6 @@ import { getLocale, parseDate } from '@ghostfolio/common/helper';
import { LineChartItem } from '@ghostfolio/common/interfaces';
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface';
import { ColorScheme, GroupBy } from '@ghostfolio/common/types';
import {
getTimeSeriesTooltipOptions,
onPrefersColorSchemeChange,
registerChartConfiguration
} from '@ghostfolio/ui/chart';
import {
ChangeDetectionStrategy,
@ -47,6 +42,12 @@ import { type AnnotationOptions } from 'chartjs-plugin-annotation';
import { isFuture } from 'date-fns';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import {
getTimeSeriesTooltipOptions,
onPrefersColorSchemeChange,
registerChartConfiguration
} from '../chart';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgxSkeletonLoaderModule],

5
prisma/migrations/20261014000000_added_user_id_to_unique_constraint_of_account_balance/migration.sql

@ -0,0 +1,5 @@
-- DropIndex
DROP INDEX "AccountBalance_accountId_date_key";
-- CreateIndex
CREATE UNIQUE INDEX "AccountBalance_accountId_userId_date_key" ON "AccountBalance"("accountId", "userId", "date");

2
prisma/schema.prisma

@ -65,7 +65,7 @@ model AccountBalance {
userId String
value Float
@@unique([accountId, date])
@@unique([accountId, userId, date])
@@index([accountId])
@@index([date])
}

Loading…
Cancel
Save