diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ef2f042b..2bf6f6199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Improved the mobile layout of the benchmark comparator +- Migrated the date range setting from the locale storage to the user settings +- Refactored the `currency` and `view mode` in the user settings ## 1.189.0 - 08.09.2022 diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index cae6d7a24..d5b938283 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -5,7 +5,6 @@ import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.s import { PortfolioOrder } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-order.interface'; import { TimelineSpecification } from '@ghostfolio/api/app/portfolio/interfaces/timeline-specification.interface'; import { TransactionPoint } from '@ghostfolio/api/app/portfolio/interfaces/transaction-point.interface'; -import { UserSettings } from '@ghostfolio/api/app/user/interfaces/user-settings.interface'; import { UserService } from '@ghostfolio/api/app/user/user.service'; import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/current-investment'; import { AccountClusterRiskInitialInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/initial-investment'; @@ -35,7 +34,8 @@ import { PortfolioReport, PortfolioSummary, Position, - TimelinePosition + TimelinePosition, + UserSettings } from '@ghostfolio/common/interfaces'; import { InvestmentItem } from '@ghostfolio/common/interfaces/investment-item.interface'; import type { @@ -1045,7 +1045,7 @@ export class PortfolioService { accounts ) ], - { baseCurrency: currency } + this.request.user.Settings.settings ), currencyClusterRisk: await this.rulesService.evaluate( [ @@ -1066,7 +1066,7 @@ export class PortfolioService { currentPositions ) ], - { baseCurrency: currency } + this.request.user.Settings.settings ), fees: await this.rulesService.evaluate( [ @@ -1076,7 +1076,7 @@ export class PortfolioService { this.getFees(orders).toNumber() ) ], - { baseCurrency: currency } + this.request.user.Settings.settings ) } }; diff --git a/apps/api/src/app/portfolio/rules.service.ts b/apps/api/src/app/portfolio/rules.service.ts index e3767c50f..8d46b3708 100644 --- a/apps/api/src/app/portfolio/rules.service.ts +++ b/apps/api/src/app/portfolio/rules.service.ts @@ -1,5 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; @Injectable() @@ -8,7 +9,7 @@ export class RulesService { public async evaluate( aRules: Rule[], - aUserSettings: { baseCurrency: string } + aUserSettings: UserSettings ) { return aRules .filter((rule) => { diff --git a/apps/api/src/app/user/interfaces/user-settings-params.interface.ts b/apps/api/src/app/user/interfaces/user-settings-params.interface.ts deleted file mode 100644 index 2df6285f6..000000000 --- a/apps/api/src/app/user/interfaces/user-settings-params.interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ViewMode } from '@prisma/client'; - -export interface UserSettingsParams { - currency?: string; - userId: string; - viewMode?: ViewMode; -} diff --git a/apps/api/src/app/user/interfaces/user-settings.interface.ts b/apps/api/src/app/user/interfaces/user-settings.interface.ts deleted file mode 100644 index 8f8878079..000000000 --- a/apps/api/src/app/user/interfaces/user-settings.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface UserSettings { - emergencyFund?: number; - locale?: string; - isRestrictedView?: boolean; -} 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 1449bd64f..de3e9d658 100644 --- a/apps/api/src/app/user/update-user-setting.dto.ts +++ b/apps/api/src/app/user/update-user-setting.dto.ts @@ -1,6 +1,22 @@ -import { IsBoolean, IsNumber, IsOptional, IsString } from 'class-validator'; +import type { DateRange } from '@ghostfolio/common/types'; +import { ViewMode } from '@prisma/client'; +import { + IsBoolean, + IsIn, + IsNumber, + IsOptional, + IsString +} from 'class-validator'; export class UpdateUserSettingDto { + @IsOptional() + @IsString() + baseCurrency?: string; + + @IsIn(['1d', '1y', '5y', 'max', 'ytd']) + @IsOptional() + dateRange?: DateRange; + @IsNumber() @IsOptional() emergencyFund?: number; @@ -24,4 +40,8 @@ export class UpdateUserSettingDto { @IsNumber() @IsOptional() savingsRate?: number; + + @IsIn(['DEFAULT', 'ZEN']) + @IsOptional() + viewMode?: ViewMode; } diff --git a/apps/api/src/app/user/update-user-settings.dto.ts b/apps/api/src/app/user/update-user-settings.dto.ts deleted file mode 100644 index 6f7c6338e..000000000 --- a/apps/api/src/app/user/update-user-settings.dto.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ViewMode } from '@prisma/client'; -import { IsString } from 'class-validator'; - -export class UpdateUserSettingsDto { - @IsString() - baseCurrency: string; - - @IsString() - viewMode: ViewMode; -} diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index e79f61dd4..aa7db57ed 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -1,7 +1,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { PROPERTY_IS_READ_ONLY_MODE } from '@ghostfolio/common/config'; -import { User } from '@ghostfolio/common/interfaces'; +import { User, UserSettings } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import type { RequestWithUser } from '@ghostfolio/common/types'; import { @@ -24,10 +24,7 @@ import { User as UserModel } from '@prisma/client'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { UserItem } from './interfaces/user-item.interface'; -import { UserSettingsParams } from './interfaces/user-settings-params.interface'; -import { UserSettings } from './interfaces/user-settings.interface'; import { UpdateUserSettingDto } from './update-user-setting.dto'; -import { UpdateUserSettingsDto } from './update-user-settings.dto'; import { UserService } from './user.service'; @Controller('user') @@ -130,33 +127,4 @@ export class UserController { userId: this.request.user.id }); } - - @Put('settings') - @UseGuards(AuthGuard('jwt')) - public async updateUserSettings(@Body() data: UpdateUserSettingsDto) { - if ( - !hasPermission( - this.request.user.permissions, - permissions.updateUserSettings - ) - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - - const userSettings: UserSettingsParams = { - currency: data.baseCurrency, - userId: this.request.user.id - }; - - if ( - hasPermission(this.request.user.permissions, permissions.updateViewMode) - ) { - userSettings.viewMode = data.viewMode; - } - - return await this.userService.updateUserSettings(userSettings); - } } diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 49159532b..9ff37de89 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -4,19 +4,20 @@ import { PrismaService } from '@ghostfolio/api/services/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { TagService } from '@ghostfolio/api/services/tag/tag.service'; import { PROPERTY_IS_READ_ONLY_MODE, locale } from '@ghostfolio/common/config'; -import { User as IUser, UserWithSettings } from '@ghostfolio/common/interfaces'; +import { + User as IUser, + UserSettings, + UserWithSettings +} from '@ghostfolio/common/interfaces'; import { getPermissions, hasRole, permissions } from '@ghostfolio/common/permissions'; import { Injectable } from '@nestjs/common'; -import { Prisma, Role, User, ViewMode } from '@prisma/client'; +import { Prisma, Role, User } from '@prisma/client'; import { sortBy } from 'lodash'; -import { UserSettingsParams } from './interfaces/user-settings-params.interface'; -import { UserSettings } from './interfaces/user-settings.interface'; - const crypto = require('crypto'); @Injectable() @@ -68,10 +69,8 @@ export class UserService { }), accounts: Account, settings: { - ...(Settings.settings), - baseCurrency: Settings?.currency ?? UserService.DEFAULT_CURRENCY, - locale: (Settings.settings)?.locale ?? aLocale, - viewMode: Settings?.viewMode ?? ViewMode.DEFAULT + ...((Settings.settings)), + locale: ((Settings.settings))?.locale ?? aLocale } }; } @@ -89,7 +88,10 @@ export class UserService { } public isRestrictedView(aUser: UserWithSettings) { - return (aUser.Settings.settings as UserSettings)?.isRestrictedView ?? false; + return ( + (aUser.Settings.settings as unknown as UserSettings)?.isRestrictedView ?? + false + ); } public async user( @@ -126,21 +128,37 @@ export class UserService { }; if (user?.Settings) { - if (!user.Settings.currency) { - // Set default currency if needed - user.Settings.currency = UserService.DEFAULT_CURRENCY; + if (!user.Settings.settings) { + user.Settings.settings = {}; } } else if (user) { // Set default settings if needed user.Settings = { - currency: UserService.DEFAULT_CURRENCY, - settings: null, + currency: null, + settings: {}, updatedAt: new Date(), userId: user?.id, - viewMode: ViewMode.DEFAULT + viewMode: 'DEFAULT' }; } + // Set default value for base currency + if (!(user.Settings.settings as UserSettings)?.baseCurrency) { + (user.Settings.settings as UserSettings).baseCurrency = + UserService.DEFAULT_CURRENCY; + } + + // Set default value for date range + (user.Settings.settings as UserSettings).dateRange = + (user.Settings.settings as UserSettings).viewMode === 'ZEN' + ? 'max' + : (user.Settings.settings as UserSettings)?.dateRange ?? 'max'; + + // Set default value for view mode + if (!(user.Settings.settings as UserSettings).viewMode) { + (user.Settings.settings as UserSettings).viewMode = 'DEFAULT'; + } + if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { user.subscription = this.subscriptionService.getSubscription(Subscription); @@ -295,7 +313,7 @@ export class UserService { userId: string; userSettings: UserSettings; }) { - const settings = userSettings as Prisma.JsonObject; + const settings = userSettings as unknown as Prisma.JsonObject; await this.prismaService.settings.upsert({ create: { @@ -317,33 +335,6 @@ export class UserService { return; } - public async updateUserSettings({ - currency, - userId, - viewMode - }: UserSettingsParams) { - await this.prismaService.settings.upsert({ - create: { - currency, - User: { - connect: { - id: userId - } - }, - viewMode - }, - update: { - currency, - viewMode - }, - where: { - userId: userId - } - }); - - return; - } - private getRandomString(length: number) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; const result = []; diff --git a/apps/api/src/models/interfaces/rule.interface.ts b/apps/api/src/models/interfaces/rule.interface.ts index d91d1ff5c..5dcd42317 100644 --- a/apps/api/src/models/interfaces/rule.interface.ts +++ b/apps/api/src/models/interfaces/rule.interface.ts @@ -1,5 +1,5 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { EvaluationResult } from './evaluation-result.interface'; diff --git a/apps/api/src/models/interfaces/user-settings.interface.ts b/apps/api/src/models/interfaces/user-settings.interface.ts deleted file mode 100644 index 7da0c19ae..000000000 --- a/apps/api/src/models/interfaces/user-settings.interface.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface UserSettings { - baseCurrency: string; -} diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index 6bbb71e07..ad1629ac3 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -1,8 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { groupBy } from '@ghostfolio/common/helper'; -import { TimelinePosition } from '@ghostfolio/common/interfaces'; +import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces'; import { EvaluationResult } from './interfaces/evaluation-result.interface'; import { RuleInterface } from './interfaces/rule.interface'; diff --git a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts index 3893efd44..078123743 100644 --- a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts @@ -1,9 +1,9 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { PortfolioDetails, - PortfolioPosition + PortfolioPosition, + UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts b/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts index 7aa363c73..f490b0d6d 100644 --- a/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts @@ -1,9 +1,9 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { PortfolioDetails, - PortfolioPosition + PortfolioPosition, + UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/account-cluster-risk/single-account.ts b/apps/api/src/models/rules/account-cluster-risk/single-account.ts index 41988ee68..c9bd0b35f 100644 --- a/apps/api/src/models/rules/account-cluster-risk/single-account.ts +++ b/apps/api/src/models/rules/account-cluster-risk/single-account.ts @@ -1,7 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; -import { PortfolioDetails } from '@ghostfolio/common/interfaces'; +import { PortfolioDetails, UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts index bd313153f..5f1f4cf93 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts index ed7242d09..1d43f5619 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts index c8e3c30eb..c233ffc9c 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts index 95e3b4b76..331074f16 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts index f0ba72932..d3e4ea827 100644 --- a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts +++ b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts @@ -1,6 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index fff2529d4..a900a5412 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -5,10 +5,6 @@ import { PositionDetailDialog } from '@ghostfolio/client/components/position/pos import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; -import { - RANGE, - SettingsStorageService -} from '@ghostfolio/client/services/settings-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { Position, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; @@ -26,7 +22,6 @@ import { PositionDetailDialogParams } from '../position/position-detail-dialog/i templateUrl: './home-holdings.html' }) export class HomeHoldingsComponent implements OnDestroy, OnInit { - public dateRange: DateRange; public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public deviceType: string; public hasImpersonationId: boolean; @@ -44,7 +39,6 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { private impersonationStorageService: ImpersonationStorageService, private route: ActivatedRoute, private router: Router, - private settingsStorageService: SettingsStorageService, private userService: UserService ) { this.route.queryParams @@ -73,7 +67,7 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { permissions.createOrder ); - this.changeDetectorRef.markForCheck(); + this.update(); } }); } @@ -88,18 +82,24 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { this.hasImpersonationId = !!aId; }); - this.dateRange = - this.user.settings.viewMode === 'ZEN' - ? 'max' - : this.settingsStorageService.getSetting(RANGE) ?? 'max'; - this.update(); } - public onChangeDateRange(aDateRange: DateRange) { - this.dateRange = aDateRange; - this.settingsStorageService.setSetting(RANGE, this.dateRange); - this.update(); + public onChangeDateRange(dateRange: DateRange) { + this.dataService + .putUserSetting({ dateRange }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.userService.remove(); + + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + this.changeDetectorRef.markForCheck(); + }); + }); } public ngOnDestroy() { @@ -151,7 +151,7 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit { this.positions = undefined; this.dataService - .fetchPositions({ range: this.dateRange }) + .fetchPositions({ range: this.user?.settings?.dateRange }) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((response) => { this.positions = response.positions; diff --git a/apps/client/src/app/components/home-holdings/home-holdings.html b/apps/client/src/app/components/home-holdings/home-holdings.html index 5fa1ec5c9..3740f0c6b 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.html +++ b/apps/client/src/app/components/home-holdings/home-holdings.html @@ -1,7 +1,7 @@
diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index 5d4fd6aa2..c03110d75 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -2,10 +2,6 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ToggleComponent } from '@ghostfolio/client/components/toggle/toggle.component'; import { DataService } from '@ghostfolio/client/services/data.service'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; -import { - RANGE, - SettingsStorageService -} from '@ghostfolio/client/services/settings-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { LineChartItem, @@ -25,7 +21,6 @@ import { takeUntil } from 'rxjs/operators'; templateUrl: './home-overview.html' }) export class HomeOverviewComponent implements OnDestroy, OnInit { - public dateRange: DateRange; public dateRangeOptions = ToggleComponent.DEFAULT_DATE_RANGE_OPTIONS; public deviceType: string; public errors: UniqueAsset[]; @@ -47,7 +42,6 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { private dataService: DataService, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, - private settingsStorageService: SettingsStorageService, private userService: UserService ) { this.userService.stateChanged @@ -61,7 +55,7 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { permissions.createOrder ); - this.changeDetectorRef.markForCheck(); + this.update(); } }); } @@ -78,11 +72,6 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { this.changeDetectorRef.markForCheck(); }); - this.dateRange = - this.user.settings.viewMode === 'ZEN' - ? 'max' - : this.settingsStorageService.getSetting(RANGE) ?? 'max'; - this.showDetails = !this.hasImpersonationId && !this.user.settings.isRestrictedView && @@ -91,10 +80,22 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { this.update(); } - public onChangeDateRange(aDateRange: DateRange) { - this.dateRange = aDateRange; - this.settingsStorageService.setSetting(RANGE, this.dateRange); - this.update(); + public onChangeDateRange(dateRange: DateRange) { + this.dataService + .putUserSetting({ dateRange }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.userService.remove(); + + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + + this.changeDetectorRef.markForCheck(); + }); + }); } public ngOnDestroy() { @@ -107,7 +108,7 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { this.dataService .fetchChart({ - range: this.dateRange, + range: this.user?.settings?.dateRange, version: this.user?.settings?.isExperimentalFeatures ? 2 : 1 }) .pipe(takeUntil(this.unsubscribeSubject)) @@ -125,7 +126,7 @@ export class HomeOverviewComponent implements OnDestroy, OnInit { }); this.dataService - .fetchPortfolioPerformance({ range: this.dateRange }) + .fetchPortfolioPerformance({ range: this.user?.settings?.dateRange }) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((response) => { this.errors = response.errors; diff --git a/apps/client/src/app/components/home-overview/home-overview.html b/apps/client/src/app/components/home-overview/home-overview.html index a032dedf9..0a47689c8 100644 --- a/apps/client/src/app/components/home-overview/home-overview.html +++ b/apps/client/src/app/components/home-overview/home-overview.html @@ -46,7 +46,7 @@ >
{ - this.update(); + this.userService.remove(); + + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + + this.changeDetectorRef.markForCheck(); + }); }); } diff --git a/apps/client/src/app/pages/account/account-page.component.ts b/apps/client/src/app/pages/account/account-page.component.ts index 03d95a7e4..cc475ee17 100644 --- a/apps/client/src/app/pages/account/account-page.component.ts +++ b/apps/client/src/app/pages/account/account-page.component.ts @@ -175,29 +175,6 @@ export class AccountPageComponent implements OnDestroy, OnInit { }); } - public onChangeUserSettings(aKey: string, aValue: string) { - const settings = { ...this.user.settings, [aKey]: aValue }; - - this.dataService - .putUserSettings({ - baseCurrency: settings?.baseCurrency, - viewMode: settings?.viewMode - }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.userService.remove(); - - this.userService - .get() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((user) => { - this.user = user; - - this.changeDetectorRef.markForCheck(); - }); - }); - } - public onCheckout() { this.dataService .createCheckoutSession({ couponId: this.couponId, priceId: this.priceId }) diff --git a/apps/client/src/app/pages/account/account-page.html b/apps/client/src/app/pages/account/account-page.html index c0efac59a..306a9f70a 100644 --- a/apps/client/src/app/pages/account/account-page.html +++ b/apps/client/src/app/pages/account/account-page.html @@ -99,7 +99,7 @@ name="baseCurrency" [disabled]="!hasPermissionToUpdateUserSettings" [value]="user.settings.baseCurrency" - (selectionChange)="onChangeUserSettings('baseCurrency', $event.value)" + (selectionChange)="onChangeUserSetting('baseCurrency', $event.value)" > Default Zen 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 8004fd660..d4d6abb26 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 @@ -73,7 +73,18 @@ export class FirePageComponent implements OnDestroy, OnInit { this.dataService .putUserSetting({ savingsRate }) .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => {}); + .subscribe(() => { + this.userService.remove(); + + this.userService + .get() + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((user) => { + this.user = user; + + this.changeDetectorRef.markForCheck(); + }); + }); } public ngOnDestroy() { diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 763bf582f..49d7b1761 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -12,7 +12,6 @@ import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.in import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface'; import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; -import { UpdateUserSettingsDto } from '@ghostfolio/api/app/user/update-user-settings.dto'; import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { @@ -448,10 +447,6 @@ export class DataService { return this.http.put(`/api/v1/user/setting`, aData); } - public putUserSettings(aData: UpdateUserSettingsDto) { - return this.http.put(`/api/v1/user/settings`, aData); - } - public redeemCoupon(couponCode: string) { return this.http.post('/api/v1/subscription/redeem-coupon', { couponCode diff --git a/libs/common/src/lib/interfaces/user-settings.interface.ts b/libs/common/src/lib/interfaces/user-settings.interface.ts index d6f6a66e6..5f16cee7e 100644 --- a/libs/common/src/lib/interfaces/user-settings.interface.ts +++ b/libs/common/src/lib/interfaces/user-settings.interface.ts @@ -1,10 +1,13 @@ +import { DateRange } from '@ghostfolio/common/types'; import { ViewMode } from '@prisma/client'; export interface UserSettings { baseCurrency?: string; + dateRange?: DateRange; + emergencyFund?: number; isExperimentalFeatures?: boolean; isRestrictedView?: boolean; language?: string; - locale: string; + locale?: string; viewMode?: ViewMode; } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 507570eba..34cbc9003 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -102,10 +102,10 @@ model Property { } model Settings { - currency String? + currency String? /// @deprecated settings Json? updatedAt DateTime @updatedAt - viewMode ViewMode? + viewMode ViewMode? /// @deprecated userId String @id User User @relation(fields: [userId], references: [id]) }