Browse Source

Merge 60f84fb1ca into f92ba54060

pull/1692/merge
Agustin Alexander 3 years ago
committed by GitHub
parent
commit
72aaa80a51
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      apps/api/src/app/user/update-user-setting.dto.ts
  2. 4
      apps/api/src/app/user/user.service.ts
  3. 2
      apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
  4. 22
      apps/client/src/app/pages/account/account-page.component.ts
  5. 16
      apps/client/src/app/pages/account/account-page.html
  6. 4
      apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
  7. 18
      apps/client/src/app/pages/public/public-page.component.ts
  8. 3
      libs/common/src/lib/interfaces/user-settings.interface.ts
  9. 9
      libs/common/src/lib/permissions.ts
  10. 5
      libs/common/src/lib/types/index.ts
  11. 1
      libs/common/src/lib/types/view-mode.type.ts
  12. 2
      prisma/migrations/20230212232240_added_unknown_mode/migration.sql
  13. 5
      prisma/schema.prisma

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

@ -1,7 +1,8 @@
import type { import type {
ColorScheme, ColorScheme,
DateRange, DateRange,
ViewMode ViewMode,
UnknownMode
} from '@ghostfolio/common/types'; } from '@ghostfolio/common/types';
import { import {
IsBoolean, IsBoolean,
@ -68,4 +69,8 @@ export class UpdateUserSettingDto {
@IsIn(<ViewMode[]>['DEFAULT', 'ZEN']) @IsIn(<ViewMode[]>['DEFAULT', 'ZEN'])
@IsOptional() @IsOptional()
viewMode?: ViewMode; viewMode?: ViewMode;
@IsIn(<UnknownMode[]>['DEFAULT', 'OFF'])
@IsOptional()
unknownMode?: UnknownMode;
} }

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

@ -161,6 +161,10 @@ export class UserService {
(user.Settings.settings as UserSettings).viewMode = 'DEFAULT'; (user.Settings.settings as UserSettings).viewMode = 'DEFAULT';
} }
if (!(user.Settings.settings as UserSettings).unknownMode) {
(user.Settings.settings as UserSettings).unknownMode = 'DEFAULT';
}
let currentPermissions = getPermissions(user.role); let currentPermissions = getPermissions(user.role);
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {

2
apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts

@ -118,7 +118,7 @@ export class YahooFinanceService implements DataProviderInterface {
}); });
response.symbol = aSymbol; response.symbol = aSymbol;
if (assetSubClass === AssetSubClass.MUTUALFUND) { if (assetSubClass === AssetSubClass.MUTUALFUND || assetSubClass === AssetSubClass.ETF) {
response.sectors = []; response.sectors = [];
for (const sectorWeighting of assetProfile.topHoldings for (const sectorWeighting of assetProfile.topHoldings

22
apps/client/src/app/pages/account/account-page.component.ts

@ -53,6 +53,7 @@ export class AccountPageComponent implements OnDestroy, OnInit {
public hasPermissionToCreateAccess: boolean; public hasPermissionToCreateAccess: boolean;
public hasPermissionToDeleteAccess: boolean; public hasPermissionToDeleteAccess: boolean;
public hasPermissionToUpdateViewMode: boolean; public hasPermissionToUpdateViewMode: boolean;
public hasPermissionToUpdateUnknownMode: boolean;
public hasPermissionToUpdateUserSettings: boolean; public hasPermissionToUpdateUserSettings: boolean;
public language = document.documentElement.lang; public language = document.documentElement.lang;
public locales = [ public locales = [
@ -138,6 +139,11 @@ export class AccountPageComponent implements OnDestroy, OnInit {
permissions.updateViewMode permissions.updateViewMode
); );
this.hasPermissionToUpdateUnknownMode = hasPermission(
this.user.permissions,
permissions.updateUnknownMode
);
this.locales.push(this.user.settings.locale); this.locales.push(this.user.settings.locale);
this.locales = uniq(this.locales.sort()); this.locales = uniq(this.locales.sort());
@ -330,6 +336,22 @@ export class AccountPageComponent implements OnDestroy, OnInit {
}); });
}); });
} }
public onUnknownChange(aEvent: MatSlideToggleChange) {
this.dataService
.putUserSetting({ unknownMode: aEvent.checked === true ? 'DEFAULT' : 'OFF'})
.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() { public ngOnDestroy() {
this.unsubscribeSubject.next(); this.unsubscribeSubject.next();

16
apps/client/src/app/pages/account/account-page.html

@ -225,6 +225,22 @@
></mat-slide-toggle> ></mat-slide-toggle>
</div> </div>
</div> </div>
<div class="d-flex mt-4 py-1">
<div class="pr-1 w-50">
<div i18n>Unknown Mode</div>
<div class="hint-text text-muted" i18n>
Show Unknown categories in Portfolio Allocation View
</div>
</div>
<div class="pl-1 w-50">
<mat-slide-toggle
color="primary"
[checked]="user.settings.unknownMode === 'DEFAULT'"
[disabled]="!hasPermissionToUpdateUnknownMode"
(change)="onUnknownChange($event)"
></mat-slide-toggle>
</div>
</div>
<div class="align-items-center d-flex mt-4 py-1"> <div class="align-items-center d-flex mt-4 py-1">
<div class="pr-1 w-50" i18n>Sign in with fingerprint</div> <div class="pr-1 w-50" i18n>Sign in with fingerprint</div>
<div class="pl-1 w-50"> <div class="pl-1 w-50">

4
apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts

@ -309,7 +309,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
}; };
} }
} }
} else { } else if (this.user.settings.unknownMode === "DEFAULT") {
this.continents[UNKNOWN_KEY].value += this.continents[UNKNOWN_KEY].value +=
this.portfolioDetails.holdings[symbol].value; this.portfolioDetails.holdings[symbol].value;
@ -330,7 +330,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
}; };
} }
} }
} else { } else if (this.user.settings.unknownMode === "DEFAULT") {
this.sectors[UNKNOWN_KEY].value += this.sectors[UNKNOWN_KEY].value +=
this.portfolioDetails.holdings[symbol].value; this.portfolioDetails.holdings[symbol].value;
} }

