|
|
@ -1,4 +1,7 @@ |
|
|
import { LoginWithAccessTokenDialogParams } from '@ghostfolio/client/components/login-with-access-token-dialog/interfaces/interfaces'; |
|
|
import { |
|
|
|
|
|
LoginWithAccessTokenDialogParams, |
|
|
|
|
|
LoginWithAccessTokenDialogResult |
|
|
|
|
|
} from '@ghostfolio/client/components/login-with-access-token-dialog/interfaces/interfaces'; |
|
|
import { GfLoginWithAccessTokenDialogComponent } from '@ghostfolio/client/components/login-with-access-token-dialog/login-with-access-token-dialog.component'; |
|
|
import { GfLoginWithAccessTokenDialogComponent } from '@ghostfolio/client/components/login-with-access-token-dialog/login-with-access-token-dialog.component'; |
|
|
import { LayoutService } from '@ghostfolio/client/core/layout.service'; |
|
|
import { LayoutService } from '@ghostfolio/client/core/layout.service'; |
|
|
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; |
|
|
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; |
|
|
@ -24,12 +27,12 @@ import { |
|
|
Component, |
|
|
Component, |
|
|
CUSTOM_ELEMENTS_SCHEMA, |
|
|
CUSTOM_ELEMENTS_SCHEMA, |
|
|
DestroyRef, |
|
|
DestroyRef, |
|
|
EventEmitter, |
|
|
|
|
|
HostListener, |
|
|
HostListener, |
|
|
Input, |
|
|
inject, |
|
|
|
|
|
input, |
|
|
OnChanges, |
|
|
OnChanges, |
|
|
Output, |
|
|
output, |
|
|
ViewChild |
|
|
viewChild |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; |
|
|
import { MatBadgeModule } from '@angular/material/badge'; |
|
|
import { MatBadgeModule } from '@angular/material/badge'; |
|
|
@ -71,78 +74,67 @@ import { catchError } from 'rxjs/operators'; |
|
|
styleUrls: ['./header.component.scss'] |
|
|
styleUrls: ['./header.component.scss'] |
|
|
}) |
|
|
}) |
|
|
export class GfHeaderComponent implements OnChanges { |
|
|
export class GfHeaderComponent implements OnChanges { |
|
|
@HostListener('window:keydown', ['$event']) |
|
|
public readonly currentRoute = input.required<string>(); |
|
|
openAssistantWithHotKey(event: KeyboardEvent) { |
|
|
public readonly deviceType = input.required<string>(); |
|
|
if ( |
|
|
public readonly hasPermissionToChangeDateRange = input.required<boolean>(); |
|
|
event.key === '/' && |
|
|
public readonly hasPermissionToChangeFilters = input.required<boolean>(); |
|
|
event.target instanceof Element && |
|
|
public readonly hasPromotion = input.required<boolean>(); |
|
|
event.target?.nodeName?.toLowerCase() !== 'input' && |
|
|
public readonly hasTabs = input.required<boolean>(); |
|
|
event.target?.nodeName?.toLowerCase() !== 'textarea' && |
|
|
public readonly info = input.required<InfoItem | undefined>(); |
|
|
this.hasPermissionToAccessAssistant |
|
|
public readonly pageTitle = input.required<string>(); |
|
|
) { |
|
|
public readonly user = input.required<User | undefined>(); |
|
|
this.assistantElement.setIsOpen(true); |
|
|
|
|
|
this.assistentMenuTriggerElement.openMenu(); |
|
|
public readonly signOut = output<void>(); |
|
|
|
|
|
|
|
|
event.preventDefault(); |
|
|
protected readonly assistantElement = |
|
|
} |
|
|
viewChild.required<GfAssistantComponent>('assistant'); |
|
|
} |
|
|
protected readonly assistentMenuTriggerElement = |
|
|
|
|
|
viewChild.required<MatMenuTrigger>('assistantTrigger'); |
|
|
@Input() currentRoute: string; |
|
|
|
|
|
@Input() deviceType: string; |
|
|
protected hasFilters: boolean; |
|
|
@Input() hasPermissionToChangeDateRange: boolean; |
|
|
protected hasImpersonationId: boolean; |
|
|
@Input() hasPermissionToChangeFilters: boolean; |
|
|
protected hasPermissionForAuthGoogle: boolean; |
|
|
@Input() hasPromotion: boolean; |
|
|
protected hasPermissionForAuthOidc: boolean; |
|
|
@Input() hasTabs: boolean; |
|
|
protected hasPermissionForAuthToken: boolean; |
|
|
@Input() info: InfoItem; |
|
|
protected hasPermissionForSubscription: boolean; |
|
|
@Input() pageTitle: string; |
|
|
protected hasPermissionToAccessAdminControl: boolean; |
|
|
@Input() user: User; |
|
|
protected hasPermissionToAccessAssistant: boolean; |
|
|
|
|
|
protected hasPermissionToAccessFearAndGreedIndex: boolean; |
|
|
@Output() signOut = new EventEmitter<void>(); |
|
|
protected hasPermissionToCreateUser: boolean; |
|
|
|
|
|
protected impersonationId: string; |
|
|
@ViewChild('assistant') assistantElement: GfAssistantComponent; |
|
|
protected readonly internalRoutes = internalRoutes; |
|
|
@ViewChild('assistantTrigger') assistentMenuTriggerElement: MatMenuTrigger; |
|
|
protected isMenuOpen: boolean; |
|
|
|
|
|
protected readonly routeAbout = publicRoutes.about.path; |
|
|
public hasFilters: boolean; |
|
|
protected readonly routeFeatures = publicRoutes.features.path; |
|
|
public hasImpersonationId: boolean; |
|
|
protected readonly routeMarkets = publicRoutes.markets.path; |
|
|
public hasPermissionForAuthGoogle: boolean; |
|
|
protected readonly routePricing = publicRoutes.pricing.path; |
|
|
public hasPermissionForAuthOidc: boolean; |
|
|
protected readonly routeResources = publicRoutes.resources.path; |
|
|
public hasPermissionForAuthToken: boolean; |
|
|
protected readonly routerLinkAbout = publicRoutes.about.routerLink; |
|
|
public hasPermissionForSubscription: boolean; |
|
|
protected readonly routerLinkAccount = internalRoutes.account.routerLink; |
|
|
public hasPermissionToAccessAdminControl: boolean; |
|
|
protected readonly routerLinkAccounts = internalRoutes.accounts.routerLink; |
|
|
public hasPermissionToAccessAssistant: boolean; |
|
|
protected readonly routerLinkAdminControl = |
|
|
public hasPermissionToAccessFearAndGreedIndex: boolean; |
|
|
internalRoutes.adminControl.routerLink; |
|
|
public hasPermissionToCreateUser: boolean; |
|
|
protected readonly routerLinkFeatures = publicRoutes.features.routerLink; |
|
|
public impersonationId: string; |
|
|
protected readonly routerLinkMarkets = publicRoutes.markets.routerLink; |
|
|
public internalRoutes = internalRoutes; |
|
|
protected readonly routerLinkPortfolio = internalRoutes.portfolio.routerLink; |
|
|
public isMenuOpen: boolean; |
|
|
protected readonly routerLinkPricing = publicRoutes.pricing.routerLink; |
|
|
public routeAbout = publicRoutes.about.path; |
|
|
protected readonly routerLinkRegister = publicRoutes.register.routerLink; |
|
|
public routeFeatures = publicRoutes.features.path; |
|
|
protected readonly routerLinkResources = publicRoutes.resources.routerLink; |
|
|
public routeMarkets = publicRoutes.markets.path; |
|
|
|
|
|
public routePricing = publicRoutes.pricing.path; |
|
|
private readonly dataService = inject(DataService); |
|
|
public routeResources = publicRoutes.resources.path; |
|
|
private readonly destroyRef = inject(DestroyRef); |
|
|
public routerLinkAbout = publicRoutes.about.routerLink; |
|
|
private readonly dialog = inject(MatDialog); |
|
|
public routerLinkAccount = internalRoutes.account.routerLink; |
|
|
private readonly impersonationStorageService = inject( |
|
|
public routerLinkAccounts = internalRoutes.accounts.routerLink; |
|
|
ImpersonationStorageService |
|
|
public routerLinkAdminControl = internalRoutes.adminControl.routerLink; |
|
|
); |
|
|
public routerLinkFeatures = publicRoutes.features.routerLink; |
|
|
private readonly layoutService = inject(LayoutService); |
|
|
public routerLinkMarkets = publicRoutes.markets.routerLink; |
|
|
private readonly notificationService = inject(NotificationService); |
|
|
public routerLinkPortfolio = internalRoutes.portfolio.routerLink; |
|
|
private readonly router = inject(Router); |
|
|
public routerLinkPricing = publicRoutes.pricing.routerLink; |
|
|
private readonly settingsStorageService = inject(SettingsStorageService); |
|
|
public routerLinkRegister = publicRoutes.register.routerLink; |
|
|
private readonly tokenStorageService = inject(TokenStorageService); |
|
|
public routerLinkResources = publicRoutes.resources.routerLink; |
|
|
private readonly userService = inject(UserService); |
|
|
|
|
|
|
|
|
public constructor( |
|
|
public constructor() { |
|
|
private dataService: DataService, |
|
|
|
|
|
private destroyRef: DestroyRef, |
|
|
|
|
|
private dialog: MatDialog, |
|
|
|
|
|
private impersonationStorageService: ImpersonationStorageService, |
|
|
|
|
|
private layoutService: LayoutService, |
|
|
|
|
|
private notificationService: NotificationService, |
|
|
|
|
|
private router: Router, |
|
|
|
|
|
private settingsStorageService: SettingsStorageService, |
|
|
|
|
|
private tokenStorageService: TokenStorageService, |
|
|
|
|
|
private userService: UserService |
|
|
|
|
|
) { |
|
|
|
|
|
this.impersonationStorageService |
|
|
this.impersonationStorageService |
|
|
.onChangeHasImpersonation() |
|
|
.onChangeHasImpersonation() |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
@ -162,55 +154,71 @@ export class GfHeaderComponent implements OnChanges { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@HostListener('window:keydown', ['$event']) |
|
|
|
|
|
protected openAssistantWithHotKey(event: KeyboardEvent) { |
|
|
|
|
|
if ( |
|
|
|
|
|
event.key === '/' && |
|
|
|
|
|
event.target instanceof Element && |
|
|
|
|
|
event.target?.nodeName?.toLowerCase() !== 'input' && |
|
|
|
|
|
event.target?.nodeName?.toLowerCase() !== 'textarea' && |
|
|
|
|
|
this.hasPermissionToAccessAssistant |
|
|
|
|
|
) { |
|
|
|
|
|
this.assistantElement().setIsOpen(true); |
|
|
|
|
|
this.assistentMenuTriggerElement().openMenu(); |
|
|
|
|
|
|
|
|
|
|
|
event.preventDefault(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public ngOnChanges() { |
|
|
public ngOnChanges() { |
|
|
this.hasFilters = this.userService.hasFilters(); |
|
|
this.hasFilters = this.userService.hasFilters(); |
|
|
|
|
|
|
|
|
this.hasPermissionForAuthGoogle = hasPermission( |
|
|
this.hasPermissionForAuthGoogle = hasPermission( |
|
|
this.info?.globalPermissions, |
|
|
this.info()?.globalPermissions, |
|
|
permissions.enableAuthGoogle |
|
|
permissions.enableAuthGoogle |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionForAuthOidc = hasPermission( |
|
|
this.hasPermissionForAuthOidc = hasPermission( |
|
|
this.info?.globalPermissions, |
|
|
this.info()?.globalPermissions, |
|
|
permissions.enableAuthOidc |
|
|
permissions.enableAuthOidc |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionForAuthToken = hasPermission( |
|
|
this.hasPermissionForAuthToken = hasPermission( |
|
|
this.info?.globalPermissions, |
|
|
this.info()?.globalPermissions, |
|
|
permissions.enableAuthToken |
|
|
permissions.enableAuthToken |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionForSubscription = hasPermission( |
|
|
this.hasPermissionForSubscription = hasPermission( |
|
|
this.info?.globalPermissions, |
|
|
this.info()?.globalPermissions, |
|
|
permissions.enableSubscription |
|
|
permissions.enableSubscription |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionToAccessAdminControl = hasPermission( |
|
|
this.hasPermissionToAccessAdminControl = hasPermission( |
|
|
this.user?.permissions, |
|
|
this.user()?.permissions, |
|
|
permissions.accessAdminControl |
|
|
permissions.accessAdminControl |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionToAccessAssistant = hasPermission( |
|
|
this.hasPermissionToAccessAssistant = hasPermission( |
|
|
this.user?.permissions, |
|
|
this.user()?.permissions, |
|
|
permissions.accessAssistant |
|
|
permissions.accessAssistant |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionToAccessFearAndGreedIndex = hasPermission( |
|
|
this.hasPermissionToAccessFearAndGreedIndex = hasPermission( |
|
|
this.info?.globalPermissions, |
|
|
this.info()?.globalPermissions, |
|
|
permissions.enableFearAndGreedIndex |
|
|
permissions.enableFearAndGreedIndex |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
this.hasPermissionToCreateUser = hasPermission( |
|
|
this.hasPermissionToCreateUser = hasPermission( |
|
|
this.info?.globalPermissions, |
|
|
this.info()?.globalPermissions, |
|
|
permissions.createUserAccount |
|
|
permissions.createUserAccount |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public closeAssistant() { |
|
|
protected closeAssistant() { |
|
|
this.assistentMenuTriggerElement?.closeMenu(); |
|
|
this.assistentMenuTriggerElement().closeMenu(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public impersonateAccount(aId: string) { |
|
|
protected impersonateAccount(aId: string) { |
|
|
if (aId) { |
|
|
if (aId) { |
|
|
this.impersonationStorageService.setId(aId); |
|
|
this.impersonationStorageService.setId(aId); |
|
|
} else { |
|
|
} else { |
|
|
@ -220,7 +228,7 @@ export class GfHeaderComponent implements OnChanges { |
|
|
window.location.reload(); |
|
|
window.location.reload(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onDateRangeChange(dateRange: DateRange) { |
|
|
protected onDateRangeChange(dateRange: DateRange) { |
|
|
this.dataService |
|
|
this.dataService |
|
|
.putUserSetting({ dateRange }) |
|
|
.putUserSetting({ dateRange }) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
.pipe(takeUntilDestroyed(this.destroyRef)) |
|
|
@ -232,7 +240,7 @@ export class GfHeaderComponent implements OnChanges { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onFiltersChanged(filters: Filter[]) { |
|
|
protected onFiltersChanged(filters: Filter[]) { |
|
|
const userSetting: UpdateUserSettingDto = {}; |
|
|
const userSetting: UpdateUserSettingDto = {}; |
|
|
|
|
|
|
|
|
for (const filter of filters) { |
|
|
for (const filter of filters) { |
|
|
@ -260,32 +268,33 @@ export class GfHeaderComponent implements OnChanges { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onLogoClick() { |
|
|
protected onLogoClick() { |
|
|
if (['home', 'zen'].includes(this.currentRoute)) { |
|
|
if (['home', 'zen'].includes(this.currentRoute())) { |
|
|
this.layoutService.getShouldReloadSubject().next(); |
|
|
this.layoutService.getShouldReloadSubject().next(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onMenuClosed() { |
|
|
protected onMenuClosed() { |
|
|
this.isMenuOpen = false; |
|
|
this.isMenuOpen = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onMenuOpened() { |
|
|
protected onMenuOpened() { |
|
|
this.isMenuOpen = true; |
|
|
this.isMenuOpen = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onOpenAssistant() { |
|
|
protected onOpenAssistant() { |
|
|
this.assistantElement.initialize(); |
|
|
this.assistantElement().initialize(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public onSignOut() { |
|
|
protected onSignOut() { |
|
|
this.signOut.next(); |
|
|
this.signOut.emit(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public openLoginDialog() { |
|
|
protected openLoginDialog() { |
|
|
const dialogRef = this.dialog.open< |
|
|
const dialogRef = this.dialog.open< |
|
|
GfLoginWithAccessTokenDialogComponent, |
|
|
GfLoginWithAccessTokenDialogComponent, |
|
|
LoginWithAccessTokenDialogParams |
|
|
LoginWithAccessTokenDialogParams, |
|
|
|
|
|
LoginWithAccessTokenDialogResult |
|
|
>(GfLoginWithAccessTokenDialogComponent, { |
|
|
>(GfLoginWithAccessTokenDialogComponent, { |
|
|
autoFocus: false, |
|
|
autoFocus: false, |
|
|
data: { |
|
|
data: { |
|
|
@ -322,7 +331,7 @@ export class GfHeaderComponent implements OnChanges { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public setToken(aToken: string) { |
|
|
private setToken(aToken: string) { |
|
|
this.tokenStorageService.saveToken( |
|
|
this.tokenStorageService.saveToken( |
|
|
aToken, |
|
|
aToken, |
|
|
this.settingsStorageService.getSetting(KEY_STAY_SIGNED_IN) === 'true' |
|
|
this.settingsStorageService.getSetting(KEY_STAY_SIGNED_IN) === 'true' |
|
|
|