Files
zitadel/console/src/app/modules/header/header.component.html
T
0945195f68 chore: deps update (#11968)
# Which Problems Are Solved
This pr updates major and minor dependencies and is the first step on
getting our dependabot alerts cut down.

# How the Problems Are Solved

Depedency updates across the board eg:
- Upgrade Angular to v21
- Upgrade next.js to v16.2
- Upgrade tailwind to v4 in the login
- Upgrade vitest to v4 in the login

This is an uncompleted list refer to the changed files for a full
overview of all the updates.

# Additional Changes

Migrated all control flow in the console to the modern control flow
syntax.
Fixed the dependsOn setting for the @zitadel/login:test-unit nx target.

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/11274

---------

Co-authored-by: Max Peintner <[email protected]>
2026-04-02 15:53:08 +02:00

244 lines
8.6 KiB
HTML

<mat-toolbar class="header-wrapper">
<div class="header-content">
@if (authService.labelPolicyLoading$ | async) {
<div class="logo-placeholder">
<mat-spinner [diameter]="20"></mat-spinner>
</div>
} @else {
@if (authService.labelpolicy$ | async; as lP) {
<a class="title custom" [routerLink]="['/']">
@if (isDarkTheme) {
<img
class="logo"
alt="home logo"
[src]="lP.iconUrlDark ? lP.iconUrlDark : './assets/images/zitadel-logo-solo-light.svg'"
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-light.svg')"
/>
} @else {
<img
alt="home logo"
class="logo"
[src]="lP.iconUrl ? lP.iconUrl : './assets/images/zitadel-logo-solo-dark.svg'"
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-dark.svg')"
/>
}
</a>
} @else {
<a class="title" [routerLink]="(authService.zitadelPermissions | async)?.length ? ['/'] : ['/users', 'me']">
@if (isDarkTheme) {
<img class="logo" alt="zitadel logo" src="./assets/images/zitadel-logo-solo-light.svg" />
} @else {
<img alt="zitadel logo" class="logo" src="./assets/images/zitadel-logo-solo-dark.svg" />
}
</a>
}
}
<ng-container *ngFor="let bread of breadcrumbService.breadcrumbs$ | async as bc; index as i">
@if (bread.type === BreadcrumbType.INSTANCE) {
<ng-template cnslHasRole [hasRole]="['iam.read']">
<svg
class="slash hide-on-small"
viewBox="0 0 24 24"
width="32"
height="32"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
shape-rendering="geometricPrecision"
>
<path d="M16.88 3.549L7.12 20.451"></path>
</svg>
<div class="breadcrumb-context hide-on-small">
<a matRipple [matRippleUnbounded]="false" class="breadcrumb-link" [routerLink]="bread.routerLink">
{{ 'MENU.INSTANCE' | translate }}
</a>
</div>
</ng-template>
}
@if (bread.type === BreadcrumbType.ORG) {
<svg
class="slash"
viewBox="0 0 24 24"
width="32"
height="32"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
shape-rendering="geometricPrecision"
>
<path d="M16.88 3.549L7.12 20.451"></path>
</svg>
<div class="org-context">
@if (org(); as org) {
<a matRipple [matRippleUnbounded]="false" class="org-link" id="orglink" [routerLink]="['/org']">
{{ org.name ? org.name : 'NO NAME' }}</a
>
}
<div class="org-context-wrapper">
<button
cdkOverlayOrigin
#trigger="cdkOverlayOrigin"
matRipple
[matRippleUnbounded]="false"
id="orgswitchbutton"
class="org-switch-button"
(click)="showOrgContext = !showOrgContext"
>
<span class="svgspan">
<svg xmlns=" http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path
fill-rule="evenodd"
d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</span>
<cnsl-action-keys
(actionTriggered)="showOrgContext = !showOrgContext"
[type]="ActionKeysType.ORGSWITCHER"
></cnsl-action-keys>
</button>
<ng-template
cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="trigger"
[cdkConnectedOverlayOffsetY]="10"
[cdkConnectedOverlayHasBackdrop]="true"
[cdkConnectedOverlayPositions]="positions"
cdkConnectedOverlayBackdropClass="transparent-backdrop"
[cdkConnectedOverlayOpen]="showOrgContext"
(backdropClick)="showOrgContext = false"
(detach)="showOrgContext = false"
>
@if (showOrgContext && org(); as org) {
<cnsl-org-context
class="context_card"
(closedCard)="showOrgContext = false"
[org]="org"
(setOrg)="setActiveOrg($event)"
>
</cnsl-org-context>
}
</ng-template>
</div>
</div>
}
@if (bread.type !== BreadcrumbType.INSTANCE && bread.type !== BreadcrumbType.ORG) {
<svg
class="slash"
viewBox="0 0 24 24"
width="32"
height="32"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
shape-rendering="geometricPrecision"
>
<path d="M16.88 3.549L7.12 20.451"></path>
</svg>
<div class="breadcrumb-context">
<a
matRipple
[matRippleUnbounded]="false"
class="breadcrumb-link"
[ngClass]="{ maxwidth: bc.length > 1 }"
[routerLink]="bread.routerLink"
>
@if (i !== bc.length - 1) {
<span class="desk">{{ bread.name }}</span>
<span class="mob">...</span>
} @else {
<span>{{ bread.name }}</span>
}
</a>
</div>
}
</ng-container>
<span class="fill-space"></span>
@if (authService.privacypolicy$ | async; as pP) {
@if (pP.customLink) {
<a class="custom-link" href="{{ pP.customLink }}" mat-stroked-button target="_blank">
{{ pP.customLinkText }}
</a>
}
@if (pP.docsLink) {
<a class="doc-link" href="{{ pP.docsLink }}" mat-stroked-button target="_blank">
{{ 'MENU.DOCUMENTATION' | translate }}
</a>
}
}
@if (!isOnMe) {
<div class="system-rel">
@if (!isOnInstance && (['iam.read$', 'iam.write$'] | hasRole | async)) {
<a id="systembutton" [routerLink]="['/instance']" class="iam-settings" mat-stroked-button>
<div class="cnsl-action-button">
<span class="iam-label">{{ 'MENU.INSTANCE' | translate }}</span>
<i class="las la-cog"></i>
</div>
</a>
}
@if (isOnInstance && (['org.read'] | hasRole | async)) {
<a id="orgbutton" [routerLink]="['/org']" class="org-settings" mat-stroked-button>
<div class="cnsl-action-button">
<span class="iam-label">{{ 'MENU.ORGANIZATION' | translate }}</span>
<i class="las la-cog"></i>
</div>
</a>
}
</div>
}
@if (user && user.id) {
<div class="account-card-wrapper">
<button
cdkOverlayOrigin
#accounttrigger="cdkOverlayOrigin"
class="icon-container"
(click)="showAccount = !showAccount"
[ngClass]="{ 'iam-user': (['iam.write$'] | hasRole | async) }"
>
<cnsl-avatar
id="avatartoggle"
class="avatar-toggle dontcloseonclick"
[active]="showAccount"
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
[forColor]="user.preferredLoginName || ''"
[name]="user.human?.profile?.displayName ?? ''"
[size]="38"
>
</cnsl-avatar>
</button>
</div>
<ng-template
cdkConnectedOverlay
[cdkConnectedOverlayOrigin]="accounttrigger"
[cdkConnectedOverlayOffsetY]="10"
[cdkConnectedOverlayHasBackdrop]="true"
[cdkConnectedOverlayPositions]="accountCardPositions"
cdkConnectedOverlayBackdropClass="transparent-backdrop"
[cdkConnectedOverlayOpen]="showAccount"
(backdropClick)="showAccount = false"
(detach)="showAccount = false"
>
@if (showAccount) {
<cnsl-accounts-card
class="a_card"
(closedCard)="showAccount = false"
[user]="user"
[iamuser]="['iam.write$'] | hasRole | async"
>
</cnsl-accounts-card>
}
</ng-template>
}
</div>
</mat-toolbar>