mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-03 12:52:16 +00:00
feat: console flat navigation, settings (#3581)
* instance routing * instance naming * org list * rm isonsystem * breadcrumb type * routing * instance members * fragment refresh org * settings pages * settings list, sidenav grouping, i18n * org-settings, policy changes * lint * grid * rename grid * fallback to general * cleanup * general settings, remove cards * sidenav for settings, label policy * i18n * header, nav backbuild * general, project nav rehaul * login text background adapt * org nav anim * org, instance settings, fix policy layout, roles * i18n, active route for project * lint
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
<div class="sidenav-container">
|
||||
<div class="sidenav-settings-list">
|
||||
<div class="sidenav-settings-list" [ngClass]="{ indented: indented }">
|
||||
<div class="sidenav-sticky-rel">
|
||||
<h1 *ngIf="title">{{ title }}</h1>
|
||||
<p *ngIf="description" class="cnsl-secondary-text">{{ description }}</p>
|
||||
|
||||
<button
|
||||
*ngIf="currentSetting !== undefined"
|
||||
(click)="value = undefined"
|
||||
@@ -10,8 +13,19 @@
|
||||
<i class="las la-angle-left"></i>
|
||||
<span>{{ 'USER.SETTINGS.TITLE' | translate }}</span>
|
||||
</button>
|
||||
<ng-container *ngFor="let setting of settingsList">
|
||||
|
||||
<ng-container *ngFor="let setting of settingsList; index as i">
|
||||
<ng-container>
|
||||
<span
|
||||
class="sidenav-setting-group hide-on-mobile"
|
||||
[ngClass]="{ show: currentSetting === undefined }"
|
||||
*ngIf="
|
||||
(setting.groupI18nKey && i > 0 && setting.groupI18nKey !== settingsList[i - 1].groupI18nKey) ||
|
||||
(i === 0 && setting.groupI18nKey)
|
||||
"
|
||||
>{{ setting.groupI18nKey | translate }}</span
|
||||
>
|
||||
|
||||
<button
|
||||
(click)="value = setting.id"
|
||||
class="sidenav-setting-list-element hide-on-mobile"
|
||||
@@ -34,8 +48,6 @@
|
||||
</div>
|
||||
|
||||
<div class="sidenav-content">
|
||||
<div class="max-width-container">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
@mixin sidenav-theme($theme) {
|
||||
$foreground: map-get($theme, foreground);
|
||||
$background: map-get($theme, background);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
|
||||
.sidenav-container {
|
||||
padding-top: 1rem;
|
||||
display: grid;
|
||||
position: relative;
|
||||
grid-template-columns: 1fr;
|
||||
@@ -13,12 +13,54 @@
|
||||
.sidenav-settings-list {
|
||||
position: relative;
|
||||
|
||||
&.indented {
|
||||
margin-right: 2rem;
|
||||
|
||||
.sidenav-sticky-rel {
|
||||
margin-left: -2rem;
|
||||
padding-left: 2rem;
|
||||
background: map-get($background, footer);
|
||||
}
|
||||
}
|
||||
|
||||
.sidenav-sticky-rel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
padding: 1rem 2rem 1rem 0;
|
||||
top: 36px;
|
||||
padding: 20px 2rem 20px 0;
|
||||
|
||||
.sidenav-setting-group {
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: if($is-dark-theme, #ffffff60, #00000060);
|
||||
margin-top: 1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||
|
||||
&:nth-child(2) {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&.hide-on-mobile {
|
||||
@media only screen and (max-width: 500px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.show {
|
||||
display: none;
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidenav-setting-list-element {
|
||||
border: none;
|
||||
|
||||
@@ -1,30 +1,63 @@
|
||||
import { Component, forwardRef, Input } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
|
||||
|
||||
export interface SidenavSetting {
|
||||
id: string;
|
||||
i18nKey: string;
|
||||
groupI18nKey?: string;
|
||||
requiredRoles?: { [serviceType in PolicyComponentServiceType]: string[] };
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-sidenav',
|
||||
templateUrl: './sidenav.component.html',
|
||||
styleUrls: ['./sidenav.component.scss'],
|
||||
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SidenavComponent), multi: true }],
|
||||
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: SidenavComponent, multi: true }],
|
||||
})
|
||||
export class SidenavComponent {
|
||||
@Input() public currentSetting: string | undefined = 'general';
|
||||
export class SidenavComponent implements ControlValueAccessor, OnInit {
|
||||
@Input() public title: string = '';
|
||||
@Input() public description: string = '';
|
||||
@Input() public indented: boolean = false;
|
||||
@Input() public currentSetting?: string | undefined = undefined;
|
||||
@Input() public settingsList: SidenavSetting[] = [];
|
||||
@Input() public queryParam: string = '';
|
||||
|
||||
constructor() {}
|
||||
constructor(private router: Router, private route: ActivatedRoute) {}
|
||||
|
||||
private onChange: any = () => {};
|
||||
private onTouch: any = () => {};
|
||||
ngOnInit(): void {
|
||||
if (!this.value) {
|
||||
this.value = this.settingsList[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
private onChange = (current: string | undefined) => {};
|
||||
private onTouch = (current: string | undefined) => {};
|
||||
|
||||
@Input() get value(): string | undefined {
|
||||
return this.currentSetting;
|
||||
}
|
||||
|
||||
set value(setting: string | undefined) {
|
||||
this.currentSetting = setting;
|
||||
this.onChange(setting);
|
||||
this.onTouch(setting);
|
||||
|
||||
if (setting || setting === undefined) {
|
||||
this.onChange(setting);
|
||||
this.onTouch(setting);
|
||||
}
|
||||
|
||||
if (this.queryParam && setting) {
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.route,
|
||||
queryParams: {
|
||||
[this.queryParam]: setting,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
skipLocationChange: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public writeValue(value: any) {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { SidenavComponent } from './sidenav.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [SidenavComponent],
|
||||
imports: [CommonModule, MatIconModule, TranslateModule],
|
||||
imports: [CommonModule, FormsModule, RouterModule, MatIconModule, TranslateModule],
|
||||
exports: [SidenavComponent],
|
||||
})
|
||||
export class SidenavModule {}
|
||||
|
||||
Reference in New Issue
Block a user