Browse Source

Merge branch 'refs/heads/fix/prefer-optional-chain' into fix/consistent-generic-constructors

pull/3985/head
dw-0 10 months ago
parent
commit
8d76e7f56b
  1. 14
      CHANGELOG.md
  2. 6
      README.md
  3. 2
      apps/api/src/app/health/health.controller.ts
  4. 28
      apps/api/src/app/portfolio/portfolio.service.ts
  5. 2
      apps/api/src/app/subscription/subscription.controller.ts
  6. 4
      apps/api/src/app/subscription/subscription.service.ts
  7. 7
      apps/api/src/app/user/update-user-setting.dto.ts
  8. 35
      apps/api/src/app/user/user.service.ts
  9. 9
      apps/api/src/services/market-data/market-data.service.ts
  10. 6
      apps/api/src/services/queues/data-gathering/data-gathering.processor.ts
  11. 18
      apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts
  12. 6
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  13. 3
      apps/client/src/app/components/header/header.component.html
  14. 7
      apps/client/src/app/components/home-holdings/home-holdings.component.ts
  15. 6
      apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts
  16. 2
      apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts
  17. 6
      apps/client/src/app/components/rule/rule.component.ts
  18. 6
      apps/client/src/app/components/rules/rules.component.ts
  19. 2
      apps/client/src/app/components/toggle/toggle.component.ts
  20. 3
      apps/client/src/app/components/user-account-membership/user-account-membership.html
  21. 5
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  22. 3
      apps/client/src/app/pages/pricing/pricing-page.html
  23. 6
      libs/common/src/lib/interfaces/index.ts
  24. 0
      libs/common/src/lib/interfaces/toggle-option.interface.ts
  25. 4
      libs/common/src/lib/interfaces/user-settings.interface.ts
  26. 0
      libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts
  27. 6
      libs/common/src/lib/types/index.ts
  28. 6
      libs/common/src/lib/types/subscription-offer.type.ts
  29. 68
      package-lock.json
  30. 6
      package.json

14
CHANGELOG.md

@ -9,18 +9,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Switched the `no-empty-function` rule from `warn` to `error` in the `eslint` configuration
- Switched the `consistent-type-definitions` rule from `warn` to `error` in the `eslint` configuration
- Switched the `prefer-function-type` rule from `warn` to `error` in the `eslint` configuration
- Switched the `consistent-type-assertions` rule from `warn` to `error` in the `eslint` configuration - Switched the `consistent-type-assertions` rule from `warn` to `error` in the `eslint` configuration
- Switched the `prefer-optional-chain` rule from `warn` to `error` in the `eslint` configuration - Switched the `prefer-optional-chain` rule from `warn` to `error` in the `eslint` configuration
- Switched the `consistent-generic-constructors` rule from `warn` to `error` in the `eslint` configuration - Switched the `consistent-generic-constructors` rule from `warn` to `error` in the `eslint` configuration
## 2.119.0 - 2024-10-26
### Changed
- Switched the `consistent-type-definitions` rule from `warn` to `error` in the `eslint` configuration
- Switched the `no-empty-function` rule from `warn` to `error` in the `eslint` configuration
- Switched the `prefer-function-type` rule from `warn` to `error` in the `eslint` configuration
- Upgraded `prisma` from version `5.20.0` to `5.21.1`
### Fixed ### Fixed
- Fixed an issue with the X-axis scale of the dividend timeline on the analysis page - Fixed an issue with the X-axis scale of the dividend timeline on the analysis page
- Fixed an issue with the X-axis scale of the investment timeline on the analysis page - Fixed an issue with the X-axis scale of the investment timeline on the analysis page
- Fixed an issue with the X-axis scale of the portfolio evolution chart on the analysis page - Fixed an issue with the X-axis scale of the portfolio evolution chart on the analysis page
- Fixed an issue in the calculation of the static portfolio analysis rule: Allocation Cluster Risk (Developed Markets)
- Fixed an issue in the calculation of the static portfolio analysis rule: Allocation Cluster Risk (Emerging Markets)
## 2.118.0 - 2024-10-23 ## 2.118.0 - 2024-10-23

