feat(console): rehauled navigation for instances including breadcrumb (#10283)

This PR significantly improves user navigation by introducing a new
instance-level navigation bar. This new bar, positioned above the
existing organization navigation, provides quick access to key sections:
Home, Organizations, Actions, and Settings.

Additionally, the breadcrumb component has been refined for more
consistent behavior, reintroducing intuitive breadcrumb buttons to
easily navigate up the hierarchy. These changes also include design
improvements for a cleaner and more streamlined appearance across the
interface.

<img width="423" height="138" alt="Screenshot 2025-07-17 at 14 55 46"
src="https://github.com/user-attachments/assets/ba9e40a1-1077-4cb6-8735-ac7ab637abe7"
/>
<img width="562" height="132" alt="Screenshot 2025-07-17 at 14 56 41"
src="https://github.com/user-attachments/assets/d85dc673-0df8-4677-9d2b-dc031dde42c3"
/>
<img width="545" height="254" alt="Screenshot 2025-07-17 at 14 56 10"
src="https://github.com/user-attachments/assets/eaf10117-079e-4181-8dbb-60c89b24556a"
/>
<img width="689" height="261" alt="Screenshot 2025-07-17 at 14 56 20"
src="https://github.com/user-attachments/assets/510ad550-1d9a-4c6a-8af1-66cb0b23619c"
/>

---------

Co-authored-by: conblem <mail@conblem.me>
Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
Co-authored-by: Florian Forster <florian@zitadel.com>
This commit is contained in:
Max Peintner
2025-08-28 11:23:14 +02:00
committed by GitHub
parent cccba3f8f3
commit f963ea9f86
117 changed files with 3286 additions and 2360 deletions

View File

@@ -1,5 +1,5 @@
import { KeyValue } from '@angular/common';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Component, DestroyRef, Input, OnDestroy, OnInit } from '@angular/core';
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
import { BehaviorSubject, from, Observable, of, Subject } from 'rxjs';
import { catchError, debounceTime, scan, take, takeUntil, tap } from 'rxjs/operators';
@@ -13,6 +13,7 @@ import {
} from 'src/app/proto/generated/zitadel/management_pb';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
export enum ChangeType {
MYUSER = 'myuser',
@@ -45,17 +46,18 @@ type ListChanges =
| ListOrgChangesResponse.AsObject
| ListAppChangesResponse.AsObject;
// todo: update this component to react to input changes
@Component({
selector: 'cnsl-changes',
templateUrl: './changes.component.html',
styleUrls: ['./changes.component.scss'],
})
export class ChangesComponent implements OnInit, OnDestroy {
@Input() public changeType: ChangeType = ChangeType.USER;
export class ChangesComponent implements OnInit {
@Input({ required: true }) public changeType!: ChangeType;
@Input() public id: string = '';
@Input() public secId: string = '';
@Input() public sortDirectionAsc: boolean = true;
@Input() public refresh!: Observable<void>;
@Input() public refresh?: Observable<void>;
public bottom: boolean = false;
private _done: BehaviorSubject<any> = new BehaviorSubject(false);
@@ -65,30 +67,26 @@ export class ChangesComponent implements OnInit, OnDestroy {
loading: Observable<boolean> = this._loading.asObservable();
public data: Observable<MappedChange[]> = this._data.asObservable().pipe(
scan((acc, val) => {
return false ? val.concat(acc) : acc.concat(val);
return acc.concat(val);
}),
);
public changes!: ListChanges;
private destroyed$: Subject<void> = new Subject();
constructor(
private mgmtUserService: ManagementService,
private authUserService: GrpcAuthService,
private readonly mgmtUserService: ManagementService,
private readonly authUserService: GrpcAuthService,
private readonly destroyRef: DestroyRef,
) {}
ngOnInit(): void {
this.init();
if (this.refresh) {
this.refresh.pipe(takeUntil(this.destroyed$), debounceTime(2000)).subscribe(() => {
this.refresh.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(2000)).subscribe(() => {
this._data = new BehaviorSubject([]);
this.init();
});
}
}
ngOnDestroy(): void {
this.destroyed$.next();
}
public init(): void {
let first: Promise<ListChanges>;
switch (this.changeType) {