mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
8.1 KiB
269 lines
8.1 KiB
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
|
|
import { LoginWithAccessTokenDialog } from '@ghostfolio/client/components/login-with-access-token-dialog/login-with-access-token-dialog.component';
|
|
import { LayoutService } from '@ghostfolio/client/core/layout.service';
|
|
import { NotificationService } from '@ghostfolio/client/core/notification/notification.service';
|
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
|
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
|
|
import {
|
|
KEY_STAY_SIGNED_IN,
|
|
SettingsStorageService
|
|
} from '@ghostfolio/client/services/settings-storage.service';
|
|
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
|
|
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
|
import { Filter, InfoItem, User } from '@ghostfolio/common/interfaces';
|
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
|
import { DateRange } from '@ghostfolio/common/types';
|
|
import { GfAssistantComponent } from '@ghostfolio/ui/assistant/assistant.component';
|
|
|
|
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
EventEmitter,
|
|
HostListener,
|
|
Input,
|
|
OnChanges,
|
|
Output,
|
|
ViewChild
|
|
} from '@angular/core';
|
|
import { MatDialog } from '@angular/material/dialog';
|
|
import { MatMenuTrigger } from '@angular/material/menu';
|
|
import { Router } from '@angular/router';
|
|
import { EMPTY, Subject } from 'rxjs';
|
|
import { catchError, takeUntil } from 'rxjs/operators';
|
|
|
|
@Component({
|
|
selector: 'gf-header',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
templateUrl: './header.component.html',
|
|
styleUrls: ['./header.component.scss']
|
|
})
|
|
export class HeaderComponent implements OnChanges {
|
|
@HostListener('window:keydown', ['$event'])
|
|
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();
|
|
}
|
|
}
|
|
|
|
@Input() currentRoute: string;
|
|
@Input() deviceType: string;
|
|
@Input() hasTabs: boolean;
|
|
@Input() info: InfoItem;
|
|
@Input() pageTitle: string;
|
|
@Input() user: User;
|
|
|
|
@Output() signOut = new EventEmitter<void>();
|
|
|
|
@ViewChild('assistant') assistantElement: GfAssistantComponent;
|
|
@ViewChild('assistantTrigger') assistentMenuTriggerElement: MatMenuTrigger;
|
|
|
|
public hasFilters: boolean;
|
|
public hasPermissionForSocialLogin: boolean;
|
|
public hasPermissionForSubscription: boolean;
|
|
public hasPermissionToAccessAdminControl: boolean;
|
|
public hasPermissionToAccessAssistant: boolean;
|
|
public hasPermissionToAccessFearAndGreedIndex: boolean;
|
|
public hasPermissionToCreateUser: boolean;
|
|
public impersonationId: string;
|
|
public isMenuOpen: boolean;
|
|
public routeAbout = $localize`about`;
|
|
public routeFeatures = $localize`features`;
|
|
public routeMarkets = $localize`markets`;
|
|
public routePricing = $localize`pricing`;
|
|
public routeResources = $localize`resources`;
|
|
public routerLinkAbout = ['/' + $localize`about`];
|
|
public routerLinkFeatures = ['/' + $localize`features`];
|
|
public routerLinkMarkets = ['/' + $localize`markets`];
|
|
public routerLinkPricing = ['/' + $localize`pricing`];
|
|
public routerLinkRegister = ['/' + $localize`register`];
|
|
public routerLinkResources = ['/' + $localize`resources`];
|
|
|
|
private unsubscribeSubject = new Subject<void>();
|
|
|
|
public constructor(
|
|
private dataService: DataService,
|
|
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
|
|
.onChangeHasImpersonation()
|
|
.pipe(takeUntil(this.unsubscribeSubject))
|
|
.subscribe((impersonationId) => {
|
|
this.impersonationId = impersonationId;
|
|
});
|
|
}
|
|
|
|
public ngOnChanges() {
|
|
this.hasFilters = this.userService.hasFilters();
|
|
|
|
this.hasPermissionForSocialLogin = hasPermission(
|
|
this.info?.globalPermissions,
|
|
permissions.enableSocialLogin
|
|
);
|
|
|
|
this.hasPermissionForSubscription = hasPermission(
|
|
this.info?.globalPermissions,
|
|
permissions.enableSubscription
|
|
);
|
|
|
|
this.hasPermissionToAccessAdminControl = hasPermission(
|
|
this.user?.permissions,
|
|
permissions.accessAdminControl
|
|
);
|
|
|
|
this.hasPermissionToAccessAssistant = hasPermission(
|
|
this.user?.permissions,
|
|
permissions.accessAssistant
|
|
);
|
|
|
|
this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
|
|
this.info?.globalPermissions,
|
|
permissions.enableFearAndGreedIndex
|
|
);
|
|
|
|
this.hasPermissionToCreateUser = hasPermission(
|
|
this.info?.globalPermissions,
|
|
permissions.createUserAccount
|
|
);
|
|
}
|
|
|
|
public closeAssistant() {
|
|
this.assistentMenuTriggerElement?.closeMenu();
|
|
}
|
|
|
|
public impersonateAccount(aId: string) {
|
|
if (aId) {
|
|
this.impersonationStorageService.setId(aId);
|
|
} else {
|
|
this.impersonationStorageService.removeId();
|
|
}
|
|
|
|
window.location.reload();
|
|
}
|
|
|
|
public onDateRangeChange(dateRange: DateRange) {
|
|
this.dataService
|
|
.putUserSetting({ dateRange })
|
|
.pipe(takeUntil(this.unsubscribeSubject))
|
|
.subscribe(() => {
|
|
this.userService
|
|
.get(true)
|
|
.pipe(takeUntil(this.unsubscribeSubject))
|
|
.subscribe();
|
|
});
|
|
}
|
|
|
|
public onFiltersChanged(filters: Filter[]) {
|
|
const userSetting: UpdateUserSettingDto = {};
|
|
|
|
for (const filter of filters) {
|
|
let filtersType: string;
|
|
|
|
if (filter.type === 'ACCOUNT') {
|
|
filtersType = 'accounts';
|
|
} else if (filter.type === 'ASSET_CLASS') {
|
|
filtersType = 'assetClasses';
|
|
} else if (filter.type === 'TAG') {
|
|
filtersType = 'tags';
|
|
}
|
|
|
|
userSetting[`filters.${filtersType}`] = filter.id ? [filter.id] : null;
|
|
}
|
|
|
|
this.dataService
|
|
.putUserSetting(userSetting)
|
|
.pipe(takeUntil(this.unsubscribeSubject))
|
|
.subscribe(() => {
|
|
this.userService
|
|
.get(true)
|
|
.pipe(takeUntil(this.unsubscribeSubject))
|
|
.subscribe();
|
|
});
|
|
}
|
|
|
|
public onLogoClick() {
|
|
if (this.currentRoute === 'home' || this.currentRoute === 'zen') {
|
|
this.layoutService.getShouldReloadSubject().next();
|
|
}
|
|
}
|
|
|
|
public onMenuClosed() {
|
|
this.isMenuOpen = false;
|
|
}
|
|
|
|
public onMenuOpened() {
|
|
this.isMenuOpen = true;
|
|
}
|
|
|
|
public onOpenAssistant() {
|
|
this.assistantElement.initialize();
|
|
}
|
|
|
|
public onSignOut() {
|
|
this.signOut.next();
|
|
}
|
|
|
|
public openLoginDialog() {
|
|
const dialogRef = this.dialog.open(LoginWithAccessTokenDialog, {
|
|
autoFocus: false,
|
|
data: {
|
|
accessToken: '',
|
|
hasPermissionToUseSocialLogin: this.hasPermissionForSocialLogin,
|
|
title: $localize`Sign in`
|
|
},
|
|
width: '30rem'
|
|
});
|
|
|
|
dialogRef
|
|
.afterClosed()
|
|
.pipe(takeUntil(this.unsubscribeSubject))
|
|
.subscribe((data) => {
|
|
if (data?.accessToken) {
|
|
this.dataService
|
|
.loginAnonymous(data?.accessToken)
|
|
.pipe(
|
|
catchError(() => {
|
|
this.notificationService.alert({
|
|
title: $localize`Oops! Incorrect Security Token.`
|
|
});
|
|
|
|
return EMPTY;
|
|
}),
|
|
takeUntil(this.unsubscribeSubject)
|
|
)
|
|
.subscribe(({ authToken }) => {
|
|
this.setToken(authToken);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
public setToken(aToken: string) {
|
|
this.tokenStorageService.saveToken(
|
|
aToken,
|
|
this.settingsStorageService.getSetting(KEY_STAY_SIGNED_IN) === 'true'
|
|
);
|
|
|
|
this.router.navigate(['/']);
|
|
}
|
|
|
|
public ngOnDestroy() {
|
|
this.unsubscribeSubject.next();
|
|
this.unsubscribeSubject.complete();
|
|
}
|
|
}
|
|
|