6
README.md

@ -177,6 +177,12 @@ Deprecated: `GET http://localhost:3333/api/v1/auth/anonymous/<INSERT_SECURITY_TO
`200 OK` `200 OK`
```
{
"status": "OK"
}
```
### Import Activities ### Import Activities
#### Prerequisites #### Prerequisites

2
apps/api/src/app/health/health.controller.ts

@ -21,7 +21,7 @@ export class HealthController {
@Get() @Get()
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
public getHealth() { public getHealth() {
return { status: StatusCodes.OK }; return { status: getReasonPhrase(StatusCodes.OK) };
} }
@Get('data-enhancer/:name') @Get('data-enhancer/:name')

28
apps/api/src/app/portfolio/portfolio.service.ts

@ -1169,6 +1169,12 @@ export class PortfolioService {
withSummary: true withSummary: true
}); });
const marketsTotalInBaseCurrency = getSum(
Object.values(markets).map(({ valueInBaseCurrency }) => {
return new Big(valueInBaseCurrency);
})
).toNumber();
return { return {
rules: { rules: {
accountClusterRisk: accountClusterRisk:
@ -1193,12 +1199,12 @@ export class PortfolioService {
[ [
new AllocationClusterRiskDevelopedMarkets( new AllocationClusterRiskDevelopedMarkets(
this.exchangeRateDataService, this.exchangeRateDataService,
summary.currentValueInBaseCurrency, marketsTotalInBaseCurrency,
markets.developedMarkets.valueInBaseCurrency markets.developedMarkets.valueInBaseCurrency
), ),
new AllocationClusterRiskEmergingMarkets( new AllocationClusterRiskEmergingMarkets(
this.exchangeRateDataService, this.exchangeRateDataService,
summary.currentValueInBaseCurrency, marketsTotalInBaseCurrency,
markets.emergingMarkets.valueInBaseCurrency markets.emergingMarkets.valueInBaseCurrency
) )
], ],
@ -1358,20 +1364,20 @@ export class PortfolioService {
} }
} }
const marketsTotal = const marketsTotalInBaseCurrency = getSum(
markets.developedMarkets.valueInBaseCurrency + Object.values(markets).map(({ valueInBaseCurrency }) => {
markets.emergingMarkets.valueInBaseCurrency + return new Big(valueInBaseCurrency);
markets.otherMarkets.valueInBaseCurrency + })
markets[UNKNOWN_KEY].valueInBaseCurrency; ).toNumber();
markets.developedMarkets.valueInPercentage = markets.developedMarkets.valueInPercentage =
markets.developedMarkets.valueInBaseCurrency / marketsTotal; markets.developedMarkets.valueInBaseCurrency / marketsTotalInBaseCurrency;
markets.emergingMarkets.valueInPercentage = markets.emergingMarkets.valueInPercentage =
markets.emergingMarkets.valueInBaseCurrency / marketsTotal; markets.emergingMarkets.valueInBaseCurrency / marketsTotalInBaseCurrency;
markets.otherMarkets.valueInPercentage = markets.otherMarkets.valueInPercentage =
markets.otherMarkets.valueInBaseCurrency / marketsTotal; markets.otherMarkets.valueInBaseCurrency / marketsTotalInBaseCurrency;
markets[UNKNOWN_KEY].valueInPercentage = markets[UNKNOWN_KEY].valueInPercentage =
markets[UNKNOWN_KEY].valueInBaseCurrency / marketsTotal; markets[UNKNOWN_KEY].valueInBaseCurrency / marketsTotalInBaseCurrency;
const marketsAdvancedTotal = const marketsAdvancedTotal =
marketsAdvanced.asiaPacific.valueInBaseCurrency + marketsAdvanced.asiaPacific.valueInBaseCurrency +

2
apps/api/src/app/subscription/subscription.controller.ts

@ -113,7 +113,7 @@ export class SubscriptionController {
@Post('stripe/checkout-session') @Post('stripe/checkout-session')
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async createCheckoutSession( public async createCheckoutSession(
@Body() { couponId, priceId }: { couponId: string; priceId: string } @Body() { couponId, priceId }: { couponId?: string; priceId: string }
) { ) {
try { try {
return this.subscriptionService.createCheckoutSession({ return this.subscriptionService.createCheckoutSession({

4
apps/api/src/app/subscription/subscription.service.ts

@ -124,7 +124,9 @@ export class SubscriptionService {
let offer: SubscriptionOffer = price ? 'renewal' : 'default'; let offer: SubscriptionOffer = price ? 'renewal' : 'default';
if (isBefore(createdAt, parseDate('2023-01-01'))) { if (isBefore(createdAt, parseDate('2023-01-01'))) {
offer = 'renewal-early-bird'; offer = 'renewal-early-bird-2023';
} else if (isBefore(createdAt, parseDate('2024-01-01'))) {
offer = 'renewal-early-bird-2024';
} }
return { return {

7
apps/api/src/app/user/update-user-setting.dto.ts

@ -1,9 +1,10 @@
import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code';
import { XRayRulesSettings } from '@ghostfolio/common/interfaces';
import type { import type {
ColorScheme, ColorScheme,
DateRange, DateRange,
HoldingsViewMode, HoldingsViewMode,
ViewMode, ViewMode
XRayRulesSettings
} from '@ghostfolio/common/types'; } from '@ghostfolio/common/types';
import { import {
@ -17,8 +18,6 @@ import {
} from 'class-validator'; } from 'class-validator';
import { eachYearOfInterval, format } from 'date-fns'; import { eachYearOfInterval, format } from 'date-fns';
import { IsCurrencyCode } from '../../validators/is-currency-code';
export class UpdateUserSettingDto { export class UpdateUserSettingDto {
@IsNumber() @IsNumber()
@IsOptional() @IsOptional()

35
apps/api/src/app/user/user.service.ts

@ -1,3 +1,20 @@
import { OrderService } from '@ghostfolio/api/app/order/order.service';
import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service';
import { environment } from '@ghostfolio/api/environments/environment';
import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event';
import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/current-investment';
import { AccountClusterRiskSingleAccount } from '@ghostfolio/api/models/rules/account-cluster-risk/single-account';
import { AllocationClusterRiskDevelopedMarkets } from '@ghostfolio/api/models/rules/allocation-cluster-risk/developed-markets';
import { AllocationClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/allocation-cluster-risk/emerging-markets';
import { CurrencyClusterRiskBaseCurrencyCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/base-currency-current-investment';
import { CurrencyClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/current-investment';
import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup';
import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import { TagService } from '@ghostfolio/api/services/tag/tag.service';
import { import {
DEFAULT_CURRENCY, DEFAULT_CURRENCY,
DEFAULT_LANGUAGE_CODE, DEFAULT_LANGUAGE_CODE,
@ -23,24 +40,6 @@ import { Prisma, Role, User } from '@prisma/client';
import { differenceInDays } from 'date-fns'; import { differenceInDays } from 'date-fns';
import { sortBy, without } from 'lodash'; import { sortBy, without } from 'lodash';
import { environment } from '../../environments/environment';
import { PortfolioChangedEvent } from '../../events/portfolio-changed.event';
import { AccountClusterRiskCurrentInvestment } from '../../models/rules/account-cluster-risk/current-investment';
import { AccountClusterRiskSingleAccount } from '../../models/rules/account-cluster-risk/single-account';
import { AllocationClusterRiskDevelopedMarkets } from '../../models/rules/allocation-cluster-risk/developed-markets';
import { AllocationClusterRiskEmergingMarkets } from '../../models/rules/allocation-cluster-risk/emerging-markets';
import { CurrencyClusterRiskBaseCurrencyCurrentInvestment } from '../../models/rules/currency-cluster-risk/base-currency-current-investment';
import { CurrencyClusterRiskCurrentInvestment } from '../../models/rules/currency-cluster-risk/current-investment';
import { EmergencyFundSetup } from '../../models/rules/emergency-fund/emergency-fund-setup';
import { FeeRatioInitialInvestment } from '../../models/rules/fees/fee-ratio-initial-investment';
import { ConfigurationService } from '../../services/configuration/configuration.service';
import { I18nService } from '../../services/i18n/i18n.service';
import { PrismaService } from '../../services/prisma/prisma.service';
import { PropertyService } from '../../services/property/property.service';
import { TagService } from '../../services/tag/tag.service';
import { OrderService } from '../order/order.service';
import { SubscriptionService } from '../subscription/subscription.service';
const crypto = require('crypto'); const crypto = require('crypto');
@Injectable() @Injectable()

9
apps/api/src/services/market-data/market-data.service.ts

@ -1,3 +1,7 @@
import { UpdateMarketDataDto } from '@ghostfolio/api/app/admin/update-market-data.dto';
import { DateQuery } from '@ghostfolio/api/app/portfolio/interfaces/date-query.interface';
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { resetHours } from '@ghostfolio/common/helper'; import { resetHours } from '@ghostfolio/common/helper';
import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces'; import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
@ -9,11 +13,6 @@ import {
Prisma Prisma
} from '@prisma/client'; } from '@prisma/client';
import { UpdateMarketDataDto } from '../../app/admin/update-market-data.dto';
import { DateQuery } from '../../app/portfolio/interfaces/date-query.interface';
import { IDataGatheringItem } from '../interfaces/interfaces';
import { PrismaService } from '../prisma/prisma.service';
@Injectable() @Injectable()
export class MarketDataService { export class MarketDataService {
public constructor(private readonly prismaService: PrismaService) {} public constructor(private readonly prismaService: PrismaService) {}

6
apps/api/src/services/queues/data-gathering/data-gathering.processor.ts

@ -1,3 +1,6 @@
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { import {
DATA_GATHERING_QUEUE, DATA_GATHERING_QUEUE,
DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY, DEFAULT_PROCESSOR_GATHER_ASSET_PROFILE_CONCURRENCY,
@ -22,9 +25,6 @@ import {
parseISO parseISO
} from 'date-fns'; } from 'date-fns';
import { DataProviderService } from '../../data-provider/data-provider.service';
import { IDataGatheringItem } from '../../interfaces/interfaces';
import { MarketDataService } from '../../market-data/market-data.service';
import { DataGatheringService } from './data-gathering.service'; import { DataGatheringService } from './data-gathering.service';
@Injectable() @Injectable()

18
apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts

@ -1,3 +1,12 @@
import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service';
import { OrderService } from '@ghostfolio/api/app/order/order.service';
import {
PerformanceCalculationType,
PortfolioCalculatorFactory
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface';
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { import {
CACHE_TTL_INFINITE, CACHE_TTL_INFINITE,
DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_CONCURRENCY, DEFAULT_PROCESSOR_PORTFOLIO_SNAPSHOT_COMPUTATION_CONCURRENCY,
@ -10,15 +19,6 @@ import { Injectable, Logger } from '@nestjs/common';
import { Job } from 'bull'; import { Job } from 'bull';
import { addMilliseconds } from 'date-fns'; import { addMilliseconds } from 'date-fns';
import { AccountBalanceService } from '../../../app/account-balance/account-balance.service';
import { OrderService } from '../../../app/order/order.service';
import {
PerformanceCalculationType,
PortfolioCalculatorFactory
} from '../../../app/portfolio/calculator/portfolio-calculator.factory';
import { PortfolioSnapshotValue } from '../../../app/portfolio/interfaces/snapshot-value.interface';
import { RedisCacheService } from '../../../app/redis-cache/redis-cache.service';
import { ConfigurationService } from '../../configuration/configuration.service';
import { IPortfolioSnapshotQueueJob } from './interfaces/portfolio-snapshot-queue-job.interface'; import { IPortfolioSnapshotQueueJob } from './interfaces/portfolio-snapshot-queue-job.interface';
@Injectable() @Injectable()

6
apps/client/src/app/components/admin-market-data/admin-market-data.component.ts

@ -1,3 +1,6 @@
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';
import { import {
DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE,
ghostfolioScraperApiSymbolPrefix ghostfolioScraperApiSymbolPrefix
@ -34,9 +37,6 @@ import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators'; import { distinctUntilChanged, switchMap, takeUntil } from 'rxjs/operators';
import { AdminService } from '../../services/admin.service';
import { DataService } from '../../services/data.service';
import { UserService } from '../../services/user/user.service';
import { AdminMarketDataService } from './admin-market-data.service'; import { AdminMarketDataService } from './admin-market-data.service';
import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component'; import { AssetProfileDialog } from './asset-profile-dialog/asset-profile-dialog.component';
import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces'; import { AssetProfileDialogParams } from './asset-profile-dialog/interfaces/interfaces';

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

@ -180,7 +180,8 @@
<ng-container i18n>Upgrade Plan</ng-container> <ng-container i18n>Upgrade Plan</ng-container>
} @else if ( } @else if (
user.subscription.offer === 'renewal' || user.subscription.offer === 'renewal' ||
user.subscription.offer === 'renewal-early-bird' user.subscription.offer === 'renewal-early-bird-2023' ||
user.subscription.offer === 'renewal-early-bird-2024'
) { ) {
<ng-container i18n>Renew Plan</ng-container> <ng-container i18n>Renew Plan</ng-container>
} }

7
apps/client/src/app/components/home-holdings/home-holdings.component.ts

@ -4,14 +4,11 @@ import { UserService } from '@ghostfolio/client/services/user/user.service';
import { import {
AssetProfileIdentifier, AssetProfileIdentifier,
PortfolioPosition, PortfolioPosition,
ToggleOption,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { import { HoldingType, HoldingsViewMode } from '@ghostfolio/common/types';
HoldingType,
HoldingsViewMode,
ToggleOption
} from '@ghostfolio/common/types';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';

6
apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts

@ -1,5 +1,7 @@
import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; import {
import { XRayRulesSettings } from '@ghostfolio/common/types'; PortfolioReportRule,
XRayRulesSettings
} from '@ghostfolio/common/interfaces';
export interface IRuleSettingsDialogParams { export interface IRuleSettingsDialogParams {
rule: PortfolioReportRule; rule: PortfolioReportRule;

2
apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts

@ -1,4 +1,4 @@
import { XRayRulesSettings } from '@ghostfolio/common/types'; import { XRayRulesSettings } from '@ghostfolio/common/interfaces';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core'; import { Component, Inject } from '@angular/core';

6
apps/client/src/app/components/rule/rule.component.ts

@ -1,7 +1,9 @@
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; import {
import { XRayRulesSettings } from '@ghostfolio/common/types'; PortfolioReportRule,
XRayRulesSettings
} from '@ghostfolio/common/interfaces';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,

6
apps/client/src/app/components/rules/rules.component.ts

@ -1,6 +1,8 @@
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { PortfolioReportRule } from '@ghostfolio/common/interfaces'; import {
import { XRayRulesSettings } from '@ghostfolio/common/types'; PortfolioReportRule,
XRayRulesSettings
} from '@ghostfolio/common/interfaces';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,

2
apps/client/src/app/components/toggle/toggle.component.ts

@ -1,4 +1,4 @@
import { ToggleOption } from '@ghostfolio/common/types'; import { ToggleOption } from '@ghostfolio/common/interfaces';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,

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

@ -16,7 +16,8 @@
<ng-container i18n>Upgrade Plan</ng-container> <ng-container i18n>Upgrade Plan</ng-container>
} @else if ( } @else if (
user.subscription.offer === 'renewal' || user.subscription.offer === 'renewal' ||
user.subscription.offer === 'renewal-early-bird' user.subscription.offer === 'renewal-early-bird-2023' ||
user.subscription.offer === 'renewal-early-bird-2024'
) { ) {
<ng-container i18n>Renew Plan</ng-container> <ng-container i18n>Renew Plan</ng-container>
} }

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

@ -4,13 +4,14 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/imperso
import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UserService } from '@ghostfolio/client/services/user/user.service';
import { import {
HistoricalDataItem, HistoricalDataItem,
InvestmentItem,
PortfolioInvestments, PortfolioInvestments,
PortfolioPerformance, PortfolioPerformance,
PortfolioPosition, PortfolioPosition,
ToggleOption,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; import { GroupBy } from '@ghostfolio/common/types';
import { GroupBy, ToggleOption } from '@ghostfolio/common/types';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';

3
apps/client/src/app/pages/pricing/pricing-page.html

@ -278,7 +278,8 @@
<ng-container i18n>Upgrade Plan</ng-container> <ng-container i18n>Upgrade Plan</ng-container>
} @else if ( } @else if (
user.subscription.offer === 'renewal' || user.subscription.offer === 'renewal' ||
user.subscription.offer === 'renewal-early-bird' user.subscription.offer === 'renewal-early-bird-2023' ||
user.subscription.offer === 'renewal-early-bird-2024'
) { ) {
<ng-container i18n>Renew Plan</ng-container> <ng-container i18n>Renew Plan</ng-container>
} }

6
libs/common/src/lib/interfaces/index.ts

@ -50,8 +50,10 @@ import type { Subscription } from './subscription.interface';
import type { SymbolMetrics } from './symbol-metrics.interface'; import type { SymbolMetrics } from './symbol-metrics.interface';
import type { SystemMessage } from './system-message.interface'; import type { SystemMessage } from './system-message.interface';
import type { TabConfiguration } from './tab-configuration.interface'; import type { TabConfiguration } from './tab-configuration.interface';
import type { ToggleOption } from './toggle-option.interface';
import type { UserSettings } from './user-settings.interface'; import type { UserSettings } from './user-settings.interface';
import type { User } from './user.interface'; import type { User } from './user.interface';
import type { XRayRulesSettings } from './x-ray-rules-settings.interface';
export { export {
Access, Access,
@ -104,6 +106,8 @@ export {
Subscription, Subscription,
SymbolMetrics, SymbolMetrics,
TabConfiguration, TabConfiguration,
ToggleOption,
User, User,
UserSettings UserSettings,
XRayRulesSettings
}; };

0
libs/common/src/lib/types/toggle-option.type.ts → libs/common/src/lib/interfaces/toggle-option.interface.ts

4
libs/common/src/lib/interfaces/user-settings.interface.ts

@ -1,9 +1,9 @@
import { XRayRulesSettings } from '@ghostfolio/common/interfaces/x-ray-rules-settings.interface';
import { import {
ColorScheme, ColorScheme,
DateRange, DateRange,
HoldingsViewMode, HoldingsViewMode,
ViewMode, ViewMode
XRayRulesSettings
} from '@ghostfolio/common/types'; } from '@ghostfolio/common/types';
export interface UserSettings { export interface UserSettings {

0
libs/common/src/lib/types/x-ray-rules-settings.type.ts → libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts

6
libs/common/src/lib/types/index.ts

@ -16,10 +16,8 @@ import type { Market } from './market.type';
import type { OrderWithAccount } from './order-with-account.type'; import type { OrderWithAccount } from './order-with-account.type';
import type { RequestWithUser } from './request-with-user.type'; import type { RequestWithUser } from './request-with-user.type';
import type { SubscriptionOffer } from './subscription-offer.type'; import type { SubscriptionOffer } from './subscription-offer.type';
import type { ToggleOption } from './toggle-option.type';
import type { UserWithSettings } from './user-with-settings.type'; import type { UserWithSettings } from './user-with-settings.type';
import type { ViewMode } from './view-mode.type'; import type { ViewMode } from './view-mode.type';
import type { XRayRulesSettings } from './x-ray-rules-settings.type';
export type { export type {
AccessType, AccessType,
@ -40,8 +38,6 @@ export type {
OrderWithAccount, OrderWithAccount,
RequestWithUser, RequestWithUser,
SubscriptionOffer, SubscriptionOffer,
ToggleOption,
UserWithSettings, UserWithSettings,
ViewMode, ViewMode
XRayRulesSettings
}; };

6
libs/common/src/lib/types/subscription-offer.type.ts

@ -1 +1,5 @@
export type SubscriptionOffer = 'default' | 'renewal' | 'renewal-early-bird'; export type SubscriptionOffer =
| 'default'
| 'renewal'
| 'renewal-early-bird-2023'
| 'renewal-early-bird-2024';

68
package-lock.json

@ -1,12 +1,12 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.117.0", "version": "2.118.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.117.0", "version": "2.118.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
@ -40,7 +40,7 @@
"@nestjs/platform-express": "10.1.3", "@nestjs/platform-express": "10.1.3",
"@nestjs/schedule": "3.0.2", "@nestjs/schedule": "3.0.2",
"@nestjs/serve-static": "4.0.0", "@nestjs/serve-static": "4.0.0",
"@prisma/client": "5.20.0", "@prisma/client": "5.21.1",
"@simplewebauthn/browser": "9.0.1", "@simplewebauthn/browser": "9.0.1",
"@simplewebauthn/server": "9.0.3", "@simplewebauthn/server": "9.0.3",
"@stripe/stripe-js": "3.5.0", "@stripe/stripe-js": "3.5.0",
@ -150,7 +150,7 @@
"nx": "20.0.3", "nx": "20.0.3",
"prettier": "3.3.3", "prettier": "3.3.3",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "5.20.0", "prisma": "5.21.1",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"replace-in-file": "7.0.1", "replace-in-file": "7.0.1",
@ -8753,9 +8753,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@prisma/client": { "node_modules/@prisma/client": {
"version": "5.20.0", "version": "5.21.1",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.20.0.tgz", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.21.1.tgz",
"integrity": "sha512-CLv55ZuMuUawMsxoqxGtLT3bEZoa2W8L3Qnp6rDIFWy+ZBrUcOFKdoeGPSnbBqxc3SkdxJrF+D1veN/WNynZYA==", "integrity": "sha512-3n+GgbAZYjaS/k0M03yQsQfR1APbr411r74foknnsGpmhNKBG49VuUkxIU6jORgvJPChoD4WC4PqoHImN1FP0w==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -8771,53 +8771,53 @@
} }
}, },
"node_modules/@prisma/debug": { "node_modules/@prisma/debug": {
"version": "5.20.0", "version": "5.21.1",
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.20.0.tgz", "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.21.1.tgz",
"integrity": "sha512-oCx79MJ4HSujokA8S1g0xgZUGybD4SyIOydoHMngFYiwEwYDQ5tBQkK5XoEHuwOYDKUOKRn/J0MEymckc4IgsQ==", "integrity": "sha512-uY8SAhcnORhvgtOrNdvWS98Aq/nkQ9QDUxrWAgW8XrCZaI3j2X7zb7Xe6GQSh6xSesKffFbFlkw0c2luHQviZA==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/@prisma/engines": { "node_modules/@prisma/engines": {
"version": "5.20.0", "version": "5.21.1",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.20.0.tgz", "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.21.1.tgz",
"integrity": "sha512-DtqkP+hcZvPEbj8t8dK5df2b7d3B8GNauKqaddRRqQBBlgkbdhJkxhoJTrOowlS3vaRt2iMCkU0+CSNn0KhqAQ==", "integrity": "sha512-hGVTldUkIkTwoV8//hmnAAiAchi4oMEKD3aW5H2RrnI50tTdwza7VQbTTAyN3OIHWlK5DVg6xV7X8N/9dtOydA==",
"devOptional": true, "devOptional": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@prisma/debug": "5.20.0", "@prisma/debug": "5.21.1",
"@prisma/engines-version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", "@prisma/engines-version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36",
"@prisma/fetch-engine": "5.20.0", "@prisma/fetch-engine": "5.21.1",
"@prisma/get-platform": "5.20.0" "@prisma/get-platform": "5.21.1"
} }
}, },
"node_modules/@prisma/engines-version": { "node_modules/@prisma/engines-version": {
"version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", "version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284.tgz", "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36.tgz",
"integrity": "sha512-Lg8AS5lpi0auZe2Mn4gjuCg081UZf88k3cn0RCwHgR+6cyHHpttPZBElJTHf83ZGsRNAmVCZCfUGA57WB4u4JA==", "integrity": "sha512-qvnEflL0//lh44S/T9NcvTMxfyowNeUxTunPcDfKPjyJNrCNf2F1zQLcUv5UHAruECpX+zz21CzsC7V2xAeM7Q==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/@prisma/fetch-engine": { "node_modules/@prisma/fetch-engine": {
"version": "5.20.0", "version": "5.21.1",
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.20.0.tgz", "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.21.1.tgz",
"integrity": "sha512-JVcaPXC940wOGpCOwuqQRTz6I9SaBK0c1BAyC1pcz9xBi+dzFgUu3G/p9GV1FhFs9OKpfSpIhQfUJE9y00zhqw==", "integrity": "sha512-70S31vgpCGcp9J+mh/wHtLCkVezLUqe/fGWk3J3JWZIN7prdYSlr1C0niaWUyNK2VflLXYi8kMjAmSxUVq6WGQ==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@prisma/debug": "5.20.0", "@prisma/debug": "5.21.1",
"@prisma/engines-version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", "@prisma/engines-version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36",
"@prisma/get-platform": "5.20.0" "@prisma/get-platform": "5.21.1"
} }
}, },
"node_modules/@prisma/get-platform": { "node_modules/@prisma/get-platform": {
"version": "5.20.0", "version": "5.21.1",
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.20.0.tgz", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.21.1.tgz",
"integrity": "sha512-8/+CehTZZNzJlvuryRgc77hZCWrUDYd/PmlZ7p2yNXtmf2Una4BWnTbak3us6WVdqoz5wmptk6IhsXdG2v5fmA==", "integrity": "sha512-sRxjL3Igst3ct+e8ya/x//cDXmpLbZQ5vfps2N4tWl4VGKQAmym77C/IG/psSMsQKszc8uFC/q1dgmKFLUgXZQ==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@prisma/debug": "5.20.0" "@prisma/debug": "5.21.1"
} }
}, },
"node_modules/@redis/bloom": { "node_modules/@redis/bloom": {
@ -29794,14 +29794,14 @@
} }
}, },
"node_modules/prisma": { "node_modules/prisma": {
"version": "5.20.0", "version": "5.21.1",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.20.0.tgz", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.21.1.tgz",
"integrity": "sha512-6obb3ucKgAnsGS9x9gLOe8qa51XxvJ3vLQtmyf52CTey1Qcez3A6W6ROH5HIz5Q5bW+0VpmZb8WBohieMFGpig==", "integrity": "sha512-PB+Iqzld/uQBPaaw2UVIk84kb0ITsLajzsxzsadxxl54eaU5Gyl2/L02ysivHxK89t7YrfQJm+Ggk37uvM70oQ==",
"devOptional": true, "devOptional": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@prisma/engines": "5.20.0" "@prisma/engines": "5.21.1"
}, },
"bin": { "bin": {
"prisma": "build/index.js" "prisma": "build/index.js"

6
package.json

@ -1,6 +1,6 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.118.0", "version": "2.119.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",
@ -86,7 +86,7 @@
"@nestjs/platform-express": "10.1.3", "@nestjs/platform-express": "10.1.3",
"@nestjs/schedule": "3.0.2", "@nestjs/schedule": "3.0.2",
"@nestjs/serve-static": "4.0.0", "@nestjs/serve-static": "4.0.0",
"@prisma/client": "5.20.0", "@prisma/client": "5.21.1",
"@simplewebauthn/browser": "9.0.1", "@simplewebauthn/browser": "9.0.1",
"@simplewebauthn/server": "9.0.3", "@simplewebauthn/server": "9.0.3",
"@stripe/stripe-js": "3.5.0", "@stripe/stripe-js": "3.5.0",
@ -196,7 +196,7 @@
"nx": "20.0.3", "nx": "20.0.3",
"prettier": "3.3.3", "prettier": "3.3.3",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "5.20.0", "prisma": "5.21.1",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"replace-in-file": "7.0.1", "replace-in-file": "7.0.1",

Loading…
Cancel
Save