18
apps/client/src/app/pages/public/public-page.component.ts

@ -5,7 +5,7 @@ import { UNKNOWN_KEY } from '@ghostfolio/common/config';
import { prettifySymbol } from '@ghostfolio/common/helper'; import { prettifySymbol } from '@ghostfolio/common/helper';
import { import {
PortfolioPosition, PortfolioPosition,
PortfolioPublicDetails PortfolioPublicDetails, User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { Market } from '@ghostfolio/common/types'; import { Market } from '@ghostfolio/common/types';
import { StatusCodes } from 'http-status-codes'; import { StatusCodes } from 'http-status-codes';
@ -13,6 +13,7 @@ import { isNumber } from 'lodash';
import { DeviceDetectorService } from 'ngx-device-detector'; import { DeviceDetectorService } from 'ngx-device-detector';
import { EMPTY, Subject } from 'rxjs'; import { EMPTY, Subject } from 'rxjs';
import { catchError, takeUntil } from 'rxjs/operators'; import { catchError, takeUntil } from 'rxjs/operators';
import { UserService } from '@ghostfolio/client/services/user/user.service';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
@ -47,23 +48,34 @@ export class PublicPageComponent implements OnInit {
}; };
private id: string; private id: string;
private user: User;
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();
public constructor( public constructor(
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService, private dataService: DataService,
private userService: UserService,
private deviceService: DeviceDetectorService, private deviceService: DeviceDetectorService,
private router: Router private router: Router
) { ) {
this.activatedRoute.params.subscribe((params) => { this.activatedRoute.params.subscribe((params) => {
this.id = params['id']; this.id = params['id'];
}); });
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => {
if (state?.user) {
this.user = state.user;
this.initializeAnalysisData()
}
});
} }
public ngOnInit() { public ngOnInit() {
this.deviceType = this.deviceService.getDeviceInfo().deviceType; this.deviceType = this.deviceService.getDeviceInfo().deviceType;
this.dataService this.dataService
.fetchPortfolioPublic(this.id) .fetchPortfolioPublic(this.id)
.pipe( .pipe(
@ -191,7 +203,7 @@ export class PublicPageComponent implements OnInit {
}; };
} }
} }
} else { } else if (this.user.settings.unknownMode === "DEFAULT") {
this.sectors[UNKNOWN_KEY].value += this.sectors[UNKNOWN_KEY].value +=
this.portfolioPublicDetails.holdings[symbol].value; this.portfolioPublicDetails.holdings[symbol].value;
} }

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

