Browse Source

feat(client): implement input signals

pull/6913/head
KenTandrian 6 days ago
parent
commit
e6832406a6
  1. 116
      apps/client/src/app/components/header/header.component.html
  2. 38
      apps/client/src/app/components/header/header.component.ts

116
apps/client/src/app/components/header/header.component.html

@ -1,14 +1,14 @@
<mat-toolbar class="px-0"> <mat-toolbar class="px-0">
@if (user) { @if (user()) {
<div class="d-flex h-100 logo-container" [class.filled]="hasTabs"> <div class="d-flex h-100 logo-container" [class.filled]="hasTabs()">
<a <a
class="align-items-center h-100 justify-content-start px-2 px-sm-3 rounded-0" class="align-items-center h-100 justify-content-start px-2 px-sm-3 rounded-0"
mat-button mat-button
[class.w-100]="hasTabs" [class.w-100]="hasTabs()"
[routerLink]="['/']" [routerLink]="['/']"
(click)="onLogoClick()" (click)="onLogoClick()"
> >
<gf-logo [label]="pageTitle" /> <gf-logo [label]="pageTitle()" />
</a> </a>
</div> </div>
<span class="gf-spacer"></span> <span class="gf-spacer"></span>
@ -20,11 +20,11 @@
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': 'font-weight-bold':
currentRoute === internalRoutes.home.path || currentRoute() === internalRoutes.home.path ||
currentRoute === internalRoutes.zen.path, currentRoute() === internalRoutes.zen.path,
'text-decoration-underline': 'text-decoration-underline':
currentRoute === internalRoutes.home.path || currentRoute() === internalRoutes.home.path ||
currentRoute === internalRoutes.zen.path currentRoute() === internalRoutes.zen.path
}" }"
[routerLink]="['/']" [routerLink]="['/']"
>Overview</a >Overview</a
@ -36,9 +36,9 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === internalRoutes.portfolio.path, 'font-weight-bold': currentRoute() === internalRoutes.portfolio.path,
'text-decoration-underline': 'text-decoration-underline':
currentRoute === internalRoutes.portfolio.path currentRoute() === internalRoutes.portfolio.path
}" }"
[routerLink]="routerLinkPortfolio" [routerLink]="routerLinkPortfolio"
>Portfolio</a >Portfolio</a
@ -50,9 +50,9 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === internalRoutes.accounts.path, 'font-weight-bold': currentRoute() === internalRoutes.accounts.path,
'text-decoration-underline': 'text-decoration-underline':
currentRoute === internalRoutes.accounts.path currentRoute() === internalRoutes.accounts.path
}" }"
[routerLink]="routerLinkAccounts" [routerLink]="routerLinkAccounts"
>Accounts</a >Accounts</a
@ -66,9 +66,9 @@
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': 'font-weight-bold':
currentRoute === internalRoutes.adminControl.path, currentRoute() === internalRoutes.adminControl.path,
'text-decoration-underline': 'text-decoration-underline':
currentRoute === internalRoutes.adminControl.path currentRoute() === internalRoutes.adminControl.path
}" }"
[routerLink]="routerLinkAdminControl" [routerLink]="routerLinkAdminControl"
>Admin Control</a >Admin Control</a
@ -81,29 +81,29 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routeResources, 'font-weight-bold': currentRoute() === routeResources,
'text-decoration-underline': currentRoute === routeResources 'text-decoration-underline': currentRoute() === routeResources
}" }"
[routerLink]="routerLinkResources" [routerLink]="routerLinkResources"
>Resources</a >Resources</a
> >
</li> </li>
@if ( @if (
hasPermissionForSubscription && user?.subscription?.type === 'Basic' hasPermissionForSubscription && user()?.subscription?.type === 'Basic'
) { ) {
<li class="list-inline-item"> <li class="list-inline-item">
<a <a
class="d-none d-sm-block rounded" class="d-none d-sm-block rounded"
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routePricing, 'font-weight-bold': currentRoute() === routePricing,
'text-decoration-underline': currentRoute === routePricing 'text-decoration-underline': currentRoute() === routePricing
}" }"
[routerLink]="routerLinkPricing" [routerLink]="routerLinkPricing"
> >
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<span i18n>Pricing</span> <span i18n>Pricing</span>
@if (currentRoute !== routePricing && hasPromotion) { @if (currentRoute() !== routePricing && hasPromotion()) {
<span class="badge badge-warning ml-1">%</span> <span class="badge badge-warning ml-1">%</span>
} }
</span> </span>
@ -116,8 +116,8 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routeAbout, 'font-weight-bold': currentRoute() === routeAbout,
'text-decoration-underline': currentRoute === routeAbout 'text-decoration-underline': currentRoute() === routeAbout
}" }"
[routerLink]="routerLinkAbout" [routerLink]="routerLinkAbout"
>About</a >About</a
@ -131,7 +131,7 @@
matBadge="&NoBreak;" matBadge="&NoBreak;"
matBadgeSize="small" matBadgeSize="small"
matButton matButton
[matBadgeHidden]="!hasFilters || !hasPermissionToChangeFilters" [matBadgeHidden]="!hasFilters || !hasPermissionToChangeFilters()"
[matMenuTriggerFor]="assistantMenu" [matMenuTriggerFor]="assistantMenu"
[matMenuTriggerRestoreFocus]="false" [matMenuTriggerRestoreFocus]="false"
(menuOpened)="onOpenAssistant()" (menuOpened)="onOpenAssistant()"
@ -143,17 +143,17 @@
class="no-max-width" class="no-max-width"
xPosition="before" xPosition="before"
[overlapTrigger]="true" [overlapTrigger]="true"
(closed)="assistantElement?.setIsOpen(false)" (closed)="assistantElement()?.setIsOpen(false)"
> >
<gf-assistant <gf-assistant
#assistant #assistant
[deviceType]="deviceType" [deviceType]="deviceType()"
[hasPermissionToAccessAdminControl]=" [hasPermissionToAccessAdminControl]="
hasPermissionToAccessAdminControl hasPermissionToAccessAdminControl
" "
[hasPermissionToChangeDateRange]="hasPermissionToChangeDateRange" [hasPermissionToChangeDateRange]="hasPermissionToChangeDateRange()"
[hasPermissionToChangeFilters]="hasPermissionToChangeFilters" [hasPermissionToChangeFilters]="hasPermissionToChangeFilters()"
[user]="user" [user]="user()"
(closed)="closeAssistant()" (closed)="closeAssistant()"
(dateRangeChanged)="onDateRangeChange($event)" (dateRangeChanged)="onDateRangeChange($event)"
(filtersChanged)="onFiltersChanged($event)" (filtersChanged)="onFiltersChanged($event)"
@ -182,12 +182,12 @@
</button> </button>
<mat-menu #accountMenu="matMenu" xPosition="before"> <mat-menu #accountMenu="matMenu" xPosition="before">
@if ( @if (
hasPermissionForSubscription && user?.subscription?.type === 'Basic' hasPermissionForSubscription && user()?.subscription?.type === 'Basic'
) { ) {
<a class="d-flex" mat-menu-item [routerLink]="routerLinkPricing" <a class="d-flex" mat-menu-item [routerLink]="routerLinkPricing"
><span class="align-items-center d-flex" ><span class="align-items-center d-flex"
><span> ><span>
@if (user.subscription.offer.isRenewal) { @if (user().subscription.offer.isRenewal) {
<ng-container i18n>Renew Plan</ng-container> <ng-container i18n>Renew Plan</ng-container>
} @else { } @else {
<ng-container i18n>Upgrade Plan</ng-container> <ng-container i18n>Upgrade Plan</ng-container>
@ -199,7 +199,7 @@
></a> ></a>
<hr class="m-0" /> <hr class="m-0" />
} }
@if (user?.access?.length > 0) { @if (user()?.access?.length > 0) {
<button mat-menu-item (click)="impersonateAccount(null)"> <button mat-menu-item (click)="impersonateAccount(null)">
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<ion-icon <ion-icon
@ -213,7 +213,7 @@
<span i18n>Me</span> <span i18n>Me</span>
</span> </span>
</button> </button>
@for (accessItem of user?.access; track accessItem) { @for (accessItem of user()?.access; track accessItem) {
<button mat-menu-item (click)="impersonateAccount(accessItem.id)"> <button mat-menu-item (click)="impersonateAccount(accessItem.id)">
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<ion-icon <ion-icon
@ -240,8 +240,8 @@
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]=" [class.font-weight-bold]="
currentRoute === internalRoutes.home.path || currentRoute() === internalRoutes.home.path ||
currentRoute === internalRoutes.zen.path currentRoute() === internalRoutes.zen.path
" "
[routerLink]="['/']" [routerLink]="['/']"
>Overview</a >Overview</a
@ -251,7 +251,7 @@
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]=" [class.font-weight-bold]="
currentRoute === internalRoutes.portfolio.path currentRoute() === internalRoutes.portfolio.path
" "
[routerLink]="routerLinkPortfolio" [routerLink]="routerLinkPortfolio"
>Portfolio</a >Portfolio</a
@ -261,7 +261,7 @@
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]=" [class.font-weight-bold]="
currentRoute === internalRoutes.accounts.path currentRoute() === internalRoutes.accounts.path
" "
[routerLink]="routerLinkAccounts" [routerLink]="routerLinkAccounts"
>Accounts</a >Accounts</a
@ -270,7 +270,7 @@
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]=" [class.font-weight-bold]="
currentRoute === internalRoutes.account.path currentRoute() === internalRoutes.account.path
" "
[routerLink]="routerLinkAccount" [routerLink]="routerLinkAccount"
>My Ghostfolio</a >My Ghostfolio</a
@ -281,7 +281,7 @@
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]=" [class.font-weight-bold]="
currentRoute === internalRoutes.adminControl.path currentRoute() === internalRoutes.adminControl.path
" "
[routerLink]="routerLinkAdminControl" [routerLink]="routerLinkAdminControl"
>Admin Control</a >Admin Control</a
@ -292,22 +292,22 @@
class="d-flex d-sm-none" class="d-flex d-sm-none"
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]="currentRoute === routeResources" [class.font-weight-bold]="currentRoute() === routeResources"
[routerLink]="routerLinkResources" [routerLink]="routerLinkResources"
>Resources</a >Resources</a
> >
@if ( @if (
hasPermissionForSubscription && user?.subscription?.type === 'Basic' hasPermissionForSubscription && user()?.subscription?.type === 'Basic'
) { ) {
<a <a
class="d-flex d-sm-none" class="d-flex d-sm-none"
mat-menu-item mat-menu-item
[class.font-weight-bold]="currentRoute === routePricing" [class.font-weight-bold]="currentRoute() === routePricing"
[routerLink]="routerLinkPricing" [routerLink]="routerLinkPricing"
> >
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<span i18n>Pricing</span> <span i18n>Pricing</span>
@if (currentRoute !== routePricing && hasPromotion) { @if (currentRoute() !== routePricing && hasPromotion()) {
<span class="badge badge-warning ml-1">%</span> <span class="badge badge-warning ml-1">%</span>
} }
</span> </span>
@ -317,7 +317,7 @@
class="d-flex d-sm-none" class="d-flex d-sm-none"
i18n i18n
mat-menu-item mat-menu-item
[class.font-weight-bold]="currentRoute === routeAbout" [class.font-weight-bold]="currentRoute() === routeAbout"
[routerLink]="routerLinkAbout" [routerLink]="routerLinkAbout"
>About Ghostfolio</a >About Ghostfolio</a
> >
@ -327,17 +327,17 @@
</li> </li>
</ul> </ul>
} }
@if (user === null) { @if (user() === null) {
<div class="d-flex h-100 logo-container" [class.filled]="hasTabs"> <div class="d-flex h-100 logo-container" [class.filled]="hasTabs()">
<a <a
class="align-items-center h-100 justify-content-start px-2 px-sm-3 rounded-0" class="align-items-center h-100 justify-content-start px-2 px-sm-3 rounded-0"
mat-button mat-button
[class.w-100]="hasTabs" [class.w-100]="hasTabs()"
[routerLink]="['/']" [routerLink]="['/']"
> >
<gf-logo <gf-logo
[label]="pageTitle" [label]="pageTitle()"
[showLabel]="currentRoute !== 'register'" [showLabel]="currentRoute() !== 'register'"
/> />
</a> </a>
</div> </div>
@ -349,8 +349,8 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routeFeatures, 'font-weight-bold': currentRoute() === routeFeatures,
'text-decoration-underline': currentRoute === routeFeatures 'text-decoration-underline': currentRoute() === routeFeatures
}" }"
[routerLink]="routerLinkFeatures" [routerLink]="routerLinkFeatures"
>Features</a >Features</a
@ -362,8 +362,8 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routeAbout, 'font-weight-bold': currentRoute() === routeAbout,
'text-decoration-underline': currentRoute === routeAbout 'text-decoration-underline': currentRoute() === routeAbout
}" }"
[routerLink]="routerLinkAbout" [routerLink]="routerLinkAbout"
>About</a >About</a
@ -375,14 +375,14 @@
class="d-sm-block rounded" class="d-sm-block rounded"
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routePricing, 'font-weight-bold': currentRoute() === routePricing,
'text-decoration-underline': currentRoute === routePricing 'text-decoration-underline': currentRoute() === routePricing
}" }"
[routerLink]="routerLinkPricing" [routerLink]="routerLinkPricing"
> >
<span class="align-items-center d-flex"> <span class="align-items-center d-flex">
<span i18n>Pricing</span> <span i18n>Pricing</span>
@if (currentRoute !== routePricing && hasPromotion) { @if (currentRoute() !== routePricing && hasPromotion()) {
<span class="badge badge-warning ml-1">%</span> <span class="badge badge-warning ml-1">%</span>
} }
</span> </span>
@ -396,8 +396,8 @@
i18n i18n
mat-button mat-button
[class]="{ [class]="{
'font-weight-bold': currentRoute === routeMarkets, 'font-weight-bold': currentRoute() === routeMarkets,
'text-decoration-underline': currentRoute === routeMarkets 'text-decoration-underline': currentRoute() === routeMarkets
}" }"
[routerLink]="routerLinkMarkets" [routerLink]="routerLinkMarkets"
>Markets</a >Markets</a
@ -421,7 +421,7 @@
<ng-container i18n>Sign in</ng-container> <ng-container i18n>Sign in</ng-container>
</button> </button>
</li> </li>
@if (currentRoute !== 'register' && hasPermissionToCreateUser) { @if (currentRoute() !== 'register' && hasPermissionToCreateUser) {
<li class="list-inline-item ml-1"> <li class="list-inline-item ml-1">
<a <a
class="d-none d-sm-block px-3 rounded" class="d-none d-sm-block px-3 rounded"

38
apps/client/src/app/components/header/header.component.ts

@ -29,7 +29,7 @@ import {
DestroyRef, DestroyRef,
HostListener, HostListener,
inject, inject,
Input, input,
OnChanges, OnChanges,
output, output,
viewChild viewChild
@ -74,15 +74,15 @@ import { catchError } from 'rxjs/operators';
styleUrls: ['./header.component.scss'] styleUrls: ['./header.component.scss']
}) })
export class GfHeaderComponent implements OnChanges { export class GfHeaderComponent implements OnChanges {
@Input() public currentRoute: string; public readonly currentRoute = input.required<string>();
@Input() public deviceType: string; public readonly deviceType = input.required<string>();
@Input() public hasPermissionToChangeDateRange: boolean; public readonly hasPermissionToChangeDateRange = input.required<boolean>();
@Input() public hasPermissionToChangeFilters: boolean; public readonly hasPermissionToChangeFilters = input.required<boolean>();
@Input() public hasPromotion: boolean; public readonly hasPromotion = input.required<boolean>();
@Input() public hasTabs: boolean; public readonly hasTabs = input.required<boolean>();
@Input() public info: InfoItem; public readonly info = input.required<InfoItem | undefined>();
@Input() public pageTitle: string; public readonly pageTitle = input.required<string>();
@Input() public user: User; public readonly user = input.required<User | undefined>();
public readonly signOut = output<void>(); public readonly signOut = output<void>();
@ -174,42 +174,42 @@ export class GfHeaderComponent implements OnChanges {
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
); );
} }
@ -269,7 +269,7 @@ export class GfHeaderComponent implements OnChanges {
} }
protected onLogoClick() { protected onLogoClick() {
if (['home', 'zen'].includes(this.currentRoute)) { if (['home', 'zen'].includes(this.currentRoute())) {
this.layoutService.getShouldReloadSubject().next(); this.layoutService.getShouldReloadSubject().next();
} }
} }

Loading…
Cancel
Save