Feature/persist view mode of holdings tab on home page (#3624)
* Persist view mode of holdings in user settings * Update changelog
This commit is contained in:
parent
c87b08ca8b
commit
02db0db733
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Improved the color assignment in the chart of the holdings tab on the home page (experimental)
|
- Improved the color assignment in the chart of the holdings tab on the home page (experimental)
|
||||||
|
- Persisted the view mode of the holdings tab on the home page (experimental)
|
||||||
- Improved the language localization for Catalan (`ca`)
|
- Improved the language localization for Catalan (`ca`)
|
||||||
- Improved the language localization for Spanish (`es`)
|
- Improved the language localization for Spanish (`es`)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { IsCurrencyCode } from '@ghostfolio/api/validators/is-currency-code';
|
|||||||
import type {
|
import type {
|
||||||
ColorScheme,
|
ColorScheme,
|
||||||
DateRange,
|
DateRange,
|
||||||
|
HoldingsViewMode,
|
||||||
ViewMode
|
ViewMode
|
||||||
} from '@ghostfolio/common/types';
|
} from '@ghostfolio/common/types';
|
||||||
|
|
||||||
@ -66,6 +67,10 @@ export class UpdateUserSettingDto {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
'filters.tags'?: string[];
|
'filters.tags'?: string[];
|
||||||
|
|
||||||
|
@IsIn(<HoldingsViewMode[]>['CHART', 'TABLE'])
|
||||||
|
@IsOptional()
|
||||||
|
holdingsViewMode?: HoldingsViewMode;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
isExperimentalFeatures?: boolean;
|
isExperimentalFeatures?: boolean;
|
||||||
|
@ -190,7 +190,7 @@ export class UserService {
|
|||||||
(user.Settings.settings as UserSettings).dateRange =
|
(user.Settings.settings as UserSettings).dateRange =
|
||||||
(user.Settings.settings as UserSettings).viewMode === 'ZEN'
|
(user.Settings.settings as UserSettings).viewMode === 'ZEN'
|
||||||
? 'max'
|
? 'max'
|
||||||
: (user.Settings.settings as UserSettings)?.dateRange ?? 'max';
|
: ((user.Settings.settings as UserSettings)?.dateRange ?? 'max');
|
||||||
|
|
||||||
// Set default value for view mode
|
// Set default value for view mode
|
||||||
if (!(user.Settings.settings as UserSettings).viewMode) {
|
if (!(user.Settings.settings as UserSettings).viewMode) {
|
||||||
@ -243,6 +243,9 @@ export class UserService {
|
|||||||
|
|
||||||
// Reset benchmark
|
// Reset benchmark
|
||||||
user.Settings.settings.benchmark = undefined;
|
user.Settings.settings.benchmark = undefined;
|
||||||
|
|
||||||
|
// Reset holdings view mode
|
||||||
|
user.Settings.settings.holdingsViewMode = undefined;
|
||||||
} else if (user.subscription?.type === 'Premium') {
|
} else if (user.subscription?.type === 'Premium') {
|
||||||
currentPermissions.push(permissions.reportDataGlitch);
|
currentPermissions.push(permissions.reportDataGlitch);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||||
import {
|
import {
|
||||||
HoldingType,
|
HoldingType,
|
||||||
HoldingViewMode,
|
HoldingsViewMode,
|
||||||
ToggleOption
|
ToggleOption
|
||||||
} from '@ghostfolio/common/types';
|
} from '@ghostfolio/common/types';
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ import { FormControl } from '@angular/forms';
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { skip, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'gf-home-holdings',
|
selector: 'gf-home-holdings',
|
||||||
@ -26,6 +26,8 @@ import { takeUntil } from 'rxjs/operators';
|
|||||||
templateUrl: './home-holdings.html'
|
templateUrl: './home-holdings.html'
|
||||||
})
|
})
|
||||||
export class HomeHoldingsComponent implements OnDestroy, OnInit {
|
export class HomeHoldingsComponent implements OnDestroy, OnInit {
|
||||||
|
public static DEFAULT_HOLDINGS_VIEW_MODE: HoldingsViewMode = 'TABLE';
|
||||||
|
|
||||||
public deviceType: string;
|
public deviceType: string;
|
||||||
public hasImpersonationId: boolean;
|
public hasImpersonationId: boolean;
|
||||||
public hasPermissionToAccessHoldingsChart: boolean;
|
public hasPermissionToAccessHoldingsChart: boolean;
|
||||||
@ -37,7 +39,9 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit {
|
|||||||
{ label: $localize`Closed`, value: 'CLOSED' }
|
{ label: $localize`Closed`, value: 'CLOSED' }
|
||||||
];
|
];
|
||||||
public user: User;
|
public user: User;
|
||||||
public viewModeFormControl = new FormControl<HoldingViewMode>('TABLE');
|
public viewModeFormControl = new FormControl<HoldingsViewMode>(
|
||||||
|
HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE
|
||||||
|
);
|
||||||
|
|
||||||
private unsubscribeSubject = new Subject<void>();
|
private unsubscribeSubject = new Subject<void>();
|
||||||
|
|
||||||
@ -81,6 +85,21 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit {
|
|||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.viewModeFormControl.valueChanges
|
||||||
|
.pipe(
|
||||||
|
// Skip inizialization: "new FormControl"
|
||||||
|
skip(1),
|
||||||
|
takeUntil(this.unsubscribeSubject)
|
||||||
|
)
|
||||||
|
.subscribe((holdingsViewMode) => {
|
||||||
|
this.dataService
|
||||||
|
.putUserSetting({ holdingsViewMode })
|
||||||
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.userService.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public onChangeHoldingType(aHoldingType: HoldingType) {
|
public onChangeHoldingType(aHoldingType: HoldingType) {
|
||||||
@ -122,9 +141,20 @@ export class HomeHoldingsComponent implements OnDestroy, OnInit {
|
|||||||
this.hasPermissionToAccessHoldingsChart &&
|
this.hasPermissionToAccessHoldingsChart &&
|
||||||
this.holdingType === 'ACTIVE'
|
this.holdingType === 'ACTIVE'
|
||||||
) {
|
) {
|
||||||
this.viewModeFormControl.enable();
|
this.viewModeFormControl.enable({ emitEvent: false });
|
||||||
|
|
||||||
|
this.viewModeFormControl.setValue(
|
||||||
|
this.deviceType === 'mobile'
|
||||||
|
? HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE
|
||||||
|
: this.user?.settings?.holdingsViewMode ||
|
||||||
|
HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE,
|
||||||
|
{ emitEvent: false }
|
||||||
|
);
|
||||||
} else if (this.holdingType === 'CLOSED') {
|
} else if (this.holdingType === 'CLOSED') {
|
||||||
this.viewModeFormControl.setValue('TABLE');
|
this.viewModeFormControl.setValue(
|
||||||
|
HomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE,
|
||||||
|
{ emitEvent: false }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.holdings = undefined;
|
this.holdings = undefined;
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { ColorScheme, DateRange, ViewMode } from '@ghostfolio/common/types';
|
import {
|
||||||
|
ColorScheme,
|
||||||
|
DateRange,
|
||||||
|
HoldingsViewMode,
|
||||||
|
ViewMode
|
||||||
|
} from '@ghostfolio/common/types';
|
||||||
|
|
||||||
export interface UserSettings {
|
export interface UserSettings {
|
||||||
annualInterestRate?: number;
|
annualInterestRate?: number;
|
||||||
@ -9,6 +14,7 @@ export interface UserSettings {
|
|||||||
emergencyFund?: number;
|
emergencyFund?: number;
|
||||||
'filters.accounts'?: string[];
|
'filters.accounts'?: string[];
|
||||||
'filters.tags'?: string[];
|
'filters.tags'?: string[];
|
||||||
|
holdingsViewMode?: HoldingsViewMode;
|
||||||
isExperimentalFeatures?: boolean;
|
isExperimentalFeatures?: boolean;
|
||||||
isRestrictedView?: boolean;
|
isRestrictedView?: boolean;
|
||||||
language?: string;
|
language?: string;
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export type HoldingViewMode = 'CHART' | 'TABLE';
|
|
1
libs/common/src/lib/types/holdings-view-mode.type.ts
Normal file
1
libs/common/src/lib/types/holdings-view-mode.type.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type HoldingsViewMode = 'CHART' | 'TABLE';
|
@ -8,7 +8,7 @@ import type { DateRange } from './date-range.type';
|
|||||||
import type { Granularity } from './granularity.type';
|
import type { Granularity } from './granularity.type';
|
||||||
import type { GroupBy } from './group-by.type';
|
import type { GroupBy } from './group-by.type';
|
||||||
import type { HoldingType } from './holding-type.type';
|
import type { HoldingType } from './holding-type.type';
|
||||||
import type { HoldingViewMode } from './holding-view-mode.type';
|
import type { HoldingsViewMode } from './holdings-view-mode.type';
|
||||||
import type { MarketAdvanced } from './market-advanced.type';
|
import type { MarketAdvanced } from './market-advanced.type';
|
||||||
import type { MarketDataPreset } from './market-data-preset.type';
|
import type { MarketDataPreset } from './market-data-preset.type';
|
||||||
import type { MarketState } from './market-state.type';
|
import type { MarketState } from './market-state.type';
|
||||||
@ -31,7 +31,7 @@ export type {
|
|||||||
Granularity,
|
Granularity,
|
||||||
GroupBy,
|
GroupBy,
|
||||||
HoldingType,
|
HoldingType,
|
||||||
HoldingViewMode,
|
HoldingsViewMode,
|
||||||
Market,
|
Market,
|
||||||
MarketAdvanced,
|
MarketAdvanced,
|
||||||
MarketDataPreset,
|
MarketDataPreset,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user