@ -1,4 +1,4 @@
import { ColorScheme, DateRange, ViewMode } from '@ghostfolio/common/types'; import {ColorScheme, DateRange, UnknownMode, ViewMode} from '@ghostfolio/common/types';
export interface UserSettings { export interface UserSettings {
annualInterestRate?: number; annualInterestRate?: number;
@ -15,4 +15,5 @@ export interface UserSettings {
retirementDate?: string; retirementDate?: string;
savingsRate?: number; savingsRate?: number;
viewMode?: ViewMode; viewMode?: ViewMode;
unknownMode?: UnknownMode;
} }

9
libs/common/src/lib/permissions.ts

@ -27,7 +27,8 @@ export const permissions = {
updateAuthDevice: 'updateAuthDevice', updateAuthDevice: 'updateAuthDevice',
updateOrder: 'updateOrder', updateOrder: 'updateOrder',
updateUserSettings: 'updateUserSettings', updateUserSettings: 'updateUserSettings',
updateViewMode: 'updateViewMode' updateViewMode: 'updateViewMode',
updateUnknownMode: 'updateUnknownMode'
}; };
export function getPermissions(aRole: Role): string[] { export function getPermissions(aRole: Role): string[] {
@ -47,7 +48,8 @@ export function getPermissions(aRole: Role): string[] {
permissions.updateAuthDevice, permissions.updateAuthDevice,
permissions.updateOrder, permissions.updateOrder,
permissions.updateUserSettings, permissions.updateUserSettings,
permissions.updateViewMode permissions.updateViewMode,
permissions.updateUnknownMode
]; ];
case 'DEMO': case 'DEMO':
@ -66,7 +68,8 @@ export function getPermissions(aRole: Role): string[] {
permissions.updateAuthDevice, permissions.updateAuthDevice,
permissions.updateOrder, permissions.updateOrder,
permissions.updateUserSettings, permissions.updateUserSettings,
permissions.updateViewMode permissions.updateViewMode,
permissions.updateUnknownMode
]; ];
default: default:

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

@ -10,7 +10,7 @@ import { 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 { ToggleOption } from './toggle-option.type'; import { ToggleOption } from './toggle-option.type';
import type { ViewMode } from './view-mode.type'; import type { ViewMode, UnknownMode } from './view-mode.type';
export type { export type {
AccessWithGranteeUser, AccessWithGranteeUser,
@ -25,5 +25,6 @@ export type {
OrderWithAccount, OrderWithAccount,
RequestWithUser, RequestWithUser,
ToggleOption, ToggleOption,
ViewMode ViewMode,
UnknownMode
}; };

1
libs/common/src/lib/types/view-mode.type.ts

@ -1 +1,2 @@
export type ViewMode = 'DEFAULT' | 'ZEN'; export type ViewMode = 'DEFAULT' | 'ZEN';
export type UnknownMode = 'DEFAULT' | 'OFF';

2
prisma/migrations/20230212232240_added_unknown_mode/migration.sql

@ -0,0 +1,2 @@
-- CreateEnum
CREATE TYPE "UnknownMode" AS ENUM ('DEFAULT', 'OFF');

5
prisma/schema.prisma

@ -219,6 +219,11 @@ enum ViewMode {
ZEN ZEN
} }
enum UnknownMode {
DEFAULT
OFF
}
enum Provider { enum Provider {
ANONYMOUS ANONYMOUS
GOOGLE GOOGLE

Loading…
Cancel
Save